[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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@xxxxxxxxxxxxxxx>

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@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.