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

KVM: arm64: Stop save/restoring host tpidr_el1 on VHE

Now that a VHE host uses tpidr_el2 for the cpu offset we no longer
need KVM to save/restore tpidr_el1. Move this from the 'common' code
into the non-vhe code. While we're at it, on VHE we don't need to
save the ELR or SPSR as kernel_entry in entry.S will have pushed these
onto the kernel stack, and will restore them from there. Move these
to the non-vhe code as we need them to get back to the host.

Finally remove the always-copy-tpidr we hid in the stage2 setup
code, cpufeature's enable callback will do this for VHE, we only
need KVM to do it for non-vhe. Add the copy into kvm-init instead.

Signed-off-by: James Morse <james.morse@arm.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>

authored by

James Morse and committed by
Catalin Marinas
1f742679 6d99b689

+12 -11
+4
arch/arm64/kvm/hyp-init.S
··· 120 120 kern_hyp_va x2 121 121 msr vbar_el2, x2 122 122 123 + /* copy tpidr_el1 into tpidr_el2 for use by HYP */ 124 + mrs x1, tpidr_el1 125 + msr tpidr_el2, x1 126 + 123 127 /* Hello, World! */ 124 128 eret 125 129 ENDPROC(__kvm_hyp_init)
-3
arch/arm64/kvm/hyp/s2-setup.c
··· 86 86 87 87 write_sysreg(val, vtcr_el2); 88 88 89 - /* copy tpidr_el1 into tpidr_el2 for use by HYP */ 90 - write_sysreg(read_sysreg(tpidr_el1), tpidr_el2); 91 - 92 89 return parange; 93 90 }
+8 -8
arch/arm64/kvm/hyp/sysreg-sr.c
··· 27 27 /* 28 28 * Non-VHE: Both host and guest must save everything. 29 29 * 30 - * VHE: Host must save tpidr*_el[01], actlr_el1, mdscr_el1, sp0, pc, 31 - * pstate, and guest must save everything. 30 + * VHE: Host must save tpidr*_el0, actlr_el1, mdscr_el1, sp_el0, 31 + * and guest must save everything. 32 32 */ 33 33 34 34 static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) ··· 36 36 ctxt->sys_regs[ACTLR_EL1] = read_sysreg(actlr_el1); 37 37 ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0); 38 38 ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0); 39 - ctxt->sys_regs[TPIDR_EL1] = read_sysreg(tpidr_el1); 40 39 ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1); 41 40 ctxt->gp_regs.regs.sp = read_sysreg(sp_el0); 42 - ctxt->gp_regs.regs.pc = read_sysreg_el2(elr); 43 - ctxt->gp_regs.regs.pstate = read_sysreg_el2(spsr); 44 41 } 45 42 46 43 static void __hyp_text __sysreg_save_state(struct kvm_cpu_context *ctxt) ··· 59 62 ctxt->sys_regs[AMAIR_EL1] = read_sysreg_el1(amair); 60 63 ctxt->sys_regs[CNTKCTL_EL1] = read_sysreg_el1(cntkctl); 61 64 ctxt->sys_regs[PAR_EL1] = read_sysreg(par_el1); 65 + ctxt->sys_regs[TPIDR_EL1] = read_sysreg(tpidr_el1); 62 66 63 67 ctxt->gp_regs.sp_el1 = read_sysreg(sp_el1); 64 68 ctxt->gp_regs.elr_el1 = read_sysreg_el1(elr); 65 69 ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg_el1(spsr); 70 + ctxt->gp_regs.regs.pc = read_sysreg_el2(elr); 71 + ctxt->gp_regs.regs.pstate = read_sysreg_el2(spsr); 66 72 } 67 73 68 74 static hyp_alternate_select(__sysreg_call_save_host_state, ··· 89 89 write_sysreg(ctxt->sys_regs[ACTLR_EL1], actlr_el1); 90 90 write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0); 91 91 write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0); 92 - write_sysreg(ctxt->sys_regs[TPIDR_EL1], tpidr_el1); 93 92 write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1); 94 93 write_sysreg(ctxt->gp_regs.regs.sp, sp_el0); 95 - write_sysreg_el2(ctxt->gp_regs.regs.pc, elr); 96 - write_sysreg_el2(ctxt->gp_regs.regs.pstate, spsr); 97 94 } 98 95 99 96 static void __hyp_text __sysreg_restore_state(struct kvm_cpu_context *ctxt) ··· 112 115 write_sysreg_el1(ctxt->sys_regs[AMAIR_EL1], amair); 113 116 write_sysreg_el1(ctxt->sys_regs[CNTKCTL_EL1], cntkctl); 114 117 write_sysreg(ctxt->sys_regs[PAR_EL1], par_el1); 118 + write_sysreg(ctxt->sys_regs[TPIDR_EL1], tpidr_el1); 115 119 116 120 write_sysreg(ctxt->gp_regs.sp_el1, sp_el1); 117 121 write_sysreg_el1(ctxt->gp_regs.elr_el1, elr); 118 122 write_sysreg_el1(ctxt->gp_regs.spsr[KVM_SPSR_EL1],spsr); 123 + write_sysreg_el2(ctxt->gp_regs.regs.pc, elr); 124 + write_sysreg_el2(ctxt->gp_regs.regs.pstate, spsr); 119 125 } 120 126 121 127 static hyp_alternate_select(__sysreg_call_restore_host_state,