From 8925eb5647cee743c9bc6aa4bd21354a97fee1a2 Mon Sep 17 00:00:00 2001 From: Zide Chen Date: Fri, 13 Jul 2018 11:27:30 -0700 Subject: [PATCH] hv: set guest segment base to zero if VCPU does not start in real mode In non real mode, for segment registers other than CS, the guest segment base should be zero, otherwise the guest's segmentation results in wrong effective addresses. Linux boots with the wrong segment registers (base address in hidden part), because it happens that it assigns the segment registers before using any of them, which effectively reloads the segment base addresses from GDT. --- hypervisor/arch/x86/vmx.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/hypervisor/arch/x86/vmx.c b/hypervisor/arch/x86/vmx.c index bd39d2e85..c17673f92 100644 --- a/hypervisor/arch/x86/vmx.c +++ b/hypervisor/arch/x86/vmx.c @@ -872,21 +872,26 @@ static void init_guest_state(struct vcpu *vcpu) pr_dbg("VMX_GUEST_GS_ATTR: 0x%x ", value32); /* Base */ - value = 0UL; + if (vcpu_mode == CPU_MODE_REAL) { + value = es << 4; + } else { + value = 0UL; + } + field = VMX_GUEST_ES_BASE; - exec_vmwrite(field, es << 4); + exec_vmwrite(field, value); pr_dbg("VMX_GUEST_ES_BASE: 0x%016llx ", value); field = VMX_GUEST_SS_BASE; - exec_vmwrite(field, ss << 4); + exec_vmwrite(field, value); pr_dbg("VMX_GUEST_SS_BASE: 0x%016llx ", value); field = VMX_GUEST_DS_BASE; - exec_vmwrite(field, ds << 4); + exec_vmwrite(field, value); pr_dbg("VMX_GUEST_DS_BASE: 0x%016llx ", value); field = VMX_GUEST_FS_BASE; - exec_vmwrite(field, fs << 4); + exec_vmwrite(field, value); pr_dbg("VMX_GUEST_FS_BASE: 0x%016llx ", value); field = VMX_GUEST_GS_BASE; - exec_vmwrite(field, gs << 4); + exec_vmwrite(field, value); pr_dbg("VMX_GUEST_GS_BASE: 0x%016llx ", value); /***************************************************/