xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Arianna Avanzini <avanzini.arianna@gmail.com>
To: xen-devel@lists.xen.org
Cc: Ian.Campbell@eu.citrix.com, paolo.valente@unimore.it,
	stefano.stabellini@eu.citrix.com, dario.faggioli@citrix.com,
	ian.jackson@eu.citrix.com, julien.grall@citrix.com,
	etrudeau@broadcom.com, JBeulich@suse.com,
	avanzini.arianna@gmail.com, viktor.kleinik@globallogic.com,
	andrii.tseglytskyi@globallogic.com
Subject: [PATCH 1/3] tools/libxl: explicitly grant access to needed I/O-memory ranges
Date: Mon,  8 Sep 2014 17:05:32 +0200	[thread overview]
Message-ID: <1410188734-1752-2-git-send-email-avanzini.arianna@gmail.com> (raw)
In-Reply-To: <1410188734-1752-1-git-send-email-avanzini.arianna@gmail.com>

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@gmail.com>
Cc: Dario Faggioli <dario.faggioli@citrix.com>
Cc: Paolo Valente <paolo.valente@unimore.it>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Cc: Julien Grall <julien.grall@citrix.com>
Cc: Ian Campbell <Ian.Campbell@eu.citrix.com>
Cc: Jan Beulich <JBeulich@suse.com>
Cc: Ian Jackson <Ian.Jackson@eu.citrix.com>
Cc: Eric Trudeau <etrudeau@broadcom.com>
Cc: Viktor Kleinik <viktor.kleinik@globallogic.com>
Cc: Andrii Tseglytskyi <andrii.tseglytskyi@globallogic.com>

---

    With respect to the v12 memory_mapping series ([1]):
        - Use libxl_defbool_val() to access the value of the gfx_passthru
          configuration option.

    v12:
        - Fix commit description and add a paragraph about outstanding issues.

    v11:
        - Move the VGA-related hunk to a libxl helper; evaluate gfx_passthru.val
          only once as it is static in the scope of the helper.
        - Remove leftover debug fprintf().
        - Improve code readability by separating blocks of code.

    v10:
        - Use a class-based check on the PCI device to determine if VGA-related
          I/O-memory ranges must be made accessible to a guest that needs gfx
          passthrough.

    v9:
        - Allow a domain access to the VGA framebuffer only if the user has
          signaled that one of the passthru GPUs is primary via domain config.

    v8:
        - Explain better in the commit description VGA-related code additions.
        - Fix v6 changelog which, being too generic, ended up to uncorrectly
          state that one of the requests had been addressed.
        - Remove tentative phrases from commit description.

    v7:
        - Let libxl not handle I/O ports and I/O memory differently when access
          to a PCI device is allowed to a domain.
        - Change the construct used by libxl during PCI-related initialization
          from a switch to an if to better suit the new execution flow.

    [1] http://markmail.org/thread/cx2q7vhlwuzssmzp

---
 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 ee328e9..8062e4d 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 04c9378..e27861b 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -951,6 +951,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 2782d0e..f8c980b 100644
--- a/tools/libxl/libxl_pci.c
+++ b/tools/libxl/libxl_pci.c
@@ -846,10 +846,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) {
@@ -867,8 +870,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);
@@ -937,11 +940,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));
@@ -1166,6 +1166,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;
 
@@ -1181,8 +1182,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)
@@ -1203,8 +1203,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);
@@ -1254,10 +1254,6 @@ skip1:
             }
         }
         fclose(f);
-        break;
-    }
-    default:
-        abort();
     }
 out:
     /* don't do multiple resets while some functions are still passed through */
@@ -1435,6 +1431,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
-- 
2.1.0

  reply	other threads:[~2014-09-08 15:05 UTC|newest]

Thread overview: 41+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-08-30 16:29 [PATCH v12 00/14] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 01/14] arch/arm: add consistency check to REMOVE p2m changes Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 02/14] arch/arm: unmap partially-mapped memory regions Arianna Avanzini
2014-09-01 17:53   ` Julien Grall
2014-09-01 20:13     ` Arianna Avanzini
2014-09-01 23:47     ` [PATCH] " Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 03/14] arch/x86: warn if to-be-removed mapping does not exist Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 04/14] arch/x86: cleanup memory_mapping DOMCTL Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 05/14] xen/common: add ARM stub for the function memory_type_changed() Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 06/14] xen/x86: factor out map and unmap from the memory_mapping DOMCTL Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 07/14] xen/common: move the memory_mapping DOMCTL hypercall to common code Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 08/14] tools/libxl: parse optional start gfn from the iomem config option Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 09/14] tools/libxl: handle the iomem parameter with the memory_mapping hcall Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 10/14] xsm/flask: avoid spurious error messages when mapping I/O-memory Arianna Avanzini
2014-09-03 11:22   ` Ian Campbell
2014-09-03 11:30     ` Ian Campbell
2014-09-03 14:41   ` Daniel De Graaf
2014-09-04 11:49     ` [PATCH] xsm/flask: handle XEN_DOMCTL_memory_mapping for all architectures Arianna Avanzini
2014-09-08 10:11       ` Ian Campbell
2014-09-08 12:24         ` Arianna Avanzini
2014-09-08 12:38           ` Ian Campbell
2014-09-08 12:50             ` Arianna Avanzini
2014-09-09 12:35               ` Ian Campbell
2014-09-09 13:13                 ` Arianna Avanzini
2014-09-09 14:45                   ` Ian Campbell
2014-09-10 20:07                     ` Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 11/14] flask/policy: allow domU to use previously-mapped I/O-memory Arianna Avanzini
2014-09-03 11:21   ` Ian Campbell
2014-09-03 14:45     ` Daniel De Graaf
2014-09-05 23:25       ` Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 12/14] tools/libxl: explicitly grant access to needed I/O-memory ranges Arianna Avanzini
2014-09-03 11:26   ` Ian Campbell
2014-09-08 15:05     ` [PATCH 0/3] Separate the functions of the memory_mapping and iomem_permission DOMCTLs Arianna Avanzini
2014-09-08 15:05       ` Arianna Avanzini [this message]
2014-09-08 15:05       ` [PATCH 2/3] tools/libxl: cleanup the do_pci_add() function Arianna Avanzini
2014-09-08 15:05       ` [PATCH 3/3] xen/common: do not implicitly permit access to mapped I/O memory Arianna Avanzini
2014-08-30 16:29 ` [PATCH v12 13/14] tools/libxl: cleanup the do_pci_add() function Arianna Avanzini
2014-09-03 11:27   ` Ian Campbell
2014-08-30 16:29 ` [PATCH v12 14/14] xen/common: do not implicitly permit access to mapped I/O memory Arianna Avanzini
2014-09-03 12:15 ` [PATCH v12 00/14] Implement the XEN_DOMCTL_memory_mapping hypercall for ARM Ian Campbell
2014-09-03 13:55   ` Arianna Avanzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1410188734-1752-2-git-send-email-avanzini.arianna@gmail.com \
    --to=avanzini.arianna@gmail.com \
    --cc=Ian.Campbell@eu.citrix.com \
    --cc=JBeulich@suse.com \
    --cc=andrii.tseglytskyi@globallogic.com \
    --cc=dario.faggioli@citrix.com \
    --cc=etrudeau@broadcom.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=julien.grall@citrix.com \
    --cc=paolo.valente@unimore.it \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=viktor.kleinik@globallogic.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).