]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
arm64: KVM: Handle guest's ARCH_WORKAROUND_2 requests
authorMarc Zyngier <marc.zyngier@arm.com>
Tue, 29 May 2018 12:11:17 +0000 (13:11 +0100)
committerCatalin Marinas <catalin.marinas@arm.com>
Thu, 31 May 2018 17:00:57 +0000 (18:00 +0100)
In order to forward the guest's ARCH_WORKAROUND_2 calls to EL3,
add a small(-ish) sequence to handle it at EL2. Special care must
be taken to track the state of the guest itself by updating the
workaround flags. We also rely on patching to enable calls into
the firmware.

Note that since we need to execute branches, this always executes
after the Spectre-v2 mitigation has been applied.

Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/kernel/asm-offsets.c
arch/arm64/kvm/hyp/hyp-entry.S

index 5bdda651bd0507f5c2fa96b85ae8309ff2692a0b..323aeb5f2fe62c743d1855a0968a836c5f8e6094 100644 (file)
@@ -136,6 +136,7 @@ int main(void)
 #ifdef CONFIG_KVM_ARM_HOST
   DEFINE(VCPU_CONTEXT,         offsetof(struct kvm_vcpu, arch.ctxt));
   DEFINE(VCPU_FAULT_DISR,      offsetof(struct kvm_vcpu, arch.fault.disr_el1));
+  DEFINE(VCPU_WORKAROUND_FLAGS,        offsetof(struct kvm_vcpu, arch.workaround_flags));
   DEFINE(CPU_GP_REGS,          offsetof(struct kvm_cpu_context, gp_regs));
   DEFINE(CPU_USER_PT_REGS,     offsetof(struct kvm_regs, regs));
   DEFINE(CPU_FP_REGS,          offsetof(struct kvm_regs, fp_regs));
index bffece27b5c109061ef801277319f6b0a2d0e790..05d8369790321e48f895eb4e5b802c7b3fdaf16a 100644 (file)
@@ -106,8 +106,44 @@ el1_hvc_guest:
         */
        ldr     x1, [sp]                                // Guest's x0
        eor     w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1
+       cbz     w1, wa_epilogue
+
+       /* ARM_SMCCC_ARCH_WORKAROUND_2 handling */
+       eor     w1, w1, #(ARM_SMCCC_ARCH_WORKAROUND_1 ^ \
+                         ARM_SMCCC_ARCH_WORKAROUND_2)
        cbnz    w1, el1_trap
-       mov     x0, x1
+
+#ifdef CONFIG_ARM64_SSBD
+alternative_cb arm64_enable_wa2_handling
+       b       wa2_end
+alternative_cb_end
+       get_vcpu_ptr    x2, x0
+       ldr     x0, [x2, #VCPU_WORKAROUND_FLAGS]
+
+       // Sanitize the argument and update the guest flags
+       ldr     x1, [sp, #8]                    // Guest's x1
+       clz     w1, w1                          // Murphy's device:
+       lsr     w1, w1, #5                      // w1 = !!w1 without using
+       eor     w1, w1, #1                      // the flags...
+       bfi     x0, x1, #VCPU_WORKAROUND_2_FLAG_SHIFT, #1
+       str     x0, [x2, #VCPU_WORKAROUND_FLAGS]
+
+       /* Check that we actually need to perform the call */
+       hyp_ldr_this_cpu x0, arm64_ssbd_callback_required, x2
+       cbz     x0, wa2_end
+
+       mov     w0, #ARM_SMCCC_ARCH_WORKAROUND_2
+       smc     #0
+
+       /* Don't leak data from the SMC call */
+       mov     x3, xzr
+wa2_end:
+       mov     x2, xzr
+       mov     x1, xzr
+#endif
+
+wa_epilogue:
+       mov     x0, xzr
        add     sp, sp, #16
        eret