了解arm64的kvm_vcpu_run_vhe函数

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 代码。

use*_*170 4

是的,它会阻塞主机并开始运行客户机,直到下一个中​​断。

\n

__guest_enter传递一个指向描述 guest\xe2\x80\x99s CPU 状态的内核结构的指针。汇编例程将该状态传输到适当的(主机)CPU 寄存器并执行将控制传输到客户的指令。

\n

该指令名为eret,是 \xe2\x80\x98exception return\xe2\x80\x99 的缩写。这是因为从CPU的角度来看,客户程序触发了异常,内核在处理后返回给客户程序。但从内核的角度来看,它\xe2\x80\x99是被调用的guest,稍后将返回到内核!无论从哪种角度来看,这都是来宾代码开始执行的点。

\n

在来宾执行期间的某个时刻,将发生中断,需要管理程序的干预(例如当来宾访问模拟硬件或需要注意的主机硬件时)。内核中的其他代码确保当发生这种情况时,内核根据引发的异常继续在__guest_exit_panic或处执行。__guest_exit前者触发内核恐慌,而后者将退出原因和来宾状态存储回内核结构中,并将执行返回给 的调用者__guest_enter。呼叫者可以决定从此以后如何接待客人。正如我们所看到的,一些退出是立即调度的,甚至没有通知调用者__kvm_vcpu_run_vhe;其他的则返回给调用者,并最终返回给用户空间。

\n