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