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.

Reply via email to