diff options
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 2180109d794c..b4c95a501cca 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -962,6 +962,13 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 data) | |||
962 | pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", msr_index, data); | 962 | pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", msr_index, data); |
963 | 963 | ||
964 | break; | 964 | break; |
965 | case MSR_IA32_CR_PAT: | ||
966 | if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) { | ||
967 | vmcs_write64(GUEST_IA32_PAT, data); | ||
968 | vcpu->arch.pat = data; | ||
969 | break; | ||
970 | } | ||
971 | /* Otherwise falls through to kvm_set_msr_common */ | ||
965 | default: | 972 | default: |
966 | vmx_load_host_state(vmx); | 973 | vmx_load_host_state(vmx); |
967 | msr = find_msr_entry(vmx, msr_index); | 974 | msr = find_msr_entry(vmx, msr_index); |
@@ -1181,12 +1188,13 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
1181 | #ifdef CONFIG_X86_64 | 1188 | #ifdef CONFIG_X86_64 |
1182 | min |= VM_EXIT_HOST_ADDR_SPACE_SIZE; | 1189 | min |= VM_EXIT_HOST_ADDR_SPACE_SIZE; |
1183 | #endif | 1190 | #endif |
1184 | opt = 0; | 1191 | opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT; |
1185 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS, | 1192 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS, |
1186 | &_vmexit_control) < 0) | 1193 | &_vmexit_control) < 0) |
1187 | return -EIO; | 1194 | return -EIO; |
1188 | 1195 | ||
1189 | min = opt = 0; | 1196 | min = 0; |
1197 | opt = VM_ENTRY_LOAD_IA32_PAT; | ||
1190 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS, | 1198 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS, |
1191 | &_vmentry_control) < 0) | 1199 | &_vmentry_control) < 0) |
1192 | return -EIO; | 1200 | return -EIO; |
@@ -2092,8 +2100,9 @@ static void vmx_disable_intercept_for_msr(struct page *msr_bitmap, u32 msr) | |||
2092 | */ | 2100 | */ |
2093 | static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | 2101 | static int vmx_vcpu_setup(struct vcpu_vmx *vmx) |
2094 | { | 2102 | { |
2095 | u32 host_sysenter_cs; | 2103 | u32 host_sysenter_cs, msr_low, msr_high; |
2096 | u32 junk; | 2104 | u32 junk; |
2105 | u64 host_pat; | ||
2097 | unsigned long a; | 2106 | unsigned long a; |
2098 | struct descriptor_table dt; | 2107 | struct descriptor_table dt; |
2099 | int i; | 2108 | int i; |
@@ -2181,6 +2190,20 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx) | |||
2181 | rdmsrl(MSR_IA32_SYSENTER_EIP, a); | 2190 | rdmsrl(MSR_IA32_SYSENTER_EIP, a); |
2182 | vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */ | 2191 | vmcs_writel(HOST_IA32_SYSENTER_EIP, a); /* 22.2.3 */ |
2183 | 2192 | ||
2193 | if (vmcs_config.vmexit_ctrl & VM_EXIT_LOAD_IA32_PAT) { | ||
2194 | rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high); | ||
2195 | host_pat = msr_low | ((u64) msr_high << 32); | ||
2196 | vmcs_write64(HOST_IA32_PAT, host_pat); | ||
2197 | } | ||
2198 | if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) { | ||
2199 | rdmsr(MSR_IA32_CR_PAT, msr_low, msr_high); | ||
2200 | host_pat = msr_low | ((u64) msr_high << 32); | ||
2201 | /* Write the default value follow host pat */ | ||
2202 | vmcs_write64(GUEST_IA32_PAT, host_pat); | ||
2203 | /* Keep arch.pat sync with GUEST_IA32_PAT */ | ||
2204 | vmx->vcpu.arch.pat = host_pat; | ||
2205 | } | ||
2206 | |||
2184 | for (i = 0; i < NR_VMX_MSR; ++i) { | 2207 | for (i = 0; i < NR_VMX_MSR; ++i) { |
2185 | u32 index = vmx_msr_index[i]; | 2208 | u32 index = vmx_msr_index[i]; |
2186 | u32 data_low, data_high; | 2209 | u32 data_low, data_high; |