In arch/arm64/kvm/hyp/vhe/switch.c, we have this code that runs the CPU in EL2 (the virtualization layer) on arm64:
/* Switch to the guest for VHE systems running in EL2 */
static int __kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
{
struct kvm_cpu_context *host_ctxt;
struct kvm_cpu_context *guest_ctxt;
u64 exit_code;
host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
host_ctxt->__hyp_running_vcpu = vcpu;
guest_ctxt = &vcpu->arch.ctxt;
sysreg_save_host_state_vhe(host_ctxt);
/*
* ARM erratum 1165522 requires us to configure both stage 1 and
* stage 2 translation for the guest context before we clear
* HCR_EL2.TGE.
*
* We have already configured the guest's stage 1 translation in
* kvm_vcpu_load_sysregs_vhe above. We must now call
* __load_guest_stage2 before __activate_traps, because
* __load_guest_stage2 configures stage 2 translation, and
* __activate_traps clear HCR_EL2.TGE (among other things).
*/
__load_guest_stage2(vcpu->arch.hw_mmu);
__activate_traps(vcpu);
__kvm_adjust_pc(vcpu);
sysreg_restore_guest_state_vhe(guest_ctxt);
__debug_switch_to_guest(vcpu);
do {
/* Jump in the fire! */
exit_code = __guest_enter(vcpu);
/* And we're baaack! */
} while (fixup_guest_exit(vcpu, &exit_code));
sysreg_save_guest_state_vhe(guest_ctxt);
__deactivate_traps(vcpu);
sysreg_restore_host_state_vhe(host_ctxt);
if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED)
__fpsimd_save_fpexc32(vcpu);
__debug_switch_to_host(vcpu);
return exit_code;
}
NOKPROBE_SYMBOL(__kvm_vcpu_run_vhe);
I think the important line here is the __guest_enter
, which is defined here.
I'm trying to understand what does __kvm_vcpu_run_vhe
do exactly. Does it block the caller? What does __guest_enter
do? I've looked at the code and it saves and then restores some registers, but I couldn't identify where it runs the VM code.
setjmp
, the routine may return an error code. Otherwise, it blocks the caller. All code does not have to have a return semantic. Co-routines, state-machines, etc. do not need to save state on a stack so that things are 'nested'. As with the Linux scheduler context switch, a Trustzone world switch andsetjmp
, this code needs to careful about registers and may not have a traditionalreturn
semantic. Note: ARM code often uses banked registers for context switch; pay attention to modes – Samhitaeret
? It returns to__kvm_vcpu_run_vhe
but then what happens? Does the code afterexit_code = __guest_enter(vcpu);
run on the guest? Where is the part that the cpu starts running guest code? – Valoiseret
doesn't return to__kvm_vcpu_run_vhe
. It branches to the address held inELR
, which presumably is set somewhere else to point to the guest code. So it really is theeret
itself that triggers the start of guest code. How we get back is a separate question - presumably the only way to get out of guest code is via exception, so that exception handler must arrange to branch back into__kvm_vcpu_run_vhe
, perhaps at the point right after the call to__guest_enter
, as if it had returned normally. – Managerial