From 2ea8a5cdb921187dea2d10db2aa5ad47d6e6ac03 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Fri, 30 Jul 2021 20:45:22 -0700 Subject: [PATCH] x86/tdx: Use direct paravirt call for wrmsrl TDX normally handles MSR writes using the #VE exception, or directly for some special MSRs. But there is at least one performance critical MSR which triggers #VE, which is the TSC deadline MSR. It gets reprogrammed every timer interrupt, and also every idle exit. There are noticeable slow downs by relying on #VE for this, since a #VE requires at least 3 exits to the TDX module, which adds up in overhead. Use a direct paravirt call for MSR writes. This will only be used for wrmsrl(), some of the other MSR write paths still use #VE (but these don't seem to be performance critical, so it shouldn't matter) Also remove the redundant check for being a context switched MSR because this is already checked on this path, and shouldn't really happen anyways. Signed-off-by: Andi Kleen Signed-off-by: Kuppuswamy Sathyanarayanan --- arch/x86/kernel/tdx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/tdx.c b/arch/x86/kernel/tdx.c index 5161e2c3259a2..834e6482093d3 100644 --- a/arch/x86/kernel/tdx.c +++ b/arch/x86/kernel/tdx.c @@ -418,14 +418,20 @@ static int tdx_write_msr_safe(unsigned int msr, unsigned int low, { u64 ret; - WARN_ON_ONCE(tdx_is_context_switched_msr(msr)); - ret = _trace_tdx_hypercall(EXIT_REASON_MSR_WRITE, msr, (u64)high << 32 | low, 0, 0, NULL); return ret ? -EIO : 0; } +void notrace tdx_write_msr(unsigned int msr, u32 low, u32 high) +{ + if (tdx_is_context_switched_msr(msr)) + native_write_msr(msr, low, high); + else + tdx_write_msr_safe(msr, low, high); +} + static u64 tdx_handle_cpuid(struct pt_regs *regs) { struct tdx_hypercall_output out = {0}; @@ -757,6 +763,7 @@ void __init tdx_early_init(void) pv_ops.irq.safe_halt = tdx_safe_halt; pv_ops.irq.halt = tdx_halt; + pv_ops.cpu.write_msr = tdx_write_msr; legacy_pic = &null_legacy_pic; swiotlb_force = SWIOTLB_FORCE;