diff -r 02003bee3e80 -r c9df3571e4d2 xen/arch/x86/mpparse.c --- a/xen/arch/x86/mpparse.c Thu Jun 25 18:31:10 2009 +0100 +++ b/xen/arch/x86/mpparse.c Tue Jul 07 16:37:03 2009 -0700 @@ -871,7 +871,7 @@ } mp_ioapic_routing[MAX_IO_APICS]; -static int mp_find_ioapic ( +int mp_find_ioapic ( int gsi) { int i = 0; @@ -887,7 +887,13 @@ return -1; } - + +int mp_find_pin ( + int ioapic, + int gsi) +{ + return gsi - mp_ioapic_routing[ioapic].gsi_base; +} void __init mp_register_ioapic ( u8 id, @@ -962,7 +968,7 @@ ioapic = mp_find_ioapic(gsi); if (ioapic < 0) return; - pin = gsi - mp_ioapic_routing[ioapic].gsi_base; + pin = mp_find_pin(ioapic, gsi); /* * TBD: This check is for faulty timer entries, where the override @@ -1084,7 +1090,7 @@ return gsi; } - ioapic_pin = gsi - mp_ioapic_routing[ioapic].gsi_base; + ioapic_pin = mp_find_pin(ioapic, gsi); if (ioapic_renumber_irq) gsi = ioapic_renumber_irq(ioapic, gsi); diff -r 02003bee3e80 -r c9df3571e4d2 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Thu Jun 25 18:31:10 2009 +0100 +++ b/xen/arch/x86/physdev.c Tue Jul 07 16:37:03 2009 -0700 @@ -361,6 +361,63 @@ break; } + case PHYSDEVOP_route_gsi: { + struct physdev_route_gsi route_gsi; + unsigned gsi; + int vector; + int ioapic, pin; + int level, active_low; + + ret = -EFAULT; + if ( copy_from_guest(&route_gsi, arg, 1) != 0 ) + break; + + ret = -EPERM; + if ( !IS_PRIV(v->domain) ) + break; + + ret = xsm_assign_vector(v->domain, route_gsi.pirq); + if ( ret ) + break; + + irq = route_gsi.pirq; + ret = -EINVAL; + if ( (irq < 0) || (irq >= nr_irqs) ) + break; + + vector = irq_to_vector(irq); + if ( vector < 0 ) { + ret = vector; + break; + } + + spin_lock(&pcidevs_lock); + spin_lock(&dom0->event_lock); + ret = map_domain_pirq(dom0, irq, vector, + MAP_PIRQ_TYPE_GSI, NULL); + spin_unlock(&dom0->event_lock); + spin_unlock(&pcidevs_lock); + + if ( ret < 0 ) + break; + + gsi = route_gsi.gsi; + + ret = -ENOENT; + ioapic = mp_find_ioapic(gsi); + if ( ioapic < 0 ) + break; + + pin = mp_find_pin(ioapic, gsi); + + level = (route_gsi.flags & XENROUTEGSI_level) != 0; + active_low = (route_gsi.flags & XENROUTEGSI_active_low) != 0; + + ret = io_apic_set_pci_routing(ioapic, pin, irq, level, active_low); + + break; + } + case PHYSDEVOP_set_iopl: { struct physdev_set_iopl set_iopl; ret = -EFAULT; diff -r 02003bee3e80 -r c9df3571e4d2 xen/include/asm-x86/mpspec.h --- a/xen/include/asm-x86/mpspec.h Thu Jun 25 18:31:10 2009 +0100 +++ b/xen/include/asm-x86/mpspec.h Tue Jul 07 16:37:03 2009 -0700 @@ -34,6 +34,10 @@ extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi); extern void mp_config_acpi_legacy_irqs (void); extern int mp_register_gsi (u32 gsi, int edge_level, int active_high_low); + +extern int mp_find_ioapic (int gsi); +extern int mp_find_pin (int ioapic, int gsi); + #endif /* CONFIG_ACPI */ #define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS) diff -r 02003bee3e80 -r c9df3571e4d2 xen/include/public/physdev.h --- a/xen/include/public/physdev.h Thu Jun 25 18:31:10 2009 +0100 +++ b/xen/include/public/physdev.h Tue Jul 07 16:37:03 2009 -0700 @@ -210,6 +210,31 @@ typedef struct physdev_manage_pci_ext physdev_manage_pci_ext_t; DEFINE_XEN_GUEST_HANDLE(physdev_manage_pci_ext_t); +/* + * Allocate a vector for an irq (if necessary) and set up routing for + * the GSI in the appropriate IO/APIC. May be used to update the + * IO/APIC routing once it has been initially set. + * + * @arg = pointer to physdev_route_gsi structure. + */ +#define PHYSDEVOP_route_gsi 21 +struct physdev_route_gsi { + /* IN */ + uint32_t pirq; + uint32_t gsi; + uint32_t flags; /* XENROUTEGSI_* */ +}; + +typedef struct physdev_route_gsi physdev_route_gsi_t; +DEFINE_XEN_GUEST_HANDLE(physdev_route_gsi_t); + +#define _XENROUTEGSI_level (0) +#define XENROUTEGSI_level (1U<<_XENROUTEGSI_level) +#define _XENROUTEGSI_active_low (1) +#define XENROUTEGSI_active_low (1U<<_XENROUTEGSI_active_low) +#define _XENROUTEGSI_masked (2) +#define XENROUTEGSI_masked (1U<<_XENROUTEGSI_masked) + /* * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op() * hypercall since 0x00030202.