|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 3/4] xen/arm64: allow to make aarch32 support optional
Hi Grygorii,
Grygorii Strashko <grygorii_strashko@xxxxxxxx> writes:
> From: Grygorii Strashko <grygorii_strashko@xxxxxxxx>
>
> Now Arm64 AArch32 guest support is always enabled and built-in while not
> all Arm64 platforms supports AArch32 (for exmaple on Armv9A) or this
> support might not be needed (Arm64 AArch32 is used quite rarely in embedded
> systems). More over, when focusing on safety certification, AArch32 related
> code in Xen leaves a gap in terms of coverage that cannot really be
> justified in words. This leaves two options: either support it (lots of
> additional testing, requirements and documents would be needed) or compile
> it out.
>
> Hence, this patch introduces basic support to allow make Arm64
> AArch32 guest support optional. The following changes are introduced:
>
> - Introduce Kconfig option CONFIG_ARM64_AARCH32 to allow enable/disable
> Arm64 AArch32 guest support (default y)
>
> - Introduce is_aarch32_enabled() helper which accounts Arm64 HW capability
> and CONFIG_ARM64_AARCH32 setting
>
> - Introduce arm64_set_domain_type() to configure Arm64 domain type in
> unified way instead of open coding (d)->arch.type, and account
> CONFIG_ARM64_AARCH32 configuration.
>
> - toolstack: do not advertise "xen-3.0-armv7l " capability if AArch32 is
> disabled.
>
> - do not expose EL1 AArch32 support to guest in ID_AA64PFR0_EL1 reg if
> AArch32 is disabled.
>
> - Set Arm64 domain type to DOMAIN_64BIT by default.
> - the Arm Xen boot code is handling this case properly already;
> - for toolstack case the XEN_DOMCTL_set_address_size hypercall handling
> updated to forcibly configure domain type regardless of current domain
> type configuration, so toolstack behavior is unchanged.
>
> With CONFIG_ARM64_AARCH32=n the Xen will reject AArch32 guests (kernels) if
> configured by user in the following way:
> - Xen boot will fail with panic during dom0 or dom0less domains creation
> - toolstack domain creation will be rejected due to xc_dom_compat_check()
> failure.
>
> Making Arm64 AArch32 guest support open further possibilities for build
> optimizations of Arm64 AArch32 guest support code.
>
> Signed-off-by: Grygorii Strashko <grygorii_strashko@xxxxxxxx>
> ---
> changes in v2:
> - use Arm64 "cpu_has_el1_32" in all places to check if HW has AArch32 support
> - rework Arm64 XEN_DOMCTL_set_address_size hypercall handling to work with any
> initial domain type set (32bit or 64 bit)
> - fix comments related to macro parameters evaluation issues
> - do not expose EL1 AArch32 support to guest in ID_AA64PFR0_EL1 reg if
> AArch32 is disabled
>
> xen/arch/arm/Kconfig | 7 ++++
> xen/arch/arm/arm64/domain-build.c | 46 +++++++++++++++++++++++--
> xen/arch/arm/arm64/domctl.c | 16 +++++----
> xen/arch/arm/arm64/vsysreg.c | 9 +++++
> xen/arch/arm/domain.c | 9 +++++
> xen/arch/arm/domain_build.c | 21 +++--------
> xen/arch/arm/include/asm/arm32/domain.h | 12 +++++++
> xen/arch/arm/include/asm/arm64/domain.h | 23 +++++++++++++
> xen/arch/arm/setup.c | 2 +-
> 9 files changed, 119 insertions(+), 26 deletions(-)
>
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index a0c816047427..bf6dd73caf73 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -266,6 +266,13 @@ config PCI_PASSTHROUGH
> help
> This option enables PCI device passthrough
>
> +config ARM64_AARCH32
> + bool "AArch32 Guests support on on ARM64 (UNSUPPORTED)" if UNSUPPORTED
But aarch32 guests are supported... I understand that you wanted to say
"Disabling aarch32 support is unsupported". But currently this entry
reads backwards. I think it should be reworded better. But I have no
idea - how to do this.
> + depends on ARM_64
> + default y
> + help
> + This option enables AArch32 Guests on ARM64.
> +
> endmenu
>
> menu "ARM errata workaround via the alternative framework"
> diff --git a/xen/arch/arm/arm64/domain-build.c
> b/xen/arch/arm/arm64/domain-build.c
> index 3a89ee46b8c6..5951f002e3af 100644
> --- a/xen/arch/arm/arm64/domain-build.c
> +++ b/xen/arch/arm/arm64/domain-build.c
> @@ -4,13 +4,55 @@
> #include <xen/sched.h>
>
> #include <asm/domain.h>
> +#include <asm/arm64/sve.h>
> +
> +int __init arm64_set_domain_type(struct kernel_info *kinfo)
> +{
> + struct domain *d = kinfo->bd.d;
> + enum domain_type type;
> +
> + ASSERT(d);
> + ASSERT(kinfo);
I don't think there is a sense in asserting that kinfo != NULL after you
dereferenced it retrieve "d"
> +
> + type = kinfo->arch.type;
> +
> + if ( !is_aarch32_enabled() )
> + {
> + ASSERT(d->arch.type == DOMAIN_64BIT);
> +
> + if ( type == DOMAIN_32BIT )
> + {
> + const char *str = "not available";
> +
> + if ( !IS_ENABLED(CONFIG_ARM64_AARCH32) )
> + str = "disabled";
> + printk("aarch32 guests support is %s\n", str);
XENLOG_ERROR?
> + return -EINVAL;
> + }
> +
> + return 0;
> + }
> +
> + if ( is_sve_domain(d) && type == DOMAIN_32BIT )
> + {
> + printk("SVE is not available for 32-bit domain\n");
XENLOG_ERROR?
> + return -EINVAL;
> + }
> +
> + d->arch.type = type;
> +
> + return 0;
> +}
>
> #ifdef CONFIG_DOM0LESS_BOOT
> /* TODO: make arch.type generic ? */
> void __init set_domain_type(struct domain *d, struct kernel_info *kinfo)
> {
> - /* type must be set before allocate memory */
> - d->arch.type = kinfo->arch.type;
> + int rc;
> +
> + rc = arm64_set_domain_type(kinfo);
> + if ( rc < 0 )
> + panic("Unsupported guest type\n");
> }
> #endif
>
> diff --git a/xen/arch/arm/arm64/domctl.c b/xen/arch/arm/arm64/domctl.c
> index 8720d126c97d..4f0f143daef8 100644
> --- a/xen/arch/arm/arm64/domctl.c
> +++ b/xen/arch/arm/arm64/domctl.c
> @@ -13,6 +13,11 @@
> #include <asm/arm64/sve.h>
> #include <asm/cpufeature.h>
>
> +static void vcpu_switch_to_aarch32_mode(struct vcpu *v)
> +{
> + v->arch.hcr_el2 &= ~HCR_RW;
> +}
> +
> static long switch_mode(struct domain *d, enum domain_type type)
> {
> struct vcpu *v;
> @@ -21,14 +26,14 @@ static long switch_mode(struct domain *d, enum
> domain_type type)
> return -EINVAL;
> if ( domain_tot_pages(d) != 0 )
> return -EBUSY;
> - if ( d->arch.type == type )
> - return 0;
>
> d->arch.type = type;
>
> - if ( is_64bit_domain(d) )
> - for_each_vcpu(d, v)
> + for_each_vcpu(d, v)
> + if ( is_64bit_domain(d) )
Do you really need to check domain type for every vCPU? I think that
original variant was better.
> vcpu_switch_to_aarch64_mode(v);
> + else
> + vcpu_switch_to_aarch32_mode(v);
>
> return 0;
> }
> @@ -38,7 +43,7 @@ static long set_address_size(struct domain *d, uint32_t
> address_size)
> switch ( address_size )
> {
> case 32:
> - if ( !cpu_has_el1_32 )
> + if ( !is_aarch32_enabled() )
> return -EINVAL;
> /* SVE is not supported for 32 bit domain */
> if ( is_sve_domain(d) )
> @@ -58,7 +63,6 @@ long subarch_do_domctl(struct xen_domctl *domctl, struct
> domain *d,
> {
> case XEN_DOMCTL_set_address_size:
> return set_address_size(d, domctl->u.address_size.size);
> -
Stray change?
> default:
> return -ENOSYS;
> }
> diff --git a/xen/arch/arm/arm64/vsysreg.c b/xen/arch/arm/arm64/vsysreg.c
> index d14258290ff0..9f7e735c9b74 100644
> --- a/xen/arch/arm/arm64/vsysreg.c
> +++ b/xen/arch/arm/arm64/vsysreg.c
> @@ -330,6 +330,15 @@ void do_sysreg(struct cpu_user_regs *regs,
> {
> register_t guest_reg_value = domain_cpuinfo.pfr64.bits[0];
>
> + if ( !is_aarch32_enabled() )
> + {
> + /* do not expose EL1 AArch32 support if disabled */
> + register_t mask = GENMASK(ID_AA64PFR0_EL1_SHIFT + 4 - 1,
> + ID_AA64PFR0_EL1_SHIFT);
> + guest_reg_value &= ~mask;
> + guest_reg_value |= (1 << ID_AA64PFR0_EL1_SHIFT) & mask;
Why do you need to apply mask here?
> + }
> +
> if ( is_sve_domain(v->domain) )
> {
> /* 4 is the SVE field width in id_aa64pfr0_el1 */
> diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
> index 310c5789096d..544d1422a793 100644
> --- a/xen/arch/arm/domain.c
> +++ b/xen/arch/arm/domain.c
> @@ -791,6 +791,15 @@ int arch_domain_create(struct domain *d,
> d->arch.sve_vl = config->arch.sve_vl;
> #endif
>
> +#ifdef CONFIG_ARM_64
> + /*
> + * Set default Execution State to AArch64 (64bit)
> + * - Xen will reconfigure it properly at boot time
> + * - toolstack will reconfigure it properly by
> XEN_DOMCTL_set_address_size
> + */
> + d->arch.type = DOMAIN_64BIT;
> +#endif
> +
> return 0;
>
> fail:
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 47ba920fc6b0..c616127e8da5 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1873,19 +1873,6 @@ int __init construct_domain(struct domain *d, struct
> kernel_info *kinfo)
> BUG_ON(v->is_initialised);
>
> #ifdef CONFIG_ARM_64
> - /* if aarch32 mode is not supported at EL1 do not allow 32-bit domain */
> - if ( !(cpu_has_el1_32) && kinfo->arch.type == DOMAIN_32BIT )
> - {
> - printk("Platform does not support 32-bit domain\n");
> - return -EINVAL;
> - }
> -
> - if ( is_sve_domain(d) && (kinfo->arch.type == DOMAIN_32BIT) )
> - {
> - printk("SVE is not available for 32-bit domain\n");
> - return -EINVAL;
> - }
> -
> if ( is_64bit_domain(d) )
> vcpu_switch_to_aarch64_mode(v);
>
> @@ -1983,6 +1970,10 @@ static int __init construct_dom0(struct domain *d)
> if ( rc < 0 )
> return rc;
>
> + rc = arm64_set_domain_type(&kinfo);
> + if ( rc < 0 )
> + return rc;
> +
> return construct_hwdom(&kinfo, NULL);
> }
>
> @@ -1994,10 +1985,6 @@ int __init construct_hwdom(struct kernel_info *kinfo,
>
> iommu_hwdom_init(d);
>
> -#ifdef CONFIG_ARM_64
> - /* type must be set before allocate_memory */
> - d->arch.type = kinfo->arch.type;
> -#endif
> find_gnttab_region(d, kinfo);
> if ( is_domain_direct_mapped(d) )
> allocate_memory_11(d, kinfo);
> diff --git a/xen/arch/arm/include/asm/arm32/domain.h
> b/xen/arch/arm/include/asm/arm32/domain.h
> index 1bd0735c9194..30e8818ff2ae 100644
> --- a/xen/arch/arm/include/asm/arm32/domain.h
> +++ b/xen/arch/arm/include/asm/arm32/domain.h
> @@ -3,11 +3,23 @@
> #ifndef ARM_ARM32_DOMAIN_H
> #define ARM_ARM32_DOMAIN_H
>
> +struct kernel_info;
> +
> /* Arm32 always runs guests in AArch32 mode */
>
> #define is_32bit_domain(d) ((void)(d), 1)
> #define is_64bit_domain(d) ((void)(d), 0)
>
> +static inline bool is_aarch32_enabled(void)
> +{
> + return true;
> +}
> +
> +static inline int arm64_set_domain_type(struct kernel_info *kinfo)
> +{
> + return 0;
> +}
> +
> #endif /* ARM_ARM32_DOMAIN_H */
>
> /*
> diff --git a/xen/arch/arm/include/asm/arm64/domain.h
> b/xen/arch/arm/include/asm/arm64/domain.h
> index 1a2d73950bf0..bebcbc582f97 100644
> --- a/xen/arch/arm/include/asm/arm64/domain.h
> +++ b/xen/arch/arm/include/asm/arm64/domain.h
> @@ -3,6 +3,10 @@
> #ifndef ARM_ARM64_DOMAIN_H
> #define ARM_ARM64_DOMAIN_H
>
> +#include <asm/cpufeature.h>
> +
> +struct kernel_info;
> +
> /*
> * Returns true if guest execution state is AArch32
> *
> @@ -17,6 +21,25 @@
> */
> #define is_64bit_domain(d) ((d)->arch.type == DOMAIN_64BIT)
>
> +/*
> + * Arm64 declares AArch32 (32bit) Execution State support in the
> + * Processor Feature Registers (PFR0), but also can be disabled manually.
> + */
> +static inline bool is_aarch32_enabled(void)
> +{
> + return IS_ENABLED(CONFIG_ARM64_AARCH32) && cpu_has_el1_32;
> +}
> +
> +/*
> + * Set domain type from struct kernel_info which defines guest Execution
> + * State AArch32/AArch64 during regular dom0 or predefined (dom0less)
> + * domains creation .
Extra space before full stop
> + * Type must be set before allocate_memory or create vcpus.
> + *
> + * @kinfo: pointer to the kinfo structure.
> + */
> +int arm64_set_domain_type(struct kernel_info *kinfo);
> +
> #endif /* ARM_ARM64_DOMAIN_H */
>
> /*
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index bb35afe56cec..c29573f0ffec 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -530,7 +530,7 @@ static int __init init_xen_cap_info(void)
> #ifdef CONFIG_ARM_64
> safe_strcat(xen_cap_info, "xen-3.0-aarch64 ");
> #endif
> - if ( cpu_has_aarch32 )
> + if ( is_aarch32_enabled() )
> safe_strcat(xen_cap_info, "xen-3.0-armv7l ");
>
> return 0;
--
WBR, Volodymyr
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |