diff --git a/0002-anolis-csv-i386-add-CSV-context.patch b/0002-anolis-csv-i386-add-CSV-context.patch new file mode 100644 index 0000000000000000000000000000000000000000..72cb6ae9356b2c2b4c48e61d94df6c9ab6aa8a8e --- /dev/null +++ b/0002-anolis-csv-i386-add-CSV-context.patch @@ -0,0 +1,195 @@ +From 0080a84a9fe46aea59773975d9aebbc18a6cb210 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Tue, 24 Aug 2021 14:57:28 +0800 +Subject: [PATCH 2/9] anolis: csv/i386: add CSV context + +CSV is the secure virtualization feature on Hygon CPU. +It is compatible with the AMD SEV/SEV-ES and extends out +specific funtionality by setting bit 6 of guest policy. + +Add the context and the build option. + +Signed-off-by: Xin Jiang +Change-Id: I5dba29a487e3a763c832ac30cef5c7fe63eac26a +--- + configs/devices/i386-softmmu/default.mak | 1 + + hw/i386/Kconfig | 5 +++ + target/i386/csv-sysemu-stub.c | 16 ++++++++ + target/i386/csv.c | 51 ++++++++++++++++++++++++ + target/i386/csv.h | 35 ++++++++++++++++ + target/i386/meson.build | 1 + + 6 files changed, 109 insertions(+) + create mode 100644 target/i386/csv-sysemu-stub.c + create mode 100644 target/i386/csv.c + create mode 100644 target/i386/csv.h + +diff --git a/configs/devices/i386-softmmu/default.mak b/configs/devices/i386-softmmu/default.mak +index 598c6646df..db83ffcab9 100644 +--- a/configs/devices/i386-softmmu/default.mak ++++ b/configs/devices/i386-softmmu/default.mak +@@ -23,6 +23,7 @@ + #CONFIG_TPM_TIS_ISA=n + #CONFIG_VTD=n + #CONFIG_SGX=n ++#CONFIG_CSV=n + + # Boards: + # +diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig +index d22ac4a4b9..ed35d762b3 100644 +--- a/hw/i386/Kconfig ++++ b/hw/i386/Kconfig +@@ -10,6 +10,10 @@ config SGX + bool + depends on KVM + ++config CSV ++ bool ++ depends on SEV ++ + config PC + bool + imply APPLESMC +@@ -26,6 +30,7 @@ config PC + imply QXL + imply SEV + imply SGX ++ imply CSV + imply SGA + imply TEST_DEVICES + imply TPM_CRB +diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c +new file mode 100644 +index 0000000000..a89b2600e7 +--- /dev/null ++++ b/target/i386/csv-sysemu-stub.c +@@ -0,0 +1,16 @@ ++/* ++ * QEMU CSV support ++ * ++ * Copyright: Hygon Info Technologies Ltd. 2022 ++ * ++ * Author: ++ * Jiang Xin ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#include "qemu/osdep.h" ++#include "sev.h" ++#include "csv.h" +diff --git a/target/i386/csv.c b/target/i386/csv.c +new file mode 100644 +index 0000000000..aac825d3f9 +--- /dev/null ++++ b/target/i386/csv.c +@@ -0,0 +1,51 @@ ++/* ++ * QEMU CSV support ++ * ++ * Copyright: Hygon Info Technologies Ltd. 2022 ++ * ++ * Author: ++ * Jiang Xin ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#include "qemu/osdep.h" ++ ++#include "cpu.h" ++#include "sev.h" ++#include "csv.h" ++ ++CsvGuestState csv_guest = { 0 }; ++ ++#define CPUID_VENDOR_HYGON_EBX 0x6f677948 /* "Hygo" */ ++#define CPUID_VENDOR_HYGON_ECX 0x656e6975 /* "uine" */ ++#define CPUID_VENDOR_HYGON_EDX 0x6e65476e /* "nGen" */ ++ ++#define GUEST_POLICY_CSV_BIT (1 << 6) ++ ++static bool is_hygon_cpu(void) ++{ ++ uint32_t ebx = 0; ++ uint32_t ecx = 0; ++ uint32_t edx = 0; ++ ++ host_cpuid(0, 0, NULL, &ebx, &ecx, &edx); ++ ++ if (ebx == CPUID_VENDOR_HYGON_EBX && ++ ecx == CPUID_VENDOR_HYGON_ECX && ++ edx == CPUID_VENDOR_HYGON_EDX) ++ return true; ++ else ++ return false; ++} ++ ++bool ++csv_enabled(void) ++{ ++ if (!is_hygon_cpu()) ++ return false; ++ ++ return sev_es_enabled() && (csv_guest.policy & GUEST_POLICY_CSV_BIT); ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +new file mode 100644 +index 0000000000..057d37d975 +--- /dev/null ++++ b/target/i386/csv.h +@@ -0,0 +1,35 @@ ++/* ++ * QEMU CSV support ++ * ++ * Copyright: Hygon Info Technologies Ltd. 2022 ++ * ++ * Author: ++ * Jiang Xin ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or later. ++ * See the COPYING file in the top-level directory. ++ * ++ */ ++ ++#ifndef QEMU_CSV_H ++#define QEMU_CSV_H ++ ++#include "qapi/qapi-commands-misc-target.h" ++ ++#ifdef CONFIG_CSV ++bool csv_enabled(void); ++#else ++#define csv_enabled() 0 ++#endif ++ ++struct CsvGuestState { ++ uint32_t policy; ++ int sev_fd; ++ void *state; ++}; ++ ++typedef struct CsvGuestState CsvGuestState; ++ ++extern struct CsvGuestState csv_guest; ++ ++#endif +diff --git a/target/i386/meson.build b/target/i386/meson.build +index ae38dc9563..361dea9290 100644 +--- a/target/i386/meson.build ++++ b/target/i386/meson.build +@@ -21,6 +21,7 @@ i386_softmmu_ss.add(files( + 'cpu-sysemu.c', + )) + i386_softmmu_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-sysemu-stub.c')) ++i386_softmmu_ss.add(when: 'CONFIG_CSV', if_true: files('csv.c'), if_false: files('csv-sysemu-stub.c')) + + i386_user_ss = ss.source_set() + +-- +2.17.1 + diff --git a/0003-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch b/0003-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch new file mode 100644 index 0000000000000000000000000000000000000000..d4144f745d6068b8900f51403cb179dc05cf45f5 --- /dev/null +++ b/0003-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch @@ -0,0 +1,204 @@ +From e9343731c5de9052c0ea8faaec4f04e1bf23c7b6 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 11:07:41 +0800 +Subject: [PATCH 3/9] anolis: csv/i386: add command to initialize CSV context + +When CSV is enabled, KVM_CSV_INIT command is used to initialize +the platform, which is implemented by reusing the SEV API +framework and extending the functionality. + +The KVM_CSV_INIT command should be performed earlier than +any other command. + +Signed-off-by: Xin Jiang +Change-Id: I20573286b621c38432384c1d6e198fc85d88f38e +--- + linux-headers/linux/kvm.h | 11 +++++++++ + target/i386/csv-sysemu-stub.c | 5 ++++ + target/i386/csv.c | 44 +++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 3 +++ + target/i386/sev.c | 17 ++++++++++++++ + target/i386/sev.h | 5 ++++ + 6 files changed, 85 insertions(+) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index ebdafa576d..a67173cef0 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1983,6 +1983,17 @@ struct kvm_sev_receive_update_data { + __u32 trans_len; + }; + ++/* CSV command */ ++enum csv_cmd_id { ++ KVM_CSV_NR_MIN = 0xc0, ++ ++ KVM_CSV_INIT = KVM_CSV_NR_MIN, ++}; ++ ++struct kvm_csv_init_data { ++ __u64 nodemask; ++}; ++ + #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-sysemu-stub.c b/target/i386/csv-sysemu-stub.c +index a89b2600e7..dbd710dc6f 100644 +--- a/target/i386/csv-sysemu-stub.c ++++ b/target/i386/csv-sysemu-stub.c +@@ -14,3 +14,8 @@ + #include "qemu/osdep.h" + #include "sev.h" + #include "csv.h" ++ ++int csv_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) ++{ ++ return 0; ++} +diff --git a/target/i386/csv.c b/target/i386/csv.c +index aac825d3f9..c11f59f30c 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -13,6 +13,12 @@ + + #include "qemu/osdep.h" + ++#include ++ ++#ifdef CONFIG_NUMA ++#include ++#endif ++ + #include "cpu.h" + #include "sev.h" + #include "csv.h" +@@ -41,6 +47,44 @@ static bool is_hygon_cpu(void) + return false; + } + ++int ++csv_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) ++{ ++ int fw_error; ++ int ret; ++ struct kvm_csv_init_data data = { 0 }; ++ ++#ifdef CONFIG_NUMA ++ int mode; ++ unsigned long nodemask; ++ ++ /* Set flags as 0 to retrieve the default NUMA policy. */ ++ ret = get_mempolicy(&mode, &nodemask, sizeof(nodemask) * 8, NULL, 0); ++ if (ret == 0 && (mode == MPOL_BIND)) ++ data.nodemask = nodemask; ++#endif ++ ++ if (!ops || !ops->sev_ioctl || !ops->fw_error_to_str) ++ return -1; ++ ++ csv_guest.policy = policy; ++ if (csv_enabled()) { ++ ret = ops->sev_ioctl(fd, KVM_CSV_INIT, &data, &fw_error); ++ if (ret) { ++ csv_guest.policy = 0; ++ error_report("%s: Fail to initialize ret=%d fw_error=%d '%s'", ++ __func__, ret, fw_error, ops->fw_error_to_str(fw_error)); ++ return -1; ++ } ++ ++ csv_guest.sev_fd = fd; ++ csv_guest.state = state; ++ csv_guest.sev_ioctl = ops->sev_ioctl; ++ csv_guest.fw_error_to_str = ops->fw_error_to_str; ++ } ++ return 0; ++} ++ + bool + csv_enabled(void) + { +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 057d37d975..886dbb2613 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -26,10 +26,13 @@ struct CsvGuestState { + uint32_t policy; + int sev_fd; + void *state; ++ int (*sev_ioctl)(int fd, int cmd, void *data, int *error); ++ const char *(*fw_error_to_str)(int code); + }; + + typedef struct CsvGuestState CsvGuestState; + + extern struct CsvGuestState csv_guest; ++extern int csv_init(uint32_t policy, int fd, void *state, struct sev_ops *ops); + + #endif +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 32f7dbac4e..20507da004 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -26,6 +26,7 @@ + #include "crypto/hash.h" + #include "sysemu/kvm.h" + #include "sev.h" ++#include "csv.h" + #include "sysemu/sysemu.h" + #include "sysemu/runstate.h" + #include "trace.h" +@@ -43,6 +44,8 @@ + OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST) + + ++extern struct sev_ops sev_ops; ++ + /** + * SevGuestState: + * +@@ -992,6 +995,15 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) + goto err; + } + ++ /* Support CSV */ ++ if (!ret && cmd == KVM_SEV_ES_INIT) { ++ ret = csv_init(sev_guest->policy, sev->sev_fd, (void *)&sev->state, &sev_ops); ++ if (ret) { ++ error_setg(errp, "%s: failed to init csv context", __func__); ++ goto err; ++ } ++ } ++ + ret = sev_launch_start(sev); + if (ret) { + error_setg(errp, "%s: failed to create encryption context", __func__); +@@ -1372,6 +1384,11 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) + return ret; + } + ++struct sev_ops sev_ops = { ++ .sev_ioctl = sev_ioctl, ++ .fw_error_to_str = fw_error_to_str, ++}; ++ + static void + sev_register_types(void) + { +diff --git a/target/i386/sev.h b/target/i386/sev.h +index 7b1528248a..0a82f97f35 100644 +--- a/target/i386/sev.h ++++ b/target/i386/sev.h +@@ -59,4 +59,9 @@ void sev_es_set_reset_vector(CPUState *cpu); + + int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp); + ++struct sev_ops { ++ int (*sev_ioctl)(int fd, int cmd, void *data, int *error); ++ const char *(*fw_error_to_str)(int code); ++}; ++ + #endif +-- +2.17.1 + diff --git a/0004-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch b/0004-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b11faaf0766f3ecce097698459768bda09c1134 --- /dev/null +++ b/0004-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch @@ -0,0 +1,164 @@ +From 13d1098ac04a90ed183877133a30b791bd00b56d Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 09:59:16 +0800 +Subject: [PATCH 4/9] anolis: csv/i386: add command to load data to guest + memory + +The KVM_CSV_LAUNCH_ENCRYPT_DATA command is used to load data to an +encrypted guest memory in an isolated memory region that guest owns. + +Signed-off-by: Xin Jiang +Change-Id: Ibebef9ad29a411d93936b373b3b2e874e56e40f4 +--- + linux-headers/linux/kvm.h | 7 ++++ + target/i386/csv-sysemu-stub.c | 5 +++ + target/i386/csv.c | 69 +++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 2 + + target/i386/trace-events | 3 ++ + 5 files changed, 86 insertions(+) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index a67173cef0..456aed121f 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1988,6 +1988,13 @@ enum csv_cmd_id { + KVM_CSV_NR_MIN = 0xc0, + + KVM_CSV_INIT = KVM_CSV_NR_MIN, ++ KVM_CSV_LAUNCH_ENCRYPT_DATA, ++}; ++ ++struct kvm_csv_launch_encrypt_data { ++ __u64 gpa; ++ __u64 uaddr; ++ __u32 len; + }; + + struct kvm_csv_init_data { +diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c +index dbd710dc6f..236a6909d2 100644 +--- a/target/i386/csv-sysemu-stub.c ++++ b/target/i386/csv-sysemu-stub.c +@@ -19,3 +19,8 @@ int csv_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) + { + return 0; + } ++ ++int csv_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp) ++{ ++ g_assert_not_reached(); ++} +diff --git a/target/i386/csv.c b/target/i386/csv.c +index c11f59f30c..3b3dff5174 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -14,11 +14,13 @@ + #include "qemu/osdep.h" + + #include ++#include "qapi/error.h" + + #ifdef CONFIG_NUMA + #include + #endif + ++#include "trace.h" + #include "cpu.h" + #include "sev.h" + #include "csv.h" +@@ -93,3 +95,70 @@ csv_enabled(void) + + return sev_es_enabled() && (csv_guest.policy & GUEST_POLICY_CSV_BIT); + } ++ ++static bool ++csv_check_state(SevState state) ++{ ++ return *((SevState *)csv_guest.state) == state ? true : false; ++} ++ ++static int ++csv_ioctl(int cmd, void *data, int *error) ++{ ++ if (csv_guest.sev_ioctl) ++ return csv_guest.sev_ioctl(csv_guest.sev_fd, cmd, data, error); ++ else ++ return -1; ++} ++ ++static const char * ++fw_error_to_str(int code) ++{ ++ if (csv_guest.fw_error_to_str) ++ return csv_guest.fw_error_to_str(code); ++ else ++ return NULL; ++} ++ ++static int ++csv_launch_encrypt_data(uint64_t gpa, uint8_t *addr, uint64_t len) ++{ ++ int ret, fw_error; ++ struct kvm_csv_launch_encrypt_data update; ++ ++ if (!addr || !len) { ++ return 1; ++ } ++ ++ update.gpa = (__u64)gpa; ++ update.uaddr = (__u64)(unsigned long)addr; ++ update.len = len; ++ trace_kvm_csv_launch_encrypt_data(gpa, addr, len); ++ ret = csv_ioctl(KVM_CSV_LAUNCH_ENCRYPT_DATA, &update, &fw_error); ++ if (ret) { ++ error_report("%s: CSV LAUNCH_ENCRYPT_DATA ret=%d fw_error=%d '%s'", ++ __func__, ret, fw_error, fw_error_to_str(fw_error)); ++ } ++ ++ return ret; ++} ++ ++int ++csv_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp) ++{ ++ int ret = 0; ++ ++ if (!csv_enabled()) { ++ error_setg(errp, "%s: CSV is not enabled", __func__); ++ return -1; ++ } ++ ++ /* if CSV is in update state then load the data to secure memory */ ++ if (csv_check_state(SEV_STATE_LAUNCH_UPDATE)) { ++ ret = csv_launch_encrypt_data(gpa, ptr, len); ++ if (ret) ++ error_setg(errp, "%s: CSV fail to encrypt data", __func__); ++ } ++ ++ return ret; ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 886dbb2613..6f7b112d96 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -35,4 +35,6 @@ typedef struct CsvGuestState CsvGuestState; + extern struct CsvGuestState csv_guest; + extern int csv_init(uint32_t policy, int fd, void *state, struct sev_ops *ops); + ++int csv_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); ++ + #endif +diff --git a/target/i386/trace-events b/target/i386/trace-events +index 2cd8726eeb..b7da9bd748 100644 +--- a/target/i386/trace-events ++++ b/target/i386/trace-events +@@ -11,3 +11,6 @@ kvm_sev_launch_measurement(const char *value) "data %s" + 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" ++ ++# csv.c ++kvm_csv_launch_encrypt_data(uint64_t gpa, void *addr, uint64_t len) "gpa 0x%" PRIx64 "addr %p len 0x%" PRIu64 +-- +2.17.1 + diff --git a/0005-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch b/0005-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch new file mode 100644 index 0000000000000000000000000000000000000000..843943c10da6f13eef4fc8a044fcdefd43ef51e1 --- /dev/null +++ b/0005-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch @@ -0,0 +1,107 @@ +From 0c10f36276fef9f5983dc4b503aff6abf6af5961 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 12:25:05 +0800 +Subject: [PATCH 5/9] anolis: csv/i386: add command to load vmcb to guest + memory + +The KVM_CSV_LAUNCH_ENCRYPT_VMCB command is used to load and encrypt +the initial VMCB data to secure memory in an isolated region +that guest owns. + +Signed-off-by: Xin Jiang +Change-Id: I9dacc9e6b1b73c168b28a88b96c298bba4baa1ee +--- + linux-headers/linux/kvm.h | 1 + + target/i386/csv-sysemu-stub.c | 5 +++++ + target/i386/csv.c | 21 +++++++++++++++++++++ + target/i386/csv.h | 1 + + target/i386/sev.c | 7 +++++-- + 5 files changed, 33 insertions(+), 2 deletions(-) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 456aed121f..e5b45c384d 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1989,6 +1989,7 @@ enum csv_cmd_id { + + KVM_CSV_INIT = KVM_CSV_NR_MIN, + KVM_CSV_LAUNCH_ENCRYPT_DATA, ++ KVM_CSV_LAUNCH_ENCRYPT_VMCB, + }; + + struct kvm_csv_launch_encrypt_data { +diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c +index 236a6909d2..a5ce986e3c 100644 +--- a/target/i386/csv-sysemu-stub.c ++++ b/target/i386/csv-sysemu-stub.c +@@ -24,3 +24,8 @@ int csv_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp) + { + g_assert_not_reached(); + } ++ ++int csv_launch_encrypt_vmcb(void) ++{ ++ g_assert_not_reached(); ++} +diff --git a/target/i386/csv.c b/target/i386/csv.c +index 3b3dff5174..d166d3775e 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -162,3 +162,24 @@ csv_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp) + + return ret; + } ++ ++int ++csv_launch_encrypt_vmcb(void) ++{ ++ int ret, fw_error; ++ ++ if (!csv_enabled()) { ++ error_report("%s: CSV is not enabled",__func__); ++ return -1; ++ } ++ ++ ret = csv_ioctl(KVM_CSV_LAUNCH_ENCRYPT_VMCB, NULL, &fw_error); ++ if (ret) { ++ error_report("%s: CSV LAUNCH_ENCRYPT_VMCB ret=%d fw_error=%d '%s'", ++ __func__, ret, fw_error, fw_error_to_str(fw_error)); ++ goto err; ++ } ++ ++err: ++ return ret; ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 6f7b112d96..640eafd45b 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -34,6 +34,7 @@ typedef struct CsvGuestState CsvGuestState; + + extern struct CsvGuestState csv_guest; + extern int csv_init(uint32_t policy, int fd, void *state, struct sev_ops *ops); ++extern int csv_launch_encrypt_vmcb(void); + + int csv_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); + +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 20507da004..efbe48fc30 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -810,8 +810,11 @@ sev_launch_get_measure(Notifier *notifier, void *unused) + } + + if (sev_es_enabled()) { +- /* measure all the VM save areas before getting launch_measure */ +- ret = sev_launch_update_vmsa(sev); ++ if (csv_enabled()) ++ ret = csv_launch_encrypt_vmcb(); ++ else ++ /* measure all the VM save areas before getting launch_measure */ ++ ret = sev_launch_update_vmsa(sev); + if (ret) { + exit(1); + } +-- +2.17.1 + diff --git a/0006-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch b/0006-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch new file mode 100644 index 0000000000000000000000000000000000000000..82b079ff46ed1f657395431e030786603026bc0e --- /dev/null +++ b/0006-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch @@ -0,0 +1,41 @@ +From 2ab84ef10562be99e01e2407daaef8bdaf2a89e8 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Tue, 24 Aug 2021 17:31:28 +0800 +Subject: [PATCH 6/9] anolis: cpu/i386: populate CPUID 0x8000_001F when CSV is + active + +On Hygon platform, bit 30 of EAX indicates whether +this feature is supported in hardware. + +When CSV is active, CPUID 0x8000_001F provides +information for it. + +Signed-off-by: Xin Jiang +Change-Id: I19322a73d0df091c0bbb4ca2a3cc5f4225cc2c9f +--- + target/i386/cpu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 0f71ff9fea..f8e7498971 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -28,6 +28,7 @@ + #include "sysemu/hvf.h" + #include "kvm/kvm_i386.h" + #include "sev.h" ++#include "csv.h" + #include "qapi/error.h" + #include "qapi/qapi-visit-machine.h" + #include "qapi/qmp/qerror.h" +@@ -5853,6 +5854,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + if (sev_enabled()) { + *eax = 0x2; + *eax |= sev_es_enabled() ? 0x8 : 0; ++ *eax |= csv_enabled() ? 0x40000000 : 0; /* bit 30 for CSV */ + *ebx = sev_get_cbit_position(); + *ebx |= sev_get_reduced_phys_bits() << 6; + } +-- +2.17.1 + diff --git a/0007-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch b/0007-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch new file mode 100644 index 0000000000000000000000000000000000000000..76da826ccc264ae7cc4479f78449d1f3d68477de --- /dev/null +++ b/0007-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch @@ -0,0 +1,35 @@ +From 98df47b94deeee784e36f6084b2ac8c18b4d51f1 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 12:36:00 +0800 +Subject: [PATCH 7/9] anolis: csv/i386: CSV guest do not need + register/unregister guest secure memory + +CSV guest memory is allocated by firmware in secure processor +from dedicated memory reserved upon system boot up, +consequently it is not necessary to add notifier to pin/unpin memory. + +Signed-off-by: Xin Jiang +Change-Id: Idfe109b3925971ed71116bed2975133255ba11cc +--- + target/i386/sev.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/target/i386/sev.c b/target/i386/sev.c +index efbe48fc30..6a672c4398 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -1013,7 +1013,10 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) + goto err; + } + +- ram_block_notifier_add(&sev_ram_notifier); ++ /* CSV guest needs no notifier to reg/unreg memory */ ++ if (!csv_enabled()) { ++ 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); + +-- +2.17.1 + diff --git a/0008-anolis-target-i386-csv-load-initial-image-to-private.patch b/0008-anolis-target-i386-csv-load-initial-image-to-private.patch new file mode 100644 index 0000000000000000000000000000000000000000..da2e8809080fd0a8da47074f9789664ada896ce1 --- /dev/null +++ b/0008-anolis-target-i386-csv-load-initial-image-to-private.patch @@ -0,0 +1,51 @@ +From 2d31ae0925df36b3a17031bb43d267fb675b4733 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 14:29:40 +0800 +Subject: [PATCH 8/9] anolis: target/i386: csv: load initial image to private + memory + +The initial image of CSV guest should be loaded into private memory +before guest boot. + +Add APIs to implement the image load. + +Signed-off-by: Xin Jiang +Change-Id: I8bd63bd788098c97260c255db1a689751b40dc45 +--- + hw/i386/pc_sysfw.c | 13 ++++++++++++- + 1 file changed, 12 insertions(+), 1 deletion(-) + +diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c +index c8d9e71b88..d7d5e94da7 100644 +--- a/hw/i386/pc_sysfw.c ++++ b/hw/i386/pc_sysfw.c +@@ -37,6 +37,7 @@ + #include "hw/block/flash.h" + #include "sysemu/kvm.h" + #include "sev.h" ++#include "csv.h" + + #define FLASH_SECTOR_SIZE 4096 + +@@ -263,7 +264,17 @@ void x86_firmware_configure(void *ptr, int size) + error_report("failed to locate and/or save reset vector"); + exit(1); + } ++ if (csv_enabled()) { ++ ram_addr_t offset = 0; ++ MemoryRegion *mr; + +- sev_encrypt_flash(ptr, size, &error_fatal); ++ mr = memory_region_from_host(ptr, &offset); ++ if (!mr) { ++ error_report("failed to get memory region of flash"); ++ exit(1); ++ } ++ csv_load_data(mr->addr + offset, ptr, size, &error_fatal); ++ } else ++ sev_encrypt_flash(ptr, size, &error_fatal); + } + } +-- +2.17.1 + diff --git a/0009-anolis-vga-force-full-update-for-CSV-guest.patch b/0009-anolis-vga-force-full-update-for-CSV-guest.patch new file mode 100644 index 0000000000000000000000000000000000000000..bb5b122269807beff1a421281d7335aa1f0ff1db --- /dev/null +++ b/0009-anolis-vga-force-full-update-for-CSV-guest.patch @@ -0,0 +1,47 @@ +From 91a0ddd8f13f02a1250ba9e15db72be0f1fc7c9e Mon Sep 17 00:00:00 2001 +From: Xin Jiang +Date: Thu, 13 Jul 2023 09:35:10 +0800 +Subject: [PATCH 9/9] anolis: vga: force full update for CSV guest + +As CSV's NPT(nested page table) is managed by firmware, VMM is hard +to track the dirty pages of vga buffer. Although VMM could perform +a command to firmware to update read/write attribute of vga buffer +in NPT, it costs more time due to communication between VMM and +firmware. So the simplest method is to fully update vga buffer +always. + +Signed-off-by: Xin Jiang +Change-Id: I093cebad952157aa38edf43fcf861926f7204dd6 +--- + hw/display/vga.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/display/vga.c b/hw/display/vga.c +index 0cb26a791b..1b5bd5f363 100644 +--- a/hw/display/vga.c ++++ b/hw/display/vga.c +@@ -37,6 +37,9 @@ + #include "migration/vmstate.h" + #include "trace.h" + ++#include "target/i386/sev.h" ++#include "target/i386/csv.h" ++ + //#define DEBUG_VGA_MEM + //#define DEBUG_VGA_REG + +@@ -1781,6 +1784,11 @@ static void vga_update_display(void *opaque) + s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + full_update = 1; + } ++ ++ /* Force to full update in CSV guest. */ ++ if (csv_enabled()) ++ full_update = 1; ++ + switch(graphic_mode) { + case GMODE_TEXT: + vga_draw_text(s, full_update); +-- +2.17.1 + diff --git a/qemu.spec b/qemu.spec index 282afcb21aea2e45fe5363de8f2c27c0bc0a5940..d01eeb366e0373f1937c0294084551abbd7a7ac7 100644 --- a/qemu.spec +++ b/qemu.spec @@ -1,4 +1,4 @@ -%define anolis_release 1 +%define anolis_release 2 %bcond_with check @@ -264,6 +264,14 @@ Source31: kvm-x86.conf Source36: README.tests Patch0001: 0001-sgx-stub-fix.patch +Patch0002: 0002-anolis-csv-i386-add-CSV-context.patch +Patch0003: 0003-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch +Patch0004: 0004-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch +Patch0005: 0005-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch +Patch0006: 0006-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch +Patch0007: 0007-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch +Patch0008: 0008-anolis-target-i386-csv-load-initial-image-to-private.patch +Patch0009: 0009-anolis-vga-force-full-update-for-CSV-guest.patch BuildRequires: meson >= %{meson_version} BuildRequires: zlib-devel @@ -1830,6 +1838,17 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %endif %changelog +* Tue Oct 17 2023 Xin Jiang - 15:7.2.6-2 +- Patch0002: 0002-anolis-csv-i386-add-CSV-context.patch +- Patch0003: 0003-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch +- Patch0004: 0004-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch +- Patch0005: 0005-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch +- Patch0006: 0006-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch +- Patch0007: 0007-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch +- Patch0008: 0008-anolis-target-i386-csv-load-initial-image-to-private.patch +- Patch0009: 0009-anolis-vga-force-full-update-for-CSV-guest.patch + (Support Hygon CSV3 feature) + * Mon Oct 16 2023 Funda Wang - 15:7.2.6-1 - New version 7.2.6