Introduce generation of the riscv,isa string passed to the guest via the Device Tree riscv,isa property.
The following changes are introduced: - According to the RISC-V privileged specification, M-mode software controls the XLEN value used by S-mode and U-mode. For RV64 harts, the SXL and UXL fields of the mstatus register are WARL fields that define the XLEN for S-mode and U-mode. The XLEN value is provided by M-mode software (OpenSBI in the case of Xen) via the riscv,isa DT property. Introduce and initialize an xlen variable when parsing the host riscv,isa string in riscv_isa_parse_string(). - Introduce the guest_isa_str variable to store the riscv,isa string generated for a guest domain during riscv,isa property parsing. Update match_isa_ext() to populate guest_isa_str accordingly. - Introduce guest_unsupp_bmp and guest_unsupp_exts[] to filter out ISA extensions that should not be exposed to guests. For example, FPU-related extensions are currently not supported for guests (at the moment) and are therefore removed from the guest riscv,isa string. Signed-off-by: Oleksii Kurochko <[email protected]> --- xen/arch/riscv/cpufeature.c | 33 +++++++++++++++++++++++++ xen/arch/riscv/include/asm/cpufeature.h | 2 ++ 2 files changed, 35 insertions(+) diff --git a/xen/arch/riscv/cpufeature.c b/xen/arch/riscv/cpufeature.c index 987d36dc7eee..d7e483603dbe 100644 --- a/xen/arch/riscv/cpufeature.c +++ b/xen/arch/riscv/cpufeature.c @@ -38,6 +38,8 @@ struct riscv_isa_ext_data { /* Host ISA bitmap */ static __ro_after_init DECLARE_BITMAP(riscv_isa, RISCV_ISA_EXT_MAX); +static __ro_after_init unsigned int xlen; + static int __init dt_get_cpuid_from_node(const struct dt_device_node *cpu, unsigned long *dt_cpuid) { @@ -160,6 +162,19 @@ static const struct riscv_isa_ext_data __initconst required_extensions[] = { RISCV_ISA_EXT_DATA(svpbmt), }; +static const unsigned int __initconst guest_unsupp_exts[] = { + RISCV_ISA_EXT_f, + RISCV_ISA_EXT_d, + RISCV_ISA_EXT_h, + RISCV_ISA_EXT_q, + RISCV_ISA_EXT_v, +}; + +static __ro_after_init DECLARE_BITMAP(guest_unsupp_bmp, RISCV_ISA_EXT_MAX); + +#define MAX_GUEST_ISA_STR_LEN 256 +char guest_isa_str[MAX_GUEST_ISA_STR_LEN]; + static bool __init is_lowercase_extension_name(const char *str) { /* @@ -193,6 +208,15 @@ static void __init match_isa_ext(const char *name, const char *name_end, !memcmp(name, ext->name, name_end - name) ) { __set_bit(ext->id, bitmap); + + if ( riscv_isa_extension_available(guest_unsupp_bmp, ext->id) ) + break; + + if ( ext->id >= RISCV_ISA_EXT_BASE ) + safe_strcat(guest_isa_str, "_"); + + safe_strcat(guest_isa_str, ext->name); + break; } } @@ -207,13 +231,17 @@ static int __init riscv_isa_parse_string(const char *isa, #if defined(CONFIG_RISCV_32) if ( isa[2] != '3' && isa[3] != '2' ) return -EINVAL; + xlen = 32; #elif defined(CONFIG_RISCV_64) if ( isa[2] != '6' && isa[3] != '4' ) return -EINVAL; + xlen = 64; #else # error "unsupported RISC-V bitness" #endif + snprintf(guest_isa_str, sizeof(guest_isa_str), "rv%d", xlen); + /* * In unpriv. specification (*_20240411) is mentioned the following: * (1) A RISC-V ISA is defined as a base integer ISA, which must be @@ -487,6 +515,11 @@ void __init riscv_fill_hwcap(void) bool all_extns_available = true; struct trap_info trap; + for ( i = 0; i < ARRAY_SIZE(guest_unsupp_exts); i++ ) + { + __set_bit(guest_unsupp_exts[i], guest_unsupp_bmp); + } + riscv_fill_hwcap_from_isa_string(); if ( bitmap_empty(riscv_isa, RISCV_ISA_EXT_MAX) ) diff --git a/xen/arch/riscv/include/asm/cpufeature.h b/xen/arch/riscv/include/asm/cpufeature.h index ef02a3e26d2c..aabbbf0c2cc3 100644 --- a/xen/arch/riscv/include/asm/cpufeature.h +++ b/xen/arch/riscv/include/asm/cpufeature.h @@ -43,6 +43,8 @@ enum riscv_isa_ext_id { RISCV_ISA_EXT_MAX }; +extern char guest_isa_str[]; + void riscv_fill_hwcap(void); bool riscv_isa_extension_available(const unsigned long *isa_bitmap, -- 2.53.0
