From: Isaku Yamahata Fix apic and vmexit test cases to pass with APIC timer virtualization by replacing the NOP instruction with the CPUID instruction, a serializing instruction. Use CPUID instead of the SERIALIZE instruction for simplicity because SERIALIZE is not universally available, but CPUID is. apic and vmexit test cases use "wrmsr(TSCDEADLINE, past value); nop" sequence to cause the deadline timer to fire immediately at the NOP instruction. It's not guaranteed because wrmsr(TSCDEADLINE) isn't a serializing instruction according to SDM [1]. With APIC timer virtualization enabled, those tests can fail. It worked before because KVM intercepts wrmsr(TSCDEADLINE). KVM doesn't intercept it with APIC timer virtualization enabled. [1] From SDM 3a Serializing intructions An execution of WRMSR to any non-serializing MSR is not serializing. Non-serializing MSRs include the following: IA32_SPEC_CTRL MSR (MSR index 48H), IA32_PRED_CMD MSR (MSR index 49H), IA32_TSX_CTRL MSR (MSR index 122H), IA32_TSC_DEADLINE MSR (MSR index 6E0H), IA32_PKRS MSR (MSR index 6E1H), IA32_HWP_REQUEST MSR (MSR index 774H), or any of the x2APIC MSRs (MSR indices 802H to 83FH). Suggested-by: Sean Christopherson Signed-off-by: Isaku Yamahata -- Changes v1 -> v2: - Introduce wrmsr_tscdeadline_serialize(). - use cpuid(0, 0) instread of serialize instruction. --- lib/x86/processor.h | 10 ++++++++++ x86/apic.c | 3 +-- x86/vmexit.c | 3 +-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/x86/processor.h b/lib/x86/processor.h index 42dd2d2a4787..7255e515f548 100644 --- a/lib/x86/processor.h +++ b/lib/x86/processor.h @@ -1085,6 +1085,16 @@ static inline void wrtsc(u64 tsc) wrmsr(MSR_IA32_TSC, tsc); } +static inline void wrmsr_tscdeadline_serialize(u64 deadline) +{ + wrmsr(MSR_IA32_TSCDEADLINE, deadline); + + /* + * Use the CPUID instruction to serialize because the SERIALZE + * instruction is not universally available. + */ + raw_cpuid(0, 0); +} static inline void invlpg(volatile void *va) { diff --git a/x86/apic.c b/x86/apic.c index 0a52e9a45f1c..4c9659626911 100644 --- a/x86/apic.c +++ b/x86/apic.c @@ -34,8 +34,7 @@ static void __test_tsc_deadline_timer(void) { handle_irq(TSC_DEADLINE_TIMER_VECTOR, tsc_deadline_timer_isr); - wrmsr(MSR_IA32_TSCDEADLINE, rdmsr(MSR_IA32_TSC)); - asm volatile ("nop"); + wrmsr_tscdeadline_serialize(rdmsr(MSR_IA32_TSC)); report(tdt_count == 1, "tsc deadline timer"); report(rdmsr(MSR_IA32_TSCDEADLINE) == 0, "tsc deadline timer clearing"); } diff --git a/x86/vmexit.c b/x86/vmexit.c index 5296ed38aa34..1b675c00f930 100644 --- a/x86/vmexit.c +++ b/x86/vmexit.c @@ -436,8 +436,7 @@ static int has_tscdeadline(void) static void tscdeadline_immed(void) { - wrmsr(MSR_IA32_TSCDEADLINE, rdtsc()); - asm volatile("nop"); + wrmsr_tscdeadline_serialize(rdtsc()); } static void tscdeadline(void) base-commit: 86e53277ac80dabb04f4fa5fa6a6cc7649392bdc -- 2.45.2