by discovering its features. The first step is to check the PSCI version. Don't even try to do any SMCCC calls without having checked the proper PSCI version (current QEMU horribly crashes).
Probe if SMCCC_ARCH_FEATURES is available. If so, probe for SMCCC_ARCH_WORKAROUND_1 and expose its availability by setting a flag inside the percpu structure. The availability is stored per-cpu, as we might have big.LITTLE systems, where only a subset of cores need mitigations. Signed-off-by: Ralf Ramsauer <[email protected]> --- .../arch/arm-common/include/asm/percpu.h | 3 ++ .../arch/arm-common/include/asm/smccc.h | 5 +++ hypervisor/arch/arm-common/setup.c | 3 ++ hypervisor/arch/arm-common/smccc.c | 32 +++++++++++++++++++ .../arch/arm/include/asm/percpu_fields.h | 1 + .../arch/arm64/include/asm/percpu_fields.h | 1 + 6 files changed, 45 insertions(+) diff --git a/hypervisor/arch/arm-common/include/asm/percpu.h b/hypervisor/arch/arm-common/include/asm/percpu.h index b9278117..4b37e1be 100644 --- a/hypervisor/arch/arm-common/include/asm/percpu.h +++ b/hypervisor/arch/arm-common/include/asm/percpu.h @@ -15,6 +15,9 @@ #define STACK_SIZE PAGE_SIZE +#define ARM_PERCPU_FIELDS \ + bool smccc_has_workaround_1; + #define ARCH_PUBLIC_PERCPU_FIELDS \ unsigned long mpidr; \ \ diff --git a/hypervisor/arch/arm-common/include/asm/smccc.h b/hypervisor/arch/arm-common/include/asm/smccc.h index 563ab9ef..6c490fad 100644 --- a/hypervisor/arch/arm-common/include/asm/smccc.h +++ b/hypervisor/arch/arm-common/include/asm/smccc.h @@ -12,6 +12,8 @@ #define SMCCC_VERSION 0x80000000 #define SMCCC_ARCH_FEATURES 0x80000001 +#define SMCCC_ARCH_WORKAROUND_1 0x80008000 +#define SMCCC_ARCH_WORKAROUND_2 0x80007fff #define ARM_SMCCC_OWNER_MASK BIT_MASK(29, 24) #define ARM_SMCCC_OWNER_SHIFT 24 @@ -33,4 +35,7 @@ #define SMCCC_IS_CONV_64(function_id) !!(function_id & (1 << 30)) +struct trap_context; + +void smccc_discover(void); enum trap_return handle_smc(struct trap_context *ctx); diff --git a/hypervisor/arch/arm-common/setup.c b/hypervisor/arch/arm-common/setup.c index 4cc045ec..2a04cdb7 100644 --- a/hypervisor/arch/arm-common/setup.c +++ b/hypervisor/arch/arm-common/setup.c @@ -14,6 +14,7 @@ #include <jailhouse/paging.h> #include <jailhouse/processor.h> #include <asm/setup.h> +#include <asm/smccc.h> static u32 __attribute__((aligned(PAGE_SIZE))) parking_code[PAGE_SIZE / 4] = { ARM_PARKING_CODE @@ -42,5 +43,7 @@ int arm_cpu_init(struct per_cpu *cpu_data) arm_paging_vcpu_init(&root_cell.arch.mm); + smccc_discover(); + return irqchip_cpu_init(cpu_data); } diff --git a/hypervisor/arch/arm-common/smccc.c b/hypervisor/arch/arm-common/smccc.c index 211d6cd7..37c05b42 100644 --- a/hypervisor/arch/arm-common/smccc.c +++ b/hypervisor/arch/arm-common/smccc.c @@ -11,10 +11,42 @@ */ #include <jailhouse/control.h> +#include <jailhouse/printk.h> #include <asm/psci.h> #include <asm/traps.h> +#include <asm/smc.h> #include <asm/smccc.h> +void smccc_discover(void) +{ + int ret; + + ret = smc(PSCI_0_2_FN_VERSION); + + /* We need >=PSCIv1.0 for SMCCC */ + if (PSCI_VERSION_MAJOR(ret) < 1) + return; + + /* Check if PSCI supports SMCCC version call */ + ret = smc_arg1(PSCI_1_0_FN_FEATURES, SMCCC_VERSION); + if (ret != ARM_SMCCC_SUCCESS) + return; + + /* We need to have SMCCC v1.1 */ + ret = smc(SMCCC_VERSION); + if (ret != ARM_SMCCC_VERSION_1_1) + return; + + /* check if SMCCC_ARCH_FEATURES is actually available */ + ret = smc_arg1(SMCCC_ARCH_FEATURES, SMCCC_ARCH_FEATURES); + if (ret != ARM_SMCCC_SUCCESS) + return; + + ret = smc_arg1(SMCCC_ARCH_FEATURES, SMCCC_ARCH_WORKAROUND_1); + + this_cpu_data()->smccc_has_workaround_1 = ret >= ARM_SMCCC_SUCCESS; +} + static long handle_arch(struct trap_context *ctx) { u32 function_id = ctx->regs[0]; diff --git a/hypervisor/arch/arm/include/asm/percpu_fields.h b/hypervisor/arch/arm/include/asm/percpu_fields.h index a7f68e10..ae1f2fc0 100644 --- a/hypervisor/arch/arm/include/asm/percpu_fields.h +++ b/hypervisor/arch/arm/include/asm/percpu_fields.h @@ -13,6 +13,7 @@ #define NUM_ENTRY_REGS 13 #define ARCH_PERCPU_FIELDS \ + ARM_PERCPU_FIELDS \ /** Linux stack pointer, used for handover to the hypervisor. */ \ unsigned long linux_sp; \ unsigned long linux_ret; \ diff --git a/hypervisor/arch/arm64/include/asm/percpu_fields.h b/hypervisor/arch/arm64/include/asm/percpu_fields.h index 0c9f35c7..2afd32a8 100644 --- a/hypervisor/arch/arm64/include/asm/percpu_fields.h +++ b/hypervisor/arch/arm64/include/asm/percpu_fields.h @@ -11,4 +11,5 @@ */ #define ARCH_PERCPU_FIELDS \ + ARM_PERCPU_FIELDS \ unsigned long id_aa64mmfr0; -- 2.20.1 -- You received this message because you are subscribed to the Google Groups "Jailhouse" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. For more options, visit https://groups.google.com/d/optout.
