diff -r 4b51d081378d xen/arch/ia64/linux-xen/iosapic.c --- a/xen/arch/ia64/linux-xen/iosapic.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/arch/ia64/linux-xen/iosapic.c Fri Jun 30 12:47:17 2006 -0600 @@ -1122,6 +1122,53 @@ core_initcall (iosapic_enable_kmalloc); #endif #ifdef XEN +static void unmask_xen_redirect(unsigned int irq) +{ + int i; + + for (i = 0 ; i < NR_IRQS ; i++) { + if (guest_vector[i].vector == irq) { + guest_vector[i].enabled = 1; + return; + } + } +} + +static void mask_xen_redirect(unsigned int irq) +{ + int i; + + for (i = 0 ; i < NR_IRQS ; i++) { + if (guest_vector[i].vector == irq) { + guest_vector[i].enabled = 0; + return; + } + } +} + +static unsigned int startup_xen_redirect(unsigned int irq) +{ + unmask_xen_redirect(irq); + return 0; +} + +#define shutdown_xen_redirect mask_xen_redirect +#define enable_xen_redirect unmask_xen_redirect +#define disable_xen_redirect mask_xen_redirect +#define ack_xen_redirect nop +#define end_xen_redirect nop + +struct hw_interrupt_type irq_type_xen_redirect = { + .typename = "XEN-redirect", + .startup = startup_xen_redirect, + .shutdown = shutdown_xen_redirect, + .enable = enable_xen_redirect, + .disable = disable_xen_redirect, + .ack = ack_xen_redirect, + .end = end_xen_redirect, + .set_affinity = NULL, +}; + /* nop for now */ void set_irq_affinity_info(unsigned int irq, int hwid, int redir) {} @@ -1161,6 +1208,7 @@ int iosapic_guest_write(unsigned long ph struct iosapic_intr_info *info; struct rte_entry rte; unsigned long flags; + int xen_vector; if ((id = (iosapic_physbase_to_id(physbase))) < 0) return -EINVAL; @@ -1185,13 +1233,41 @@ int iosapic_guest_write(unsigned long ph /* Sanity check. Vector should be allocated before this update */ if ((rte_index > ios->num_rte) || - test_bit(vec, ia64_xen_vector) || ((vec > IA64_FIRST_DEVICE_VECTOR) && (vec < IA64_LAST_DEVICE_VECTOR) && (!test_bit(vec - IA64_FIRST_DEVICE_VECTOR, ia64_vector_mask)))) return -EINVAL; gsi = ios->gsi_base + rte_index; + xen_vector = gsi_to_vector(gsi); + if (xen_vector >= 0 && test_bit(xen_vector, ia64_xen_vector)) { + + if (guest_vector[xen_vector].vector) { + printk("WARN: Xen GSI %d (vector %d) already in use " + "and redirected to guest vector %d\n", gsi, + xen_vector, guest_vector[xen_vector].vector); + return -EINVAL; + } + + info = &iosapic_intr_info[xen_vector]; + if ((info->trigger != rte.lo.trigger) || + (info->polarity != rte.lo.polarity)) { + printk("WARN: Xen GSI %d (vector %d) trigger/polairty " + "incompatible with guest vector %d\n", gsi, + xen_vector, vec); + return -EINVAL; + } + + spin_lock_irqsave(&irq_descp(vec)->lock, flags); + irq_descp(vec)->handler = &irq_type_xen_redirect; + spin_unlock_irqrestore(&irq_descp(vec)->lock, flags); + + spin_lock_irqsave(&irq_descp(xen_vector)->lock, flags); + guest_vector[xen_vector].vector = vec; + spin_unlock_irqrestore(&irq_descp(xen_vector)->lock, flags); + return 0; + } + info = &iosapic_intr_info[vec]; spin_lock_irqsave(&irq_descp(vec)->lock, flags); spin_lock(&iosapic_lock); diff -r 4b51d081378d xen/arch/ia64/xen/irq.c --- a/xen/arch/ia64/xen/irq.c Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/arch/ia64/xen/irq.c Fri Jun 30 12:47:17 2006 -0600 @@ -45,6 +45,7 @@ #include #include #include +#include #include #define apicid_to_phys_cpu_present(x) 1 @@ -75,6 +76,8 @@ irq_desc_t irq_desc[NR_IRQS] __cacheline .lock = SPIN_LOCK_UNLOCKED } }; + +struct guest_vector_t guest_vector[NR_IRQS]; void __do_IRQ_guest(int irq); @@ -211,6 +214,16 @@ fastcall unsigned int __do_IRQ(unsigned desc->status &= ~IRQ_INPROGRESS; out: + if (guest_vector[irq].enabled) { + irq_desc_t *guest_desc = irq_desc + guest_vector[irq].vector; + + if (likely(guest_desc->status & IRQ_GUEST)) { + spin_lock(&guest_desc->lock); + __do_IRQ_guest(guest_vector[irq].vector); + spin_unlock(&guest_desc->lock); + } + } + /* * The ->end() handler has to deal with interrupts which got * disabled while the handler was running. diff -r 4b51d081378d xen/include/asm-ia64/linux-xen/asm/iosapic.h --- a/xen/include/asm-ia64/linux-xen/asm/iosapic.h Wed Jun 28 07:52:21 2006 -0600 +++ b/xen/include/asm-ia64/linux-xen/asm/iosapic.h Fri Jun 30 12:47:17 2006 -0600 @@ -159,6 +159,13 @@ struct rte_entry { #define IOSAPIC_RTEINDEX(reg) (((reg) - 0x10) >> 1) extern unsigned long ia64_vector_mask[]; extern unsigned long ia64_xen_vector[]; + +struct guest_vector_t { + u16 vector : 8, + __reserved : 7, + enabled : 1; +}; +extern struct guest_vector_t guest_vector[]; #endif /* XEN */ # endif /* !__ASSEMBLY__ */