Re: [PATCH v2 07/11] x86/sev: Change TSC MSR behavior for Secure TSC enabled guests

From: Tom Lendacky
Date: Mon Apr 03 2023 - 17:15:32 EST


On 3/26/23 09:46, Nikunj A Dadhania wrote:
Secure TSC enabled guests should not write MSR_IA32_TSC(10H) register
as the subsequent TSC value reads are undefined. MSR_IA32_TSC related
accesses should not exit to the hypervisor for such guests.

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

Signed-off-by: Nikunj A Dadhania <nikunj@xxxxxxx>

Reviewed-by: Tom Lendacky <thomas.lendacky@xxxxxxx>

---
arch/x86/kernel/sev.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)

diff --git a/arch/x86/kernel/sev.c b/arch/x86/kernel/sev.c
index c5ca97aab8c1..3750e545d688 100644
--- a/arch/x86/kernel/sev.c
+++ b/arch/x86/kernel/sev.c
@@ -1642,6 +1642,30 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
/* Is it a WRMSR? */
exit_info_1 = (ctxt->insn.opcode.bytes[1] == 0x30) ? 1 : 0;
+ /*
+ * TSC related accesses should not exit to the hypervisor when a
+ * guest is executing with SecureTSC enabled, so special handling
+ * is required for accesses of MSR_IA32_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.
+ */
+ if (regs->cx == MSR_IA32_TSC && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) {
+ u64 tsc;
+
+ if (exit_info_1)
+ return ES_OK;
+
+ tsc = rdtsc();
+ regs->ax = UINT_MAX & tsc;
+ regs->dx = UINT_MAX & (tsc >> 32);
+
+ return ES_OK;
+ }
+
ghcb_set_rcx(ghcb, regs->cx);
if (exit_info_1) {
ghcb_set_rax(ghcb, regs->ax);