Skip to content

Commit 5eb1bcd

Browse files
nikunjadbp3tk0v
authored andcommitted
x86/sev: Improve handling of writes to intercepted TSC MSRs
Currently, when a Secure TSC enabled SNP guest attempts to write to the intercepted GUEST_TSC_FREQ MSR (a read-only MSR), the guest kernel response incorrectly implies a VMM configuration error, when in fact it is the usual VMM configuration to intercept writes to read-only MSRs, unless explicitly documented. Modify the intercepted TSC MSR #VC handling: * Write to GUEST_TSC_FREQ will generate a #GP instead of terminating the guest * Write to MSR_IA32_TSC will generate a #GP instead of silently ignoring it However, continue to terminate the guest when reading from intercepted GUEST_TSC_FREQ MSR with Secure TSC enabled, as intercepted reads indicate an improper VMM configuration for Secure TSC enabled SNP guests. [ bp: simplify comment. ] Fixes: 38cc649 ("x86/sev: Prevent GUEST_TSC_FREQ MSR interception for Secure TSC enabled guests") Suggested-by: Sean Christopherson <[email protected]> Signed-off-by: Nikunj A Dadhania <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Reviewed-by: Tom Lendacky <[email protected]> Link: https://lore.kernel.org/[email protected]
1 parent 31cd31c commit 5eb1bcd

File tree

1 file changed

+16
-15
lines changed

1 file changed

+16
-15
lines changed

arch/x86/coco/sev/vc-handle.c

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -371,29 +371,30 @@ static enum es_result __vc_handle_msr_caa(struct pt_regs *regs, bool write)
371371
* executing with Secure TSC enabled, so special handling is required for
372372
* accesses of MSR_IA32_TSC and MSR_AMD64_GUEST_TSC_FREQ.
373373
*/
374-
static enum es_result __vc_handle_secure_tsc_msrs(struct pt_regs *regs, bool write)
374+
static enum es_result __vc_handle_secure_tsc_msrs(struct es_em_ctxt *ctxt, bool write)
375375
{
376+
struct pt_regs *regs = ctxt->regs;
376377
u64 tsc;
377378

378379
/*
379-
* GUEST_TSC_FREQ should not be intercepted when Secure TSC is enabled.
380-
* Terminate the SNP guest when the interception is enabled.
380+
* Writing to MSR_IA32_TSC can cause subsequent reads of the TSC to
381+
* return undefined values, and GUEST_TSC_FREQ is read-only. Generate
382+
* a #GP on all writes.
381383
*/
382-
if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ)
383-
return ES_VMM_ERROR;
384+
if (write) {
385+
ctxt->fi.vector = X86_TRAP_GP;
386+
ctxt->fi.error_code = 0;
387+
return ES_EXCEPTION;
388+
}
384389

385390
/*
386-
* Writes: Writing to MSR_IA32_TSC can cause subsequent reads of the TSC
387-
* to return undefined values, so ignore all writes.
388-
*
389-
* Reads: Reads of MSR_IA32_TSC should return the current TSC value, use
390-
* the value returned by rdtsc_ordered().
391+
* GUEST_TSC_FREQ read should not be intercepted when Secure TSC is
392+
* enabled. Terminate the guest if a read is attempted.
391393
*/
392-
if (write) {
393-
WARN_ONCE(1, "TSC MSR writes are verboten!\n");
394-
return ES_OK;
395-
}
394+
if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ)
395+
return ES_VMM_ERROR;
396396

397+
/* Reads of MSR_IA32_TSC should return the current TSC value. */
397398
tsc = rdtsc_ordered();
398399
regs->ax = lower_32_bits(tsc);
399400
regs->dx = upper_32_bits(tsc);
@@ -416,7 +417,7 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
416417
case MSR_IA32_TSC:
417418
case MSR_AMD64_GUEST_TSC_FREQ:
418419
if (sev_status & MSR_AMD64_SNP_SECURE_TSC)
419-
return __vc_handle_secure_tsc_msrs(regs, write);
420+
return __vc_handle_secure_tsc_msrs(ctxt, write);
420421
break;
421422
default:
422423
break;

0 commit comments

Comments
 (0)