@samitouri / QOSamiQemu / commits / f79c89c296

target/i386: SEV: Add support for setting TSC frequency for Secure TSC

Add support for configuring the TSC frequency when Secure TSC is enabled in SEV-SNP guests through a new "tsc-frequency" property on SEV-SNP guest objects, similar to the vCPU-specific property used by regular guests and TDX. A new property is needed since SEV-SNP guests require the TSC frequency to be specified during early SNP_LAUNCH_START command before any vCPUs are created. The user-provided TSC frequency is set through KVM_SET_TSC_KHZ before issuing KVM_SEV_SNP_LAUNCH_START. Attempts to set TSC frequency on both the SEV_SNP object and the cpu object result in an error from KVM (on the vCPU ioctl), so do not add separate checks for the same. Sample command-line: -machine q35,confidential-guest-support=sev0 \ -object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1,secure-tsc=on,tsc-frequency=2500000000 Co-developed-by: Ketan Chaturvedi <Ketan.Chaturvedi@amd.com> 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> Signed-off-by: Naveen N Rao (AMD) <naveen@kernel.org> Link: https://lore.kernel.org/r/af688610978f213a456a7753e1d9fe7d3a51e80a.1779281646.git.naveen@kernel.org Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

Naveen N Rao (AMD) committed May 20, 2026 at 18:58 UTC f79c89c296896d97f5c6dc4f1635dbbe897bfdbc
2 files changed +51 -1
qapi/qom.json
+5 -1
@@ -1116,6 +1116,9 @@
1116 # @secure-tsc: enable Secure TSC
1117 # (default: false) (since 11.1)
1118 #
1119 +# @tsc-frequency: set secure TSC frequency. Only valid if Secure TSC
1120 +# is enabled (default: zero) (since 11.1)
1121 +#
1122 # Since: 9.1
1123 ##
1124 { 'struct': 'SevSnpGuestProperties',
@@ -1128,7 +1131,8 @@
1131 '*author-key-enabled': 'bool',
1132 '*host-data': 'str',
1133 '*vcek-disabled': 'bool',
1131 - '*secure-tsc': 'bool' } }
1134 + '*secure-tsc': 'bool',
1135 + '*tsc-frequency': 'uint32' } }
1136
1137 ##
1138 # @TdxGuestProperties:
target/i386/sev.c
+46
@@ -183,6 +183,7 @@ struct SevSnpGuestState {
183 char *id_auth_base64;
184 uint8_t *id_auth;
185 char *host_data;
186 + uint32_t tsc_khz;
187
188 struct kvm_sev_snp_launch_start kvm_start_conf;
189 struct kvm_sev_snp_launch_finish kvm_finish_conf;
@@ -547,6 +548,13 @@ static int check_sev_features(SevCommonState *sev_common, uint64_t sev_features,
548 __func__, sev_features, sev_common->supported_sev_features);
549 return -1;
550 }
551 + if (sev_snp_enabled() && SEV_SNP_GUEST(sev_common)->tsc_khz &&
552 + !(sev_features & SVM_SEV_FEAT_SECURE_TSC)) {
553 + error_setg(errp,
554 + "%s: TSC frequency can only be set if Secure TSC is enabled",
555 + __func__);
556 + return -1;
557 + }
558 return 0;
559 }
560
@@ -1095,6 +1103,19 @@ sev_snp_launch_start(SevCommonState *sev_common)
1103 return 1;
1104 }
1105
1106 + if (is_sev_feature_set(sev_common, SVM_SEV_FEAT_SECURE_TSC) &&
1107 + sev_snp_guest->tsc_khz) {
1108 + rc = -EINVAL;
1109 + if (kvm_check_extension(kvm_state, KVM_CAP_VM_TSC_CONTROL)) {
1110 + rc = kvm_vm_ioctl(kvm_state, KVM_SET_TSC_KHZ, sev_snp_guest->tsc_khz);
1111 + }
1112 + if (rc < 0) {
1113 + error_report("%s: Unable to set Secure TSC frequency to %u kHz ret=%d",
1114 + __func__, sev_snp_guest->tsc_khz, rc);
1115 + return 1;
1116 + }
1117 + }
1118 +
1119 rc = sev_ioctl(sev_common->sev_fd, KVM_SEV_SNP_LAUNCH_START,
1120 start, &fw_error);
1121 if (rc < 0) {
@@ -3222,6 +3243,28 @@ static void sev_snp_guest_set_secure_tsc(Object *obj, bool value, Error **errp)
3243 sev_set_feature(SEV_COMMON(obj), SVM_SEV_FEAT_SECURE_TSC, value);
3244 }
3245
3246 +static void
3247 +sev_snp_guest_get_tsc_frequency(Object *obj, Visitor *v, const char *name,
3248 + void *opaque, Error **errp)
3249 +{
3250 + uint32_t value = SEV_SNP_GUEST(obj)->tsc_khz * 1000;
3251 +
3252 + visit_type_uint32(v, name, &value, errp);
3253 +}
3254 +
3255 +static void
3256 +sev_snp_guest_set_tsc_frequency(Object *obj, Visitor *v, const char *name,
3257 + void *opaque, Error **errp)
3258 +{
3259 + uint32_t value;
3260 +
3261 + if (!visit_type_uint32(v, name, &value, errp)) {
3262 + return;
3263 + }
3264 +
3265 + SEV_SNP_GUEST(obj)->tsc_khz = value / 1000;
3266 +}
3267 +
3268 static void
3269 sev_snp_guest_class_init(ObjectClass *oc, const void *data)
3270 {
@@ -3260,6 +3303,9 @@ sev_snp_guest_class_init(ObjectClass *oc, const void *data)
3303 object_class_property_add_bool(oc, "secure-tsc",
3304 sev_snp_guest_get_secure_tsc,
3305 sev_snp_guest_set_secure_tsc);
3306 + object_class_property_add(oc, "tsc-frequency", "uint32",
3307 + sev_snp_guest_get_tsc_frequency,
3308 + sev_snp_guest_set_tsc_frequency, NULL, NULL);
3309 }
3310
3311 static void