]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
x86/sev: Change TSC MSR behavior for Secure TSC enabled guests
authorNikunj A Dadhania <nikunj@amd.com>
Mon, 6 Jan 2025 12:46:26 +0000 (18:16 +0530)
committerBorislav Petkov (AMD) <bp@alien8.de>
Tue, 7 Jan 2025 20:26:06 +0000 (21:26 +0100)
Secure TSC enabled guests should not write to the MSR_IA32_TSC (0x10) register
as the subsequent TSC value reads are undefined. On AMD, MSR_IA32_TSC is
intercepted by the hypervisor by default. MSR_IA32_TSC read/write accesses
should not exit to the hypervisor for such guests.

Accesses to MSR_IA32_TSC need special handling in the #VC handler for the
guests with Secure TSC enabled. Writes to MSR_IA32_TSC should be ignored and
flagged once with a warning, and reads of MSR_IA32_TSC should return the
result of the RDTSC instruction.

  [ bp: Massage commit message. ]

Suggested-by: Borislav Petkov (AMD) <bp@alien8.de>
Signed-off-by: Nikunj A Dadhania <nikunj@amd.com>
Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
Reviewed-by: Tom Lendacky <thomas.lendacky@amd.com>
Link: https://lore.kernel.org/r/20250106124633.1418972-7-nikunj@amd.com
arch/x86/coco/sev/core.c

index 7458805b8f0e571895c5a439763c613f0fb7c1db..cd5b9b7237555fd0e28631394d801b6c7de07ca4 100644 (file)
@@ -1433,6 +1433,34 @@ static enum es_result __vc_handle_msr_caa(struct pt_regs *regs, bool write)
        return ES_OK;
 }
 
+/*
+ * TSC related accesses should not exit to the hypervisor when a guest is
+ * executing with Secure TSC enabled, so special handling is required for
+ * accesses of MSR_IA32_TSC.
+ */
+static enum es_result __vc_handle_secure_tsc_msrs(struct pt_regs *regs, bool write)
+{
+       u64 tsc;
+
+       /*
+        * Writes: Writing to MSR_IA32_TSC can cause subsequent reads of the TSC
+        *         to return undefined values, so ignore all writes.
+        *
+        * Reads: Reads of MSR_IA32_TSC should return the current TSC value, use
+        *        the value returned by rdtsc_ordered().
+        */
+       if (write) {
+               WARN_ONCE(1, "TSC MSR writes are verboten!\n");
+               return ES_OK;
+       }
+
+       tsc = rdtsc_ordered();
+       regs->ax = lower_32_bits(tsc);
+       regs->dx = upper_32_bits(tsc);
+
+       return ES_OK;
+}
+
 static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
 {
        struct pt_regs *regs = ctxt->regs;
@@ -1442,8 +1470,17 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
        /* Is it a WRMSR? */
        write = ctxt->insn.opcode.bytes[1] == 0x30;
 
-       if (regs->cx == MSR_SVSM_CAA)
+       switch (regs->cx) {
+       case MSR_SVSM_CAA:
                return __vc_handle_msr_caa(regs, write);
+       case MSR_IA32_TSC:
+               if (sev_status & MSR_AMD64_SNP_SECURE_TSC)
+                       return __vc_handle_secure_tsc_msrs(regs, write);
+               else
+                       break;
+       default:
+               break;
+       }
 
        ghcb_set_rcx(ghcb, regs->cx);
        if (write) {