aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kiszka <jan.kiszka@siemens.com>2013-03-13 06:31:24 -0400
committerGleb Natapov <gleb@redhat.com>2013-03-14 04:01:21 -0400
commit0238ea913c21a89387f93097acfbdfeebc9c9257 (patch)
tree679e48065643a243ce9ee5ada932fd558ba39b40
parentc18911a23ce1dec27fa3325b50587de2569d26f8 (diff)
KVM: nVMX: Add preemption timer support
Provided the host has this feature, it's straightforward to offer it to the guest as well. We just need to load to timer value on L2 entry if the feature was enabled by L1 and watch out for the corresponding exit reason. Reviewed-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Gleb Natapov <gleb@redhat.com>
-rw-r--r--arch/x86/include/asm/vmx.h3
-rw-r--r--arch/x86/include/uapi/asm/vmx.h5
-rw-r--r--arch/x86/kvm/vmx.c17
3 files changed, 20 insertions, 5 deletions
diff --git a/arch/x86/include/asm/vmx.h b/arch/x86/include/asm/vmx.h
index 056bda586a45..fc1c3134473b 100644
--- a/arch/x86/include/asm/vmx.h
+++ b/arch/x86/include/asm/vmx.h
@@ -70,6 +70,7 @@
70#define PIN_BASED_EXT_INTR_MASK 0x00000001 70#define PIN_BASED_EXT_INTR_MASK 0x00000001
71#define PIN_BASED_NMI_EXITING 0x00000008 71#define PIN_BASED_NMI_EXITING 0x00000008
72#define PIN_BASED_VIRTUAL_NMIS 0x00000020 72#define PIN_BASED_VIRTUAL_NMIS 0x00000020
73#define PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040
73 74
74#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016 75#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016
75 76
@@ -95,6 +96,7 @@
95 96
96#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff 97#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff
97 98
99#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK 0x0000001f
98#define VMX_MISC_SAVE_EFER_LMA 0x00000020 100#define VMX_MISC_SAVE_EFER_LMA 0x00000020
99 101
100/* VMCS Encodings */ 102/* VMCS Encodings */
@@ -217,6 +219,7 @@ enum vmcs_field {
217 GUEST_INTERRUPTIBILITY_INFO = 0x00004824, 219 GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
218 GUEST_ACTIVITY_STATE = 0X00004826, 220 GUEST_ACTIVITY_STATE = 0X00004826,
219 GUEST_SYSENTER_CS = 0x0000482A, 221 GUEST_SYSENTER_CS = 0x0000482A,
222 VMX_PREEMPTION_TIMER_VALUE = 0x0000482E,
220 HOST_IA32_SYSENTER_CS = 0x00004c00, 223 HOST_IA32_SYSENTER_CS = 0x00004c00,
221 CR0_GUEST_HOST_MASK = 0x00006000, 224 CR0_GUEST_HOST_MASK = 0x00006000,
222 CR4_GUEST_HOST_MASK = 0x00006002, 225 CR4_GUEST_HOST_MASK = 0x00006002,
diff --git a/arch/x86/include/uapi/asm/vmx.h b/arch/x86/include/uapi/asm/vmx.h
index 2871fccfee68..d651082c7cf7 100644
--- a/arch/x86/include/uapi/asm/vmx.h
+++ b/arch/x86/include/uapi/asm/vmx.h
@@ -65,6 +65,7 @@
65#define EXIT_REASON_EOI_INDUCED 45 65#define EXIT_REASON_EOI_INDUCED 45
66#define EXIT_REASON_EPT_VIOLATION 48 66#define EXIT_REASON_EPT_VIOLATION 48
67#define EXIT_REASON_EPT_MISCONFIG 49 67#define EXIT_REASON_EPT_MISCONFIG 49
68#define EXIT_REASON_PREEMPTION_TIMER 52
68#define EXIT_REASON_WBINVD 54 69#define EXIT_REASON_WBINVD 54
69#define EXIT_REASON_XSETBV 55 70#define EXIT_REASON_XSETBV 55
70#define EXIT_REASON_APIC_WRITE 56 71#define EXIT_REASON_APIC_WRITE 56
@@ -110,7 +111,7 @@
110 { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \ 111 { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \
111 { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \ 112 { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \
112 { EXIT_REASON_INVD, "INVD" }, \ 113 { EXIT_REASON_INVD, "INVD" }, \
113 { EXIT_REASON_INVPCID, "INVPCID" } 114 { EXIT_REASON_INVPCID, "INVPCID" }, \
114 115 { EXIT_REASON_PREEMPTION_TIMER, "PREEMPTION_TIMER" }
115 116
116#endif /* _UAPIVMX_H */ 117#endif /* _UAPIVMX_H */
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 02f8c32b9b08..17a693868458 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -298,7 +298,8 @@ struct __packed vmcs12 {
298 u32 guest_activity_state; 298 u32 guest_activity_state;
299 u32 guest_sysenter_cs; 299 u32 guest_sysenter_cs;
300 u32 host_ia32_sysenter_cs; 300 u32 host_ia32_sysenter_cs;
301 u32 padding32[8]; /* room for future expansion */ 301 u32 vmx_preemption_timer_value;
302 u32 padding32[7]; /* room for future expansion */
302 u16 virtual_processor_id; 303 u16 virtual_processor_id;
303 u16 guest_es_selector; 304 u16 guest_es_selector;
304 u16 guest_cs_selector; 305 u16 guest_cs_selector;
@@ -537,6 +538,7 @@ static const unsigned short vmcs_field_to_offset_table[] = {
537 FIELD(GUEST_ACTIVITY_STATE, guest_activity_state), 538 FIELD(GUEST_ACTIVITY_STATE, guest_activity_state),
538 FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs), 539 FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs),
539 FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs), 540 FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs),
541 FIELD(VMX_PREEMPTION_TIMER_VALUE, vmx_preemption_timer_value),
540 FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask), 542 FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask),
541 FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask), 543 FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask),
542 FIELD(CR0_READ_SHADOW, cr0_read_shadow), 544 FIELD(CR0_READ_SHADOW, cr0_read_shadow),
@@ -2049,7 +2051,8 @@ static __init void nested_vmx_setup_ctls_msrs(void)
2049 */ 2051 */
2050 nested_vmx_pinbased_ctls_low |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR; 2052 nested_vmx_pinbased_ctls_low |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
2051 nested_vmx_pinbased_ctls_high &= PIN_BASED_EXT_INTR_MASK | 2053 nested_vmx_pinbased_ctls_high &= PIN_BASED_EXT_INTR_MASK |
2052 PIN_BASED_NMI_EXITING | PIN_BASED_VIRTUAL_NMIS; 2054 PIN_BASED_NMI_EXITING | PIN_BASED_VIRTUAL_NMIS |
2055 PIN_BASED_VMX_PREEMPTION_TIMER;
2053 nested_vmx_pinbased_ctls_high |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR; 2056 nested_vmx_pinbased_ctls_high |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
2054 2057
2055 /* 2058 /*
@@ -2110,7 +2113,8 @@ static __init void nested_vmx_setup_ctls_msrs(void)
2110 2113
2111 /* miscellaneous data */ 2114 /* miscellaneous data */
2112 rdmsr(MSR_IA32_VMX_MISC, nested_vmx_misc_low, nested_vmx_misc_high); 2115 rdmsr(MSR_IA32_VMX_MISC, nested_vmx_misc_low, nested_vmx_misc_high);
2113 nested_vmx_misc_low &= VMX_MISC_SAVE_EFER_LMA; 2116 nested_vmx_misc_low &= VMX_MISC_PREEMPTION_TIMER_RATE_MASK |
2117 VMX_MISC_SAVE_EFER_LMA;
2114 nested_vmx_misc_high = 0; 2118 nested_vmx_misc_high = 0;
2115} 2119}
2116 2120
@@ -6190,6 +6194,9 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
6190 case EXIT_REASON_EPT_VIOLATION: 6194 case EXIT_REASON_EPT_VIOLATION:
6191 case EXIT_REASON_EPT_MISCONFIG: 6195 case EXIT_REASON_EPT_MISCONFIG:
6192 return 0; 6196 return 0;
6197 case EXIT_REASON_PREEMPTION_TIMER:
6198 return vmcs12->pin_based_vm_exec_control &
6199 PIN_BASED_VMX_PREEMPTION_TIMER;
6193 case EXIT_REASON_WBINVD: 6200 case EXIT_REASON_WBINVD:
6194 return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING); 6201 return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
6195 case EXIT_REASON_XSETBV: 6202 case EXIT_REASON_XSETBV:
@@ -7011,6 +7018,10 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
7011 (vmcs_config.pin_based_exec_ctrl | 7018 (vmcs_config.pin_based_exec_ctrl |
7012 vmcs12->pin_based_vm_exec_control)); 7019 vmcs12->pin_based_vm_exec_control));
7013 7020
7021 if (vmcs12->pin_based_vm_exec_control & PIN_BASED_VMX_PREEMPTION_TIMER)
7022 vmcs_write32(VMX_PREEMPTION_TIMER_VALUE,
7023 vmcs12->vmx_preemption_timer_value);
7024
7014 /* 7025 /*
7015 * Whether page-faults are trapped is determined by a combination of 7026 * Whether page-faults are trapped is determined by a combination of
7016 * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF. 7027 * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF.