# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID fab6deef7e87a8b980de81311f34d91fcf550a6c
# Parent 8aa45d7713e3c81cdd2305df125b82c9fe7bb202
Domain0 identifies IOAPIC by physical base address rather than BIOS-assigned
identifier.
This seems a more reliable method since it seems that we always trust the base
address
and we don't need to work around renumbering/rebasing as we do with APICIDs.
This is an alternative to the Yonah networking patch from Allen Kay at Intel.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r 8aa45d7713e3 -r fab6deef7e87
linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c
--- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c Fri Mar 3
13:10:35 2006
+++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c Fri Mar 3
14:05:25 2006
@@ -61,8 +61,8 @@
int ret;
op.cmd = PHYSDEVOP_APIC_READ;
- op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
- op.u.apic_op.offset = reg;
+ op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+ op.u.apic_op.reg = reg;
ret = HYPERVISOR_physdev_op(&op);
if (ret)
return ret;
@@ -74,8 +74,8 @@
physdev_op_t op;
op.cmd = PHYSDEVOP_APIC_WRITE;
- op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
- op.u.apic_op.offset = reg;
+ op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+ op.u.apic_op.reg = reg;
op.u.apic_op.value = value;
HYPERVISOR_physdev_op(&op);
}
diff -r 8aa45d7713e3 -r fab6deef7e87
linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c
--- a/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c Fri Mar 3
13:10:35 2006
+++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c Fri Mar 3
14:05:25 2006
@@ -108,8 +108,8 @@
int ret;
op.cmd = PHYSDEVOP_APIC_READ;
- op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
- op.u.apic_op.offset = reg;
+ op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+ op.u.apic_op.reg = reg;
ret = HYPERVISOR_physdev_op(&op);
if (ret)
return ret;
@@ -121,8 +121,8 @@
physdev_op_t op;
op.cmd = PHYSDEVOP_APIC_WRITE;
- op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
- op.u.apic_op.offset = reg;
+ op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
+ op.u.apic_op.reg = reg;
op.u.apic_op.value = value;
HYPERVISOR_physdev_op(&op);
}
diff -r 8aa45d7713e3 -r fab6deef7e87 xen/arch/x86/io_apic.c
--- a/xen/arch/x86/io_apic.c Fri Mar 3 13:10:35 2006
+++ b/xen/arch/x86/io_apic.c Fri Mar 3 14:05:25 2006
@@ -1634,16 +1634,6 @@
"report. Then try booting with the 'noapic' option");
}
-#define NR_IOAPIC_BIOSIDS 256
-static u8 ioapic_biosid_to_apic_enum[NR_IOAPIC_BIOSIDS];
-static void store_ioapic_biosid_mapping(void)
-{
- u8 apic;
- memset(ioapic_biosid_to_apic_enum, ~0, NR_IOAPIC_BIOSIDS);
- for ( apic = 0; apic < nr_ioapics; apic++ )
- ioapic_biosid_to_apic_enum[mp_ioapics[apic].mpc_apicid] = apic;
-}
-
/*
*
* IRQ's that are handled by the PIC in the MPS IOAPIC case.
@@ -1655,8 +1645,6 @@
void __init setup_IO_APIC(void)
{
- store_ioapic_biosid_mapping();
-
enable_IO_APIC();
if (acpi_ioapic)
@@ -1840,50 +1828,45 @@
#endif /*CONFIG_ACPI_BOOT*/
-
-int ioapic_guest_read(int apicid, int address, u32 *pval)
-{
- u32 val;
- int apicenum;
- union IO_APIC_reg_00 reg_00;
+static int ioapic_physbase_to_id(unsigned long physbase)
+{
+ int apic;
+ for ( apic = 0; apic < nr_ioapics; apic++ )
+ if ( mp_ioapics[apic].mpc_apicaddr == physbase )
+ return apic;
+ return -EINVAL;
+}
+
+int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval)
+{
+ int apic;
unsigned long flags;
- if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
- ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
- return -EINVAL;
+ if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
+ return apic;
spin_lock_irqsave(&ioapic_lock, flags);
- val = io_apic_read(apicenum, address);
+ *pval = io_apic_read(apic, reg);
spin_unlock_irqrestore(&ioapic_lock, flags);
- /* Rewrite APIC ID to what the BIOS originally specified. */
- if ( address == 0 )
- {
- reg_00.raw = val;
- reg_00.bits.ID = apicid;
- val = reg_00.raw;
- }
-
- *pval = val;
return 0;
}
-int ioapic_guest_write(int apicid, int address, u32 val)
-{
- int apicenum, pin, irq;
+int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
+{
+ int apic, pin, irq;
struct IO_APIC_route_entry rte = { 0 };
struct irq_pin_list *entry;
unsigned long flags;
- if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
- ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
- return -EINVAL;
+ if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
+ return apic;
/* Only write to the first half of a route entry. */
- if ( (address < 0x10) || (address & 1) )
+ if ( (reg < 0x10) || (reg & 1) )
return 0;
- pin = (address - 0x10) >> 1;
+ pin = (reg - 0x10) >> 1;
*(u32 *)&rte = val;
rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
@@ -1899,7 +1882,7 @@
if ( rte.delivery_mode > dest_LowestPrio )
{
printk("ERROR: Attempt to write weird IOAPIC destination mode!\n");
- printk(" APIC=%d/%d, lo-reg=%x\n", apicid, pin, val);
+ printk(" APIC=%d/%d, lo-reg=%x\n", apic, pin, val);
return -EINVAL;
}
@@ -1924,19 +1907,19 @@
/* Record the pin<->irq mapping. */
for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] )
{
- if ( (entry->apic == apicenum) && (entry->pin == pin) )
+ if ( (entry->apic == apic) && (entry->pin == pin) )
break;
if ( !entry->next )
{
- add_pin_to_irq(irq, apicenum, pin);
+ add_pin_to_irq(irq, apic, pin);
break;
}
}
}
spin_lock_irqsave(&ioapic_lock, flags);
- io_apic_write(apicenum, 0x10 + 2 * pin, *(((int *)&rte) + 0));
- io_apic_write(apicenum, 0x11 + 2 * pin, *(((int *)&rte) + 1));
+ io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0));
+ io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1));
spin_unlock_irqrestore(&ioapic_lock, flags);
return 0;
diff -r 8aa45d7713e3 -r fab6deef7e87 xen/arch/x86/physdev.c
--- a/xen/arch/x86/physdev.c Fri Mar 3 13:10:35 2006
+++ b/xen/arch/x86/physdev.c Fri Mar 3 14:05:25 2006
@@ -11,8 +11,12 @@
#include <public/xen.h>
#include <public/physdev.h>
-extern int ioapic_guest_read(int apicid, int address, u32 *pval);
-extern int ioapic_guest_write(int apicid, int address, u32 pval);
+extern int
+ioapic_guest_read(
+ unsigned long physbase, unsigned int reg, u32 *pval);
+extern int
+ioapic_guest_write(
+ unsigned long physbase, unsigned int reg, u32 pval);
/*
* Demuxing hypercall.
@@ -49,7 +53,9 @@
if ( !IS_PRIV(current->domain) )
break;
ret = ioapic_guest_read(
- op.u.apic_op.apic, op.u.apic_op.offset, &op.u.apic_op.value);
+ op.u.apic_op.apic_physbase,
+ op.u.apic_op.reg,
+ &op.u.apic_op.value);
break;
case PHYSDEVOP_APIC_WRITE:
@@ -57,7 +63,9 @@
if ( !IS_PRIV(current->domain) )
break;
ret = ioapic_guest_write(
- op.u.apic_op.apic, op.u.apic_op.offset, op.u.apic_op.value);
+ op.u.apic_op.apic_physbase,
+ op.u.apic_op.reg,
+ op.u.apic_op.value);
break;
case PHYSDEVOP_ASSIGN_VECTOR:
diff -r 8aa45d7713e3 -r fab6deef7e87 xen/include/public/physdev.h
--- a/xen/include/public/physdev.h Fri Mar 3 13:10:35 2006
+++ b/xen/include/public/physdev.h Fri Mar 3 14:05:25 2006
@@ -33,8 +33,8 @@
typedef struct physdevop_apic {
/* IN */
- uint32_t apic;
- uint32_t offset;
+ unsigned long apic_physbase;
+ uint32_t reg;
/* IN or OUT */
uint32_t value;
} physdevop_apic_t;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|