From: Brijesh Singh <brijesh.singh@xxxxxxx> The KVM_SEV_SNP_LAUNCH_UPDATE command is used for encrypting the bios image used for booting the SEV-SNP guest. Signed-off-by: Brijesh Singh <brijesh.singh@xxxxxxx> Signed-off-by: Michael Roth <michael.roth@xxxxxxx> --- hw/i386/pc_sysfw.c | 7 ++++--- include/sysemu/sev.h | 2 +- target/i386/sev-stub.c | 2 +- target/i386/sev.c | 40 ++++++++++++++++++++++++++++++++++++++-- target/i386/trace-events | 1 + 5 files changed, 45 insertions(+), 7 deletions(-) diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c index 68d6b1f783..54ccf13c0e 100644 --- a/hw/i386/pc_sysfw.c +++ b/hw/i386/pc_sysfw.c @@ -149,6 +149,7 @@ static void pc_system_flash_map(PCMachineState *pcms, void *flash_ptr; int flash_size; int ret; + hwaddr gpa; assert(PC_MACHINE_GET_CLASS(pcms)->pci_enabled); @@ -182,11 +183,11 @@ static void pc_system_flash_map(PCMachineState *pcms, } total_size += size; + gpa = 0x100000000ULL - total_size; /* where the flash is mapped */ qdev_prop_set_uint32(DEVICE(system_flash), "num-blocks", size / FLASH_SECTOR_SIZE); sysbus_realize_and_unref(SYS_BUS_DEVICE(system_flash), &error_fatal); - sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0, - 0x100000000ULL - total_size); + sysbus_mmio_map(SYS_BUS_DEVICE(system_flash), 0, gpa); if (i == 0) { flash_mem = pflash_cfi01_get_memory(system_flash); @@ -208,7 +209,7 @@ static void pc_system_flash_map(PCMachineState *pcms, exit(1); } - sev_encrypt_flash(flash_ptr, flash_size, &error_fatal); + sev_encrypt_flash(gpa, flash_ptr, flash_size, &error_fatal); } } } diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h index 94d821d737..78e3bf97e8 100644 --- a/include/sysemu/sev.h +++ b/include/sysemu/sev.h @@ -18,7 +18,7 @@ bool sev_enabled(void); int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp); -int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp); +int sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp); int sev_inject_launch_secret(const char *hdr, const char *secret, uint64_t gpa, Error **errp); diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c index e4fb8e882e..8b35704937 100644 --- a/target/i386/sev-stub.c +++ b/target/i386/sev-stub.c @@ -56,7 +56,7 @@ int sev_inject_launch_secret(const char *hdr, const char *secret, return 1; } -int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp) +int sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp) { return 0; } diff --git a/target/i386/sev.c b/target/i386/sev.c index 51689d4fa4..867c0cb457 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -946,6 +946,35 @@ out: return ret; } +static int +sev_snp_launch_update(SevSnpGuestState *sev_snp_guest, hwaddr gpa, uint8_t *addr, + uint64_t len, int type) +{ + int ret, fw_error; + struct kvm_sev_snp_launch_update update = {0}; + + if (!addr || !len) { + error_report("%s: SNP_LAUNCH_UPDATE called with invalid address / length: %lx / %lx", + __func__, gpa, len); + return 1; + } + + update.uaddr = (__u64)(unsigned long)addr; + update.start_gfn = gpa >> TARGET_PAGE_BITS; + update.len = len; + update.page_type = type; + trace_kvm_sev_snp_launch_update(addr, len, type); + ret = sev_ioctl(SEV_COMMON(sev_snp_guest)->sev_fd, + KVM_SEV_SNP_LAUNCH_UPDATE, + &update, &fw_error); + if (ret) { + error_report("%s: SNP_LAUNCH_UPDATE ret=%d fw_error=%d '%s'", + __func__, ret, fw_error, fw_error_to_str(fw_error)); + } + + return ret; +} + static int sev_launch_update_data(SevGuestState *sev_guest, uint8_t *addr, uint64_t len) { @@ -1219,7 +1248,7 @@ err: } int -sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp) +sev_encrypt_flash(hwaddr gpa, uint8_t *ptr, uint64_t len, Error **errp) { SevCommonState *sev_common = SEV_COMMON(MACHINE(qdev_get_machine())->cgs); @@ -1229,7 +1258,14 @@ sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp) /* if SEV is in update state then encrypt the data else do nothing */ if (sev_check_state(sev_common, SEV_STATE_LAUNCH_UPDATE)) { - int ret = sev_launch_update_data(SEV_GUEST(sev_common), ptr, len); + int ret; + + if (sev_snp_enabled()) { + ret = sev_snp_launch_update(SEV_SNP_GUEST(sev_common), gpa, ptr, + len, KVM_SEV_SNP_PAGE_TYPE_NORMAL); + } else { + ret = sev_launch_update_data(SEV_GUEST(sev_common), ptr, len); + } if (ret < 0) { error_setg(errp, "failed to encrypt pflash rom"); return ret; diff --git a/target/i386/trace-events b/target/i386/trace-events index 18cc14b956..0c2d250206 100644 --- a/target/i386/trace-events +++ b/target/i386/trace-events @@ -12,3 +12,4 @@ kvm_sev_launch_finish(void) "" kvm_sev_launch_secret(uint64_t hpa, uint64_t hva, uint64_t secret, int len) "hpa 0x%" PRIx64 " hva 0x%" PRIx64 " data 0x%" PRIx64 " len %d" kvm_sev_attestation_report(const char *mnonce, const char *data) "mnonce %s data %s" kvm_sev_snp_launch_start(uint64_t policy) "policy 0x%" PRIx64 +kvm_sev_snp_launch_update(void *addr, uint64_t len, int type) "addr %p len 0x%" PRIx64 " type %d" -- 2.25.1