[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Domain0 identifies IOAPIC by physical base address rather than BIOS-assigned identifier.



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.