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

[Xen-changelog] [xen master] tools/libxl: explicitly grant access to needed I/O-memory ranges



commit abfb006f1ff4af1424e5b0d0589f0226377fda36
Author:     Arianna Avanzini <avanzini.arianna@xxxxxxxxx>
AuthorDate: Mon Sep 8 17:05:32 2014 +0200
Commit:     Ian Campbell <ian.campbell@xxxxxxxxxx>
CommitDate: Tue Sep 9 13:25:36 2014 +0100

    tools/libxl: explicitly grant access to needed I/O-memory ranges
    
    This commit changes the existing libxl code to be sure to grant access
    permission to PCI-related I/O memory ranges, while setting up passthrough
    of PCI devices specified in the domain's configuration, and to VGA-related
    memory ranges, while setting up VGA passthrough (if gfx_passthru = 1 in
    the domain's configuration).
    As for the latter, the newly-added code does not replace any existing one,
    but instead matches the calls to xc_domain_memory_mapping() performed by
    QEMU on the path that is executed if gfx passthru is enabled and follows
    the registration of a new VGA controller (in register_vga_regions(),
    defined in hw/pt-graphics.c). In fact, VGA needs some extra memory
    ranges to be mapped with respect to PCI; QEMU expects that access to those
    memory ranges is implicitly granted when he calls the hypervisor with the
    function xc_domain_memory_mapping(): this commit calls iomem_permission
    for it when needed by checking the passthru PCI device's class.
    
    NOTE: the code added by this commit still does not verify if the passthru
          of the framebuffer area is being performed for the primary GPU, but
          only replicates the behavior of QEMU which is limited to performing
          the passthru for all PCI devices of VGA class.
    
    This commit is instrumental to the last one in the series, which will
    separate the functions of the iomem_permission and memory_mapping DOMCTLs,
    so that requesting an I/O-memory range will not imply that access to such
    a range is implicitly granted.
    
    Signed-off-by: Arianna Avanzini <avanzini.arianna@xxxxxxxxx>
    Acked-by: Ian Campbell <Ian.Campbell@xxxxxxxxxxxxx>
    Cc: Dario Faggioli <dario.faggioli@xxxxxxxxxx>
    Cc: Paolo Valente <paolo.valente@xxxxxxxxxx>
    Cc: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
    Cc: Julien Grall <julien.grall@xxxxxxxxxx>
    Cc: Jan Beulich <JBeulich@xxxxxxxx>
    Cc: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>
    Cc: Eric Trudeau <etrudeau@xxxxxxxxxxxx>
    Cc: Viktor Kleinik <viktor.kleinik@xxxxxxxxxxxxxxx>
    Cc: Andrii Tseglytskyi <andrii.tseglytskyi@xxxxxxxxxxxxxxx>
---
 tools/libxl/libxl_create.c   |    9 ++++
 tools/libxl/libxl_internal.h |    2 +
 tools/libxl/libxl_pci.c      |   91 ++++++++++++++++++++++++++++++++++-------
 3 files changed, 86 insertions(+), 16 deletions(-)

diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 57a0ece..b36c719 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -1216,6 +1216,15 @@ static void domcreate_launch_dm(libxl__egc *egc, 
libxl__multidev *multidev,
             libxl__spawn_stub_dm(egc, &dcs->dmss);
         else
             libxl__spawn_local_dm(egc, &dcs->dmss.dm);
+
+        /*
+         * Handle the domain's (and the related stubdomain's) access to
+         * the VGA framebuffer.
+         */
+        ret = libxl__grant_vga_iomem_permission(gc, domid, d_config);
+        if ( ret )
+            goto error_out;
+
         return;
     }
     case LIBXL_DOMAIN_TYPE_PV:
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index fafef5a..03e9978 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -952,6 +952,8 @@ _hidden int libxl__domain_cpupool(libxl__gc *gc, uint32_t 
domid);
 _hidden libxl_scheduler libxl__domain_scheduler(libxl__gc *gc, uint32_t domid);
 _hidden int libxl__sched_set_params(libxl__gc *gc, uint32_t domid,
                                     libxl_domain_sched_params *scparams);
+_hidden int libxl__grant_vga_iomem_permission(libxl__gc *gc, const uint32_t 
domid,
+                                              libxl_domain_config *const 
d_config);
 
 typedef struct {
     uint32_t store_port;
diff --git a/tools/libxl/libxl_pci.c b/tools/libxl/libxl_pci.c
index 38a9642..c4fd0e1 100644
--- a/tools/libxl/libxl_pci.c
+++ b/tools/libxl/libxl_pci.c
@@ -874,10 +874,13 @@ static int qemu_pci_add_xenstore(libxl__gc *gc, uint32_t 
domid,
 static int do_pci_add(libxl__gc *gc, uint32_t domid, libxl_device_pci *pcidev, 
int starting)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
+    libxl_domain_type type = libxl__domain_type(gc, domid);
     int rc, hvm = 0;
 
-    switch (libxl__domain_type(gc, domid)) {
-    case LIBXL_DOMAIN_TYPE_HVM:
+    if (type == LIBXL_DOMAIN_TYPE_INVALID)
+        return ERROR_FAIL;
+
+    if (type == LIBXL_DOMAIN_TYPE_HVM) {
         hvm = 1;
         if (libxl__wait_for_device_model_deprecated(gc, domid, "running",
                                          NULL, NULL, NULL) < 0) {
@@ -895,8 +898,8 @@ static int do_pci_add(libxl__gc *gc, uint32_t domid, 
libxl_device_pci *pcidev, i
         }
         if ( rc )
             return ERROR_FAIL;
-        break;
-    case LIBXL_DOMAIN_TYPE_PV:
+    }
+
     {
         char *sysfs_path = libxl__sprintf(gc, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
                                          pcidev->bus, pcidev->dev, 
pcidev->func);
@@ -965,11 +968,8 @@ static int do_pci_add(libxl__gc *gc, uint32_t domid, 
libxl_device_pci *pcidev, i
                 return ERROR_FAIL;
             }
         }
-        break;
-    }
-    case LIBXL_DOMAIN_TYPE_INVALID:
-        return ERROR_FAIL;
     }
+
 out:
     if (!libxl_is_stubdom(ctx, domid, NULL)) {
         rc = xc_assign_device(ctx->xch, domid, pcidev_encode_bdf(pcidev));
@@ -1194,6 +1194,7 @@ static int do_pci_remove(libxl__gc *gc, uint32_t domid,
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
     libxl_device_pci *assigned;
+    libxl_domain_type type = libxl__domain_type(gc, domid);
     int hvm = 0, rc, num;
     int stubdomid = 0;
 
@@ -1209,8 +1210,7 @@ static int do_pci_remove(libxl__gc *gc, uint32_t domid,
     }
 
     rc = ERROR_FAIL;
-    switch (libxl__domain_type(gc, domid)) {
-    case LIBXL_DOMAIN_TYPE_HVM:
+    if (type == LIBXL_DOMAIN_TYPE_HVM) {
         hvm = 1;
         if (libxl__wait_for_device_model_deprecated(gc, domid, "running",
                                          NULL, NULL, NULL) < 0)
@@ -1231,8 +1231,8 @@ static int do_pci_remove(libxl__gc *gc, uint32_t domid,
             rc = ERROR_FAIL;
             goto out_fail;
         }
-        break;
-    case LIBXL_DOMAIN_TYPE_PV:
+    } else if (type != LIBXL_DOMAIN_TYPE_PV)
+        abort();
     {
         char *sysfs_path = libxl__sprintf(gc, 
SYSFS_PCI_DEV"/"PCI_BDF"/resource", pcidev->domain,
                                          pcidev->bus, pcidev->dev, 
pcidev->func);
@@ -1282,10 +1282,6 @@ skip1:
             }
         }
         fclose(f);
-        break;
-    }
-    default:
-        abort();
     }
 out:
     /* don't do multiple resets while some functions are still passed through 
*/
@@ -1463,6 +1459,69 @@ int libxl__device_pci_destroy_all(libxl__gc *gc, 
uint32_t domid)
     return 0;
 }
 
+int libxl__grant_vga_iomem_permission(libxl__gc *gc, const uint32_t domid,
+                                      libxl_domain_config *const d_config)
+{
+    int i, ret;
+
+    if (!libxl_defbool_val(d_config->b_info.u.hvm.gfx_passthru))
+        return 0;
+
+    for (i = 0 ; i < d_config->num_pcidevs ; i++) {
+        uint64_t vga_iomem_start = 0xa0000 >> XC_PAGE_SHIFT;
+        uint32_t stubdom_domid;
+        libxl_device_pci *pcidev = &d_config->pcidevs[i];
+        char *pci_device_class_path =
+            libxl__sprintf(gc, SYSFS_PCI_DEV"/"PCI_BDF"/class",
+                           pcidev->domain, pcidev->bus, pcidev->dev,
+                           pcidev->func);
+        int read_items;
+        unsigned long pci_device_class;
+
+        FILE *f = fopen(pci_device_class_path, "r");
+        if (!f) {
+            LOGE(ERROR,
+                 "pci device "PCI_BDF" does not have class attribute",
+                 pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
+            continue;
+        }
+        read_items = fscanf(f, "0x%lx\n", &pci_device_class);
+        fclose(f);
+        if (read_items != 1) {
+            LOGE(ERROR,
+                 "cannot read class of pci device "PCI_BDF,
+                 pcidev->domain, pcidev->bus, pcidev->dev, pcidev->func);
+            continue;
+        }
+        if (pci_device_class != 0x030000) /* VGA class */
+            continue;
+
+        stubdom_domid = libxl_get_stubdom_id(CTX, domid);
+        ret = xc_domain_iomem_permission(CTX->xch, stubdom_domid,
+                                         vga_iomem_start, 0x20, 1);
+        if (ret < 0) {
+            LOGE(ERROR,
+                 "failed to give stubdom%d access to iomem range "
+                 "%"PRIx64"-%"PRIx64" for VGA passthru",
+                 stubdom_domid,
+                 vga_iomem_start, (vga_iomem_start + 0x20 - 1));
+            return ret;
+        }
+        ret = xc_domain_iomem_permission(CTX->xch, domid,
+                                         vga_iomem_start, 0x20, 1);
+        if (ret < 0) {
+            LOGE(ERROR,
+                 "failed to give dom%d access to iomem range "
+                 "%"PRIx64"-%"PRIx64" for VGA passthru",
+                 domid, vga_iomem_start, (vga_iomem_start + 0x20 - 1));
+            return ret;
+        }
+        break;
+    }
+
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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