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

[PATCH v7 2/3] arm/mpu: Introduce `v8r_el1_msa` device tree property for domains



From: Harry Ramsey <harry.ramsey@xxxxxxx>

Add a new device tree property `v8r_el1_msa` to select the MSA (memory
system architecture) at EL1 for Armv8-R architecture: MPU or MMU, the
former is the default if the property is not passed.

Implement the dom0less path to parse the new device tree property, add
a new domctl hypercall input parameter `v8r_el1_msa` for arm and
add the sanitisation in arch_sanitise_domain_config(), the parameter
is intended to be used on CONFIG_MPU systems and returns an error if
selected for MMU.

While there, add explicit padding and check that it's zero during
arch domain config sanitisation, given the breaking change, bump the
XEN_DOMCTL_INTERFACE_VERSION.

Signed-off-by: Harry Ramsey <harry.ramsey@xxxxxxx>
Signed-off-by: Luca Fancellu <luca.fancellu@xxxxxxx>
---
v7:
 - Refactor domu_dt_v8r_el1_msa_parse() and v8r_el1_msa_domain_sanitise_config()
 - remove unused headers from mpu/{arm32,arm64}/mm.c
 - remove has_v8r_vmsa_support() stub from mpu/arm32/mm.c and use the one in
   asm/domain_build.h
v6:
 - Add explicit padding to `struct xen_arch_domainconfig` and check it
 - Provide common v8r_el1_msa_domain_sanitise_config() for MMU/MPU
 - During domu_dt_v8r_el1_msa_parse() set PMSA when property not present
 - constify *node in domu_dt_v8r_el1_msa_parse()
 - Print full path of the node in domu_dt_v8r_el1_msa_parse() error msgs
 - typo fixing
v5:
 - follow the way domu_dt_sci_parse and ARM_SCI is doing, but
   return error if property is present in MMU systems.
 - Align the commit message on the new changes
 - fix documentation
 - fix multiline comment
 - drop the explicit padding from struct xen_arch_domainconfig
v4:
- Rework the patch to have the v8r_el1_msa input parameter more
  enclosed in the Armv8-A (mmu)/Armv8-R (mpu) space.
v3:
- Improve commit message and device tree property description
- Remove macro protection
- Remove unused function is_mpu_domain
- Code formatting
---
 docs/misc/arm/device-tree/booting.txt   | 14 ++++++
 xen/arch/arm/dom0less-build.c           | 62 +++++++++++++++++++++++++
 xen/arch/arm/domain.c                   | 37 +++++++++++++++
 xen/arch/arm/include/asm/domain.h       |  4 ++
 xen/arch/arm/include/asm/domain_build.h | 10 ++++
 xen/arch/arm/mpu/arm64/mm.c             |  5 ++
 xen/include/public/arch-arm.h           |  7 +++
 xen/include/public/domctl.h             |  4 +-
 8 files changed, 141 insertions(+), 2 deletions(-)

diff --git a/docs/misc/arm/device-tree/booting.txt 
b/docs/misc/arm/device-tree/booting.txt
index 977b4286082f..f73839df090b 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -322,6 +322,20 @@ with the following properties:
     Should be used together with scmi-smc-passthrough Xen command line
     option.
 
+- v8r_el1_msa
+
+    A string property specifying whether, on Armv8-R systems at EL1, a domain
+    should use PMSAv8 (MPU) or VMSAv8 (MMU).
+
+    - "mmu"
+    Enables VMSAv8 at EL1. This requires hardware support and is only
+    optionally available on AArch64. Not supported on AArch32.
+
+    - "mpu"
+    Enables PMSAv8 at EL1. This is the default behavior when the property is
+    not passed. This configuration requires static allocation (xen,static-mem)
+    and direct mapping (direct-map).
+
 Under the "xen,domain" compatible node, one or more sub-nodes are present
 for the DomU kernel and ramdisk.
 
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index 52cf788a45ea..3f48f742260b 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -302,6 +302,65 @@ static int __init domu_dt_sci_parse(struct dt_device_node 
*node,
     return 0;
 }
 
