上QQ阅读APP看书,第一时间看更新
1.3.3 访问具有副作用的寄存器
Guest在访问CPU的很多寄存器时,除了读写寄存器的内容外,一些访问会产生副作用。对于这些具有副作用的访问,CPU也需要从Guest陷入VMM,由VMM进行模拟,也就是完成副作用。
典型的比如前面提到的核间中断,对于LAPIC而言,写中断控制寄存器可能需要LAPIC向另外一个处理器发送核间中断,发送核间中断就是写中断控制寄存器这个操作的副作用。因此,当Guest访问LAPIC的中断控制寄存器时,CPU需要陷入KVM中,由KVM调用虚拟LAPIC芯片提供的函数向目标CPU发送核间中断。
再比如地址翻译,每当Guest内切换进程,Guest的内核将设置cr3寄存器指向即将运行的进程的页表。而当使用影子页表机制完成虚拟机地址(GVA)到宿主机物理地址(HPA)的映射时,我们期望物理CPU的cr3寄存器指向KVM为Guest中即将投入运行的进程准备的影子页表,因此当Guest切换进程时,CPU需要从Guest陷入KVM中,让KVM将cr3寄存器设置为指向影子页表。因此,当使用影子页表机制时,KVM需要设置VMCS中的Processor-Based VM-Execution Controls的第15位CR3-load exiting,当设置了CR3-load exiting后,每当Guest访问物理CPU的cr3寄存器时,都将触发物理CPU陷入KVM,KVM调用函数handle_cr设置cr3寄存器指向影子页表,如下代码所示。关于更进一步的详细内容,我们将在“内存虚拟化”一章探讨。
commit 6aa8b732ca01c3d7a54e93f4d701b8aabbe60fb7 [PATCH] kvm: userspace interface linux.git/drivers/kvm/vmx.c static int handle_cr(struct kvm_vcpu *vcpu, …) { u64 exit_qualification; int cr; int reg; exit_qualification = vmcs_read64(EXIT_QUALIFICATION); cr = exit_qualification & 15; reg = (exit_qualification >> 8) & 15; switch ((exit_qualification >> 4) & 3) { case 0: /* mov to cr */ switch (cr) { … case 3: vcpu_load_rsp_rip(vcpu); set_cr3(vcpu, vcpu->regs[reg]); skip_emulated_instruction(vcpu); return 1; … }