ia64/xen-unstable
changeset 17541:6ecbb00e58cd
MSI 2/6: change the pirq to be per-domain
Signed-off-by: Jiang Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Shan Haitao <haitao.shan@intel.com>
Signed-off-by: Jiang Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Shan Haitao <haitao.shan@intel.com>
author | Keir Fraser <keir.fraser@citrix.com> |
---|---|
date | Thu May 01 10:30:22 2008 +0100 (2008-05-01) |
parents | 8bced3d8a907 |
children | 86c0353f19d0 |
files | tools/ioemu/hw/pass-through.c tools/libxc/xc_physdev.c tools/libxc/xc_private.h tools/libxc/xenctrl.h tools/python/xen/lowlevel/xc/xc.c tools/python/xen/xend/server/irqif.py tools/python/xen/xend/server/pciif.py xen/arch/x86/domain.c xen/arch/x86/hvm/vmx/intr.c xen/arch/x86/io_apic.c xen/arch/x86/irq.c xen/arch/x86/physdev.c xen/drivers/passthrough/io.c xen/drivers/passthrough/vtd/x86/vtd.c xen/include/asm-x86/domain.h xen/include/asm-x86/irq.h xen/include/asm-x86/pirq.h xen/include/public/physdev.h |
line diff
1.1 --- a/tools/ioemu/hw/pass-through.c Thu May 01 10:26:58 2008 +0100 1.2 +++ b/tools/ioemu/hw/pass-through.c Thu May 01 10:30:22 2008 +0100 1.3 @@ -519,7 +519,21 @@ struct pt_dev * register_real_device(PCI 1.4 e_intx = assigned_device->dev.config[0x3d]-1; 1.5 1.6 if ( PT_MACHINE_IRQ_AUTO == machine_irq ) 1.7 + { 1.8 + int pirq = pci_dev->irq; 1.9 + 1.10 machine_irq = pci_dev->irq; 1.11 + rc = xc_physdev_map_pirq(xc_handle, domid, MAP_PIRQ_TYPE_GSI, 1.12 + machine_irq, &pirq); 1.13 + 1.14 + if ( rc ) 1.15 + { 1.16 + /* TBD: unregister device in case of an error */ 1.17 + PT_LOG("Error: Mapping irq failed, rc = %d\n", rc); 1.18 + } 1.19 + else 1.20 + machine_irq = pirq; 1.21 + } 1.22 1.23 /* bind machine_irq to device */ 1.24 if ( 0 != machine_irq )
2.1 --- a/tools/libxc/xc_physdev.c Thu May 01 10:26:58 2008 +0100 2.2 +++ b/tools/libxc/xc_physdev.c Thu May 01 10:30:22 2008 +0100 2.3 @@ -19,3 +19,43 @@ int xc_physdev_pci_access_modify(int xc_ 2.4 errno = ENOSYS; 2.5 return -1; 2.6 } 2.7 + 2.8 +int xc_physdev_map_pirq(int xc_handle, 2.9 + int domid, 2.10 + int type, 2.11 + int index, 2.12 + int *pirq) 2.13 +{ 2.14 + int rc; 2.15 + struct physdev_map_pirq map; 2.16 + 2.17 + if ( !pirq ) 2.18 + return -EINVAL; 2.19 + 2.20 + map.domid = domid; 2.21 + map.type = type; 2.22 + map.index = index; 2.23 + map.pirq = *pirq; 2.24 + 2.25 + rc = do_physdev_op(xc_handle, PHYSDEVOP_map_pirq, &map); 2.26 + 2.27 + if ( !rc ) 2.28 + *pirq = map.pirq; 2.29 + 2.30 + return rc; 2.31 +} 2.32 + 2.33 +int xc_physdev_unmap_pirq(int xc_handle, 2.34 + int domid, 2.35 + int pirq) 2.36 +{ 2.37 + int rc; 2.38 + struct physdev_unmap_pirq unmap; 2.39 + 2.40 + unmap.domid = domid; 2.41 + unmap.pirq = pirq; 2.42 + 2.43 + rc = do_physdev_op(xc_handle, PHYSDEVOP_unmap_pirq, &unmap); 2.44 + 2.45 + return rc; 2.46 +}
3.1 --- a/tools/libxc/xc_private.h Thu May 01 10:26:58 2008 +0100 3.2 +++ b/tools/libxc/xc_private.h Thu May 01 10:30:22 2008 +0100 3.3 @@ -24,10 +24,12 @@ 3.4 #define DECLARE_HYPERCALL privcmd_hypercall_t hypercall = { 0 } 3.5 #define DECLARE_DOMCTL struct xen_domctl domctl = { 0 } 3.6 #define DECLARE_SYSCTL struct xen_sysctl sysctl = { 0 } 3.7 +#define DECLARE_PHYSDEV_OP struct physdev_op physdev_op = { 0 } 3.8 #else 3.9 #define DECLARE_HYPERCALL privcmd_hypercall_t hypercall 3.10 #define DECLARE_DOMCTL struct xen_domctl domctl 3.11 #define DECLARE_SYSCTL struct xen_sysctl sysctl 3.12 +#define DECLARE_PHYSDEV_OP struct physdev_op physdev_op 3.13 #endif 3.14 3.15 #undef PAGE_SHIFT 3.16 @@ -96,6 +98,34 @@ static inline int do_xen_version(int xc_ 3.17 return do_xen_hypercall(xc_handle, &hypercall); 3.18 } 3.19 3.20 +static inline int do_physdev_op(int xc_handle, int cmd, void *op) 3.21 +{ 3.22 + int ret = -1; 3.23 + 3.24 + DECLARE_HYPERCALL; 3.25 + hypercall.op = __HYPERVISOR_physdev_op; 3.26 + hypercall.arg[0] = (unsigned long) cmd; 3.27 + hypercall.arg[1] = (unsigned long) op; 3.28 + 3.29 + if ( lock_pages(op, sizeof(*op)) != 0 ) 3.30 + { 3.31 + PERROR("Could not lock memory for Xen hypercall"); 3.32 + goto out1; 3.33 + } 3.34 + 3.35 + if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 ) 3.36 + { 3.37 + if ( errno == EACCES ) 3.38 + DPRINTF("physdev operation failed -- need to" 3.39 + " rebuild the user-space tool set?\n"); 3.40 + } 3.41 + 3.42 + unlock_pages(op, sizeof(*op)); 3.43 + 3.44 +out1: 3.45 + return ret; 3.46 +} 3.47 + 3.48 static inline int do_domctl(int xc_handle, struct xen_domctl *domctl) 3.49 { 3.50 int ret = -1;
4.1 --- a/tools/libxc/xenctrl.h Thu May 01 10:26:58 2008 +0100 4.2 +++ b/tools/libxc/xenctrl.h Thu May 01 10:30:22 2008 +0100 4.3 @@ -21,6 +21,7 @@ 4.4 #include <stdint.h> 4.5 #include <xen/xen.h> 4.6 #include <xen/domctl.h> 4.7 +#include <xen/physdev.h> 4.8 #include <xen/sysctl.h> 4.9 #include <xen/version.h> 4.10 #include <xen/event_channel.h> 4.11 @@ -849,6 +850,16 @@ int xc_gnttab_munmap(int xcg_handle, 4.12 int xc_gnttab_set_max_grants(int xcg_handle, 4.13 uint32_t count); 4.14 4.15 +int xc_physdev_map_pirq(int xc_handle, 4.16 + int domid, 4.17 + int type, 4.18 + int index, 4.19 + int *pirq); 4.20 + 4.21 +int xc_physdev_unmap_pirq(int xc_handle, 4.22 + int domid, 4.23 + int pirq); 4.24 + 4.25 int xc_hvm_set_pci_intx_level( 4.26 int xc_handle, domid_t dom, 4.27 uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,
5.1 --- a/tools/python/xen/lowlevel/xc/xc.c Thu May 01 10:26:58 2008 +0100 5.2 +++ b/tools/python/xen/lowlevel/xc/xc.c Thu May 01 10:30:22 2008 +0100 5.3 @@ -799,6 +799,26 @@ static PyObject *pyxc_evtchn_reset(XcObj 5.4 return zero; 5.5 } 5.6 5.7 +static PyObject *pyxc_physdev_map_pirq(PyObject *self, 5.8 + PyObject *args, 5.9 + PyObject *kwds) 5.10 +{ 5.11 + XcObject *xc = (XcObject *)self; 5.12 + uint32_t dom; 5.13 + int index, pirq, ret; 5.14 + 5.15 + static char *kwd_list[] = {"domid", "index", "pirq", NULL}; 5.16 + 5.17 + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, 5.18 + &dom, &index, &pirq) ) 5.19 + return NULL; 5.20 + ret = xc_physdev_map_pirq(xc->xc_handle, dom, MAP_PIRQ_TYPE_GSI, 5.21 + index, &pirq); 5.22 + if ( ret != 0 ) 5.23 + return pyxc_error_to_exception(); 5.24 + return PyLong_FromUnsignedLong(pirq); 5.25 +} 5.26 + 5.27 static PyObject *pyxc_physdev_pci_access_modify(XcObject *self, 5.28 PyObject *args, 5.29 PyObject *kwds) 5.30 @@ -1589,6 +1609,15 @@ static PyMethodDef pyxc_methods[] = { 5.31 "Reset all connections.\n" 5.32 " dom [int]: Domain to reset.\n" }, 5.33 5.34 + { "physdev_map_pirq", 5.35 + (PyCFunction)pyxc_physdev_map_pirq, 5.36 + METH_VARARGS | METH_KEYWORDS, "\n" 5.37 + "map physical irq to guest pirq.\n" 5.38 + " dom [int]: Identifier of domain to map for.\n" 5.39 + " index [int]: physical irq.\n" 5.40 + " pirq [int]: guest pirq.\n" 5.41 + "Returns: [long] value of the param.\n" }, 5.42 + 5.43 { "physdev_pci_access_modify", 5.44 (PyCFunction)pyxc_physdev_pci_access_modify, 5.45 METH_VARARGS | METH_KEYWORDS, "\n"
6.1 --- a/tools/python/xen/xend/server/irqif.py Thu May 01 10:26:58 2008 +0100 6.2 +++ b/tools/python/xen/xend/server/irqif.py Thu May 01 10:30:22 2008 +0100 6.3 @@ -69,5 +69,10 @@ class IRQController(DevController): 6.4 #todo non-fatal 6.5 raise VmError( 6.6 'irq: Failed to configure irq: %d' % (pirq)) 6.7 - 6.8 + rc = xc.physdev_map_pirq(domid = self.getDomid(), 6.9 + index = pirq, 6.10 + pirq = pirq) 6.11 + if rc < 0: 6.12 + raise VmError( 6.13 + 'irq: Failed to map irq %x' % (pirq)) 6.14 return (None, {}, {})
7.1 --- a/tools/python/xen/xend/server/pciif.py Thu May 01 10:26:58 2008 +0100 7.2 +++ b/tools/python/xen/xend/server/pciif.py Thu May 01 10:30:22 2008 +0100 7.3 @@ -271,6 +271,12 @@ class PciController(DevController): 7.4 if rc<0: 7.5 raise VmError(('pci: failed to configure I/O memory on device '+ 7.6 '%s - errno=%d')%(dev.name,rc)) 7.7 + rc = xc.physdev_map_pirq(domid = fe_domid, 7.8 + index = dev.irq, 7.9 + pirq = dev.irq) 7.10 + if rc < 0: 7.11 + raise VmError(('pci: failed to map irq on device '+ 7.12 + '%s - errno=%d')%(dev.name,rc)) 7.13 7.14 if dev.irq>0: 7.15 log.debug('pci: enabling irq %d'%dev.irq)
8.1 --- a/xen/arch/x86/domain.c Thu May 01 10:26:58 2008 +0100 8.2 +++ b/xen/arch/x86/domain.c Thu May 01 10:30:22 2008 +0100 8.3 @@ -525,6 +525,8 @@ int arch_domain_create(struct domain *d, 8.4 goto fail; 8.5 } 8.6 8.7 + spin_lock_init(&d->arch.irq_lock); 8.8 + 8.9 if ( is_hvm_domain(d) ) 8.10 { 8.11 if ( (rc = hvm_domain_initialise(d)) != 0 )
9.1 --- a/xen/arch/x86/hvm/vmx/intr.c Thu May 01 10:26:58 2008 +0100 9.2 +++ b/xen/arch/x86/hvm/vmx/intr.c Thu May 01 10:30:22 2008 +0100 9.3 @@ -121,7 +121,7 @@ static void vmx_dirq_assist(struct vcpu 9.4 if ( !test_and_clear_bit(irq, &hvm_irq_dpci->dirq_mask) ) 9.5 continue; 9.6 9.7 - stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)]); 9.8 + stop_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)]); 9.9 9.10 list_for_each_entry ( digl, &hvm_irq_dpci->mirq[irq].digl_list, list ) 9.11 { 9.12 @@ -140,7 +140,7 @@ static void vmx_dirq_assist(struct vcpu 9.13 * guest will never deal with the irq, then the physical interrupt line 9.14 * will never be deasserted. 9.15 */ 9.16 - set_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(irq)], 9.17 + set_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, irq)], 9.18 NOW() + PT_IRQ_TIME_OUT); 9.19 } 9.20 }
10.1 --- a/xen/arch/x86/io_apic.c Thu May 01 10:26:58 2008 +0100 10.2 +++ b/xen/arch/x86/io_apic.c Thu May 01 10:30:22 2008 +0100 10.3 @@ -41,6 +41,25 @@ 10.4 int (*ioapic_renumber_irq)(int ioapic, int irq); 10.5 atomic_t irq_mis_count; 10.6 10.7 +int msi_irq_enable = 0; 10.8 +boolean_param("msi_irq_enable", msi_irq_enable); 10.9 + 10.10 +int domain_irq_to_vector(struct domain *d, int irq) 10.11 +{ 10.12 + if ( !msi_irq_enable ) 10.13 + return irq_to_vector(irq); 10.14 + else 10.15 + return d->arch.pirq_vector[irq]; 10.16 +} 10.17 + 10.18 +int domain_vector_to_irq(struct domain *d, int vector) 10.19 +{ 10.20 + if ( !msi_irq_enable ) 10.21 + return vector_to_irq(vector); 10.22 + else 10.23 + return d->arch.vector_pirq[vector]; 10.24 +} 10.25 + 10.26 /* Where if anywhere is the i8259 connect in external int mode */ 10.27 static struct { int pin, apic; } ioapic_i8259 = { -1, -1 }; 10.28
11.1 --- a/xen/arch/x86/irq.c Thu May 01 10:26:58 2008 +0100 11.2 +++ b/xen/arch/x86/irq.c Thu May 01 10:30:22 2008 +0100 11.3 @@ -203,7 +203,6 @@ static DEFINE_PER_CPU(struct pending_eoi 11.4 11.5 static void __do_IRQ_guest(int vector) 11.6 { 11.7 - unsigned int irq = vector_to_irq(vector); 11.8 irq_desc_t *desc = &irq_desc[vector]; 11.9 irq_guest_action_t *action = (irq_guest_action_t *)desc->action; 11.10 struct domain *d; 11.11 @@ -232,7 +231,9 @@ static void __do_IRQ_guest(int vector) 11.12 11.13 for ( i = 0; i < action->nr_guests; i++ ) 11.14 { 11.15 + unsigned int irq; 11.16 d = action->guest[i]; 11.17 + irq = domain_vector_to_irq(d, vector); 11.18 if ( (action->ack_type != ACKTYPE_NONE) && 11.19 !test_and_set_bit(irq, d->pirq_mask) ) 11.20 action->in_flight++; 11.21 @@ -305,8 +306,10 @@ static void __pirq_guest_eoi(struct doma 11.22 irq_desc_t *desc; 11.23 irq_guest_action_t *action; 11.24 cpumask_t cpu_eoi_map; 11.25 + int vector; 11.26 11.27 - desc = &irq_desc[irq_to_vector(irq)]; 11.28 + vector = domain_irq_to_vector(d, irq); 11.29 + desc = &irq_desc[vector]; 11.30 action = (irq_guest_action_t *)desc->action; 11.31 11.32 spin_lock_irq(&desc->lock); 11.33 @@ -324,7 +327,7 @@ static void __pirq_guest_eoi(struct doma 11.34 if ( action->ack_type == ACKTYPE_UNMASK ) 11.35 { 11.36 ASSERT(cpus_empty(action->cpu_eoi_map)); 11.37 - desc->handler->end(irq_to_vector(irq)); 11.38 + desc->handler->end(vector); 11.39 spin_unlock_irq(&desc->lock); 11.40 return; 11.41 } 11.42 @@ -375,12 +378,12 @@ int pirq_guest_unmask(struct domain *d) 11.43 } 11.44 11.45 extern int ioapic_ack_new; 11.46 -int pirq_acktype(int irq) 11.47 +int pirq_acktype(struct domain *d, int irq) 11.48 { 11.49 irq_desc_t *desc; 11.50 unsigned int vector; 11.51 11.52 - vector = irq_to_vector(irq); 11.53 + vector = domain_irq_to_vector(d, irq); 11.54 if ( vector == 0 ) 11.55 return ACKTYPE_NONE; 11.56 11.57 @@ -421,7 +424,7 @@ int pirq_acktype(int irq) 11.58 return 0; 11.59 } 11.60 11.61 -int pirq_shared(int irq) 11.62 +int pirq_shared(struct domain *d, int irq) 11.63 { 11.64 unsigned int vector; 11.65 irq_desc_t *desc; 11.66 @@ -429,7 +432,7 @@ int pirq_shared(int irq) 11.67 unsigned long flags; 11.68 int shared; 11.69 11.70 - vector = irq_to_vector(irq); 11.71 + vector = domain_irq_to_vector(d, irq); 11.72 if ( vector == 0 ) 11.73 return 0; 11.74 11.75 @@ -453,7 +456,7 @@ int pirq_guest_bind(struct vcpu *v, int 11.76 cpumask_t cpumask = CPU_MASK_NONE; 11.77 11.78 retry: 11.79 - vector = irq_to_vector(irq); 11.80 + vector = domain_irq_to_vector(v->domain, irq); 11.81 if ( vector == 0 ) 11.82 return -EINVAL; 11.83 11.84 @@ -487,7 +490,7 @@ int pirq_guest_bind(struct vcpu *v, int 11.85 action->nr_guests = 0; 11.86 action->in_flight = 0; 11.87 action->shareable = will_share; 11.88 - action->ack_type = pirq_acktype(irq); 11.89 + action->ack_type = pirq_acktype(v->domain, irq); 11.90 cpus_clear(action->cpu_eoi_map); 11.91 11.92 desc->depth = 0; 11.93 @@ -538,13 +541,15 @@ int pirq_guest_bind(struct vcpu *v, int 11.94 11.95 int pirq_guest_unbind(struct domain *d, int irq) 11.96 { 11.97 - unsigned int vector = irq_to_vector(irq); 11.98 - irq_desc_t *desc = &irq_desc[vector]; 11.99 + unsigned int vector; 11.100 + irq_desc_t *desc; 11.101 irq_guest_action_t *action; 11.102 cpumask_t cpu_eoi_map; 11.103 unsigned long flags; 11.104 int i; 11.105 11.106 + vector = domain_irq_to_vector(d, irq); 11.107 + desc = &irq_desc[vector]; 11.108 BUG_ON(vector == 0); 11.109 11.110 spin_lock_irqsave(&desc->lock, flags);
12.1 --- a/xen/arch/x86/physdev.c Thu May 01 10:26:58 2008 +0100 12.2 +++ b/xen/arch/x86/physdev.c Thu May 01 10:30:22 2008 +0100 12.3 @@ -7,6 +7,7 @@ 12.4 #include <xen/irq.h> 12.5 #include <xen/event.h> 12.6 #include <xen/guest_access.h> 12.7 +#include <xen/iocap.h> 12.8 #include <asm/current.h> 12.9 #include <asm/hypercall.h> 12.10 #include <public/xen.h> 12.11 @@ -24,6 +25,263 @@ int 12.12 ioapic_guest_write( 12.13 unsigned long physbase, unsigned int reg, u32 pval); 12.14 12.15 +static int get_free_pirq(struct domain *d, int type, int index) 12.16 +{ 12.17 + int i; 12.18 + 12.19 + if ( d == NULL ) 12.20 + return -EINVAL; 12.21 + 12.22 + ASSERT(spin_is_locked(&d->arch.irq_lock)); 12.23 + 12.24 + if ( type == MAP_PIRQ_TYPE_GSI ) 12.25 + { 12.26 + for ( i = 16; i < NR_PIRQS; i++ ) 12.27 + if ( !d->arch.pirq_vector[i] ) 12.28 + break; 12.29 + if ( i == NR_PIRQS ) 12.30 + return -ENOSPC; 12.31 + } 12.32 + else 12.33 + { 12.34 + for ( i = NR_PIRQS - 1; i >= 16; i-- ) 12.35 + if ( !d->arch.pirq_vector[i] ) 12.36 + break; 12.37 + if ( i == 16 ) 12.38 + return -ENOSPC; 12.39 + } 12.40 + 12.41 + return i; 12.42 +} 12.43 + 12.44 +/* 12.45 + * Caller hold the irq_lock 12.46 + */ 12.47 +static int map_domain_pirq(struct domain *d, int pirq, int vector, int type) 12.48 +{ 12.49 + int ret = 0; 12.50 + int old_vector, old_pirq; 12.51 + 12.52 + if ( d == NULL ) 12.53 + return -EINVAL; 12.54 + 12.55 + ASSERT(spin_is_locked(&d->arch.irq_lock)); 12.56 + 12.57 + if ( !IS_PRIV(current->domain) ) 12.58 + return -EPERM; 12.59 + 12.60 + if ( pirq < 0 || pirq >= NR_PIRQS || vector < 0 || vector >= NR_VECTORS ) 12.61 + { 12.62 + gdprintk(XENLOG_G_ERR, 12.63 + "invalid pirq %x or vector %x\n", pirq, vector); 12.64 + return -EINVAL; 12.65 + } 12.66 + 12.67 + old_vector = d->arch.pirq_vector[pirq]; 12.68 + old_pirq = d->arch.vector_pirq[vector]; 12.69 + 12.70 + if ( (old_vector && (old_vector != vector) ) || 12.71 + (old_pirq && (old_pirq != pirq)) ) 12.72 + { 12.73 + gdprintk(XENLOG_G_ERR, "remap pirq %x vector %x while not unmap\n", 12.74 + pirq, vector); 12.75 + ret = -EINVAL; 12.76 + goto done; 12.77 + } 12.78 + 12.79 + ret = irq_permit_access(d, pirq); 12.80 + if ( ret ) 12.81 + { 12.82 + gdprintk(XENLOG_G_ERR, "add irq permit access %x failed\n", pirq); 12.83 + ret = -EINVAL; 12.84 + goto done; 12.85 + } 12.86 + 12.87 + d->arch.pirq_vector[pirq] = vector; 12.88 + d->arch.vector_pirq[vector] = pirq; 12.89 + 12.90 +done: 12.91 + return ret; 12.92 +} 12.93 + 12.94 +/* 12.95 + * The pirq should has been unbound before this call 12.96 + */ 12.97 +static int unmap_domain_pirq(struct domain *d, int pirq) 12.98 +{ 12.99 + int ret = 0; 12.100 + int vector; 12.101 + 12.102 + if ( d == NULL || pirq < 0 || pirq > NR_PIRQS ) 12.103 + return -EINVAL; 12.104 + 12.105 + if ( !IS_PRIV(current->domain) ) 12.106 + return -EINVAL; 12.107 + 12.108 + ASSERT(spin_is_locked(&d->arch.irq_lock)); 12.109 + 12.110 + vector = d->arch.pirq_vector[pirq]; 12.111 + 12.112 + if ( !vector ) 12.113 + { 12.114 + gdprintk(XENLOG_G_ERR, "domain %X: pirq %x not mapped still\n", 12.115 + d->domain_id, pirq); 12.116 + ret = -EINVAL; 12.117 + } 12.118 + else 12.119 + d->arch.pirq_vector[pirq] = d->arch.vector_pirq[vector] = 0; 12.120 + ret = irq_deny_access(d, pirq); 12.121 + 12.122 + if ( ret ) 12.123 + gdprintk(XENLOG_G_ERR, "deny irq %x access failed\n", pirq); 12.124 + 12.125 + return ret; 12.126 +} 12.127 + 12.128 +extern int msi_irq_enable; 12.129 +static int physdev_map_pirq(struct physdev_map_pirq *map) 12.130 +{ 12.131 + struct domain *d; 12.132 + int vector, pirq, ret = 0; 12.133 + unsigned long flags; 12.134 + 12.135 + /* if msi_irq_enable is not enabled,map always success */ 12.136 + if ( !msi_irq_enable ) 12.137 + return 0; 12.138 + 12.139 + if ( !IS_PRIV(current->domain) ) 12.140 + return -EPERM; 12.141 + 12.142 + if ( !map ) 12.143 + return -EINVAL; 12.144 + 12.145 + if ( map->domid == DOMID_SELF ) 12.146 + d = rcu_lock_domain(current->domain); 12.147 + else 12.148 + d = rcu_lock_domain_by_id(map->domid); 12.149 + 12.150 + if ( d == NULL ) 12.151 + { 12.152 + ret = -ESRCH; 12.153 + goto free_domain; 12.154 + } 12.155 + 12.156 + switch ( map->type ) 12.157 + { 12.158 + case MAP_PIRQ_TYPE_GSI: 12.159 + if ( map->index >= NR_IRQS ) 12.160 + { 12.161 + ret = -EINVAL; 12.162 + gdprintk(XENLOG_G_ERR, 12.163 + "map invalid irq %x\n", map->index); 12.164 + goto free_domain; 12.165 + } 12.166 + vector = IO_APIC_VECTOR(map->index); 12.167 + if ( !vector ) 12.168 + { 12.169 + ret = -EINVAL; 12.170 + gdprintk(XENLOG_G_ERR, 12.171 + "map irq with no vector %x\n", map->index); 12.172 + goto free_domain; 12.173 + } 12.174 + break; 12.175 + case MAP_PIRQ_TYPE_MSI: 12.176 + vector = map->index; 12.177 + if ( vector < 0 || vector >= NR_VECTORS ) 12.178 + { 12.179 + ret = -EINVAL; 12.180 + gdprintk(XENLOG_G_ERR, 12.181 + "map_pirq with wrong vector %x\n", map->index); 12.182 + goto free_domain; 12.183 + } 12.184 + break; 12.185 + default: 12.186 + ret = -EINVAL; 12.187 + gdprintk(XENLOG_G_ERR, "wrong map_pirq type %x\n", map->type); 12.188 + goto free_domain; 12.189 + break; 12.190 + } 12.191 + 12.192 + spin_lock_irqsave(&d->arch.irq_lock, flags); 12.193 + if ( map->pirq == -1 ) 12.194 + { 12.195 + if ( d->arch.vector_pirq[vector] ) 12.196 + { 12.197 + gdprintk(XENLOG_G_ERR, "%x %x mapped already%x\n", 12.198 + map->index, map->pirq, 12.199 + d->arch.vector_pirq[vector]); 12.200 + pirq = d->arch.vector_pirq[vector]; 12.201 + } 12.202 + else 12.203 + { 12.204 + pirq = get_free_pirq(d, map->type, map->index); 12.205 + if ( pirq < 0 ) 12.206 + { 12.207 + ret = pirq; 12.208 + gdprintk(XENLOG_G_ERR, "No free pirq\n"); 12.209 + goto done; 12.210 + } 12.211 + } 12.212 + } 12.213 + else 12.214 + { 12.215 + if ( d->arch.vector_pirq[vector] && 12.216 + d->arch.vector_pirq[vector] != map->pirq ) 12.217 + { 12.218 + gdprintk(XENLOG_G_ERR, "%x conflict with %x\n", 12.219 + map->index, map->pirq); 12.220 + ret = -EEXIST; 12.221 + goto done; 12.222 + } 12.223 + else 12.224 + pirq = map->pirq; 12.225 + } 12.226 + 12.227 + ret = map_domain_pirq(d, pirq, vector, map->type); 12.228 + 12.229 + if ( !ret ) 12.230 + map->pirq = pirq; 12.231 +done: 12.232 + spin_unlock_irqrestore(&d->arch.irq_lock, flags); 12.233 +free_domain: 12.234 + rcu_unlock_domain(d); 12.235 + return ret; 12.236 +} 12.237 + 12.238 +static int physdev_unmap_pirq(struct physdev_unmap_pirq *unmap) 12.239 +{ 12.240 + struct domain *d; 12.241 + unsigned long flags; 12.242 + int ret; 12.243 + 12.244 + if ( !msi_irq_enable ) 12.245 + return 0; 12.246 + 12.247 + if ( !IS_PRIV(current->domain) ) 12.248 + return -EPERM; 12.249 + 12.250 + if ( !unmap ) 12.251 + return -EINVAL; 12.252 + 12.253 + if ( unmap->domid == DOMID_SELF ) 12.254 + d = rcu_lock_domain(current->domain); 12.255 + else 12.256 + d = rcu_lock_domain_by_id(unmap->domid); 12.257 + 12.258 + if ( d == NULL ) 12.259 + { 12.260 + rcu_unlock_domain(d); 12.261 + return -ESRCH; 12.262 + } 12.263 + 12.264 + spin_lock_irqsave(&d->arch.irq_lock, flags); 12.265 + ret = unmap_domain_pirq(d, unmap->pirq); 12.266 + spin_unlock_irqrestore(&d->arch.irq_lock, flags); 12.267 + rcu_unlock_domain(d); 12.268 + 12.269 + return ret; 12.270 +} 12.271 + 12.272 ret_t do_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg) 12.273 { 12.274 int irq; 12.275 @@ -57,14 +315,38 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H 12.276 if ( (irq < 0) || (irq >= NR_IRQS) ) 12.277 break; 12.278 irq_status_query.flags = 0; 12.279 - if ( pirq_acktype(irq) != 0 ) 12.280 + if ( pirq_acktype(v->domain, irq) != 0 ) 12.281 irq_status_query.flags |= XENIRQSTAT_needs_eoi; 12.282 - if ( pirq_shared(irq) ) 12.283 + if ( pirq_shared(v->domain, irq) ) 12.284 irq_status_query.flags |= XENIRQSTAT_shared; 12.285 ret = copy_to_guest(arg, &irq_status_query, 1) ? -EFAULT : 0; 12.286 break; 12.287 } 12.288 12.289 + case PHYSDEVOP_map_pirq: { 12.290 + struct physdev_map_pirq map; 12.291 + 12.292 + ret = -EFAULT; 12.293 + if ( copy_from_guest(&map, arg, 1) != 0 ) 12.294 + break; 12.295 + 12.296 + ret = physdev_map_pirq(&map); 12.297 + if ( copy_to_guest(arg, &map, 1) != 0 ) 12.298 + ret = -EFAULT; 12.299 + break; 12.300 + } 12.301 + 12.302 + case PHYSDEVOP_unmap_pirq: { 12.303 + struct physdev_unmap_pirq unmap; 12.304 + 12.305 + ret = -EFAULT; 12.306 + if ( copy_from_guest(&unmap, arg, 1) != 0 ) 12.307 + break; 12.308 + 12.309 + ret = physdev_unmap_pirq(&unmap); 12.310 + break; 12.311 + } 12.312 + 12.313 case PHYSDEVOP_apic_read: { 12.314 struct physdev_apic apic; 12.315 ret = -EFAULT; 12.316 @@ -99,6 +381,7 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H 12.317 12.318 case PHYSDEVOP_alloc_irq_vector: { 12.319 struct physdev_irq irq_op; 12.320 + unsigned long flags; 12.321 12.322 ret = -EFAULT; 12.323 if ( copy_from_guest(&irq_op, arg, 1) != 0 ) 12.324 @@ -118,7 +401,20 @@ ret_t do_physdev_op(int cmd, XEN_GUEST_H 12.325 break; 12.326 12.327 irq_op.vector = assign_irq_vector(irq); 12.328 - ret = copy_to_guest(arg, &irq_op, 1) ? -EFAULT : 0; 12.329 + 12.330 + ret = 0; 12.331 + 12.332 + if ( msi_irq_enable ) 12.333 + { 12.334 + spin_lock_irqsave(&dom0->arch.irq_lock, flags); 12.335 + if ( irq != AUTO_ASSIGN ) 12.336 + ret = map_domain_pirq(dom0, irq_op.irq, irq_op.vector, 12.337 + MAP_PIRQ_TYPE_GSI); 12.338 + spin_unlock_irqrestore(&dom0->arch.irq_lock, flags); 12.339 + } 12.340 + 12.341 + if ( copy_to_guest(arg, &irq_op, 1) != 0 ) 12.342 + ret = -EFAULT; 12.343 break; 12.344 } 12.345
13.1 --- a/xen/drivers/passthrough/io.c Thu May 01 10:26:58 2008 +0100 13.2 +++ b/xen/drivers/passthrough/io.c Thu May 01 10:30:22 2008 +0100 13.3 @@ -25,6 +25,7 @@ static void pt_irq_time_out(void *data) 13.4 { 13.5 struct hvm_mirq_dpci_mapping *irq_map = data; 13.6 unsigned int guest_gsi, machine_gsi = 0; 13.7 + int vector; 13.8 struct hvm_irq_dpci *dpci = domain_get_irq_dpci(irq_map->dom); 13.9 struct dev_intx_gsi_link *digl; 13.10 uint32_t device, intx; 13.11 @@ -39,7 +40,8 @@ static void pt_irq_time_out(void *data) 13.12 } 13.13 13.14 clear_bit(machine_gsi, dpci->dirq_mask); 13.15 - stop_timer(&dpci->hvm_timer[irq_to_vector(machine_gsi)]); 13.16 + vector = domain_irq_to_vector(irq_map->dom, machine_gsi); 13.17 + stop_timer(&dpci->hvm_timer[vector]); 13.18 spin_lock(&dpci->dirq_lock); 13.19 dpci->mirq[machine_gsi].pending = 0; 13.20 spin_unlock(&dpci->dirq_lock); 13.21 @@ -98,7 +100,7 @@ int pt_irq_create_bind_vtd( 13.22 hvm_irq_dpci->mirq[machine_gsi].valid = 1; 13.23 hvm_irq_dpci->mirq[machine_gsi].dom = d; 13.24 13.25 - init_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)], 13.26 + init_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, machine_gsi)], 13.27 pt_irq_time_out, &hvm_irq_dpci->mirq[machine_gsi], 0); 13.28 /* Deal with gsi for legacy devices */ 13.29 pirq_guest_bind(d->vcpu[0], machine_gsi, BIND_PIRQ__WILL_SHARE); 13.30 @@ -157,7 +159,7 @@ int pt_irq_destroy_bind_vtd( 13.31 if ( list_empty(&hvm_irq_dpci->mirq[machine_gsi].digl_list) ) 13.32 { 13.33 pirq_guest_unbind(d, machine_gsi); 13.34 - kill_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)]); 13.35 + kill_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, machine_gsi)]); 13.36 hvm_irq_dpci->mirq[machine_gsi].dom = NULL; 13.37 hvm_irq_dpci->mirq[machine_gsi].valid = 0; 13.38 } 13.39 @@ -185,7 +187,7 @@ int hvm_do_IRQ_dpci(struct domain *d, un 13.40 * PIC) and we need to detect that. 13.41 */ 13.42 set_bit(mirq, dpci->dirq_mask); 13.43 - set_timer(&dpci->hvm_timer[irq_to_vector(mirq)], 13.44 + set_timer(&dpci->hvm_timer[domain_irq_to_vector(d, mirq)], 13.45 NOW() + PT_IRQ_TIME_OUT); 13.46 vcpu_kick(d->vcpu[0]); 13.47 13.48 @@ -221,7 +223,7 @@ void hvm_dpci_eoi(struct domain *d, unsi 13.49 13.50 gdprintk(XENLOG_INFO VTDPREFIX, 13.51 "hvm_dpci_eoi:: mirq = %x\n", machine_gsi); 13.52 - stop_timer(&hvm_irq_dpci->hvm_timer[irq_to_vector(machine_gsi)]); 13.53 + stop_timer(&hvm_irq_dpci->hvm_timer[domain_irq_to_vector(d, machine_gsi)]); 13.54 if ( (ent == NULL) || !ent->fields.mask ) 13.55 pirq_guest_eoi(d, machine_gsi); 13.56 }
14.1 --- a/xen/drivers/passthrough/vtd/x86/vtd.c Thu May 01 10:26:58 2008 +0100 14.2 +++ b/xen/drivers/passthrough/vtd/x86/vtd.c Thu May 01 10:30:22 2008 +0100 14.3 @@ -114,7 +114,7 @@ void hvm_dpci_isairq_eoi(struct domain * 14.4 if ( --dpci->mirq[i].pending == 0 ) 14.5 { 14.6 spin_unlock(&dpci->dirq_lock); 14.7 - stop_timer(&dpci->hvm_timer[irq_to_vector(i)]); 14.8 + stop_timer(&dpci->hvm_timer[domain_irq_to_vector(d, i)]); 14.9 pirq_guest_eoi(d, i); 14.10 } 14.11 else
15.1 --- a/xen/include/asm-x86/domain.h Thu May 01 10:26:58 2008 +0100 15.2 +++ b/xen/include/asm-x86/domain.h Thu May 01 10:30:22 2008 +0100 15.3 @@ -6,6 +6,7 @@ 15.4 #include <asm/hvm/vcpu.h> 15.5 #include <asm/hvm/domain.h> 15.6 #include <asm/e820.h> 15.7 +#include <asm/pirq.h> 15.8 15.9 #define has_32bit_shinfo(d) ((d)->arch.has_32bit_shinfo) 15.10 #define is_pv_32bit_domain(d) ((d)->arch.is_32bit_pv) 15.11 @@ -222,6 +223,10 @@ struct arch_domain 15.12 /* Shadow translated domain: P2M mapping */ 15.13 pagetable_t phys_table; 15.14 15.15 + spinlock_t irq_lock; 15.16 + int vector_pirq[NR_VECTORS]; 15.17 + int pirq_vector[NR_PIRQS]; 15.18 + 15.19 /* Pseudophysical e820 map (XENMEM_memory_map). */ 15.20 struct e820entry e820[3]; 15.21 unsigned int nr_e820;
16.1 --- a/xen/include/asm-x86/irq.h Thu May 01 10:26:58 2008 +0100 16.2 +++ b/xen/include/asm-x86/irq.h Thu May 01 10:30:22 2008 +0100 16.3 @@ -49,7 +49,9 @@ extern unsigned long io_apic_irqs; 16.4 extern atomic_t irq_err_count; 16.5 extern atomic_t irq_mis_count; 16.6 16.7 -int pirq_acktype(int irq); 16.8 -int pirq_shared(int irq); 16.9 +int pirq_acktype(struct domain *d, int irq); 16.10 +int pirq_shared(struct domain *d , int irq); 16.11 16.12 +extern int domain_irq_to_vector(struct domain *d, int irq); 16.13 +extern int domain_vector_to_irq(struct domain *d, int vector); 16.14 #endif /* _ASM_HW_IRQ_H */
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 17.2 +++ b/xen/include/asm-x86/pirq.h Thu May 01 10:30:22 2008 +0100 17.3 @@ -0,0 +1,11 @@ 17.4 +#ifndef __XEN_PIRQ_H 17.5 +#define __XEN_PIRQ_H 17.6 + 17.7 +#define PIRQ_BASE 0 17.8 +#define NR_PIRQS 256 17.9 + 17.10 +#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS) 17.11 +#define NR_DYNIRQS 256 17.12 + 17.13 +#endif /* __XEN_PIRQ_H */ 17.14 +
18.1 --- a/xen/include/public/physdev.h Thu May 01 10:26:58 2008 +0100 18.2 +++ b/xen/include/public/physdev.h Thu May 01 10:30:22 2008 +0100 18.3 @@ -121,6 +121,33 @@ struct physdev_irq { 18.4 }; 18.5 typedef struct physdev_irq physdev_irq_t; 18.6 DEFINE_XEN_GUEST_HANDLE(physdev_irq_t); 18.7 + 18.8 +#define MAP_PIRQ_TYPE_MSI 0x0 18.9 +#define MAP_PIRQ_TYPE_GSI 0x1 18.10 +#define MAP_PIRQ_TYPE_UNKNOWN 0x2 18.11 + 18.12 +#define PHYSDEVOP_map_pirq 13 18.13 +struct physdev_map_pirq { 18.14 + domid_t domid; 18.15 + /* IN */ 18.16 + int type; 18.17 + /* IN */ 18.18 + int index; 18.19 + /* IN or OUT */ 18.20 + int pirq; 18.21 +}; 18.22 +typedef struct physdev_map_pirq physdev_map_pirq_t; 18.23 +DEFINE_XEN_GUEST_HANDLE(physdev_map_pirq_t); 18.24 + 18.25 +#define PHYSDEVOP_unmap_pirq 14 18.26 +struct physdev_unmap_pirq { 18.27 + domid_t domid; 18.28 + /* IN */ 18.29 + int pirq; 18.30 +}; 18.31 + 18.32 +typedef struct physdev_unmap_pirq physdev_unmap_pirq_t; 18.33 +DEFINE_XEN_GUEST_HANDLE(physdev_unmap_pirq_t); 18.34 18.35 /* 18.36 * Argument to physdev_op_compat() hypercall. Superceded by new physdev_op()