+static int __init
+domu_dt_v8r_el1_msa_parse(const struct dt_device_node *node,
+                          struct xen_domctl_createdomain *d_cfg,
+                          unsigned int flags)
+{
+    const char *value;
+    int ret;
+
+    if ( !IS_ENABLED(CONFIG_MPU) )
+    {
+        d_cfg->arch.v8r_el1_msa = XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_NONE;
+
+        if ( !dt_property_read_bool(node, "v8r_el1_msa") )
+            return 0;
+
+        printk(XENLOG_ERR
+               "v8r_el1_msa not supported on this build for domain %s\n",
+               dt_node_full_name(node));
+        return -EINVAL;
+    }
+
+    ret = dt_property_read_string(node, "v8r_el1_msa", &value);
+    /* Property absent: PMSA is the default */
+    if ( ret == -EINVAL )
+        value = "mpu";
+    else if ( ret )
+        return ret;
+
+    if ( !strcmp(value, "mpu") )
+    {
+        if ( !(flags & CDF_staticmem) || !(flags & CDF_directmap) )
+        {
+            printk(XENLOG_ERR
+                   "v8r_el1_msa=mpu requires static-mem and direct-map for 
domain %s\n",
+                   dt_node_full_name(node));
+            return -EINVAL;
+        }
+        d_cfg->arch.v8r_el1_msa = XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_PMSA;
+        return 0;
+    }
+
+    if ( !strcmp(value, "mmu") )
+    {
+        if ( !has_v8r_vmsa_support() )
+        {
+            printk(XENLOG_ERR
+                   "v8r_el1_msa=mmu unsupported by platform for domain %s\n",
+                   dt_node_full_name(node));
+            return -EINVAL;
+        }
+        d_cfg->arch.v8r_el1_msa = XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_VMSA;
+        return 0;
+    }
+
+    printk(XENLOG_ERR "v8r_el1_msa value '%s' not valid for domain %s\n",
+           value, dt_node_full_name(node));
+    return -EINVAL;
+}
+
 int __init arch_parse_dom0less_node(struct dt_device_node *node,
                                     struct boot_domain *bd)
 {
@@ -315,6 +374,9 @@ int __init arch_parse_dom0less_node(struct dt_device_node 
*node,
     if ( domu_dt_sci_parse(node, d_cfg) )
         panic("Error getting SCI configuration\n");
 
+    if ( domu_dt_v8r_el1_msa_parse(node, d_cfg, flags) )
+        panic("Error getting v8r_el1_msa configuration\n");
+
     if ( !dt_property_read_u32(node, "nr_spis", &d_cfg->arch.nr_spis) )
     {
         int vpl011_virq = GUEST_VPL011_SPI;
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 26380a807cad..baa3a5d7086c 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -538,6 +538,25 @@ void vcpu_switch_to_aarch64_mode(struct vcpu *v)
     v->arch.hcr_el2 |= HCR_RW;
 }
 
+static bool v8r_el1_msa_domain_sanitise_config(
+    const struct xen_domctl_createdomain *config)
+{
+    switch ( config->arch.v8r_el1_msa )
+    {
+    case XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_NONE:
+        return !IS_ENABLED(CONFIG_MPU);
+
+    case XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_PMSA:
+        return IS_ENABLED(CONFIG_MPU);
+
+    case XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_VMSA:
+        return IS_ENABLED(CONFIG_MPU) && IS_ENABLED(CONFIG_ARM_64);
+
+    default:
+        return false;
+    }
+}
+
 int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
 {
     unsigned int max_vcpus;
@@ -554,6 +573,14 @@ int arch_sanitise_domain_config(struct 
xen_domctl_createdomain *config)
         return -EINVAL;
     }
 
+    /* Check config structure padding */
+    if ( config->arch.pad )
+    {
+        dprintk(XENLOG_INFO,
+                "Invalid domain configuration during domain creation\n");
+        return -EINVAL;
+    }
+
     /* Check feature flags */
     if ( sve_vl_bits > 0 )
     {
@@ -630,6 +657,12 @@ int arch_sanitise_domain_config(struct 
xen_domctl_createdomain *config)
         return -EINVAL;
     }
 
+    if ( !v8r_el1_msa_domain_sanitise_config(config) )
+    {
+        dprintk(XENLOG_INFO, "Unsupported v8r_el1_msa value\n");
+        return -EINVAL;
+    }
+
     return sci_domain_sanitise_config(config);
 }
 
@@ -722,6 +755,10 @@ int arch_domain_create(struct domain *d,
     d->arch.sve_vl = config->arch.sve_vl;
 #endif
 
+#ifdef CONFIG_MPU
+    d->arch.v8r_el1_msa = config->arch.v8r_el1_msa;
+#endif
+
     if ( (rc = sci_domain_init(d, config)) != 0 )
         goto fail;
 
diff --git a/xen/arch/arm/include/asm/domain.h 
b/xen/arch/arm/include/asm/domain.h
index b24f02d269be..ac7300e41fcd 100644
--- a/xen/arch/arm/include/asm/domain.h
+++ b/xen/arch/arm/include/asm/domain.h
@@ -112,6 +112,10 @@ struct arch_domain
 #endif
 
     struct resume_info resume_ctx;
+
+#ifdef CONFIG_MPU
+    uint8_t v8r_el1_msa;
+#endif
 }  __cacheline_aligned;
 
 struct arch_vcpu
diff --git a/xen/arch/arm/include/asm/domain_build.h 
b/xen/arch/arm/include/asm/domain_build.h
index 6674dac5e2f8..df8b361b3da5 100644
--- a/xen/arch/arm/include/asm/domain_build.h
+++ b/xen/arch/arm/include/asm/domain_build.h
@@ -19,6 +19,16 @@ int prepare_acpi(struct domain *d, struct kernel_info 
*kinfo);
 
 int add_ext_regions(unsigned long s_gfn, unsigned long e_gfn, void *data);
 
+#if defined(CONFIG_MPU) && defined(CONFIG_ARM_64)
+/* Utility function to determine if an Armv8-R processor supports VMSA. */
+bool has_v8r_vmsa_support(void);
+#else
+static inline bool has_v8r_vmsa_support(void)
+{
+    return false;
+}
+#endif /* CONFIG_MPU */
+
 #endif
 
 /*
diff --git a/xen/arch/arm/mpu/arm64/mm.c b/xen/arch/arm/mpu/arm64/mm.c
index ed643cad4073..b07e729a7d05 100644
--- a/xen/arch/arm/mpu/arm64/mm.c
+++ b/xen/arch/arm/mpu/arm64/mm.c
@@ -32,6 +32,11 @@
         break;                                                  \
     }
 
+bool has_v8r_vmsa_support(void)
+{
+    return system_cpuinfo.mm64.msa_frac == MM64_MSA_FRAC_VMSA_SUPPORT;
+}
+
 /*
  * Armv8-R supports direct access and indirect access to the MPU regions 
through
  * registers:
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index cd563cf70684..7d6f87e8b2b1 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -330,6 +330,10 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_context_t);
 #define XEN_DOMCTL_CONFIG_ARM_SCI_NONE      0
 #define XEN_DOMCTL_CONFIG_ARM_SCI_SCMI_SMC  1
 
+#define XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_NONE    0
+#define XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_PMSA    1
+#define XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_VMSA    2
+
 struct xen_arch_domainconfig {
     /* IN/OUT */
     uint8_t gic_version;
@@ -355,6 +359,9 @@ struct xen_arch_domainconfig {
     uint32_t clock_frequency;
     /* IN */
     uint8_t arm_sci_type;
+    /* IN */
+    uint8_t v8r_el1_msa;
+    uint16_t pad;
 };
 #endif /* __XEN__ || __XEN_TOOLS__ */
 
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 8f6708c0a7cd..23124547f347 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -30,9 +30,9 @@
  * fields) don't require a change of the version.
  * Stable ops are NOT covered by XEN_DOMCTL_INTERFACE_VERSION!
  *
- * Last version bump: Xen 4.19
+ * Last version bump: Xen 4.22
  */
-#define XEN_DOMCTL_INTERFACE_VERSION 0x00000017
+#define XEN_DOMCTL_INTERFACE_VERSION 0x00000018
 
 /*
  * NB. xen_domctl.domain is an IN/OUT parameter for this operation.
-- 
2.34.1




 


Rackspace

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