Raf*_*elo 8 c assembly arm kvm linux-kernel
在arch/arm64/kvm/hyp/vhe/switch.c 中,我们有以下代码在 arm64 上运行 EL2(虚拟化层)中的 CPU:
/* 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);
Run Code Online (Sandbox Code Playgroud)
我认为这里重要的一行是__guest_enter,它在这里定义。
我试图了解究竟__kvm_vcpu_run_vhe做了什么。它会阻止呼叫者吗?有什么作用__guest_enter?我查看了代码,它保存并恢复了一些寄存器,但我无法确定它在哪里运行 VM 代码。
是的,它会阻塞主机并开始运行客户机,直到下一个中断。
\n__guest_enter传递一个指向描述 guest\xe2\x80\x99s CPU 状态的内核结构的指针。汇编例程将该状态传输到适当的(主机)CPU 寄存器并执行将控制传输到客户的指令。
该指令名为eret,是 \xe2\x80\x98exception return\xe2\x80\x99 的缩写。这是因为从CPU的角度来看,客户程序触发了异常,内核在处理后返回给客户程序。但从内核的角度来看,它\xe2\x80\x99是被调用的guest,稍后将返回到内核!无论从哪种角度来看,这都是来宾代码开始执行的点。
在来宾执行期间的某个时刻,将发生中断,需要管理程序的干预(例如当来宾访问模拟硬件或需要注意的主机硬件时)。内核中的其他代码确保当发生这种情况时,内核根据引发的异常继续在__guest_exit_panic或处执行。__guest_exit前者触发内核恐慌,而后者将退出原因和来宾状态存储回内核结构中,并将执行返回给 的调用者__guest_enter。呼叫者可以决定从此以后如何接待客人。正如我们所看到的,一些退出是立即调度的,甚至没有通知调用者__kvm_vcpu_run_vhe;其他的则返回给调用者,并最终返回给用户空间。