Projects
Eulaceura:Mainline:GA
qemu
_service:obs_scm:target-i386-csv-add-support-to...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:target-i386-csv-add-support-to-encrypt-the-outgoing-.patch of Package qemu
From b2091d245563f4bd2974c8d8e6ef186de614f8e2 Mon Sep 17 00:00:00 2001 From: fangbaoshun <fangbaoshun@hygon.cn> Date: Mon, 2 Aug 2021 11:41:58 +0800 Subject: [PATCH] target/i386: csv: add support to encrypt the outgoing pages in the list queued before. The csv_save_queued_outgoing_pages() provide the implementation to encrypt the guest private pages during transmission. The routines uses SEND_START command to create the outgoing encryption context on the first call then uses COMMAND_BATCH command to send the SEND_UPDATE_DATA commands queued in the list to encrypt the data before writing it to the socket. While encrypting the data SEND_UPDATE_DATA produces some metadata (e.g MAC, IV). The metadata is also sent to the target machine. After migration is completed, we issue the SEND_FINISH command to transition the SEV guest state from sending to unrunnable state. Signed-off-by: hanliyang <hanliyang@hygon.cn> --- include/exec/confidential-guest-support.h | 4 ++ linux-headers/linux/kvm.h | 8 +++ target/i386/csv.h | 1 + target/i386/sev.c | 88 +++++++++++++++++++++++ target/i386/sev.h | 3 + 5 files changed, 104 insertions(+) diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h index 8949568acc..c84f8c1efc 100644 --- a/include/exec/confidential-guest-support.h +++ b/include/exec/confidential-guest-support.h @@ -80,6 +80,10 @@ struct ConfidentialGuestMemoryEncryptionOps { /* Queue the encrypted page and metadata associated with it into a list */ int (*queue_outgoing_page)(uint8_t *ptr, uint32_t size, uint64_t addr); + + /* Write the list queued with encrypted pages and metadata associated + * with them */ + int (*save_queued_outgoing_pages)(QEMUFile *f, uint64_t *bytes_sent); }; typedef struct ConfidentialGuestSupportClass { diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index ca78fdc8b6..fcd09126a1 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -1971,6 +1971,9 @@ enum sev_cmd_id { /* Guest Migration Extension */ KVM_SEV_SEND_CANCEL, + /* Hygon CSV batch command */ + KVM_CSV_COMMAND_BATCH = 0x18, + KVM_SEV_NR_MAX, }; @@ -2073,6 +2076,11 @@ struct kvm_csv_batch_list_node { __u64 next_cmd_addr; }; +struct kvm_csv_command_batch { + __u32 command_id; + __u64 csv_batch_list_uaddr; +}; + #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) #define KVM_DEV_ASSIGN_MASK_INTX (1 << 2) diff --git a/target/i386/csv.h b/target/i386/csv.h index 4c1ef20029..2a3a3119d9 100644 --- a/target/i386/csv.h +++ b/target/i386/csv.h @@ -54,5 +54,6 @@ struct CsvBatchCmdList { }; int csv_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr); +int csv_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent); #endif diff --git a/target/i386/sev.c b/target/i386/sev.c index 7dd35d64ee..1e2bbafe36 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -191,6 +191,7 @@ static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = { .save_outgoing_shared_regions_list = sev_save_outgoing_shared_regions_list, .load_incoming_shared_regions_list = sev_load_incoming_shared_regions_list, .queue_outgoing_page = csv_queue_outgoing_page, + .save_queued_outgoing_pages = csv_save_queued_outgoing_pages, }; static int @@ -2012,6 +2013,69 @@ err: return ret; } +static int +csv_command_batch(uint32_t cmd_id, uint64_t head_uaddr, int *fw_err) +{ + int ret; + struct kvm_csv_command_batch command_batch = { }; + + command_batch.command_id = cmd_id; + command_batch.csv_batch_list_uaddr = head_uaddr; + + ret = sev_ioctl(sev_guest->sev_fd, KVM_CSV_COMMAND_BATCH, + &command_batch, fw_err); + if (ret) { + error_report("%s: COMMAND_BATCH ret=%d fw_err=%d '%s'", + __func__, ret, *fw_err, fw_error_to_str(*fw_err)); + } + + return ret; +} + +static int +csv_send_update_data_batch(SevGuestState *s, QEMUFile *f, uint64_t *bytes_sent) +{ + int ret, fw_error = 0; + struct kvm_sev_send_update_data *update; + struct kvm_csv_batch_list_node *node; + + ret = csv_command_batch(KVM_SEV_SEND_UPDATE_DATA, + (uint64_t)s->csv_batch_cmd_list->head, &fw_error); + if (ret) { + error_report("%s: csv_command_batch ret=%d fw_error=%d '%s'", + __func__, ret, fw_error, fw_error_to_str(fw_error)); + goto err; + } + + for (node = s->csv_batch_cmd_list->head; + node != NULL; + node = (struct kvm_csv_batch_list_node *)node->next_cmd_addr) { + if (node != s->csv_batch_cmd_list->head) { + /* head's page header is saved before send_update_data */ + qemu_put_be64(f, node->addr); + *bytes_sent += 8; + if (node->next_cmd_addr != 0) + qemu_put_be32(f, RAM_SAVE_ENCRYPTED_PAGE_BATCH); + else + qemu_put_be32(f, RAM_SAVE_ENCRYPTED_PAGE_BATCH_END); + *bytes_sent += 4; + } + update = (struct kvm_sev_send_update_data *)node->cmd_data_addr; + qemu_put_be32(f, update->hdr_len); + qemu_put_buffer(f, (uint8_t *)update->hdr_uaddr, update->hdr_len); + *bytes_sent += (4 + update->hdr_len); + + qemu_put_be32(f, update->trans_len); + qemu_put_buffer(f, (uint8_t *)update->trans_uaddr, update->trans_len); + *bytes_sent += (4 + update->trans_len); + } + +err: + csv_batch_cmd_list_destroy(s->csv_batch_cmd_list); + s->csv_batch_cmd_list = NULL; + return ret; +} + int csv_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr) { @@ -2026,6 +2090,30 @@ csv_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr) return csv_send_queue_data(s, ptr, sz, addr); } +int +csv_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent) +{ + SevGuestState *s = sev_guest; + + /* Only support for HYGON CSV */ + if (!is_hygon_cpu()) { + error_report("Only support transfer queued pages for HYGON CSV"); + return -EINVAL; + } + + /* + * If this is a first buffer then create outgoing encryption context + * and write our PDH, policy and session data. + */ + if (!sev_check_state(s, SEV_STATE_SEND_UPDATE) && + sev_send_start(s, f, bytes_sent)) { + error_report("Failed to create outgoing context"); + return 1; + } + + return csv_send_update_data_batch(s, f, bytes_sent); +} + static const QemuUUID sev_hash_table_header_guid = { .data = UUID_LE(0x9438d606, 0x4f22, 0x4cc9, 0xb4, 0x79, 0xa7, 0x93, 0xd4, 0x11, 0xfd, 0x21) diff --git a/target/i386/sev.h b/target/i386/sev.h index 84e3bdf2df..f7886116e7 100644 --- a/target/i386/sev.h +++ b/target/i386/sev.h @@ -41,6 +41,9 @@ typedef struct SevKernelLoaderContext { #define RAM_SAVE_ENCRYPTED_PAGE 0x1 #define RAM_SAVE_SHARED_REGIONS_LIST 0x2 +#define RAM_SAVE_ENCRYPTED_PAGE_BATCH 0x4 +#define RAM_SAVE_ENCRYPTED_PAGE_BATCH_END 0x5 + #ifdef CONFIG_SEV bool sev_enabled(void); bool sev_es_enabled(void); -- 2.41.0.windows.1
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2