Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm64: Introduce hyp context

During __guest_enter, save and restore from a new hyp context rather
than the host context. This is preparation for separation of the hyp and
host context in nVHE.

Signed-off-by: Andrew Scull <ascull@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20200915104643.2543892-9-ascull@google.com

authored by

Andrew Scull and committed by
Marc Zyngier
b619d9aa 472fc011

+21 -9
+2 -1
arch/arm64/include/asm/kvm_hyp.h
··· 12 12 #include <asm/alternative.h> 13 13 #include <asm/sysreg.h> 14 14 15 + DECLARE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); 15 16 DECLARE_PER_CPU(unsigned long, kvm_hyp_vector); 16 17 17 18 #define read_sysreg_elx(r,nvh,vh) \ ··· 90 89 void deactivate_traps_vhe_put(void); 91 90 #endif 92 91 93 - u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt); 92 + u64 __guest_enter(struct kvm_vcpu *vcpu); 94 93 95 94 void __noreturn hyp_panic(void); 96 95 #ifdef __KVM_NVHE_HYPERVISOR__
+1
arch/arm64/kernel/image-vars.h
··· 71 71 /* Global kernel state accessed by nVHE hyp code. */ 72 72 KVM_NVHE_ALIAS(arm64_ssbd_callback_required); 73 73 KVM_NVHE_ALIAS(kvm_host_data); 74 + KVM_NVHE_ALIAS(kvm_hyp_ctxt); 74 75 KVM_NVHE_ALIAS(kvm_hyp_vector); 75 76 KVM_NVHE_ALIAS(kvm_vgic_global_state); 76 77
+10
arch/arm64/kvm/arm.c
··· 47 47 #endif 48 48 49 49 DEFINE_PER_CPU(struct kvm_host_data, kvm_host_data); 50 + DEFINE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt); 50 51 DEFINE_PER_CPU(unsigned long, kvm_hyp_vector); 51 52 static DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page); 52 53 ··· 1543 1542 1544 1543 for_each_possible_cpu(cpu) { 1545 1544 struct kvm_host_data *cpu_data; 1545 + struct kvm_cpu_context *hyp_ctxt; 1546 1546 unsigned long *vector; 1547 1547 1548 1548 cpu_data = per_cpu_ptr(&kvm_host_data, cpu); ··· 1551 1549 1552 1550 if (err) { 1553 1551 kvm_err("Cannot map host CPU state: %d\n", err); 1552 + goto out_err; 1553 + } 1554 + 1555 + hyp_ctxt = per_cpu_ptr(&kvm_hyp_ctxt, cpu); 1556 + err = create_hyp_mappings(hyp_ctxt, hyp_ctxt + 1, PAGE_HYP); 1557 + 1558 + if (err) { 1559 + kvm_err("Cannot map hyp context: %d\n", err); 1554 1560 goto out_err; 1555 1561 } 1556 1562
+5 -5
arch/arm64/kvm/hyp/entry.S
··· 57 57 .endm 58 58 59 59 /* 60 - * u64 __guest_enter(struct kvm_vcpu *vcpu, 61 - * struct kvm_cpu_context *host_ctxt); 60 + * u64 __guest_enter(struct kvm_vcpu *vcpu); 62 61 */ 63 62 SYM_FUNC_START(__guest_enter) 64 63 // x0: vcpu 65 - // x1: host context 66 - // x2-x17: clobbered by macros 64 + // x1-x17: clobbered by macros 67 65 // x29: guest context 66 + 67 + hyp_adr_this_cpu x1, kvm_hyp_ctxt, x2 68 68 69 69 // Store the host regs 70 70 save_callee_saved_regs x1 ··· 148 148 // Store the guest's sp_el0 149 149 save_sp_el0 x1, x2 150 150 151 - get_host_ctxt x2, x3 151 + hyp_adr_this_cpu x2, kvm_hyp_ctxt, x3 152 152 153 153 // Macro ptrauth_switch_to_guest format: 154 154 // ptrauth_switch_to_host(guest cxt, host cxt, tmp1, tmp2, tmp3)
+1 -1
arch/arm64/kvm/hyp/include/hyp/switch.h
··· 381 381 !esr_is_ptrauth_trap(kvm_vcpu_get_esr(vcpu))) 382 382 return false; 383 383 384 - ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; 384 + ctxt = __hyp_this_cpu_ptr(kvm_hyp_ctxt); 385 385 __ptrauth_save_key(ctxt, APIA); 386 386 __ptrauth_save_key(ctxt, APIB); 387 387 __ptrauth_save_key(ctxt, APDA);
+1 -1
arch/arm64/kvm/hyp/nvhe/switch.c
··· 209 209 210 210 do { 211 211 /* Jump in the fire! */ 212 - exit_code = __guest_enter(vcpu, host_ctxt); 212 + exit_code = __guest_enter(vcpu); 213 213 214 214 /* And we're baaack! */ 215 215 } while (fixup_guest_exit(vcpu, &exit_code));
+1 -1
arch/arm64/kvm/hyp/vhe/switch.c
··· 135 135 136 136 do { 137 137 /* Jump in the fire! */ 138 - exit_code = __guest_enter(vcpu, host_ctxt); 138 + exit_code = __guest_enter(vcpu); 139 139 140 140 /* And we're baaack! */ 141 141 } while (fixup_guest_exit(vcpu, &exit_code));