arm: Add a hypercall for device mmio mapping
authorShannon Zhao <shannon.zhao@linaro.org>
Wed, 30 Mar 2016 10:09:00 +0000 (12:09 +0200)
committerJan Beulich <jbeulich@suse.com>
Wed, 30 Mar 2016 15:05:49 +0000 (17:05 +0200)
It needs to map platform or amba device mmio to Dom0 on ARM. But when
booting with ACPI, it can't get the mmio region in Xen due to lack of
AML interpreter to parse DSDT table. Therefore, let Dom0 call a
hypercall to map mmio region when it adds the devices.

Here we add a new map space like the XEN_DOMCTL_memory_mapping to map
mmio region for Dom0. Also add a helper to combine the
xsm_add_to_physmap and XENMAPSPACE_dev_mmio space check together.

Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Acked-by: Julien Grall <julien.grall@arm.com>
xen/arch/arm/mm.c
xen/arch/arm/p2m.c
xen/common/memory.c
xen/include/asm-arm/p2m.h
xen/include/public/memory.h

index 81f9e2e823a7770d86ab6e093d11e1e1917804b8..0aae6c50fa35d4ab95c6f81094cbf2dccf1754d6 100644 (file)
@@ -1138,6 +1138,9 @@ int xenmem_add_to_physmap_one(
         rcu_unlock_domain(od);
         break;
     }
+    case XENMAPSPACE_dev_mmio:
+        rc = map_dev_mmio_region(d, gpfn, 1, idx);
+        return rc;
 
     default:
         return -ENOSYS;
index 7e5f5d14e2b2b9915535f7cd71dede1b263e53d7..0011708bc812c6c155dd7fbcb4af3812c8aaaeec 100644 (file)
@@ -7,6 +7,7 @@
 #include <xen/bitops.h>
 #include <xen/vm_event.h>
 #include <xen/mem_access.h>
+#include <xen/iocap.h>
 #include <public/vm_event.h>
 #include <asm/flushtlb.h>
 #include <asm/gic.h>
@@ -1270,6 +1271,27 @@ int unmap_mmio_regions(struct domain *d,
                              d->arch.p2m.default_access);
 }
 
+int map_dev_mmio_region(struct domain *d,
+                        unsigned long start_gfn,
+                        unsigned long nr,
+                        unsigned long mfn)
+{
+    int res;
+
+    if ( !(nr && iomem_access_permitted(d, start_gfn, start_gfn + nr - 1)) )
+        return 0;
+
+    res = map_mmio_regions(d, start_gfn, nr, mfn);
+    if ( res < 0 )
+    {
+        printk(XENLOG_ERR "Unable to map [%#lx - %#lx] in Dom%d\n",
+               start_gfn, start_gfn + nr - 1, d->domain_id);
+        return res;
+    }
+
+    return 0;
+}
+
 int guest_physmap_add_entry(struct domain *d,
                             unsigned long gpfn,
                             unsigned long mfn,
index c7fca96e30bf027eff1a60b91e825c7093f9eb74..644f81a5a43c59aeaaeda551936d54627ae3ada7 100644 (file)
@@ -834,6 +834,19 @@ static int get_reserved_device_memory(xen_pfn_t start, xen_ulong_t nr,
 }
 #endif
 
+static long xatp_permission_check(struct domain *d, unsigned int space)
+{
+    /*
+     * XENMAPSPACE_dev_mmio mapping is only supported for hardware Domain
+     * to map this kind of space to itself.
+     */
+    if ( (space == XENMAPSPACE_dev_mmio) &&
+         (!is_hardware_domain(current->domain) || (d != current->domain)) )
+        return -EACCES;
+
+    return xsm_add_to_physmap(XSM_TARGET, current->domain, d);
+}
+
 long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
 {
     struct domain *d;
@@ -980,7 +993,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -ESRCH;
 
-        rc = xsm_add_to_physmap(XSM_TARGET, current->domain, d);
+        rc = xatp_permission_check(d, xatp.space);
         if ( rc )
         {
             rcu_unlock_domain(d);
@@ -1024,7 +1037,7 @@ long do_memory_op(unsigned long cmd, XEN_GUEST_HANDLE_PARAM(void) arg)
         if ( d == NULL )
             return -ESRCH;
 
-        rc = xsm_add_to_physmap(XSM_TARGET, current->domain, d);
+        rc = xatp_permission_check(d, xatpb.space);
         if ( rc )
         {
             rcu_unlock_domain(d);
index 55626b4d5c0246fd152f92aa779d330c3310c34b..d240d1e861992a4a4b7529efd9de1eb880b8fe89 100644 (file)
@@ -154,6 +154,11 @@ int unmap_regions_rw_cache(struct domain *d,
                            unsigned long nr_mfns,
                            unsigned long mfn);
 
+int map_dev_mmio_region(struct domain *d,
+                        unsigned long start_gfn,
+                        unsigned long nr,
+                        unsigned long mfn);
+
 int guest_physmap_add_entry(struct domain *d,
                             unsigned long gfn,
                             unsigned long mfn,
index f69e92f906ed800e34b6de935c63fea2dc202f2d..fe52ee18e504a640a41247954e062fc301e623f9 100644 (file)
@@ -220,6 +220,7 @@ DEFINE_XEN_GUEST_HANDLE(xen_machphys_mapping_t);
 #define XENMAPSPACE_gmfn_range   3 /* GMFN range, XENMEM_add_to_physmap only. */
 #define XENMAPSPACE_gmfn_foreign 4 /* GMFN from another dom,
                                     * XENMEM_add_to_physmap_batch only. */
+#define XENMAPSPACE_dev_mmio     5 /* device mmio region */
 /* ` } */
 
 /*