KVM: nVMX: Set segment infomation of L1 when L2 exits
When L2 exits to L1, segment infomations of L1 are not set correctly. According to Intel SDM 27.5.2(Loading Host Segment and Descriptor Table Registers), segment base/limit/access right of L1 should be set to some designed value when L2 exits to L1. This patch fixes this. Signed-off-by: Arthur Chunqi Li <yzt356@gmail.com> Reviewed-by: Gleb Natapov <gnatapov@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Родитель
e04c5d76b0
Коммит
21feb4eb64
|
@ -7969,6 +7969,8 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
|
|||
static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
|
||||
struct vmcs12 *vmcs12)
|
||||
{
|
||||
struct kvm_segment seg;
|
||||
|
||||
if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER)
|
||||
vcpu->arch.efer = vmcs12->host_ia32_efer;
|
||||
else if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
|
||||
|
@ -8022,16 +8024,6 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
|
|||
vmcs_writel(GUEST_SYSENTER_EIP, vmcs12->host_ia32_sysenter_eip);
|
||||
vmcs_writel(GUEST_IDTR_BASE, vmcs12->host_idtr_base);
|
||||
vmcs_writel(GUEST_GDTR_BASE, vmcs12->host_gdtr_base);
|
||||
vmcs_writel(GUEST_TR_BASE, vmcs12->host_tr_base);
|
||||
vmcs_writel(GUEST_GS_BASE, vmcs12->host_gs_base);
|
||||
vmcs_writel(GUEST_FS_BASE, vmcs12->host_fs_base);
|
||||
vmcs_write16(GUEST_ES_SELECTOR, vmcs12->host_es_selector);
|
||||
vmcs_write16(GUEST_CS_SELECTOR, vmcs12->host_cs_selector);
|
||||
vmcs_write16(GUEST_SS_SELECTOR, vmcs12->host_ss_selector);
|
||||
vmcs_write16(GUEST_DS_SELECTOR, vmcs12->host_ds_selector);
|
||||
vmcs_write16(GUEST_FS_SELECTOR, vmcs12->host_fs_selector);
|
||||
vmcs_write16(GUEST_GS_SELECTOR, vmcs12->host_gs_selector);
|
||||
vmcs_write16(GUEST_TR_SELECTOR, vmcs12->host_tr_selector);
|
||||
|
||||
if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_PAT)
|
||||
vmcs_write64(GUEST_IA32_PAT, vmcs12->host_ia32_pat);
|
||||
|
@ -8039,6 +8031,52 @@ static void load_vmcs12_host_state(struct kvm_vcpu *vcpu,
|
|||
vmcs_write64(GUEST_IA32_PERF_GLOBAL_CTRL,
|
||||
vmcs12->host_ia32_perf_global_ctrl);
|
||||
|
||||
/* Set L1 segment info according to Intel SDM
|
||||
27.5.2 Loading Host Segment and Descriptor-Table Registers */
|
||||
seg = (struct kvm_segment) {
|
||||
.base = 0,
|
||||
.limit = 0xFFFFFFFF,
|
||||
.selector = vmcs12->host_cs_selector,
|
||||
.type = 11,
|
||||
.present = 1,
|
||||
.s = 1,
|
||||
.g = 1
|
||||
};
|
||||
if (vmcs12->vm_exit_controls & VM_EXIT_HOST_ADDR_SPACE_SIZE)
|
||||
seg.l = 1;
|
||||
else
|
||||
seg.db = 1;
|
||||
vmx_set_segment(vcpu, &seg, VCPU_SREG_CS);
|
||||
seg = (struct kvm_segment) {
|
||||
.base = 0,
|
||||
.limit = 0xFFFFFFFF,
|
||||
.type = 3,
|
||||
.present = 1,
|
||||
.s = 1,
|
||||
.db = 1,
|
||||
.g = 1
|
||||
};
|
||||
seg.selector = vmcs12->host_ds_selector;
|
||||
vmx_set_segment(vcpu, &seg, VCPU_SREG_DS);
|
||||
seg.selector = vmcs12->host_es_selector;
|
||||
vmx_set_segment(vcpu, &seg, VCPU_SREG_ES);
|
||||
seg.selector = vmcs12->host_ss_selector;
|
||||
vmx_set_segment(vcpu, &seg, VCPU_SREG_SS);
|
||||
seg.selector = vmcs12->host_fs_selector;
|
||||
seg.base = vmcs12->host_fs_base;
|
||||
vmx_set_segment(vcpu, &seg, VCPU_SREG_FS);
|
||||
seg.selector = vmcs12->host_gs_selector;
|
||||
seg.base = vmcs12->host_gs_base;
|
||||
vmx_set_segment(vcpu, &seg, VCPU_SREG_GS);
|
||||
seg = (struct kvm_segment) {
|
||||
.base = 0,
|
||||
.limit = 0x67,
|
||||
.selector = vmcs12->host_tr_selector,
|
||||
.type = 11,
|
||||
.present = 1
|
||||
};
|
||||
vmx_set_segment(vcpu, &seg, VCPU_SREG_TR);
|
||||
|
||||
kvm_set_dr(vcpu, 7, 0x400);
|
||||
vmcs_write64(GUEST_IA32_DEBUGCTL, 0);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче