ia64/xen-unstable

changeset 9125:fab6deef7e87

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@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Fri Mar 03 15:05:25 2006 +0100 (2006-03-03)
parents 8aa45d7713e3
children d088ce2d3528
files linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c xen/arch/x86/io_apic.c xen/arch/x86/physdev.c xen/include/public/physdev.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c	Fri Mar 03 14:10:35 2006 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/io_apic-xen.c	Fri Mar 03 15:05:25 2006 +0100
     1.3 @@ -61,8 +61,8 @@ static inline unsigned int xen_io_apic_r
     1.4  	int ret;
     1.5  
     1.6  	op.cmd = PHYSDEVOP_APIC_READ;
     1.7 -	op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
     1.8 -	op.u.apic_op.offset = reg;
     1.9 +	op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
    1.10 +	op.u.apic_op.reg = reg;
    1.11  	ret = HYPERVISOR_physdev_op(&op);
    1.12  	if (ret)
    1.13  		return ret;
    1.14 @@ -74,8 +74,8 @@ static inline void xen_io_apic_write(uns
    1.15  	physdev_op_t op;
    1.16  
    1.17  	op.cmd = PHYSDEVOP_APIC_WRITE;
    1.18 -	op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
    1.19 -	op.u.apic_op.offset = reg;
    1.20 +	op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
    1.21 +	op.u.apic_op.reg = reg;
    1.22  	op.u.apic_op.value = value;
    1.23  	HYPERVISOR_physdev_op(&op);
    1.24  }
     2.1 --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c	Fri Mar 03 14:10:35 2006 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/io_apic-xen.c	Fri Mar 03 15:05:25 2006 +0100
     2.3 @@ -108,8 +108,8 @@ static inline unsigned int xen_io_apic_r
     2.4  	int ret;
     2.5  
     2.6  	op.cmd = PHYSDEVOP_APIC_READ;
     2.7 -	op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
     2.8 -	op.u.apic_op.offset = reg;
     2.9 +	op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
    2.10 +	op.u.apic_op.reg = reg;
    2.11  	ret = HYPERVISOR_physdev_op(&op);
    2.12  	if (ret)
    2.13  		return ret;
    2.14 @@ -121,8 +121,8 @@ static inline void xen_io_apic_write(uns
    2.15  	physdev_op_t op;
    2.16  
    2.17  	op.cmd = PHYSDEVOP_APIC_WRITE;
    2.18 -	op.u.apic_op.apic = mp_ioapics[apic].mpc_apicid;
    2.19 -	op.u.apic_op.offset = reg;
    2.20 +	op.u.apic_op.apic_physbase = mp_ioapics[apic].mpc_apicaddr;
    2.21 +	op.u.apic_op.reg = reg;
    2.22  	op.u.apic_op.value = value;
    2.23  	HYPERVISOR_physdev_op(&op);
    2.24  }
     3.1 --- a/xen/arch/x86/io_apic.c	Fri Mar 03 14:10:35 2006 +0100
     3.2 +++ b/xen/arch/x86/io_apic.c	Fri Mar 03 15:05:25 2006 +0100
     3.3 @@ -1634,16 +1634,6 @@ static inline void check_timer(void)
     3.4            "report.  Then try booting with the 'noapic' option");
     3.5  }
     3.6  
     3.7 -#define NR_IOAPIC_BIOSIDS 256
     3.8 -static u8 ioapic_biosid_to_apic_enum[NR_IOAPIC_BIOSIDS];
     3.9 -static void store_ioapic_biosid_mapping(void)
    3.10 -{
    3.11 -    u8 apic;
    3.12 -    memset(ioapic_biosid_to_apic_enum, ~0, NR_IOAPIC_BIOSIDS);
    3.13 -    for ( apic = 0; apic < nr_ioapics; apic++ )
    3.14 -        ioapic_biosid_to_apic_enum[mp_ioapics[apic].mpc_apicid] = apic;
    3.15 -}
    3.16 -
    3.17  /*
    3.18   *
    3.19   * IRQ's that are handled by the PIC in the MPS IOAPIC case.
    3.20 @@ -1655,8 +1645,6 @@ static void store_ioapic_biosid_mapping(
    3.21  
    3.22  void __init setup_IO_APIC(void)
    3.23  {
    3.24 -    store_ioapic_biosid_mapping();
    3.25 -
    3.26      enable_IO_APIC();
    3.27  
    3.28      if (acpi_ioapic)
    3.29 @@ -1840,50 +1828,45 @@ int io_apic_set_pci_routing (int ioapic,
    3.30  
    3.31  #endif /*CONFIG_ACPI_BOOT*/
    3.32  
    3.33 -
    3.34 -int ioapic_guest_read(int apicid, int address, u32 *pval)
    3.35 +static int ioapic_physbase_to_id(unsigned long physbase)
    3.36  {
    3.37 -    u32 val;
    3.38 -    int apicenum;
    3.39 -    union IO_APIC_reg_00 reg_00;
    3.40 +    int apic;
    3.41 +    for ( apic = 0; apic < nr_ioapics; apic++ )
    3.42 +        if ( mp_ioapics[apic].mpc_apicaddr == physbase )
    3.43 +            return apic;
    3.44 +    return -EINVAL;
    3.45 +}
    3.46 +
    3.47 +int ioapic_guest_read(unsigned long physbase, unsigned int reg, u32 *pval)
    3.48 +{
    3.49 +    int apic;
    3.50      unsigned long flags;
    3.51  
    3.52 -    if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
    3.53 -         ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
    3.54 -        return -EINVAL;
    3.55 +    if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
    3.56 +        return apic;
    3.57  
    3.58      spin_lock_irqsave(&ioapic_lock, flags);
    3.59 -    val = io_apic_read(apicenum, address);
    3.60 +    *pval = io_apic_read(apic, reg);
    3.61      spin_unlock_irqrestore(&ioapic_lock, flags);
    3.62  
    3.63 -    /* Rewrite APIC ID to what the BIOS originally specified. */
    3.64 -    if ( address == 0 )
    3.65 -    {
    3.66 -        reg_00.raw = val;
    3.67 -        reg_00.bits.ID = apicid;
    3.68 -        val = reg_00.raw;
    3.69 -    }
    3.70 -
    3.71 -    *pval = val;
    3.72      return 0;
    3.73  }
    3.74  
    3.75 -int ioapic_guest_write(int apicid, int address, u32 val)
    3.76 +int ioapic_guest_write(unsigned long physbase, unsigned int reg, u32 val)
    3.77  {
    3.78 -    int apicenum, pin, irq;
    3.79 +    int apic, pin, irq;
    3.80      struct IO_APIC_route_entry rte = { 0 };
    3.81      struct irq_pin_list *entry;
    3.82      unsigned long flags;
    3.83  
    3.84 -    if ( (apicid >= NR_IOAPIC_BIOSIDS) ||
    3.85 -         ((apicenum = ioapic_biosid_to_apic_enum[apicid]) >= nr_ioapics) )
    3.86 -        return -EINVAL;
    3.87 +    if ( (apic = ioapic_physbase_to_id(physbase)) < 0 )
    3.88 +        return apic;
    3.89  
    3.90      /* Only write to the first half of a route entry. */
    3.91 -    if ( (address < 0x10) || (address & 1) )
    3.92 +    if ( (reg < 0x10) || (reg & 1) )
    3.93          return 0;
    3.94      
    3.95 -    pin = (address - 0x10) >> 1;
    3.96 +    pin = (reg - 0x10) >> 1;
    3.97  
    3.98      *(u32 *)&rte = val;
    3.99      rte.dest.logical.logical_dest = cpu_mask_to_apicid(TARGET_CPUS);
   3.100 @@ -1899,7 +1882,7 @@ int ioapic_guest_write(int apicid, int a
   3.101      if ( rte.delivery_mode > dest_LowestPrio )
   3.102      {
   3.103          printk("ERROR: Attempt to write weird IOAPIC destination mode!\n");
   3.104 -        printk("       APIC=%d/%d, lo-reg=%x\n", apicid, pin, val);
   3.105 +        printk("       APIC=%d/%d, lo-reg=%x\n", apic, pin, val);
   3.106          return -EINVAL;
   3.107      }
   3.108  
   3.109 @@ -1924,19 +1907,19 @@ int ioapic_guest_write(int apicid, int a
   3.110          /* Record the pin<->irq mapping. */
   3.111          for ( entry = &irq_2_pin[irq]; ; entry = &irq_2_pin[entry->next] )
   3.112          {
   3.113 -            if ( (entry->apic == apicenum) && (entry->pin == pin) )
   3.114 +            if ( (entry->apic == apic) && (entry->pin == pin) )
   3.115                  break;
   3.116              if ( !entry->next )
   3.117              {
   3.118 -                add_pin_to_irq(irq, apicenum, pin);
   3.119 +                add_pin_to_irq(irq, apic, pin);
   3.120                  break;
   3.121              }
   3.122          }
   3.123      }
   3.124  
   3.125      spin_lock_irqsave(&ioapic_lock, flags);
   3.126 -    io_apic_write(apicenum, 0x10 + 2 * pin, *(((int *)&rte) + 0));
   3.127 -    io_apic_write(apicenum, 0x11 + 2 * pin, *(((int *)&rte) + 1));
   3.128 +    io_apic_write(apic, 0x10 + 2 * pin, *(((int *)&rte) + 0));
   3.129 +    io_apic_write(apic, 0x11 + 2 * pin, *(((int *)&rte) + 1));
   3.130      spin_unlock_irqrestore(&ioapic_lock, flags);
   3.131  
   3.132      return 0;
     4.1 --- a/xen/arch/x86/physdev.c	Fri Mar 03 14:10:35 2006 +0100
     4.2 +++ b/xen/arch/x86/physdev.c	Fri Mar 03 15:05:25 2006 +0100
     4.3 @@ -11,8 +11,12 @@
     4.4  #include <public/xen.h>
     4.5  #include <public/physdev.h>
     4.6  
     4.7 -extern int ioapic_guest_read(int apicid, int address, u32 *pval);
     4.8 -extern int ioapic_guest_write(int apicid, int address, u32 pval);
     4.9 +extern int
    4.10 +ioapic_guest_read(
    4.11 +    unsigned long physbase, unsigned int reg, u32 *pval);
    4.12 +extern int
    4.13 +ioapic_guest_write(
    4.14 +    unsigned long physbase, unsigned int reg, u32 pval);
    4.15  
    4.16  /*
    4.17   * Demuxing hypercall.
    4.18 @@ -49,7 +53,9 @@ long do_physdev_op(struct physdev_op *uo
    4.19          if ( !IS_PRIV(current->domain) )
    4.20              break;
    4.21          ret = ioapic_guest_read(
    4.22 -            op.u.apic_op.apic, op.u.apic_op.offset, &op.u.apic_op.value);
    4.23 +            op.u.apic_op.apic_physbase,
    4.24 +            op.u.apic_op.reg,
    4.25 +            &op.u.apic_op.value);
    4.26          break;
    4.27  
    4.28      case PHYSDEVOP_APIC_WRITE:
    4.29 @@ -57,7 +63,9 @@ long do_physdev_op(struct physdev_op *uo
    4.30          if ( !IS_PRIV(current->domain) )
    4.31              break;
    4.32          ret = ioapic_guest_write(
    4.33 -            op.u.apic_op.apic, op.u.apic_op.offset, op.u.apic_op.value);
    4.34 +            op.u.apic_op.apic_physbase,
    4.35 +            op.u.apic_op.reg,
    4.36 +            op.u.apic_op.value);
    4.37          break;
    4.38  
    4.39      case PHYSDEVOP_ASSIGN_VECTOR:
     5.1 --- a/xen/include/public/physdev.h	Fri Mar 03 14:10:35 2006 +0100
     5.2 +++ b/xen/include/public/physdev.h	Fri Mar 03 15:05:25 2006 +0100
     5.3 @@ -33,8 +33,8 @@ typedef struct physdevop_set_iobitmap {
     5.4  
     5.5  typedef struct physdevop_apic {
     5.6      /* IN */
     5.7 -    uint32_t apic;
     5.8 -    uint32_t offset;
     5.9 +    unsigned long apic_physbase;
    5.10 +    uint32_t reg;
    5.11      /* IN or OUT */
    5.12      uint32_t value;
    5.13  } physdevop_apic_t;