diff --git a/0001-anolis-csv-i386-add-CSV-context.patch b/0001-anolis-csv-i386-add-CSV-context.patch new file mode 100644 index 0000000000000000000000000000000000000000..89e3d493cab8965bf56d9d2356d5b12b25ed98ba --- /dev/null +++ b/0001-anolis-csv-i386-add-CSV-context.patch @@ -0,0 +1,205 @@ +From fda324e163898d543e215cfec1aa3d26ba816426 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Tue, 24 Aug 2021 14:57:28 +0800 +Subject: [PATCH 1/8] 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. + +Change-Id: I02b48c779dd25ddda4546fe3e28c1fe0c8c2e4c6 +Signed-off-by: Xin Jiang +--- + configs/devices/i386-softmmu/default.mak | 1 + + .../x86_64-softmmu/x86_64-rh-devices.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 + + 7 files changed, 110 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/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak +index 31ce08edab..ee1df7aa52 100644 +--- a/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak ++++ b/configs/devices/x86_64-softmmu/x86_64-rh-devices.mak +@@ -102,3 +102,4 @@ CONFIG_TPM_TIS_ISA=y + CONFIG_TPM_EMULATOR=y + CONFIG_TPM_PASSTHROUGH=y + CONFIG_SGX=y ++CONFIG_CSV=y +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/0002-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch b/0002-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch new file mode 100644 index 0000000000000000000000000000000000000000..a62796a134af0812162e9f211720ce26446732f7 --- /dev/null +++ b/0002-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch @@ -0,0 +1,204 @@ +From 3239acc6c33806fac55fc08d7e5a81ef9ce85e23 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 11:07:41 +0800 +Subject: [PATCH 2/8] 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: Ia4201dc90c250c23658e1cf5e19b528df9075330 +--- + 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 bcaf66cc4d..b15b8f5550 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1808,6 +1808,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 025ff7a6f8..023532f4ec 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: + * +@@ -952,6 +955,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, &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__); +@@ -1332,6 +1344,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 83e82aa42c..1c97bff99e 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/0003-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch b/0003-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch new file mode 100644 index 0000000000000000000000000000000000000000..ba1f14ad220d111531f83d92b2fc619607cb0c10 --- /dev/null +++ b/0003-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch @@ -0,0 +1,164 @@ +From 6dcfcd61e610da4e8d7dcfb6c3eefd7fc8a67c45 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 09:59:16 +0800 +Subject: [PATCH 3/8] 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: I6d4bea4969a0afa87fb8f2e52fb7ab02ec0db2ed +--- + 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 b15b8f5550..53f9202ffb 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1813,6 +1813,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/0004-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch b/0004-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch new file mode 100644 index 0000000000000000000000000000000000000000..1ea643b7a696a58b41c635c2e94f2be615bc4177 --- /dev/null +++ b/0004-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch @@ -0,0 +1,107 @@ +From 630d76cc15bd98669162f785861cdd81f2ee8f01 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 12:25:05 +0800 +Subject: [PATCH 4/8] 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: I821bc8ab726f1bd22df36c163196951504eaa8da +--- + 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 53f9202ffb..c6cd3a619a 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -1814,6 +1814,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..7dc5c75366 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 023532f4ec..73a794ef74 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -770,8 +770,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/0005-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch b/0005-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch new file mode 100644 index 0000000000000000000000000000000000000000..d82d10e482678ab62d5e3410806be51d8844a58c --- /dev/null +++ b/0005-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch @@ -0,0 +1,41 @@ +From 501e16b4b4cf5a302363c1ae55fb4fb8e68beb8d Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Tue, 24 Aug 2021 17:31:28 +0800 +Subject: [PATCH 5/8] 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: Ifdd2a20f7cb4a079ba918928f012e5f64f7059e6 +--- + target/i386/cpu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index aa9e636800..970d9bf184 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -27,6 +27,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" +@@ -5769,6 +5770,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/0006-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch b/0006-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch new file mode 100644 index 0000000000000000000000000000000000000000..af4851e4316b89bedaaca41d70408eb57cb6e9a3 --- /dev/null +++ b/0006-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch @@ -0,0 +1,35 @@ +From e25884e4e0ee839b591836ae33681ac9a52883ce Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 12:36:00 +0800 +Subject: [PATCH 6/8] 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: I10d5b5ee8dbc3a1bf9ed1935c006c61a094f1e8d +--- + 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 73a794ef74..36669bbdf4 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -973,7 +973,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/0007-anolis-target-i386-csv-load-initial-image-to-private.patch b/0007-anolis-target-i386-csv-load-initial-image-to-private.patch new file mode 100644 index 0000000000000000000000000000000000000000..a40bcfed05f4b54e171af7e505ad1801ec4413c6 --- /dev/null +++ b/0007-anolis-target-i386-csv-load-initial-image-to-private.patch @@ -0,0 +1,44 @@ +From 2df9c321195bd47485867e1d821913f1f3c21fc2 Mon Sep 17 00:00:00 2001 +From: Xin Jiang +Date: Fri, 25 Aug 2023 14:51:16 +0800 +Subject: [PATCH 7/8] 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: I708e7521bfe079216c0e0aea619a9c6bb1d7af04 +--- + hw/i386/pc_sysfw.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c +index c8b17af953..84aad306dc 100644 +--- a/hw/i386/pc_sysfw.c ++++ b/hw/i386/pc_sysfw.c +@@ -38,6 +38,7 @@ + #include "hw/block/flash.h" + #include "sysemu/kvm.h" + #include "sev.h" ++#include "csv.h" + + #define FLASH_SECTOR_SIZE 4096 + +@@ -208,7 +209,10 @@ static void pc_system_flash_map(PCMachineState *pcms, + exit(1); + } + +- sev_encrypt_flash(flash_ptr, flash_size, &error_fatal); ++ if (csv_enabled()) ++ csv_load_data(flash_mem->addr, flash_ptr, flash_size, &error_fatal); ++ else ++ sev_encrypt_flash(flash_ptr, flash_size, &error_fatal); + } + } + } +-- +2.17.1 + diff --git a/0008-anolis-vga-force-full-update-for-CSV-guest.patch b/0008-anolis-vga-force-full-update-for-CSV-guest.patch new file mode 100644 index 0000000000000000000000000000000000000000..40842ec7b5ebf2e728ba997fdc661f220e689b3e --- /dev/null +++ b/0008-anolis-vga-force-full-update-for-CSV-guest.patch @@ -0,0 +1,47 @@ +From 42d8658a8868721a0c4fb08295a8957e9fdc96c6 Mon Sep 17 00:00:00 2001 +From: Xin Jiang +Date: Thu, 13 Jul 2023 09:35:10 +0800 +Subject: [PATCH 8/8] 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: I51ff00440483011fb9088a75005644beb378f8dd +--- + hw/display/vga.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/display/vga.c b/hw/display/vga.c +index 9d1f66af40..be4282a2f5 100644 +--- a/hw/display/vga.c ++++ b/hw/display/vga.c +@@ -36,6 +36,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 + +@@ -1779,6 +1782,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-kvm.spec b/qemu-kvm.spec index 433dd59356282e10331a6ab4d9d124ae726de1ae..072824c7985da2d46a5cfc9dd04b1efd04350b7d 100644 --- a/qemu-kvm.spec +++ b/qemu-kvm.spec @@ -1,4 +1,4 @@ -%define anolis_release .0.2 +%define anolis_release .0.3 %global SLOF_gittagdate 20191022 %global SLOF_gittagcommit 899d9883 @@ -697,6 +697,16 @@ Patch1028: Fixed-the-issue-where-qemu-specifies-the-boot-order.patch # https://github.com/qemu/qemu/commit/10be627d2b5ec2d6b3dce045144aa739eef678b4 Patch1029: 1029-anolis-qemu-fix-CVE-2023-3354.patch +# CSV3 feature on Hygon hardware +Patch1030: 0001-anolis-csv-i386-add-CSV-context.patch +Patch1031: 0002-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch +Patch1032: 0003-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch +Patch1033: 0004-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch +Patch1034: 0005-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch +Patch1035: 0006-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch +Patch1036: 0007-anolis-target-i386-csv-load-initial-image-to-private.patch +Patch1037: 0008-anolis-vga-force-full-update-for-CSV-guest.patch + BuildRequires: wget BuildRequires: rpm-build BuildRequires: ninja-build @@ -1934,6 +1944,17 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : %endif %changelog +* Thu Sep 14 2023 Xin Jiang - 6.2.0-33.0.3 +- 0001-anolis-csv-i386-add-CSV-context.patch +- 0002-anolis-csv-i386-add-command-to-initialize-CSV-contex.patch +- 0003-anolis-csv-i386-add-command-to-load-data-to-guest-me.patch +- 0004-anolis-csv-i386-add-command-to-load-vmcb-to-guest-me.patch +- 0005-anolis-cpu-i386-populate-CPUID-0x8000_001F-when-CSV-.patch +- 0006-anolis-csv-i386-CSV-guest-do-not-need-register-unreg.patch +- 0007-anolis-target-i386-csv-load-initial-image-to-private.patch +- 0008-anolis-vga-force-full-update-for-CSV-guest.patch + (Hygon CSV3 feature) + * Thu Aug 24 2023 lixianglai - 6.2.0-33.0.2 - loongarch: Fixed the issue where qemu specifies the boot order - Fix CVE-2023-3354 (Liwei Ge )