From a236548a903aa8350fff9601d481b2f529c8d4a7 Mon Sep 17 00:00:00 2001 From: Pankaj Gupta Date: Thu, 30 May 2024 06:16:21 -0500 Subject: [PATCH 061/100] i386/sev: Add sev_kvm_init() override for SEV class RH-Author: Paolo Bonzini RH-MergeRequest: 245: SEV-SNP support RH-Jira: RHEL-39544 RH-Acked-by: Thomas Huth RH-Acked-by: Bandan Das RH-Acked-by: Vitaly Kuznetsov RH-Commit: [61/91] b24fcbc8712e7394e029312229da023c63803969 (bonzini/rhel-qemu-kvm) Some aspects of the init routine SEV are specific to SEV and not applicable for SNP guests, so move the SEV-specific bits into separate class method and retain only the common functionality. Co-developed-by: Michael Roth Signed-off-by: Michael Roth Signed-off-by: Pankaj Gupta Message-ID: <20240530111643.1091816-10-pankaj.gupta@amd.com> Signed-off-by: Paolo Bonzini (cherry picked from commit 990da8d243a8c59dafcbed78b56a0e4ffb1605d9) Signed-off-by: Paolo Bonzini --- target/i386/sev.c | 72 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 51 insertions(+), 21 deletions(-) diff --git a/target/i386/sev.c b/target/i386/sev.c index 4edfedc139..5519de1c6b 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -73,6 +73,7 @@ struct SevCommonStateClass { /* public */ int (*launch_start)(SevCommonState *sev_common); void (*launch_finish)(SevCommonState *sev_common); + int (*kvm_init)(ConfidentialGuestSupport *cgs, Error **errp); }; /** @@ -882,7 +883,7 @@ out: return sev_common->kvm_type; } -static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) +static int sev_common_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) { SevCommonState *sev_common = SEV_COMMON(cgs); char *devname; @@ -892,12 +893,6 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) struct sev_user_data_status status = {}; SevCommonStateClass *klass = SEV_COMMON_GET_CLASS(cgs); - ret = ram_block_discard_disable(true); - if (ret) { - error_report("%s: cannot disable RAM discard", __func__); - return -1; - } - sev_common->state = SEV_STATE_UNINIT; host_cpuid(0x8000001F, 0, NULL, &ebx, NULL, NULL); @@ -911,7 +906,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) if (host_cbitpos != sev_common->cbitpos) { error_setg(errp, "%s: cbitpos check failed, host '%d' requested '%d'", __func__, host_cbitpos, sev_common->cbitpos); - goto err; + return -1; } /* @@ -924,7 +919,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) error_setg(errp, "%s: reduced_phys_bits check failed," " it should be in the range of 1 to 63, requested '%d'", __func__, sev_common->reduced_phys_bits); - goto err; + return -1; } devname = object_property_get_str(OBJECT(sev_common), "sev-device", NULL); @@ -933,7 +928,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) error_setg(errp, "%s: Failed to open %s '%s'", __func__, devname, strerror(errno)); g_free(devname); - goto err; + return -1; } g_free(devname); @@ -943,7 +938,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) error_setg(errp, "%s: failed to get platform status ret=%d " "fw_error='%d: %s'", __func__, ret, fw_error, fw_error_to_str(fw_error)); - goto err; + return -1; } sev_common->build_id = status.build; sev_common->api_major = status.api_major; @@ -953,7 +948,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) if (!kvm_kernel_irqchip_allowed()) { error_setg(errp, "%s: SEV-ES guests require in-kernel irqchip" "support", __func__); - goto err; + return -1; } } @@ -962,7 +957,7 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) error_setg(errp, "%s: guest policy requires SEV-ES, but " "host SEV-ES support unavailable", __func__); - goto err; + return -1; } } @@ -980,25 +975,59 @@ static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) if (ret) { error_setg(errp, "%s: failed to initialize ret=%d fw_error=%d '%s'", __func__, ret, fw_error, fw_error_to_str(fw_error)); - goto err; + return -1; } ret = klass->launch_start(sev_common); if (ret) { error_setg(errp, "%s: failed to create encryption context", __func__); - goto err; + return -1; + } + + if (klass->kvm_init && klass->kvm_init(cgs, errp)) { + return -1; } - ram_block_notifier_add(&sev_ram_notifier); - qemu_add_machine_init_done_notifier(&sev_machine_done_notify); qemu_add_vm_change_state_handler(sev_vm_state_change, sev_common); cgs->ready = true; return 0; -err: - ram_block_discard_disable(false); - return -1; +} + +static int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) +{ + int ret; + + /* + * SEV/SEV-ES rely on pinned memory to back guest RAM so discarding + * isn't actually possible. With SNP, only guest_memfd pages are used + * for private guest memory, so discarding of shared memory is still + * possible.. + */ + ret = ram_block_discard_disable(true); + if (ret) { + error_setg(errp, "%s: cannot disable RAM discard", __func__); + return -1; + } + + /* + * SEV uses these notifiers to register/pin pages prior to guest use, + * but SNP relies on guest_memfd for private pages, which has its + * own internal mechanisms for registering/pinning private memory. + */ + ram_block_notifier_add(&sev_ram_notifier); + + /* + * The machine done notify event is used for SEV guests to get the + * measurement of the encrypted images. When SEV-SNP is enabled, the + * measurement is part of the guest attestation process where it can + * be collected without any reliance on the VMM. So skip registering + * the notifier for SNP in favor of using guest attestation instead. + */ + qemu_add_machine_init_done_notifier(&sev_machine_done_notify); + + return 0; } int @@ -1397,7 +1426,7 @@ sev_common_class_init(ObjectClass *oc, void *data) ConfidentialGuestSupportClass *klass = CONFIDENTIAL_GUEST_SUPPORT_CLASS(oc); X86ConfidentialGuestClass *x86_klass = X86_CONFIDENTIAL_GUEST_CLASS(oc); - klass->kvm_init = sev_kvm_init; + klass->kvm_init = sev_common_kvm_init; x86_klass->kvm_type = sev_kvm_type; object_class_property_add_str(oc, "sev-device", @@ -1486,6 +1515,7 @@ sev_guest_class_init(ObjectClass *oc, void *data) klass->launch_start = sev_launch_start; klass->launch_finish = sev_launch_finish; + klass->kvm_init = sev_kvm_init; object_class_property_add_str(oc, "dh-cert-file", sev_guest_get_dh_cert_file, -- 2.39.3