Message ID | 20250210092230.151034-5-nikunj@amd.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Enable Secure TSC for SEV-SNP | expand |
On 2/10/25 03:22, Nikunj A Dadhania wrote: > From: Ketan Chaturvedi <Ketan.Chaturvedi@amd.com> > > Add support for Secure TSC, allowing userspace to configure the Secure TSC > feature for SNP guests. Use the SNP specification's desired TSC frequency > parameter during the SNP_LAUNCH_START command to set the mean TSC > frequency in KHz for Secure TSC enabled guests. If the frequency is not > specified by the VMM, default to tsc_khz. > > Signed-off-by: Ketan Chaturvedi <Ketan.Chaturvedi@amd.com> > Co-developed-by: Nikunj A Dadhania <nikunj@amd.com> > Signed-off-by: Nikunj A Dadhania <nikunj@amd.com> > --- > arch/x86/include/uapi/asm/kvm.h | 3 ++- > arch/x86/kvm/svm/sev.c | 20 ++++++++++++++++++++ > include/linux/psp-sev.h | 2 ++ > 3 files changed, 24 insertions(+), 1 deletion(-) > > diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h > index 9e75da97bce0..8e090cab9aa0 100644 > --- a/arch/x86/include/uapi/asm/kvm.h > +++ b/arch/x86/include/uapi/asm/kvm.h > @@ -836,7 +836,8 @@ struct kvm_sev_snp_launch_start { > __u64 policy; > __u8 gosvw[16]; > __u16 flags; > - __u8 pad0[6]; > + __u32 desired_tsc_khz; This will put the __u32 field misaligned in the struct. You should probably move the now 2-byte pad0 field to before the desired_tsc_khz field. > + __u8 pad0[2]; > __u64 pad1[4]; > }; > > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index 0a1fd5c034e2..0edd473749f7 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -2228,6 +2228,20 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) > > start.gctx_paddr = __psp_pa(sev->snp_context); > start.policy = params.policy; > + > + if (snp_secure_tsc_enabled(kvm)) { > + u32 user_tsc_khz = params.desired_tsc_khz; > + > + /* Use tsc_khz if the VMM has not provided the TSC frequency */ > + if (!user_tsc_khz) > + user_tsc_khz = tsc_khz; > + > + start.desired_tsc_khz = user_tsc_khz; > + > + /* Set the arch default TSC for the VM*/ > + kvm->arch.default_tsc_khz = user_tsc_khz; > + } > + > memcpy(start.gosvw, params.gosvw, sizeof(params.gosvw)); > rc = __sev_issue_cmd(argp->sev_fd, SEV_CMD_SNP_LAUNCH_START, &start, &argp->error); > if (rc) { > @@ -2949,6 +2963,9 @@ void __init sev_set_cpu_caps(void) > if (sev_snp_enabled) { > kvm_cpu_cap_set(X86_FEATURE_SEV_SNP); > kvm_caps.supported_vm_types |= BIT(KVM_X86_SNP_VM); > + > + if (cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC)) > + kvm_cpu_cap_set(X86_FEATURE_SNP_SECURE_TSC); > } > } > > @@ -3071,6 +3088,9 @@ void __init sev_hardware_setup(void) > sev_supported_vmsa_features = 0; > if (sev_es_debug_swap_enabled) > sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP; > + > + if (sev_snp_enabled && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC)) > + sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC; > } > > void sev_hardware_unsetup(void) > diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h > index 903ddfea8585..613a8209bed2 100644 > --- a/include/linux/psp-sev.h > +++ b/include/linux/psp-sev.h > @@ -594,6 +594,7 @@ struct sev_data_snp_addr { > * @imi_en: launch flow is launching an IMI (Incoming Migration Image) for the > * purpose of guest-assisted migration. > * @rsvd: reserved > + * @desired_tsc_khz: hypervisor desired mean TSC freq in kHz of the guest > * @gosvw: guest OS-visible workarounds, as defined by hypervisor > */ > struct sev_data_snp_launch_start { > @@ -603,6 +604,7 @@ struct sev_data_snp_launch_start { > u32 ma_en:1; /* In */ > u32 imi_en:1; /* In */ > u32 rsvd:30; > + u32 desired_tsc_khz; /* In */ Shouldn't there be a separate fix for this before this patch? The desired_tsc_freq should have been here all along, so before this patch, the gosvw field is off by 4 bytes with sev_data_snp_launch_start not being large enough compared to what the firmware is accessing, right? Thanks, Tom > u8 gosvw[16]; /* In */ > } __packed; >
Tom Lendacky <thomas.lendacky@amd.com> writes: > On 2/10/25 03:22, Nikunj A Dadhania wrote: >> From: Ketan Chaturvedi <Ketan.Chaturvedi@amd.com> >> >> Add support for Secure TSC, allowing userspace to configure the Secure TSC >> feature for SNP guests. Use the SNP specification's desired TSC frequency >> parameter during the SNP_LAUNCH_START command to set the mean TSC >> frequency in KHz for Secure TSC enabled guests. If the frequency is not >> specified by the VMM, default to tsc_khz. >> >> Signed-off-by: Ketan Chaturvedi <Ketan.Chaturvedi@amd.com> >> Co-developed-by: Nikunj A Dadhania <nikunj@amd.com> >> Signed-off-by: Nikunj A Dadhania <nikunj@amd.com> >> --- >> arch/x86/include/uapi/asm/kvm.h | 3 ++- >> arch/x86/kvm/svm/sev.c | 20 ++++++++++++++++++++ >> include/linux/psp-sev.h | 2 ++ >> 3 files changed, 24 insertions(+), 1 deletion(-) >> >> diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h >> index 9e75da97bce0..8e090cab9aa0 100644 >> --- a/arch/x86/include/uapi/asm/kvm.h >> +++ b/arch/x86/include/uapi/asm/kvm.h >> @@ -836,7 +836,8 @@ struct kvm_sev_snp_launch_start { >> __u64 policy; >> __u8 gosvw[16]; >> __u16 flags; >> - __u8 pad0[6]; >> + __u32 desired_tsc_khz; > > This will put the __u32 field misaligned in the struct. You should > probably move the now 2-byte pad0 field to before the desired_tsc_khz field. > Sure, will update. >> + __u8 pad0[2]; >> __u64 pad1[4]; >> }; >> >> diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c >> index 0a1fd5c034e2..0edd473749f7 100644 >> --- a/arch/x86/kvm/svm/sev.c >> +++ b/arch/x86/kvm/svm/sev.c >> @@ -2228,6 +2228,20 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) >> >> start.gctx_paddr = __psp_pa(sev->snp_context); >> start.policy = params.policy; >> + >> + if (snp_secure_tsc_enabled(kvm)) { >> + u32 user_tsc_khz = params.desired_tsc_khz; >> + >> + /* Use tsc_khz if the VMM has not provided the TSC frequency */ >> + if (!user_tsc_khz) >> + user_tsc_khz = tsc_khz; >> + >> + start.desired_tsc_khz = user_tsc_khz; >> + >> + /* Set the arch default TSC for the VM*/ >> + kvm->arch.default_tsc_khz = user_tsc_khz; >> + } >> + >> memcpy(start.gosvw, params.gosvw, sizeof(params.gosvw)); >> rc = __sev_issue_cmd(argp->sev_fd, SEV_CMD_SNP_LAUNCH_START, &start, &argp->error); >> if (rc) { >> @@ -2949,6 +2963,9 @@ void __init sev_set_cpu_caps(void) >> if (sev_snp_enabled) { >> kvm_cpu_cap_set(X86_FEATURE_SEV_SNP); >> kvm_caps.supported_vm_types |= BIT(KVM_X86_SNP_VM); >> + >> + if (cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC)) >> + kvm_cpu_cap_set(X86_FEATURE_SNP_SECURE_TSC); >> } >> } >> >> @@ -3071,6 +3088,9 @@ void __init sev_hardware_setup(void) >> sev_supported_vmsa_features = 0; >> if (sev_es_debug_swap_enabled) >> sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP; >> + >> + if (sev_snp_enabled && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC)) >> + sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC; >> } >> >> void sev_hardware_unsetup(void) >> diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h >> index 903ddfea8585..613a8209bed2 100644 >> --- a/include/linux/psp-sev.h >> +++ b/include/linux/psp-sev.h >> @@ -594,6 +594,7 @@ struct sev_data_snp_addr { >> * @imi_en: launch flow is launching an IMI (Incoming Migration Image) for the >> * purpose of guest-assisted migration. >> * @rsvd: reserved >> + * @desired_tsc_khz: hypervisor desired mean TSC freq in kHz of the guest >> * @gosvw: guest OS-visible workarounds, as defined by hypervisor >> */ >> struct sev_data_snp_launch_start { >> @@ -603,6 +604,7 @@ struct sev_data_snp_launch_start { >> u32 ma_en:1; /* In */ >> u32 imi_en:1; /* In */ >> u32 rsvd:30; >> + u32 desired_tsc_khz; /* In */ > > Shouldn't there be a separate fix for this before this patch? The > desired_tsc_freq should have been here all along, so before this patch, > the gosvw field is off by 4 bytes with sev_data_snp_launch_start not > being large enough compared to what the firmware is accessing, right? Yes, this should have been part of SNP series, I will separate this change in a new patch with Fixes + stable tag. Thanks Nikunj
diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h index 9e75da97bce0..8e090cab9aa0 100644 --- a/arch/x86/include/uapi/asm/kvm.h +++ b/arch/x86/include/uapi/asm/kvm.h @@ -836,7 +836,8 @@ struct kvm_sev_snp_launch_start { __u64 policy; __u8 gosvw[16]; __u16 flags; - __u8 pad0[6]; + __u32 desired_tsc_khz; + __u8 pad0[2]; __u64 pad1[4]; }; diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 0a1fd5c034e2..0edd473749f7 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2228,6 +2228,20 @@ static int snp_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) start.gctx_paddr = __psp_pa(sev->snp_context); start.policy = params.policy; + + if (snp_secure_tsc_enabled(kvm)) { + u32 user_tsc_khz = params.desired_tsc_khz; + + /* Use tsc_khz if the VMM has not provided the TSC frequency */ + if (!user_tsc_khz) + user_tsc_khz = tsc_khz; + + start.desired_tsc_khz = user_tsc_khz; + + /* Set the arch default TSC for the VM*/ + kvm->arch.default_tsc_khz = user_tsc_khz; + } + memcpy(start.gosvw, params.gosvw, sizeof(params.gosvw)); rc = __sev_issue_cmd(argp->sev_fd, SEV_CMD_SNP_LAUNCH_START, &start, &argp->error); if (rc) { @@ -2949,6 +2963,9 @@ void __init sev_set_cpu_caps(void) if (sev_snp_enabled) { kvm_cpu_cap_set(X86_FEATURE_SEV_SNP); kvm_caps.supported_vm_types |= BIT(KVM_X86_SNP_VM); + + if (cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC)) + kvm_cpu_cap_set(X86_FEATURE_SNP_SECURE_TSC); } } @@ -3071,6 +3088,9 @@ void __init sev_hardware_setup(void) sev_supported_vmsa_features = 0; if (sev_es_debug_swap_enabled) sev_supported_vmsa_features |= SVM_SEV_FEAT_DEBUG_SWAP; + + if (sev_snp_enabled && cpu_feature_enabled(X86_FEATURE_SNP_SECURE_TSC)) + sev_supported_vmsa_features |= SVM_SEV_FEAT_SECURE_TSC; } void sev_hardware_unsetup(void) diff --git a/include/linux/psp-sev.h b/include/linux/psp-sev.h index 903ddfea8585..613a8209bed2 100644 --- a/include/linux/psp-sev.h +++ b/include/linux/psp-sev.h @@ -594,6 +594,7 @@ struct sev_data_snp_addr { * @imi_en: launch flow is launching an IMI (Incoming Migration Image) for the * purpose of guest-assisted migration. * @rsvd: reserved + * @desired_tsc_khz: hypervisor desired mean TSC freq in kHz of the guest * @gosvw: guest OS-visible workarounds, as defined by hypervisor */ struct sev_data_snp_launch_start { @@ -603,6 +604,7 @@ struct sev_data_snp_launch_start { u32 ma_en:1; /* In */ u32 imi_en:1; /* In */ u32 rsvd:30; + u32 desired_tsc_khz; /* In */ u8 gosvw[16]; /* In */ } __packed;