Shohei Fujiwara
2009-Apr-10 01:36 UTC
[Xen-devel] [RFC] [PATCH 0/2] Enable PCI passthrough with stub domain
This series of patches enables PCI passthrough with stub domain which uses de-privileged qemu. This patch isn''t intended to apply to Xen 3.4, but for developer of stub domain to be interested in passthrough with stub domain. Domain 0 (xend) calls the following hypercalls. XEN_DOMCTL_assign_device XEN_DOMCTL_deassign_device XEN_DOMCTL_ioport_permission XEN_DOMCTL_iomem_permission XEN_DOMCTL_irq_permission Stub domain (qemu) calls the following hypercalls. The target domain of the hypercalls is restricted to the target domain of per stub domain. Each resources are permitted to target domain with XEN_DOMCTL_xxx_permission hypercall from resource domain (dom0). So each domain can''t use un-permitted resources. XEN_DOMCTL_memory_mapping XEN_DOMCTL_ioport_mapping PHYSDEVOP_map_pirq PHYSDEVOP_unmap_pirq XEN_DOMCTL_bind_pt_irq XEN_DOMCTL_unbind_pt_irq Stub domain (qemu) calls this hypercall too. The target domain of the hypercalls is restricted to the target domain of stub domain. XEN_DOMCTL_pin_mem_cacheattr Currently, MSI/MSI-X/MSI-INTx translation don''t work well. Please help to work it well. I tested these patches as below. xen-unstable: 19426: 0b13d9787622 qemu: f7dd59a4d7d0b161780ed90bb0eccb2a5fbd555e linux-2.6.18: 844: 87c84f7dd850 and apply the following patch. http://lists.xensource.com/archives/html/xen-changelog/2009-03/msg00213.html Thanks, -- Shohei Fujiwara _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Shohei Fujiwara
2009-Apr-10 01:39 UTC
Re: [Xen-devel] [RFC] [PATCH 0/2] Enable PCI passthrough with stub domain
This patch allows hypercall from qemu on stub domain xend calls these hypercalls for PCI pass-through. XEN_DOMCTL_assign_device XEN_DOMCTL_deassign_device XEN_DOMCTL_ioport_permission XEN_DOMCTL_iomem_permission XEN_DOMCTL_irq_permission In addition to this, this patch allows stub domain to call the following hypercalls. Hypervisor checks permission with IS_PRIV_FOR and {ioports,iomem,irq}_access_permitted. XEN_DOMCTL_memory_mapping XEN_DOMCTL_ioport_mapping PHYSDEVOP_map_pirq PHYSDEVOP_unmap_pirq XEN_DOMCTL_bind_pt_irq XEN_DOMCTL_unbind_pt_irq This patch allows to stub domain to call the following hypercall. Hypervisor checks the permission with IS_PRIV_FOR. XEN_DOMCTL_pin_mem_cacheattr Thanks, -- Shohei Fujiwara Signed-off-by: Shohei Fujiwara <fujiwara-sxa@necst.nec.co.jp> diff -r 5b8f9ef92e00 tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Wed Mar 11 19:13:47 2009 +0000 +++ b/tools/python/xen/xend/server/pciif.py Mon Mar 23 18:19:24 2009 +0900 @@ -289,7 +289,10 @@ class PciController(DevController): def setupOneDevice(self, domain, bus, slot, func): """ Attach I/O resources for device to frontend domain """ - fe_domid = self.getDomid() + if self.vm.info.target(): + fe_domid = self.vm.info.target() + else: + fe_domid = self.getDomid() try: dev = PciDevice(domain, bus, slot, func) @@ -366,12 +369,6 @@ class PciController(DevController): if rc<0: raise VmError((''pci: failed to remove msi-x iomem'')) - rc = xc.physdev_map_pirq(domid = fe_domid, - index = dev.irq, - pirq = dev.irq) - if rc < 0: - raise VmError((''pci: failed to map irq on device ''+ - ''%s - errno=%d'')%(dev.name,rc)) if dev.irq>0: log.debug(''pci: enabling irq %d''%dev.irq) rc = xc.domain_irq_permission(domid = fe_domid, pirq = dev.irq, @@ -470,7 +467,10 @@ class PciController(DevController): def cleanupOneDevice(self, domain, bus, slot, func): """ Detach I/O resources for device from frontend domain """ - fe_domid = self.getDomid() + if self.vm.info.target(): + fe_domid = self.vm.info.target() + else: + fe_domid = self.getDomid() try: dev = PciDevice(domain, bus, slot, func) diff -r 5b8f9ef92e00 xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Wed Mar 11 19:13:47 2009 +0000 +++ b/xen/arch/x86/domctl.c Tue Mar 24 15:11:11 2009 +0900 @@ -763,6 +763,13 @@ long arch_do_domctl( goto bind_out; ret = -ESRCH; + + if ( !irq_access_permitted(d, bind->machine_irq) ) + { + gdprintk(XENLOG_ERR, "dom%d: binding of irq %d is not permitted\n", + d->domain_id, bind->machine_irq); + goto bind_out; + } if ( iommu_enabled ) { spin_lock(&pcidevs_lock); @@ -786,6 +793,14 @@ long arch_do_domctl( if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; bind = &(domctl->u.bind_pt_irq); + + if ( !irq_access_permitted(d, bind->machine_irq) ) + { + gdprintk(XENLOG_ERR, "dom%d: unbinding of irq %d is not permitted\n", + d->domain_id, bind->machine_irq); + rcu_unlock_domain(d); + break; + } if ( iommu_enabled ) { spin_lock(&pcidevs_lock); @@ -815,13 +830,26 @@ long arch_do_domctl( break; ret=0; + + if ( !iomem_access_permitted(d, mfn, mfn + nr_mfns - 1) ) + { + gdprintk(XENLOG_ERR, "dom%d: %s of memory mapping 0x%lx" + "is not permitted\n", + d->domain_id, + domctl->u.memory_mapping.add_mapping ? + "adding" : "removing", + mfn); + rcu_unlock_domain(d); + ret = -ESRCH; + break; + } + if ( domctl->u.memory_mapping.add_mapping ) { gdprintk(XENLOG_INFO, "memory_map:add: gfn=%lx mfn=%lx nr_mfns=%lx\n", gfn, mfn, nr_mfns); - ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1); for ( i = 0; i < nr_mfns; i++ ) set_mmio_p2m_entry(d, gfn+i, _mfn(mfn+i)); } @@ -833,7 +861,6 @@ long arch_do_domctl( for ( i = 0; i < nr_mfns; i++ ) clear_mmio_p2m_entry(d, gfn+i); - ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1); } rcu_unlock_domain(d); @@ -866,6 +893,21 @@ long arch_do_domctl( break; hd = domain_hvm_iommu(d); + + if ( !ioports_access_permitted(d, fmp, fmp + np - 1) ) + { + gdprintk(XENLOG_ERR, "dom%d: %s of ioport mapping 0x%x" + "is not permitted\n", + d->domain_id, + domctl->u.ioport_mapping.add_mapping ? + "adding" : "removing", + fmp ); + rcu_unlock_domain(d); + break; + } + else + ret = 0; + if ( domctl->u.ioport_mapping.add_mapping ) { gdprintk(XENLOG_INFO, @@ -888,7 +930,6 @@ long arch_do_domctl( g2m_ioport->np = np; list_add_tail(&g2m_ioport->list, &hd->g2m_ioport_list); } - ret = ioports_permit_access(d, fmp, fmp + np - 1); } else { @@ -902,7 +943,6 @@ long arch_do_domctl( xfree(g2m_ioport); break; } - ret = ioports_deny_access(d, fmp, fmp + np - 1); } rcu_unlock_domain(d); } diff -r 5b8f9ef92e00 xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Wed Mar 11 19:13:47 2009 +0000 +++ b/xen/arch/x86/irq.c Tue Mar 24 15:15:01 2009 +0900 @@ -910,7 +910,7 @@ int map_domain_pirq( ASSERT(spin_is_locked(&pcidevs_lock)); ASSERT(spin_is_locked(&d->event_lock)); - if ( !IS_PRIV(current->domain) ) + if ( !IS_PRIV_FOR(current->domain, d) ) return -EPERM; if ( pirq < 0 || pirq >= NR_IRQS || vector < 0 || vector >= NR_VECTORS ) @@ -929,14 +929,6 @@ int map_domain_pirq( dprintk(XENLOG_G_ERR, "dom%d: pirq %d or vector %d already mapped\n", d->domain_id, pirq, vector); return -EINVAL; - } - - ret = irq_permit_access(d, pirq); - if ( ret ) - { - dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d\n", - d->domain_id, pirq); - return ret; } desc = &irq_desc[vector]; @@ -988,7 +980,7 @@ int unmap_domain_pirq(struct domain *d, if ( (pirq < 0) || (pirq >= NR_IRQS) ) return -EINVAL; - if ( !IS_PRIV(current->domain) ) + if ( !IS_PRIV_FOR(current->domain, d) ) return -EINVAL; ASSERT(spin_is_locked(&pcidevs_lock)); @@ -1003,6 +995,13 @@ int unmap_domain_pirq(struct domain *d, goto done; } + if ( !irq_access_permitted(d, pirq) ) + { + dprintk(XENLOG_G_ERR, "dom%d: unmapping of pirq %d is not permitted\n", + d->domain_id, pirq); + ret = -EINVAL; + goto done; + } forced_unbind = pirq_guest_force_unbind(d, pirq); if ( forced_unbind ) dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n", diff -r 5b8f9ef92e00 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Wed Mar 11 19:13:47 2009 +0000 +++ b/xen/arch/x86/physdev.c Mon Mar 23 17:33:17 2009 +0900 @@ -34,9 +34,6 @@ static int physdev_map_pirq(struct physd struct msi_info _msi; void *map_data = NULL; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( !map ) return -EINVAL; @@ -47,6 +44,22 @@ static int physdev_map_pirq(struct physd if ( d == NULL ) { + ret = -ESRCH; + goto free_domain; + } + else + { + if ( !IS_PRIV_FOR(current->domain, d) ) + { + ret = -EPERM; + goto free_domain; + } + } + + if ( !irq_access_permitted(d, map->index) ) + { + dprintk(XENLOG_G_ERR, "dom%d: mapping of irq %d is not permitted\n", + d->domain_id, map->index); ret = -ESRCH; goto free_domain; } @@ -62,7 +75,7 @@ static int physdev_map_pirq(struct physd ret = -EINVAL; goto free_domain; } - vector = domain_irq_to_vector(current->domain, map->index); + vector = domain_irq_to_vector(dom0, map->index); if ( !vector ) { dprintk(XENLOG_G_ERR, "dom%d: map irq with no vector %d\n", @@ -160,9 +173,6 @@ static int physdev_unmap_pirq(struct phy struct domain *d; int ret; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( unmap->domid == DOMID_SELF ) d = rcu_lock_domain(current->domain); else @@ -170,6 +180,14 @@ static int physdev_unmap_pirq(struct phy if ( d == NULL ) return -ESRCH; + else + { + if ( !IS_PRIV_FOR(current->domain, d) ) + { + rcu_unlock_domain(d); + return -EPERM; + } + } spin_lock(&pcidevs_lock); spin_lock(&d->event_lock); diff -r 5b8f9ef92e00 xen/common/domctl.c --- a/xen/common/domctl.c Wed Mar 11 19:13:47 2009 +0000 +++ b/xen/common/domctl.c Mon Mar 23 18:05:20 2009 +0900 @@ -193,14 +193,45 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc long ret = 0; struct xen_domctl curop, *op = &curop; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( copy_from_guest(op, u_domctl, 1) ) return -EFAULT; if ( op->interface_version != XEN_DOMCTL_INTERFACE_VERSION ) return -EACCES; + + switch ( op->cmd ) + { + case XEN_DOMCTL_pin_mem_cacheattr: + case XEN_DOMCTL_memory_mapping: + case XEN_DOMCTL_ioport_mapping: + case XEN_DOMCTL_bind_pt_irq: + case XEN_DOMCTL_unbind_pt_irq: + { + struct domain *d; + + if (op->domain != DOMID_SELF ) + { + d = rcu_lock_domain_by_id(op->domain); + if ( d == NULL ) + return -ESRCH; + else + { + if ( !IS_PRIV_FOR(current->domain,d) ) + { + rcu_unlock_domain(d); + return -EPERM; + } + else + rcu_unlock_domain(d); + } + break; + } + } + default: + if ( !IS_PRIV(current->domain) ) + return -EPERM; + break; + } spin_lock(&domctl_lock); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Shohei Fujiwara
2009-Apr-10 01:41 UTC
[Xen-devel] [RFC] [PATCH 2/2] ioemu: fix up some issues for PCI passthrough with stub domain
This patch fixes up the following issues for enabling PCI passthrough with stub domain. - Reading and writing a data to/from device register with pci_{read/write}_block, byte swap occurs. - Can''t get a BAR in pt_libpci_fixup. - Don''t get PCI Vendor ID, Device ID and Device Class for PCI passthrough device. Thanks, -- Shohei Fujiwara Signed-off-by: Shohei Fujiwara <fujiwara-sxa@necst.nec.co.jp> diff --git a/hw/pass-through.c b/hw/pass-through.c index 4a86309..6373227 100644 --- a/hw/pass-through.c +++ b/hw/pass-through.c @@ -1104,6 +1104,58 @@ out: return index; } +static int pt_pci_write_block(struct pci_dev *d, int pos, uint32_t *val, + int len) +{ + int ret = 0; + + switch (len) + { + case 1: + ret = pci_write_byte(d, pos, *(uint8_t *)val); + break; + case 2: + ret = pci_write_word(d, pos, *(uint16_t *)val); + break; + case 4: + ret = pci_write_long(d, pos, *val); + break; + } + return ret; +} + +static int pt_pci_read_block(struct pci_dev *d, int pos, uint32_t *val, + int len) +{ + uint32_t valid_mask = 0xffffffff; + int ret = 1; + + switch (len) + { + case 1: + *val = (uint32_t)pci_read_byte(d, pos); + break; + case 2: + *val = (uint32_t)pci_read_word(d, pos); + break; + case 4: + *val = pci_read_long(d, pos); + break; + default: + ret = 0; + break; + } + + if (ret) + { + valid_mask = (0xffffffff >> ((4 - len) << 3)); + if ((*val & valid_mask) == valid_mask) + ret = 0; + } + + return ret; +} + static void pt_pci_write_config(PCIDevice *d, uint32_t address, uint32_t val, int len) { @@ -1195,7 +1247,7 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t address, uint32_t val, } /* read I/O device register value */ - ret = pci_read_block(pci_dev, address, (uint8_t *)&read_val, len); + ret = pt_pci_read_block(pci_dev, address, &read_val, len); if (!ret) { @@ -1281,7 +1333,7 @@ static void pt_pci_write_config(PCIDevice *d, uint32_t address, uint32_t val, val >>= ((address & 3) << 3); out: - ret = pci_write_block(pci_dev, address, (uint8_t *)&val, len); + ret = pt_pci_write_block(pci_dev, address, &val, len); if (!ret) PT_LOG("Error: pci_write_block failed. return value[%d].\n", ret); @@ -1364,7 +1416,7 @@ static uint32_t pt_pci_read_config(PCIDevice *d, uint32_t address, int len) } /* read I/O device register value */ - ret = pci_read_block(pci_dev, address, (uint8_t *)&val, len); + ret = pt_pci_read_block(pci_dev, address, &val, len); if (!ret) { @@ -1461,6 +1513,7 @@ exit: static void pt_libpci_fixup(struct pci_dev *dev) { #if !defined(PCI_LIB_VERSION) || PCI_LIB_VERSION < 0x030100 +#ifndef CONFIG_STUBDOM int i; FILE *fp; char path[PATH_MAX], buf[256]; @@ -1492,6 +1545,30 @@ static void pt_libpci_fixup(struct pci_dev *dev) } fclose(fp); +#else + uint32_t value = 0; + int i; + + for ( i = 0; i < PCI_NUM_REGIONS; i++ ) + { + value = pci_read_long(dev, PCI_BASE_ADDRESS_0 + i*4); + if ( i < PCI_ROM_SLOT ) + { + dev->base_addr[i] |= (value & 0x0f); + } + else + { + dev->rom_base_addr |= (value & 0x0f); + } + + if ((value & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) + == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64) ) + { + i++; + } + } + +#endif /* !CONFIG_STUBDOM */ #endif /* PCI_LIB_VERSION < 0x030100 */ } @@ -3582,7 +3659,12 @@ struct pt_dev * register_real_device(PCIBus *e_bus, PT_LOG("Error: couldn''t locate device in libpci structures\n"); return NULL; } +#ifndef CONFIG_STUBDOM pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES); +#else + pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE + | PCI_FILL_SIZES | PCI_FILL_IDENT | PCI_FILL_CLASS); +#endif pt_libpci_fixup(pci_dev); if ( e_devfn == PT_VIRT_DEVFN_AUTO ) { @@ -3711,9 +3793,16 @@ struct pt_dev * register_real_device(PCIBus *e_bus, } out: +#ifndef CONFIG_STUBDOM PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n" "IRQ type = %s\n", r_bus, r_dev, r_func, assigned_device->msi_trans_en? "MSI-INTx":"INTx"); +#else + PT_LOG("Real physical device %02x:%02x.%x registered successfuly!\n", + r_bus, r_dev, r_func); + PT_LOG("IRQ type = %s\n", + assigned_device->msi_trans_en? "MSI-INTx":"INTx"); +#endif return assigned_device; } _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Shohei Fujiwara
2009-Apr-10 01:56 UTC
[Xen-devel] [RFC] [PATCH 1/2] Allows hypercall from qemu on stub domain
## I''m resending this mail for my mistake of invalid subject. This patch allows hypercall from qemu on stub domain xend calls these hypercalls for PCI pass-through. XEN_DOMCTL_assign_device XEN_DOMCTL_deassign_device XEN_DOMCTL_ioport_permission XEN_DOMCTL_iomem_permission XEN_DOMCTL_irq_permission In addition to this, this patch allows stub domain to call the following hypercalls. Hypervisor checks permission with IS_PRIV_FOR and {ioports,iomem,irq}_access_permitted. XEN_DOMCTL_memory_mapping XEN_DOMCTL_ioport_mapping PHYSDEVOP_map_pirq PHYSDEVOP_unmap_pirq XEN_DOMCTL_bind_pt_irq XEN_DOMCTL_unbind_pt_irq This patch allows to stub domain to call the following hypercall. Hypervisor checks the permission with IS_PRIV_FOR. XEN_DOMCTL_pin_mem_cacheattr Thanks, -- Shohei Fujiwara Signed-off-by: Shohei Fujiwara <fujiwara-sxa@necst.nec.co.jp> diff -r 5b8f9ef92e00 tools/python/xen/xend/server/pciif.py --- a/tools/python/xen/xend/server/pciif.py Wed Mar 11 19:13:47 2009 +0000 +++ b/tools/python/xen/xend/server/pciif.py Mon Mar 23 18:19:24 2009 +0900 @@ -289,7 +289,10 @@ class PciController(DevController): def setupOneDevice(self, domain, bus, slot, func): """ Attach I/O resources for device to frontend domain """ - fe_domid = self.getDomid() + if self.vm.info.target(): + fe_domid = self.vm.info.target() + else: + fe_domid = self.getDomid() try: dev = PciDevice(domain, bus, slot, func) @@ -366,12 +369,6 @@ class PciController(DevController): if rc<0: raise VmError((''pci: failed to remove msi-x iomem'')) - rc = xc.physdev_map_pirq(domid = fe_domid, - index = dev.irq, - pirq = dev.irq) - if rc < 0: - raise VmError((''pci: failed to map irq on device ''+ - ''%s - errno=%d'')%(dev.name,rc)) if dev.irq>0: log.debug(''pci: enabling irq %d''%dev.irq) rc = xc.domain_irq_permission(domid = fe_domid, pirq = dev.irq, @@ -470,7 +467,10 @@ class PciController(DevController): def cleanupOneDevice(self, domain, bus, slot, func): """ Detach I/O resources for device from frontend domain """ - fe_domid = self.getDomid() + if self.vm.info.target(): + fe_domid = self.vm.info.target() + else: + fe_domid = self.getDomid() try: dev = PciDevice(domain, bus, slot, func) diff -r 5b8f9ef92e00 xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Wed Mar 11 19:13:47 2009 +0000 +++ b/xen/arch/x86/domctl.c Tue Mar 24 15:11:11 2009 +0900 @@ -763,6 +763,13 @@ long arch_do_domctl( goto bind_out; ret = -ESRCH; + + if ( !irq_access_permitted(d, bind->machine_irq) ) + { + gdprintk(XENLOG_ERR, "dom%d: binding of irq %d is not permitted\n", + d->domain_id, bind->machine_irq); + goto bind_out; + } if ( iommu_enabled ) { spin_lock(&pcidevs_lock); @@ -786,6 +793,14 @@ long arch_do_domctl( if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL ) break; bind = &(domctl->u.bind_pt_irq); + + if ( !irq_access_permitted(d, bind->machine_irq) ) + { + gdprintk(XENLOG_ERR, "dom%d: unbinding of irq %d is not permitted\n", + d->domain_id, bind->machine_irq); + rcu_unlock_domain(d); + break; + } if ( iommu_enabled ) { spin_lock(&pcidevs_lock); @@ -815,13 +830,26 @@ long arch_do_domctl( break; ret=0; + + if ( !iomem_access_permitted(d, mfn, mfn + nr_mfns - 1) ) + { + gdprintk(XENLOG_ERR, "dom%d: %s of memory mapping 0x%lx" + "is not permitted\n", + d->domain_id, + domctl->u.memory_mapping.add_mapping ? + "adding" : "removing", + mfn); + rcu_unlock_domain(d); + ret = -ESRCH; + break; + } + if ( domctl->u.memory_mapping.add_mapping ) { gdprintk(XENLOG_INFO, "memory_map:add: gfn=%lx mfn=%lx nr_mfns=%lx\n", gfn, mfn, nr_mfns); - ret = iomem_permit_access(d, mfn, mfn + nr_mfns - 1); for ( i = 0; i < nr_mfns; i++ ) set_mmio_p2m_entry(d, gfn+i, _mfn(mfn+i)); } @@ -833,7 +861,6 @@ long arch_do_domctl( for ( i = 0; i < nr_mfns; i++ ) clear_mmio_p2m_entry(d, gfn+i); - ret = iomem_deny_access(d, mfn, mfn + nr_mfns - 1); } rcu_unlock_domain(d); @@ -866,6 +893,21 @@ long arch_do_domctl( break; hd = domain_hvm_iommu(d); + + if ( !ioports_access_permitted(d, fmp, fmp + np - 1) ) + { + gdprintk(XENLOG_ERR, "dom%d: %s of ioport mapping 0x%x" + "is not permitted\n", + d->domain_id, + domctl->u.ioport_mapping.add_mapping ? + "adding" : "removing", + fmp ); + rcu_unlock_domain(d); + break; + } + else + ret = 0; + if ( domctl->u.ioport_mapping.add_mapping ) { gdprintk(XENLOG_INFO, @@ -888,7 +930,6 @@ long arch_do_domctl( g2m_ioport->np = np; list_add_tail(&g2m_ioport->list, &hd->g2m_ioport_list); } - ret = ioports_permit_access(d, fmp, fmp + np - 1); } else { @@ -902,7 +943,6 @@ long arch_do_domctl( xfree(g2m_ioport); break; } - ret = ioports_deny_access(d, fmp, fmp + np - 1); } rcu_unlock_domain(d); } diff -r 5b8f9ef92e00 xen/arch/x86/irq.c --- a/xen/arch/x86/irq.c Wed Mar 11 19:13:47 2009 +0000 +++ b/xen/arch/x86/irq.c Tue Mar 24 15:15:01 2009 +0900 @@ -910,7 +910,7 @@ int map_domain_pirq( ASSERT(spin_is_locked(&pcidevs_lock)); ASSERT(spin_is_locked(&d->event_lock)); - if ( !IS_PRIV(current->domain) ) + if ( !IS_PRIV_FOR(current->domain, d) ) return -EPERM; if ( pirq < 0 || pirq >= NR_IRQS || vector < 0 || vector >= NR_VECTORS ) @@ -929,14 +929,6 @@ int map_domain_pirq( dprintk(XENLOG_G_ERR, "dom%d: pirq %d or vector %d already mapped\n", d->domain_id, pirq, vector); return -EINVAL; - } - - ret = irq_permit_access(d, pirq); - if ( ret ) - { - dprintk(XENLOG_G_ERR, "dom%d: could not permit access to irq %d\n", - d->domain_id, pirq); - return ret; } desc = &irq_desc[vector]; @@ -988,7 +980,7 @@ int unmap_domain_pirq(struct domain *d, if ( (pirq < 0) || (pirq >= NR_IRQS) ) return -EINVAL; - if ( !IS_PRIV(current->domain) ) + if ( !IS_PRIV_FOR(current->domain, d) ) return -EINVAL; ASSERT(spin_is_locked(&pcidevs_lock)); @@ -1003,6 +995,13 @@ int unmap_domain_pirq(struct domain *d, goto done; } + if ( !irq_access_permitted(d, pirq) ) + { + dprintk(XENLOG_G_ERR, "dom%d: unmapping of pirq %d is not permitted\n", + d->domain_id, pirq); + ret = -EINVAL; + goto done; + } forced_unbind = pirq_guest_force_unbind(d, pirq); if ( forced_unbind ) dprintk(XENLOG_G_WARNING, "dom%d: forcing unbind of pirq %d\n", diff -r 5b8f9ef92e00 xen/arch/x86/physdev.c --- a/xen/arch/x86/physdev.c Wed Mar 11 19:13:47 2009 +0000 +++ b/xen/arch/x86/physdev.c Mon Mar 23 17:33:17 2009 +0900 @@ -34,9 +34,6 @@ static int physdev_map_pirq(struct physd struct msi_info _msi; void *map_data = NULL; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( !map ) return -EINVAL; @@ -47,6 +44,22 @@ static int physdev_map_pirq(struct physd if ( d == NULL ) { + ret = -ESRCH; + goto free_domain; + } + else + { + if ( !IS_PRIV_FOR(current->domain, d) ) + { + ret = -EPERM; + goto free_domain; + } + } + + if ( !irq_access_permitted(d, map->index) ) + { + dprintk(XENLOG_G_ERR, "dom%d: mapping of irq %d is not permitted\n", + d->domain_id, map->index); ret = -ESRCH; goto free_domain; } @@ -62,7 +75,7 @@ static int physdev_map_pirq(struct physd ret = -EINVAL; goto free_domain; } - vector = domain_irq_to_vector(current->domain, map->index); + vector = domain_irq_to_vector(dom0, map->index); if ( !vector ) { dprintk(XENLOG_G_ERR, "dom%d: map irq with no vector %d\n", @@ -160,9 +173,6 @@ static int physdev_unmap_pirq(struct phy struct domain *d; int ret; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( unmap->domid == DOMID_SELF ) d = rcu_lock_domain(current->domain); else @@ -170,6 +180,14 @@ static int physdev_unmap_pirq(struct phy if ( d == NULL ) return -ESRCH; + else + { + if ( !IS_PRIV_FOR(current->domain, d) ) + { + rcu_unlock_domain(d); + return -EPERM; + } + } spin_lock(&pcidevs_lock); spin_lock(&d->event_lock); diff -r 5b8f9ef92e00 xen/common/domctl.c --- a/xen/common/domctl.c Wed Mar 11 19:13:47 2009 +0000 +++ b/xen/common/domctl.c Mon Mar 23 18:05:20 2009 +0900 @@ -193,14 +193,45 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc long ret = 0; struct xen_domctl curop, *op = &curop; - if ( !IS_PRIV(current->domain) ) - return -EPERM; - if ( copy_from_guest(op, u_domctl, 1) ) return -EFAULT; if ( op->interface_version != XEN_DOMCTL_INTERFACE_VERSION ) return -EACCES; + + switch ( op->cmd ) + { + case XEN_DOMCTL_pin_mem_cacheattr: + case XEN_DOMCTL_memory_mapping: + case XEN_DOMCTL_ioport_mapping: + case XEN_DOMCTL_bind_pt_irq: + case XEN_DOMCTL_unbind_pt_irq: + { + struct domain *d; + + if (op->domain != DOMID_SELF ) + { + d = rcu_lock_domain_by_id(op->domain); + if ( d == NULL ) + return -ESRCH; + else + { + if ( !IS_PRIV_FOR(current->domain,d) ) + { + rcu_unlock_domain(d); + return -EPERM; + } + else + rcu_unlock_domain(d); + } + break; + } + } + default: + if ( !IS_PRIV(current->domain) ) + return -EPERM; + break; + } spin_lock(&domctl_lock); _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel