KVM: VMX: Fix host userspace gsbase corruption

We now use load_gs_index() to load gs safely; unfortunately this also
changes MSR_KERNEL_GS_BASE, which we managed separately. This resulted
in confusion and breakage running 32-bit host userspace on a 64-bit kernel.

Fix by
- saving guest MSR_KERNEL_GS_BASE before we we reload the host's gs
- doing the host save/load unconditionally, instead of only when in guest
long mode

Things can be cleaned up further, but this is the minmal fix for now.

Signed-off-by: Avi Kivity <avi@redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

authored by Avi Kivity and committed by Marcelo Tosatti c8770e7b 0a77fe4c

+7 -8
+7 -8
arch/x86/kvm/vmx.c
··· 821 821 #endif 822 822 823 823 #ifdef CONFIG_X86_64 824 - if (is_long_mode(&vmx->vcpu)) { 825 - rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); 824 + rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); 825 + if (is_long_mode(&vmx->vcpu)) 826 826 wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); 827 - } 828 827 #endif 829 828 for (i = 0; i < vmx->save_nmsrs; ++i) 830 829 kvm_set_shared_msr(vmx->guest_msrs[i].index, ··· 838 839 839 840 ++vmx->vcpu.stat.host_state_reload; 840 841 vmx->host_state.loaded = 0; 842 + #ifdef CONFIG_X86_64 843 + if (is_long_mode(&vmx->vcpu)) 844 + rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); 845 + #endif 841 846 if (vmx->host_state.gs_ldt_reload_needed) { 842 847 kvm_load_ldt(vmx->host_state.ldt_sel); 843 848 #ifdef CONFIG_X86_64 844 849 load_gs_index(vmx->host_state.gs_sel); 845 - wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs); 846 850 #else 847 851 loadsegment(gs, vmx->host_state.gs_sel); 848 852 #endif ··· 854 852 loadsegment(fs, vmx->host_state.fs_sel); 855 853 reload_tss(); 856 854 #ifdef CONFIG_X86_64 857 - if (is_long_mode(&vmx->vcpu)) { 858 - rdmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); 859 - wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); 860 - } 855 + wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); 861 856 #endif 862 857 if (current_thread_info()->status & TS_USEDFPU) 863 858 clts();