From: Harry Ramsey <harry.ramsey@arm.com>
Add a new device tree property `v8r_el1_msa` to select the MSA (memory
system architecture) at EL1 i.e. MPU(default) or MMU.
Signed-off-by: Harry Ramsey <harry.ramsey@arm.com>
Signed-off-by: Luca Fancellu <luca.fancellu@arm.com>
---
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 | 12 ++++++++++++
xen/arch/arm/dom0less-build.c | 24 ++++++++++++++++++++++++
xen/arch/arm/domain.c | 4 ++++
xen/arch/arm/include/asm/domain.h | 7 +++++++
xen/arch/arm/include/asm/mpu.h | 5 +++++
xen/arch/arm/mpu/arm32/mm.c | 5 +++++
xen/arch/arm/mpu/arm64/mm.c | 5 +++++
xen/include/public/arch-arm.h | 2 ++
8 files changed, 64 insertions(+)
diff --git a/docs/misc/arm/device-tree/booting.txt b/docs/misc/arm/device-tree/booting.txt
index 977b4286082f..b1a329c0e8d9 100644
--- a/docs/misc/arm/device-tree/booting.txt
+++ b/docs/misc/arm/device-tree/booting.txt
@@ -322,6 +322,18 @@ 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, a domain
+ should use PMSAv8 (MPU) at EL1 or VMSAv8 (MMU) at EL1.
+
+ - "mmu"
+ Enables VMSAv8 at EL1. This requires hardware support and is only
+ optionally available on AArch64.
+
+ - "mpu"
+ Enables PMSAv8 at EL1. (Default)
+
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 4181c105389a..456dc553bb23 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -24,6 +24,7 @@
#include <asm/domain_build.h>
#include <asm/firmware/sci.h>
#include <asm/grant_table.h>
+#include <asm/mpu.h>
#include <asm/setup.h>
#ifdef CONFIG_VGICV2
@@ -315,6 +316,7 @@ int __init arch_parse_dom0less_node(struct dt_device_node *node,
struct xen_domctl_createdomain *d_cfg = &bd->create_cfg;
unsigned int flags = bd->create_flags;
uint32_t val;
+ const char *v8r_el1_msa;
d_cfg->arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE;
d_cfg->flags |= XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap;
@@ -322,6 +324,28 @@ 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 (!dt_property_read_string(node, "v8r_el1_msa", &v8r_el1_msa))
+ {
+#ifdef CONFIG_MPU
+ if ( !strcmp(v8r_el1_msa, "mmu") )
+ {
+ if ( !has_v8r_vmsa_support() )
+ panic("Platform does not support VMSA at EL1 (v8r_el1_msa)\n");
+ d_cfg->arch.v8r_el1_msa = MPU_EL1_VMSA;
+ }
+ else if ( !strcmp(v8r_el1_msa, "mpu") )
+ {
+ d_cfg->arch.v8r_el1_msa = MPU_EL1_PMSA;
+ if ( !(flags & CDF_staticmem) || !(flags & CDF_directmap) )
+ panic("PMSA is not valid for domain without static allocation and direct map (v8r_el1_msa)\n");
+ }
+ else
+ panic("Invalid device tree option for v8r_el1_msa\n");
+#else
+ panic("'v8r_el1_msa' property found, but CONFIG_MPU not selected\n");
+#endif
+ }
+
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..c044293acd39 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -725,6 +725,10 @@ int arch_domain_create(struct domain *d,
if ( (rc = sci_domain_init(d, config)) != 0 )
goto fail;
+#ifdef CONFIG_MPU
+ d->arch.v8r_el1_msa = config->arch.v8r_el1_msa;
+#endif
+
return 0;
fail:
diff --git a/xen/arch/arm/include/asm/domain.h b/xen/arch/arm/include/asm/domain.h
index ffe5d0d9f0a6..fd0a83046893 100644
--- a/xen/arch/arm/include/asm/domain.h
+++ b/xen/arch/arm/include/asm/domain.h
@@ -30,6 +30,9 @@ enum domain_type {
#define is_64bit_domain(d) (0)
#endif
+#define MPU_EL1_PMSA 0
+#define MPU_EL1_VMSA 1
+
/*
* Is the domain using the host memory layout?
*
@@ -128,6 +131,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/mpu.h b/xen/arch/arm/include/asm/mpu.h
index 72fa5b00b861..8a8c01086206 100644
--- a/xen/arch/arm/include/asm/mpu.h
+++ b/xen/arch/arm/include/asm/mpu.h
@@ -27,6 +27,11 @@
#ifndef __ASSEMBLER__
+/*
+ * Utility function to determine if an Armv8-R processor supports VMSA.
+ */
+bool has_v8r_vmsa_support(void);
+
/*
* Set base address of MPU protection region.
*
diff --git a/xen/arch/arm/mpu/arm32/mm.c b/xen/arch/arm/mpu/arm32/mm.c
index a4673c351141..5eaeb3400e6c 100644
--- a/xen/arch/arm/mpu/arm32/mm.c
+++ b/xen/arch/arm/mpu/arm32/mm.c
@@ -38,6 +38,11 @@
break; \
}
+bool has_v8r_vmsa_support(void)
+{
+ return false;
+}
+
/*
* Armv8-R supports direct access and indirect access to the MPU regions through
* registers:
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..23df2f24cb09 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -355,6 +355,8 @@ struct xen_arch_domainconfig {
uint32_t clock_frequency;
/* IN */
uint8_t arm_sci_type;
+ /* IN */
+ uint8_t v8r_el1_msa;
};
#endif /* __XEN__ || __XEN_TOOLS__ */
--
2.34.1
On 08/04/2026 2:55 pm, Luca Fancellu wrote:
> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
> index cd563cf70684..23df2f24cb09 100644
> --- a/xen/include/public/arch-arm.h
> +++ b/xen/include/public/arch-arm.h
> @@ -355,6 +355,8 @@ struct xen_arch_domainconfig {
> uint32_t clock_frequency;
> /* IN */
> uint8_t arm_sci_type;
> + /* IN */
> + uint8_t v8r_el1_msa;
> };
> #endif /* __XEN__ || __XEN_TOOLS__ */
>
This isn't ok as the singular change to the public headers. (Also, I
haven't had time to fix the other API abuses that have crept into ARM's
arch domain config)
You're introducing a new hypercall input parameter (which is fine), but
has no defines (ones private to xen/arch/arm/include/asm/domain.h are
not permitted for use in the public API), and for which there is no
input validation. Userspace can currently pass any arbitrary byte here
which will be copied into d->arch.v8r_el1_msa, not that there's any
consumer of this field I can see in the series.
Frankly, I think this series is chopped up too much. You really must
not be introducing new hypercall parameters like this without the whole
series which lets you `xl create` such a VM.
~Andrew
Hi Andrew,
> On 8 Apr 2026, at 16:40, Andrew Cooper <andrew.cooper3@citrix.com> wrote:
>
> On 08/04/2026 2:55 pm, Luca Fancellu wrote:
>> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
>> index cd563cf70684..23df2f24cb09 100644
>> --- a/xen/include/public/arch-arm.h
>> +++ b/xen/include/public/arch-arm.h
>> @@ -355,6 +355,8 @@ struct xen_arch_domainconfig {
>> uint32_t clock_frequency;
>> /* IN */
>> uint8_t arm_sci_type;
>> + /* IN */
>> + uint8_t v8r_el1_msa;
>> };
>> #endif /* __XEN__ || __XEN_TOOLS__ */
>>
>
> This isn't ok as the singular change to the public headers. (Also, I
> haven't had time to fix the other API abuses that have crept into ARM's
> arch domain config)
>
> You're introducing a new hypercall input parameter (which is fine), but
> has no defines (ones private to xen/arch/arm/include/asm/domain.h are
> not permitted for use in the public API), and for which there is no
> input validation. Userspace can currently pass any arbitrary byte here
> which will be copied into d->arch.v8r_el1_msa, not that there's any
> consumer of this field I can see in the series.
>
> Frankly, I think this series is chopped up too much. You really must
> not be introducing new hypercall parameters like this without the whole
> series which lets you `xl create` such a VM.
Thanks for this feedback, while reworking this patch I was wrongly assuming I had always
zero from the toolstack as this is not supported atm, while instead it’s not true for malicious
userspace hypercall callers.
The full branch is available at https://gitlab.com/xen-project/people/lucafancellu/xen/-/commits/r82_rebased?ref_type=heads,
but it doesn’t support domain creation by the toolstack, only by Dom0less.
For the defines, should I have something in the file xen/xen/include/public/arch-arm.h like this:
#define XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_PMSA 0
#define XEN_DOMCTL_CONFIG_ARM_V8R_EL1_MSA_VMSA 1
And check the value of config->arch.v8r_el1_msa against them in arch_sanitise_domain_config?
Cheers,
Luca
© 2016 - 2026 Red Hat, Inc.