Message ID | 20241203090045.942078-7-nikunj@amd.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | Add Secure TSC support for SNP guests | expand |
On Tue, Dec 03, 2024 at 02:30:38PM +0530, Nikunj A Dadhania wrote: > diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c > index af28fb962309..59c5e716fdd1 100644 > --- a/arch/x86/coco/sev/core.c > +++ b/arch/x86/coco/sev/core.c > @@ -1473,6 +1473,14 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) > if (regs->cx == MSR_IA32_TSC && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) > return __vc_handle_msr_tsc(regs, write); > > + /* > + * GUEST_TSC_FREQ should not be intercepted when Secure TSC is > + * enabled. Terminate the SNP guest when the interception is enabled. > + */ > + if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) > + return ES_VMM_ERROR; > + > + If you merge this logic into the switch-case, the patch becomes even easier and the code cleaner: diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index 050170eb28e6..35d9a3bb4b06 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -1446,6 +1446,13 @@ static enum es_result __vc_handle_msr_tsc(struct pt_regs *regs, bool write) if (!(sev_status & MSR_AMD64_SNP_SECURE_TSC)) goto read_tsc; + /* + * GUEST_TSC_FREQ should not be intercepted when Secure TSC is + * enabled. Terminate the SNP guest when the interception is enabled. + */ + if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ) + return ES_VMM_ERROR; + if (write) { WARN_ONCE(1, "TSC MSR writes are verboten!\n"); return ES_UNSUPPORTED; @@ -1472,6 +1479,7 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) case MSR_SVSM_CAA: return __vc_handle_msr_caa(regs, write); case MSR_IA32_TSC: + case MSR_AMD64_GUEST_TSC_FREQ: return __vc_handle_msr_tsc(regs, write); default: break;
On 12/10/2024 5:41 PM, Borislav Petkov wrote: > On Tue, Dec 03, 2024 at 02:30:38PM +0530, Nikunj A Dadhania wrote: >> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c >> index af28fb962309..59c5e716fdd1 100644 >> --- a/arch/x86/coco/sev/core.c >> +++ b/arch/x86/coco/sev/core.c >> @@ -1473,6 +1473,14 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) >> if (regs->cx == MSR_IA32_TSC && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) >> return __vc_handle_msr_tsc(regs, write); >> >> + /* >> + * GUEST_TSC_FREQ should not be intercepted when Secure TSC is >> + * enabled. Terminate the SNP guest when the interception is enabled. >> + */ >> + if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) >> + return ES_VMM_ERROR; >> + >> + > > If you merge this logic into the switch-case, the patch becomes even easier > and the code cleaner: This is incorrect, for a non-Secure TSC guest, a read of intercepted MSR_AMD64_GUEST_TSC_FREQ will return value of rdtsc_ordered(). This is an invalid MSR when SecureTSC is not enabled. > > diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c > index 050170eb28e6..35d9a3bb4b06 100644 > --- a/arch/x86/coco/sev/core.c > +++ b/arch/x86/coco/sev/core.c > @@ -1446,6 +1446,13 @@ static enum es_result __vc_handle_msr_tsc(struct pt_regs *regs, bool write) > if (!(sev_status & MSR_AMD64_SNP_SECURE_TSC)) > goto read_tsc; > > + /* > + * GUEST_TSC_FREQ should not be intercepted when Secure TSC is > + * enabled. Terminate the SNP guest when the interception is enabled. > + */ > + if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ) > + return ES_VMM_ERROR; > + > if (write) { > WARN_ONCE(1, "TSC MSR writes are verboten!\n"); > return ES_UNSUPPORTED; > @@ -1472,6 +1479,7 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) > case MSR_SVSM_CAA: > return __vc_handle_msr_caa(regs, write); > case MSR_IA32_TSC: > + case MSR_AMD64_GUEST_TSC_FREQ: > return __vc_handle_msr_tsc(regs, write); > default: > break; > Regards Nikunj
On Tue, Dec 10, 2024 at 10:43:05PM +0530, Nikunj A Dadhania wrote: > This is incorrect, for a non-Secure TSC guest, a read of intercepted > MSR_AMD64_GUEST_TSC_FREQ will return value of rdtsc_ordered(). This is an invalid > MSR when SecureTSC is not enabled. So how would you change this diff to fix this?
On 12/10/24 11:13, Nikunj A Dadhania wrote: > On 12/10/2024 5:41 PM, Borislav Petkov wrote: >> On Tue, Dec 03, 2024 at 02:30:38PM +0530, Nikunj A Dadhania wrote: >>> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c >>> index af28fb962309..59c5e716fdd1 100644 >>> --- a/arch/x86/coco/sev/core.c >>> +++ b/arch/x86/coco/sev/core.c >>> @@ -1473,6 +1473,14 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) >>> if (regs->cx == MSR_IA32_TSC && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) >>> return __vc_handle_msr_tsc(regs, write); >>> >>> + /* >>> + * GUEST_TSC_FREQ should not be intercepted when Secure TSC is >>> + * enabled. Terminate the SNP guest when the interception is enabled. >>> + */ >>> + if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) >>> + return ES_VMM_ERROR; >>> + >>> + >> >> If you merge this logic into the switch-case, the patch becomes even easier >> and the code cleaner: > > This is incorrect, for a non-Secure TSC guest, a read of intercepted > MSR_AMD64_GUEST_TSC_FREQ will return value of rdtsc_ordered(). This is an invalid > MSR when SecureTSC is not enabled. For the non-Secure TSC guest, I still think that we should continue to use the GHCB MSR NAE event instead of switching to using rdtsc_ordered(). Thanks, Tom > >> >> diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c >> index 050170eb28e6..35d9a3bb4b06 100644 >> --- a/arch/x86/coco/sev/core.c >> +++ b/arch/x86/coco/sev/core.c >> @@ -1446,6 +1446,13 @@ static enum es_result __vc_handle_msr_tsc(struct pt_regs *regs, bool write) >> if (!(sev_status & MSR_AMD64_SNP_SECURE_TSC)) >> goto read_tsc; >> >> + /* >> + * GUEST_TSC_FREQ should not be intercepted when Secure TSC is >> + * enabled. Terminate the SNP guest when the interception is enabled. >> + */ >> + if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ) >> + return ES_VMM_ERROR; >> + >> if (write) { >> WARN_ONCE(1, "TSC MSR writes are verboten!\n"); >> return ES_UNSUPPORTED; >> @@ -1472,6 +1479,7 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) >> case MSR_SVSM_CAA: >> return __vc_handle_msr_caa(regs, write); >> case MSR_IA32_TSC: >> + case MSR_AMD64_GUEST_TSC_FREQ: >> return __vc_handle_msr_tsc(regs, write); >> default: >> break; >> > > Regards > Nikunj
On 12/10/2024 10:48 PM, Borislav Petkov wrote: > On Tue, Dec 10, 2024 at 10:43:05PM +0530, Nikunj A Dadhania wrote: >> This is incorrect, for a non-Secure TSC guest, a read of intercepted >> MSR_AMD64_GUEST_TSC_FREQ will return value of rdtsc_ordered(). This is an invalid >> MSR when SecureTSC is not enabled. > > So how would you change this diff to fix this? How about the below change, this also keeps the behavior intact for non-Secure TSC guests (SEV-ES/SNP): diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index 25a4c47f58c4..fa57adf5a2c6 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -1448,15 +1448,18 @@ static enum es_result __vc_handle_msr_tsc(struct pt_regs *regs, bool write) { u64 tsc; - if (!(sev_status & MSR_AMD64_SNP_SECURE_TSC)) - goto read_tsc; + /* + * GUEST_TSC_FREQ should not be intercepted when Secure TSC is + * enabled. Terminate the SNP guest when the interception is enabled. + */ + if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ) + return ES_VMM_ERROR; if (write) { WARN_ONCE(1, "TSC MSR writes are verboten!\n"); return ES_OK; } -read_tsc: tsc = rdtsc_ordered(); regs->ax = lower_32_bits(tsc); regs->dx = upper_32_bits(tsc); @@ -1477,19 +1480,13 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) case MSR_SVSM_CAA: return __vc_handle_msr_caa(regs, write); case MSR_IA32_TSC: - return __vc_handle_msr_tsc(regs, write); + case MSR_AMD64_GUEST_TSC_FREQ: + if (sev_status & MSR_AMD64_SNP_SECURE_TSC) + return __vc_handle_msr_tsc(regs, write); default: break; } - /* - * GUEST_TSC_FREQ should not be intercepted when Secure TSC is - * enabled. Terminate the SNP guest when the interception is enabled. - */ - if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) - return ES_VMM_ERROR; - - ghcb_set_rcx(ghcb, regs->cx); if (write) { ghcb_set_rax(ghcb, regs->ax); --- Regards Nikunj
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 3ae84c3b8e6d..233be13cc21f 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -608,6 +608,7 @@ #define MSR_AMD_PERF_CTL 0xc0010062 #define MSR_AMD_PERF_STATUS 0xc0010063 #define MSR_AMD_PSTATE_DEF_BASE 0xc0010064 +#define MSR_AMD64_GUEST_TSC_FREQ 0xc0010134 #define MSR_AMD64_OSVW_ID_LENGTH 0xc0010140 #define MSR_AMD64_OSVW_STATUS 0xc0010141 #define MSR_AMD_PPIN_CTL 0xc00102f0 diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index af28fb962309..59c5e716fdd1 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -1473,6 +1473,14 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt) if (regs->cx == MSR_IA32_TSC && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) return __vc_handle_msr_tsc(regs, write); + /* + * GUEST_TSC_FREQ should not be intercepted when Secure TSC is + * enabled. Terminate the SNP guest when the interception is enabled. + */ + if (regs->cx == MSR_AMD64_GUEST_TSC_FREQ && (sev_status & MSR_AMD64_SNP_SECURE_TSC)) + return ES_VMM_ERROR; + + ghcb_set_rcx(ghcb, regs->cx); if (write) { ghcb_set_rax(ghcb, regs->ax);