diff options
author | Liu, Jinsong <jinsong.liu@intel.com> | 2014-02-24 05:55:46 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-02-24 06:14:00 -0500 |
commit | da8999d31818fdc8508d527ba3aac2e128005af4 (patch) | |
tree | ca2f32a5f2aeaf957803e189ad7a264be63ef225 | |
parent | 56c103ec040b1944c8866f79aa768265c0dd2986 (diff) |
KVM: x86: Intel MPX vmx and msr handle
From caddc009a6d2019034af8f2346b2fd37a81608d0 Mon Sep 17 00:00:00 2001
From: Liu Jinsong <jinsong.liu@intel.com>
Date: Mon, 24 Feb 2014 18:11:11 +0800
Subject: [PATCH v5 1/3] KVM: x86: Intel MPX vmx and msr handle
This patch handle vmx and msr of Intel MPX feature.
Signed-off-by: Xudong Hao <xudong.hao@intel.com>
Signed-off-by: Liu Jinsong <jinsong.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/include/asm/kvm_host.h | 1 | ||||
-rw-r--r-- | arch/x86/include/asm/vmx.h | 4 | ||||
-rw-r--r-- | arch/x86/include/uapi/asm/msr-index.h | 1 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 18 |
4 files changed, 22 insertions, 2 deletions
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 0ffe7140d630..e714f8c08ccf 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h | |||
@@ -764,6 +764,7 @@ struct kvm_x86_ops { | |||
764 | struct x86_instruction_info *info, | 764 | struct x86_instruction_info *info, |
765 | enum x86_intercept_stage stage); | 765 | enum x86_intercept_stage stage); |
766 | void (*handle_external_intr)(struct kvm_vcpu *vcpu); | 766 | void (*handle_external_intr)(struct kvm_vcpu *vcpu); |
767 | bool (*mpx_supported)(void); | ||
767 | }; | 768 | }; |
768 | 769 | ||
769 | struct kvm_arch_async_pf { | 770 | struct kvm_arch_async_pf { |
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h index 2067264fb7f5..7004d21e6219 100644 --- a/arch/x86/include/asm/vmx.h +++ b/arch/x86/include/asm/vmx.h | |||
@@ -85,6 +85,7 @@ | |||
85 | #define VM_EXIT_SAVE_IA32_EFER 0x00100000 | 85 | #define VM_EXIT_SAVE_IA32_EFER 0x00100000 |
86 | #define VM_EXIT_LOAD_IA32_EFER 0x00200000 | 86 | #define VM_EXIT_LOAD_IA32_EFER 0x00200000 |
87 | #define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000 | 87 | #define VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000 |
88 | #define VM_EXIT_CLEAR_BNDCFGS 0x00800000 | ||
88 | 89 | ||
89 | #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff | 90 | #define VM_EXIT_ALWAYSON_WITHOUT_TRUE_MSR 0x00036dff |
90 | 91 | ||
@@ -95,6 +96,7 @@ | |||
95 | #define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000 | 96 | #define VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000 |
96 | #define VM_ENTRY_LOAD_IA32_PAT 0x00004000 | 97 | #define VM_ENTRY_LOAD_IA32_PAT 0x00004000 |
97 | #define VM_ENTRY_LOAD_IA32_EFER 0x00008000 | 98 | #define VM_ENTRY_LOAD_IA32_EFER 0x00008000 |
99 | #define VM_ENTRY_LOAD_BNDCFGS 0x00010000 | ||
98 | 100 | ||
99 | #define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff | 101 | #define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff |
100 | 102 | ||
@@ -174,6 +176,8 @@ enum vmcs_field { | |||
174 | GUEST_PDPTR2_HIGH = 0x0000280f, | 176 | GUEST_PDPTR2_HIGH = 0x0000280f, |
175 | GUEST_PDPTR3 = 0x00002810, | 177 | GUEST_PDPTR3 = 0x00002810, |
176 | GUEST_PDPTR3_HIGH = 0x00002811, | 178 | GUEST_PDPTR3_HIGH = 0x00002811, |
179 | GUEST_BNDCFGS = 0x00002812, | ||
180 | GUEST_BNDCFGS_HIGH = 0x00002813, | ||
177 | HOST_IA32_PAT = 0x00002c00, | 181 | HOST_IA32_PAT = 0x00002c00, |
178 | HOST_IA32_PAT_HIGH = 0x00002c01, | 182 | HOST_IA32_PAT_HIGH = 0x00002c01, |
179 | HOST_IA32_EFER = 0x00002c02, | 183 | HOST_IA32_EFER = 0x00002c02, |
diff --git a/arch/x86/include/uapi/asm/msr-index.h b/arch/x86/include/uapi/asm/msr-index.h index c19fc60ff062..ed821ed45eb6 100644 --- a/arch/x86/include/uapi/asm/msr-index.h +++ b/arch/x86/include/uapi/asm/msr-index.h | |||
@@ -295,6 +295,7 @@ | |||
295 | #define MSR_SMI_COUNT 0x00000034 | 295 | #define MSR_SMI_COUNT 0x00000034 |
296 | #define MSR_IA32_FEATURE_CONTROL 0x0000003a | 296 | #define MSR_IA32_FEATURE_CONTROL 0x0000003a |
297 | #define MSR_IA32_TSC_ADJUST 0x0000003b | 297 | #define MSR_IA32_TSC_ADJUST 0x0000003b |
298 | #define MSR_IA32_BNDCFGS 0x00000d90 | ||
298 | 299 | ||
299 | #define FEATURE_CONTROL_LOCKED (1<<0) | 300 | #define FEATURE_CONTROL_LOCKED (1<<0) |
300 | #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) | 301 | #define FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1<<1) |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index a06f101ef64b..e4e4b50f57e6 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -441,6 +441,7 @@ struct vcpu_vmx { | |||
441 | #endif | 441 | #endif |
442 | int gs_ldt_reload_needed; | 442 | int gs_ldt_reload_needed; |
443 | int fs_reload_needed; | 443 | int fs_reload_needed; |
444 | u64 msr_host_bndcfgs; | ||
444 | } host_state; | 445 | } host_state; |
445 | struct { | 446 | struct { |
446 | int vm86_active; | 447 | int vm86_active; |
@@ -1710,6 +1711,8 @@ static void vmx_save_host_state(struct kvm_vcpu *vcpu) | |||
1710 | if (is_long_mode(&vmx->vcpu)) | 1711 | if (is_long_mode(&vmx->vcpu)) |
1711 | wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); | 1712 | wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_guest_kernel_gs_base); |
1712 | #endif | 1713 | #endif |
1714 | if (boot_cpu_has(X86_FEATURE_MPX)) | ||
1715 | rdmsrl(MSR_IA32_BNDCFGS, vmx->host_state.msr_host_bndcfgs); | ||
1713 | for (i = 0; i < vmx->save_nmsrs; ++i) | 1716 | for (i = 0; i < vmx->save_nmsrs; ++i) |
1714 | kvm_set_shared_msr(vmx->guest_msrs[i].index, | 1717 | kvm_set_shared_msr(vmx->guest_msrs[i].index, |
1715 | vmx->guest_msrs[i].data, | 1718 | vmx->guest_msrs[i].data, |
@@ -1747,6 +1750,8 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) | |||
1747 | #ifdef CONFIG_X86_64 | 1750 | #ifdef CONFIG_X86_64 |
1748 | wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); | 1751 | wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); |
1749 | #endif | 1752 | #endif |
1753 | if (vmx->host_state.msr_host_bndcfgs) | ||
1754 | wrmsrl(MSR_IA32_BNDCFGS, vmx->host_state.msr_host_bndcfgs); | ||
1750 | /* | 1755 | /* |
1751 | * If the FPU is not active (through the host task or | 1756 | * If the FPU is not active (through the host task or |
1752 | * the guest vcpu), then restore the cr0.TS bit. | 1757 | * the guest vcpu), then restore the cr0.TS bit. |
@@ -2837,7 +2842,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
2837 | min |= VM_EXIT_HOST_ADDR_SPACE_SIZE; | 2842 | min |= VM_EXIT_HOST_ADDR_SPACE_SIZE; |
2838 | #endif | 2843 | #endif |
2839 | opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT | | 2844 | opt = VM_EXIT_SAVE_IA32_PAT | VM_EXIT_LOAD_IA32_PAT | |
2840 | VM_EXIT_ACK_INTR_ON_EXIT; | 2845 | VM_EXIT_ACK_INTR_ON_EXIT | VM_EXIT_CLEAR_BNDCFGS; |
2841 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS, | 2846 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_EXIT_CTLS, |
2842 | &_vmexit_control) < 0) | 2847 | &_vmexit_control) < 0) |
2843 | return -EIO; | 2848 | return -EIO; |
@@ -2854,7 +2859,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) | |||
2854 | _pin_based_exec_control &= ~PIN_BASED_POSTED_INTR; | 2859 | _pin_based_exec_control &= ~PIN_BASED_POSTED_INTR; |
2855 | 2860 | ||
2856 | min = 0; | 2861 | min = 0; |
2857 | opt = VM_ENTRY_LOAD_IA32_PAT; | 2862 | opt = VM_ENTRY_LOAD_IA32_PAT | VM_ENTRY_LOAD_BNDCFGS; |
2858 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS, | 2863 | if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_ENTRY_CTLS, |
2859 | &_vmentry_control) < 0) | 2864 | &_vmentry_control) < 0) |
2860 | return -EIO; | 2865 | return -EIO; |
@@ -7052,6 +7057,12 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu) | |||
7052 | local_irq_enable(); | 7057 | local_irq_enable(); |
7053 | } | 7058 | } |
7054 | 7059 | ||
7060 | static bool vmx_mpx_supported(void) | ||
7061 | { | ||
7062 | return (vmcs_config.vmexit_ctrl & VM_EXIT_CLEAR_BNDCFGS) && | ||
7063 | (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_BNDCFGS); | ||
7064 | } | ||
7065 | |||
7055 | static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) | 7066 | static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx) |
7056 | { | 7067 | { |
7057 | u32 exit_intr_info; | 7068 | u32 exit_intr_info; |
@@ -8634,6 +8645,7 @@ static struct kvm_x86_ops vmx_x86_ops = { | |||
8634 | 8645 | ||
8635 | .check_intercept = vmx_check_intercept, | 8646 | .check_intercept = vmx_check_intercept, |
8636 | .handle_external_intr = vmx_handle_external_intr, | 8647 | .handle_external_intr = vmx_handle_external_intr, |
8648 | .mpx_supported = vmx_mpx_supported, | ||
8637 | }; | 8649 | }; |
8638 | 8650 | ||
8639 | static int __init vmx_init(void) | 8651 | static int __init vmx_init(void) |
@@ -8721,6 +8733,8 @@ static int __init vmx_init(void) | |||
8721 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); | 8733 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_CS, false); |
8722 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); | 8734 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_ESP, false); |
8723 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); | 8735 | vmx_disable_intercept_for_msr(MSR_IA32_SYSENTER_EIP, false); |
8736 | vmx_disable_intercept_for_msr(MSR_IA32_BNDCFGS, true); | ||
8737 | |||
8724 | memcpy(vmx_msr_bitmap_legacy_x2apic, | 8738 | memcpy(vmx_msr_bitmap_legacy_x2apic, |
8725 | vmx_msr_bitmap_legacy, PAGE_SIZE); | 8739 | vmx_msr_bitmap_legacy, PAGE_SIZE); |
8726 | memcpy(vmx_msr_bitmap_longmode_x2apic, | 8740 | memcpy(vmx_msr_bitmap_longmode_x2apic, |