Commit 0238ea91 authored by Jan Kiszka's avatar Jan Kiszka Committed by Gleb Natapov

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: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarJan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
parent c18911a2
...@@ -70,6 +70,7 @@ ...@@ -70,6 +70,7 @@
#define PIN_BASED_EXT_INTR_MASK 0x00000001 #define PIN_BASED_EXT_INTR_MASK 0x00000001
#define PIN_BASED_NMI_EXITING 0x00000008 #define PIN_BASED_NMI_EXITING 0x00000008
#define PIN_BASED_VIRTUAL_NMIS 0x00000020 #define PIN_BASED_VIRTUAL_NMIS 0x00000020
#define PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040
#define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016 #define PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR 0x00000016
...@@ -95,6 +96,7 @@ ...@@ -95,6 +96,7 @@
#define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff #define VM_ENTRY_ALWAYSON_WITHOUT_TRUE_MSR 0x000011ff
#define VMX_MISC_PREEMPTION_TIMER_RATE_MASK 0x0000001f
#define VMX_MISC_SAVE_EFER_LMA 0x00000020 #define VMX_MISC_SAVE_EFER_LMA 0x00000020
/* VMCS Encodings */ /* VMCS Encodings */
...@@ -217,6 +219,7 @@ enum vmcs_field { ...@@ -217,6 +219,7 @@ enum vmcs_field {
GUEST_INTERRUPTIBILITY_INFO = 0x00004824, GUEST_INTERRUPTIBILITY_INFO = 0x00004824,
GUEST_ACTIVITY_STATE = 0X00004826, GUEST_ACTIVITY_STATE = 0X00004826,
GUEST_SYSENTER_CS = 0x0000482A, GUEST_SYSENTER_CS = 0x0000482A,
VMX_PREEMPTION_TIMER_VALUE = 0x0000482E,
HOST_IA32_SYSENTER_CS = 0x00004c00, HOST_IA32_SYSENTER_CS = 0x00004c00,
CR0_GUEST_HOST_MASK = 0x00006000, CR0_GUEST_HOST_MASK = 0x00006000,
CR4_GUEST_HOST_MASK = 0x00006002, CR4_GUEST_HOST_MASK = 0x00006002,
......
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
#define EXIT_REASON_EOI_INDUCED 45 #define EXIT_REASON_EOI_INDUCED 45
#define EXIT_REASON_EPT_VIOLATION 48 #define EXIT_REASON_EPT_VIOLATION 48
#define EXIT_REASON_EPT_MISCONFIG 49 #define EXIT_REASON_EPT_MISCONFIG 49
#define EXIT_REASON_PREEMPTION_TIMER 52
#define EXIT_REASON_WBINVD 54 #define EXIT_REASON_WBINVD 54
#define EXIT_REASON_XSETBV 55 #define EXIT_REASON_XSETBV 55
#define EXIT_REASON_APIC_WRITE 56 #define EXIT_REASON_APIC_WRITE 56
...@@ -110,7 +111,7 @@ ...@@ -110,7 +111,7 @@
{ EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \ { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \
{ EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \ { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \
{ EXIT_REASON_INVD, "INVD" }, \ { EXIT_REASON_INVD, "INVD" }, \
{ EXIT_REASON_INVPCID, "INVPCID" } { EXIT_REASON_INVPCID, "INVPCID" }, \
{ EXIT_REASON_PREEMPTION_TIMER, "PREEMPTION_TIMER" }
#endif /* _UAPIVMX_H */ #endif /* _UAPIVMX_H */
...@@ -298,7 +298,8 @@ struct __packed vmcs12 { ...@@ -298,7 +298,8 @@ struct __packed vmcs12 {
u32 guest_activity_state; u32 guest_activity_state;
u32 guest_sysenter_cs; u32 guest_sysenter_cs;
u32 host_ia32_sysenter_cs; u32 host_ia32_sysenter_cs;
u32 padding32[8]; /* room for future expansion */ u32 vmx_preemption_timer_value;
u32 padding32[7]; /* room for future expansion */
u16 virtual_processor_id; u16 virtual_processor_id;
u16 guest_es_selector; u16 guest_es_selector;
u16 guest_cs_selector; u16 guest_cs_selector;
...@@ -537,6 +538,7 @@ static const unsigned short vmcs_field_to_offset_table[] = { ...@@ -537,6 +538,7 @@ static const unsigned short vmcs_field_to_offset_table[] = {
FIELD(GUEST_ACTIVITY_STATE, guest_activity_state), FIELD(GUEST_ACTIVITY_STATE, guest_activity_state),
FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs), FIELD(GUEST_SYSENTER_CS, guest_sysenter_cs),
FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs), FIELD(HOST_IA32_SYSENTER_CS, host_ia32_sysenter_cs),
FIELD(VMX_PREEMPTION_TIMER_VALUE, vmx_preemption_timer_value),
FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask), FIELD(CR0_GUEST_HOST_MASK, cr0_guest_host_mask),
FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask), FIELD(CR4_GUEST_HOST_MASK, cr4_guest_host_mask),
FIELD(CR0_READ_SHADOW, cr0_read_shadow), FIELD(CR0_READ_SHADOW, cr0_read_shadow),
...@@ -2049,7 +2051,8 @@ static __init void nested_vmx_setup_ctls_msrs(void) ...@@ -2049,7 +2051,8 @@ static __init void nested_vmx_setup_ctls_msrs(void)
*/ */
nested_vmx_pinbased_ctls_low |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR; nested_vmx_pinbased_ctls_low |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
nested_vmx_pinbased_ctls_high &= PIN_BASED_EXT_INTR_MASK | nested_vmx_pinbased_ctls_high &= PIN_BASED_EXT_INTR_MASK |
PIN_BASED_NMI_EXITING | PIN_BASED_VIRTUAL_NMIS; PIN_BASED_NMI_EXITING | PIN_BASED_VIRTUAL_NMIS |
PIN_BASED_VMX_PREEMPTION_TIMER;
nested_vmx_pinbased_ctls_high |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR; nested_vmx_pinbased_ctls_high |= PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR;
/* /*
...@@ -2110,7 +2113,8 @@ static __init void nested_vmx_setup_ctls_msrs(void) ...@@ -2110,7 +2113,8 @@ static __init void nested_vmx_setup_ctls_msrs(void)
/* miscellaneous data */ /* miscellaneous data */
rdmsr(MSR_IA32_VMX_MISC, nested_vmx_misc_low, nested_vmx_misc_high); rdmsr(MSR_IA32_VMX_MISC, nested_vmx_misc_low, nested_vmx_misc_high);
nested_vmx_misc_low &= VMX_MISC_SAVE_EFER_LMA; nested_vmx_misc_low &= VMX_MISC_PREEMPTION_TIMER_RATE_MASK |
VMX_MISC_SAVE_EFER_LMA;
nested_vmx_misc_high = 0; nested_vmx_misc_high = 0;
} }
...@@ -6190,6 +6194,9 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu) ...@@ -6190,6 +6194,9 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
case EXIT_REASON_EPT_VIOLATION: case EXIT_REASON_EPT_VIOLATION:
case EXIT_REASON_EPT_MISCONFIG: case EXIT_REASON_EPT_MISCONFIG:
return 0; return 0;
case EXIT_REASON_PREEMPTION_TIMER:
return vmcs12->pin_based_vm_exec_control &
PIN_BASED_VMX_PREEMPTION_TIMER;
case EXIT_REASON_WBINVD: case EXIT_REASON_WBINVD:
return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING); return nested_cpu_has2(vmcs12, SECONDARY_EXEC_WBINVD_EXITING);
case EXIT_REASON_XSETBV: case EXIT_REASON_XSETBV:
...@@ -7011,6 +7018,10 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12) ...@@ -7011,6 +7018,10 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
(vmcs_config.pin_based_exec_ctrl | (vmcs_config.pin_based_exec_ctrl |
vmcs12->pin_based_vm_exec_control)); vmcs12->pin_based_vm_exec_control));
if (vmcs12->pin_based_vm_exec_control & PIN_BASED_VMX_PREEMPTION_TIMER)
vmcs_write32(VMX_PREEMPTION_TIMER_VALUE,
vmcs12->vmx_preemption_timer_value);
/* /*
* Whether page-faults are trapped is determined by a combination of * Whether page-faults are trapped is determined by a combination of
* 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF. * 3 settings: PFEC_MASK, PFEC_MATCH and EXCEPTION_BITMAP.PF.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment