QEMU update to version 8.2.0-18:
- hw/loongarch/virt: Fix FDT memory node address width - hw/loongarch: Fix fdt memory node wrong 'reg' - load_elf: fix iterator's type for elf file processing - migration/colo: Fix bdrv_graph_rdlock_main_loop: Assertion `!qemu_in_… - target/i386: no single-step exception after MOV or POP SS - char-stdio: Restore blocking mode of stdout on exit - backends/cryptodev-builtin: Fix local_error leaks - target/loongarch: fix a wrong print in cpu dump - virtio-pci: fix use of a released vector - target/arm: Disable SVE extensions when SVE is disabled - hw/misc/bcm2835_property: Fix handling of FRAMEBUFFER_SET_PALETTE - target/i386: Introduce SapphireRapids-v3 to add missing features - virtio-net: Ensure queue index fits with RSS (CVE-2024-6505) - nbd/server: CVE-2024-7409: Avoid use-after-free when closing server - update io/trace-events. Parameters should remain consistent. - update docs/tools/virtfs-proxy-helper.rst. This place is spelled wrong. - kvm: Add support for CSV2 reboot - target/i386/kvm: Fix the resettable info when emulate Hygon CSV2 guest - target/i386: get/set/migrate GHCB state - target/i386: csv: Add support for migrate VMSA for CSV2 guest - migration/ram: Accelerate the loading of CSV guest's encrypted pages - migration/ram: Accelerate the transmission of CSV guest's encrypted pages - target/i386: csv: add support to load incoming encrypted pages queued in the CMD list - target/i386: csv: add support to queue the incoming page into a list - target/i386: csv: add support to encrypt the outgoing pages in the list queued before. - target/i386: csv: add support to queue the outgoing page into a list - target/i386: csv: Read cert chain from file when prepared for CSV live migration - target/i386: Introduce header file csv.h - migration/ram: Fix calculation of gfn correpond to a page in ramblock - target/i386: sev: Clear shared_regions_list when reboot CSV Guest - migration/ram: Force encrypted status for VGA vram - target/i386: sev: Return 0 if sev_send_get_packet_len() fails - kvm: Add support for userspace MSR filtering and handling of MSR_KVM_MIGRATION_CONTROL. - migration/ram: Force encrypted status for flash0 & flash1 devices. - migration/ram: add support to send encrypted pages - migration: add support to migrate shared regions list - kvm: Add support for SEV shared regions list and KVM_EXIT_HYPERCALL. - target/i386: sev: add support to load incoming encrypted page - target/i386: sev: add support to encrypt the outgoing page - target/i386: sev: do not create launch context for an incoming guest - target/i386: sev: provide callback to setup outgoing context - confidential guest support: introduce ConfidentialGuestMemoryEncryptionOps for encrypted VMs - migration.json: add AMD SEV specific migration parameters - doc: update AMD SEV to include Live migration flow - crypto/tlscredspsk: Free username on finalize - hw/nvme: fix leak of uninitialized memory in io_mgmt_recv - hw/display/vhost-user-gpu.c: fix vhost_user_gpu_chr_read() - cvm : Implement command blacklist for cvm security enhancement - crypto: Introduce SM3 hash hmac pbkdf algorithm - virtio-net: Use virtual time for RSC timers - vvfat: Fix bug in writing to middle of file - hw/core/ptimer: fix timer zero period condition for freq > 1GHz - hw/misc: support vpsp Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com>
This commit is contained in:
parent
b36d41c519
commit
4f059b938c
63
backends-cryptodev-builtin-Fix-local_error-leaks.patch
Normal file
63
backends-cryptodev-builtin-Fix-local_error-leaks.patch
Normal file
@ -0,0 +1,63 @@
|
||||
From 2781f5673cc43d13b73e66fb266e7ea0b945429d Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 20:55:38 +0800
|
||||
Subject: [PATCH] backends/cryptodev-builtin: Fix local_error leaks
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cherry picked from commit 06479dbf3d7d245572c4b3016e5a1d923ff04d66
|
||||
|
||||
backends/cryptodev-builtin: Fix local_error leaks
|
||||
It seems that this error does not need to be propagated to the upper,
|
||||
directly output the error to avoid the leaks
|
||||
|
||||
Closes: https://gitlab.com/qemu-project/qemu/-/issues/2283
|
||||
Fixes: 2fda101 ("virtio-crypto: Support asynchronous mode")
|
||||
Signed-off-by: Li Zhijian <lizhijian@fujitsu.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: zhenwei pi <pizhenwei@bytedance.com>
|
||||
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
backends/cryptodev-builtin.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c
|
||||
index 39d0455280..0822f198d9 100644
|
||||
--- a/backends/cryptodev-builtin.c
|
||||
+++ b/backends/cryptodev-builtin.c
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/cryptodev.h"
|
||||
+#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "standard-headers/linux/virtio_crypto.h"
|
||||
#include "crypto/cipher.h"
|
||||
@@ -396,8 +397,8 @@ static int cryptodev_builtin_create_session(
|
||||
case VIRTIO_CRYPTO_HASH_CREATE_SESSION:
|
||||
case VIRTIO_CRYPTO_MAC_CREATE_SESSION:
|
||||
default:
|
||||
- error_setg(&local_error, "Unsupported opcode :%" PRIu32 "",
|
||||
- sess_info->op_code);
|
||||
+ error_report("Unsupported opcode :%" PRIu32 "",
|
||||
+ sess_info->op_code);
|
||||
return -VIRTIO_CRYPTO_NOTSUPP;
|
||||
}
|
||||
|
||||
@@ -552,8 +553,8 @@ static int cryptodev_builtin_operation(
|
||||
|
||||
if (op_info->session_id >= MAX_NUM_SESSIONS ||
|
||||
builtin->sessions[op_info->session_id] == NULL) {
|
||||
- error_setg(&local_error, "Cannot find a valid session id: %" PRIu64 "",
|
||||
- op_info->session_id);
|
||||
+ error_report("Cannot find a valid session id: %" PRIu64 "",
|
||||
+ op_info->session_id);
|
||||
return -VIRTIO_CRYPTO_INVSESS;
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
54
char-stdio-Restore-blocking-mode-of-stdout-on-exit.patch
Normal file
54
char-stdio-Restore-blocking-mode-of-stdout-on-exit.patch
Normal file
@ -0,0 +1,54 @@
|
||||
From 5661b12a28b650226cca100aeddd92d5cc788153 Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 20:41:18 +0800
|
||||
Subject: [PATCH] char-stdio: Restore blocking mode of stdout on exit
|
||||
|
||||
cherry picked from commit a0124e333e2176640f233e5ea57a2f413985d9b5
|
||||
|
||||
qemu_chr_open_fd() sets stdout into non-blocking mode. Restore the old
|
||||
fd flags on exit to avoid breaking unsuspecting applications that run on
|
||||
the same terminal after qemu and don't expect to get EAGAIN.
|
||||
|
||||
While at at, also ensure term_exit is called once (at the moment it's
|
||||
called both from char_stdio_finalize() and as the atexit() hook.
|
||||
|
||||
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2423
|
||||
Signed-off-by: Maxim Mikityanskiy <maxtram95@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20240703190812.3459514-1-m
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
chardev/char-stdio.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/chardev/char-stdio.c b/chardev/char-stdio.c
|
||||
index 3c648678ab..b960ddd4e4 100644
|
||||
--- a/chardev/char-stdio.c
|
||||
+++ b/chardev/char-stdio.c
|
||||
@@ -41,6 +41,7 @@
|
||||
/* init terminal so that we can grab keys */
|
||||
static struct termios oldtty;
|
||||
static int old_fd0_flags;
|
||||
+static int old_fd1_flags;
|
||||
static bool stdio_in_use;
|
||||
static bool stdio_allow_signal;
|
||||
static bool stdio_echo_state;
|
||||
@@ -50,6 +51,8 @@ static void term_exit(void)
|
||||
if (stdio_in_use) {
|
||||
tcsetattr(0, TCSANOW, &oldtty);
|
||||
fcntl(0, F_SETFL, old_fd0_flags);
|
||||
+ fcntl(1, F_SETFL, old_fd1_flags);
|
||||
+ stdio_in_use = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +105,7 @@ static void qemu_chr_open_stdio(Chardev *chr,
|
||||
|
||||
stdio_in_use = true;
|
||||
old_fd0_flags = fcntl(0, F_GETFL);
|
||||
+ old_fd1_flags = fcntl(1, F_GETFL);
|
||||
tcgetattr(0, &oldtty);
|
||||
if (!g_unix_set_fd_nonblocking(0, true, NULL)) {
|
||||
error_setg_errno(errp, errno, "Failed to set FD nonblocking");
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
67
confidential-guest-support-introduce-ConfidentialGue.patch
Normal file
67
confidential-guest-support-introduce-ConfidentialGue.patch
Normal file
@ -0,0 +1,67 @@
|
||||
From da96618de3227b87ddd78388b80278bde230ce79 Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Tue, 27 Jul 2021 11:41:37 +0000
|
||||
Subject: [PATCH] confidential guest support: introduce
|
||||
ConfidentialGuestMemoryEncryptionOps for encrypted VMs
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/74fce7be9bd.
|
||||
|
||||
When memory encryption is enabled in VM, the guest RAM will be encrypted
|
||||
with the guest-specific key, to protect the confidentiality of data while
|
||||
in transit we need to platform specific hooks to save or migrate the
|
||||
guest RAM.
|
||||
|
||||
Introduce the new ConfidentialGuestMemoryEncryptionOps in this patch
|
||||
which will be later used by the encrypted guest for migration.
|
||||
|
||||
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Co-developed-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
include/exec/confidential-guest-support.h | 27 +++++++++++++++++++++++
|
||||
1 file changed, 27 insertions(+)
|
||||
|
||||
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||
index ba2dd4b5df..343f686fc2 100644
|
||||
--- a/include/exec/confidential-guest-support.h
|
||||
+++ b/include/exec/confidential-guest-support.h
|
||||
@@ -53,8 +53,35 @@ struct ConfidentialGuestSupport {
|
||||
bool ready;
|
||||
};
|
||||
|
||||
+/**
|
||||
+ * The functions registers with ConfidentialGuestMemoryEncryptionOps will be
|
||||
+ * used during the encrypted guest migration.
|
||||
+ */
|
||||
+struct ConfidentialGuestMemoryEncryptionOps {
|
||||
+ /* Initialize the platform specific state before starting the migration */
|
||||
+ int (*save_setup)(const char *pdh, const char *plat_cert,
|
||||
+ const char *amd_cert);
|
||||
+
|
||||
+ /* Write the encrypted page and metadata associated with it */
|
||||
+ int (*save_outgoing_page)(QEMUFile *f, uint8_t *ptr, uint32_t size,
|
||||
+ uint64_t *bytes_sent);
|
||||
+
|
||||
+ /* Load the incoming encrypted page into guest memory */
|
||||
+ int (*load_incoming_page)(QEMUFile *f, uint8_t *ptr);
|
||||
+
|
||||
+ /* Check if gfn is in shared/unencrypted region */
|
||||
+ bool (*is_gfn_in_unshared_region)(unsigned long gfn);
|
||||
+
|
||||
+ /* Write the shared regions list */
|
||||
+ int (*save_outgoing_shared_regions_list)(QEMUFile *f);
|
||||
+
|
||||
+ /* Load the shared regions list */
|
||||
+ int (*load_incoming_shared_regions_list)(QEMUFile *f);
|
||||
+};
|
||||
+
|
||||
typedef struct ConfidentialGuestSupportClass {
|
||||
ObjectClass parent;
|
||||
+ struct ConfidentialGuestMemoryEncryptionOps *memory_encryption_ops;
|
||||
} ConfidentialGuestSupportClass;
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
403
crypto-Introduce-SM3-hash-hmac-pbkdf-algorithm.patch
Normal file
403
crypto-Introduce-SM3-hash-hmac-pbkdf-algorithm.patch
Normal file
@ -0,0 +1,403 @@
|
||||
From 7b7742e137fbf9283cbbfb823fcf2ebe14df3154 Mon Sep 17 00:00:00 2001
|
||||
From: gaochuanji <gaochuanji@inspur.com>
|
||||
Date: Mon, 19 Aug 2024 10:52:49 +0800
|
||||
Subject: [PATCH] crypto: Introduce SM3 hash hmac pbkdf algorithm
|
||||
|
||||
Introduce the SM3 cryptographic hash algorithm (GB/T 32905-2016).
|
||||
|
||||
SM3 (GB/T 32905-2016) is a cryptographic standard issued by the
|
||||
Organization of State Commercial Cryptography Administration (OSCCA)
|
||||
as an authorized cryptographic algorithm for use within China.
|
||||
|
||||
Detect the SM3 cryptographic hash algorithm and enable the feature silently
|
||||
if it is available.
|
||||
|
||||
Signed-off-by: cheliequan <cheliequan@inspur.com>
|
||||
---
|
||||
crypto/hash-gcrypt.c | 3 +++
|
||||
crypto/hash-nettle.c | 14 ++++++++++++
|
||||
crypto/hash.c | 3 +++
|
||||
crypto/hmac-gcrypt.c | 3 +++
|
||||
crypto/hmac-nettle.c | 11 ++++++++++
|
||||
crypto/pbkdf-gcrypt.c | 6 ++++++
|
||||
crypto/pbkdf-nettle.c | 13 ++++++++++++
|
||||
meson.build | 39 ++++++++++++++++++++++++++++++++++
|
||||
qapi/crypto.json | 4 +++-
|
||||
tests/unit/test-crypto-hash.c | 16 ++++++++++++++
|
||||
tests/unit/test-crypto-hmac.c | 8 +++++++
|
||||
tests/unit/test-crypto-pbkdf.c | 16 ++++++++++++++
|
||||
12 files changed, 135 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/crypto/hash-gcrypt.c b/crypto/hash-gcrypt.c
|
||||
index 829e48258d..d3bdfe5633 100644
|
||||
--- a/crypto/hash-gcrypt.c
|
||||
+++ b/crypto/hash-gcrypt.c
|
||||
@@ -33,6 +33,9 @@ static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||
[QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160,
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = GCRY_MD_SM3,
|
||||
+#endif
|
||||
};
|
||||
|
||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||
diff --git a/crypto/hash-nettle.c b/crypto/hash-nettle.c
|
||||
index 1ca1a41062..0c2f8ce86c 100644
|
||||
--- a/crypto/hash-nettle.c
|
||||
+++ b/crypto/hash-nettle.c
|
||||
@@ -25,6 +25,9 @@
|
||||
#include <nettle/md5.h>
|
||||
#include <nettle/sha.h>
|
||||
#include <nettle/ripemd160.h>
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+#include <nettle/sm3.h>
|
||||
+#endif
|
||||
|
||||
typedef void (*qcrypto_nettle_init)(void *ctx);
|
||||
typedef void (*qcrypto_nettle_write)(void *ctx,
|
||||
@@ -42,6 +45,9 @@ union qcrypto_hash_ctx {
|
||||
struct sha384_ctx sha384;
|
||||
struct sha512_ctx sha512;
|
||||
struct ripemd160_ctx ripemd160;
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ struct sm3_ctx sm3;
|
||||
+#endif
|
||||
};
|
||||
|
||||
struct qcrypto_hash_alg {
|
||||
@@ -92,6 +98,14 @@ struct qcrypto_hash_alg {
|
||||
.result = (qcrypto_nettle_result)ripemd160_digest,
|
||||
.len = RIPEMD160_DIGEST_SIZE,
|
||||
},
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = {
|
||||
+ .init = (qcrypto_nettle_init)sm3_init,
|
||||
+ .write = (qcrypto_nettle_write)sm3_update,
|
||||
+ .result = (qcrypto_nettle_result)sm3_digest,
|
||||
+ .len = SM3_DIGEST_SIZE,
|
||||
+ },
|
||||
+#endif
|
||||
};
|
||||
|
||||
gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
|
||||
diff --git a/crypto/hash.c b/crypto/hash.c
|
||||
index b0f8228bdc..8f1502ce68 100644
|
||||
--- a/crypto/hash.c
|
||||
+++ b/crypto/hash.c
|
||||
@@ -30,6 +30,9 @@ static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
|
||||
[QCRYPTO_HASH_ALG_SHA384] = 48,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = 64,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = 20,
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = 32,
|
||||
+#endif
|
||||
};
|
||||
|
||||
size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
|
||||
diff --git a/crypto/hmac-gcrypt.c b/crypto/hmac-gcrypt.c
|
||||
index 0c6f979711..888afb86ed 100644
|
||||
--- a/crypto/hmac-gcrypt.c
|
||||
+++ b/crypto/hmac-gcrypt.c
|
||||
@@ -26,6 +26,9 @@ static int qcrypto_hmac_alg_map[QCRYPTO_HASH_ALG__MAX] = {
|
||||
[QCRYPTO_HASH_ALG_SHA384] = GCRY_MAC_HMAC_SHA384,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = GCRY_MAC_HMAC_SHA512,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MAC_HMAC_RMD160,
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = GCRY_MAC_HMAC_SM3,
|
||||
+#endif
|
||||
};
|
||||
|
||||
typedef struct QCryptoHmacGcrypt QCryptoHmacGcrypt;
|
||||
diff --git a/crypto/hmac-nettle.c b/crypto/hmac-nettle.c
|
||||
index 1ad6c4f253..e51e3319ab 100644
|
||||
--- a/crypto/hmac-nettle.c
|
||||
+++ b/crypto/hmac-nettle.c
|
||||
@@ -38,6 +38,9 @@ struct QCryptoHmacNettle {
|
||||
struct hmac_sha256_ctx sha256_ctx; /* equals hmac_sha224_ctx */
|
||||
struct hmac_sha512_ctx sha512_ctx; /* equals hmac_sha384_ctx */
|
||||
struct hmac_ripemd160_ctx ripemd160_ctx;
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ struct hmac_sm3_ctx ctx;
|
||||
+#endif
|
||||
} u;
|
||||
};
|
||||
|
||||
@@ -89,6 +92,14 @@ struct qcrypto_nettle_hmac_alg {
|
||||
.digest = (qcrypto_nettle_hmac_digest)hmac_ripemd160_digest,
|
||||
.len = RIPEMD160_DIGEST_SIZE,
|
||||
},
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = {
|
||||
+ .setkey = (qcrypto_nettle_hmac_setkey)hmac_sm3_set_key,
|
||||
+ .update = (qcrypto_nettle_hmac_update)hmac_sm3_update,
|
||||
+ .digest = (qcrypto_nettle_hmac_digest)hmac_sm3_digest,
|
||||
+ .len = SM3_DIGEST_SIZE,
|
||||
+ },
|
||||
+#endif
|
||||
};
|
||||
|
||||
bool qcrypto_hmac_supports(QCryptoHashAlgorithm alg)
|
||||
diff --git a/crypto/pbkdf-gcrypt.c b/crypto/pbkdf-gcrypt.c
|
||||
index a8d8e64f4d..09b38d0d6e 100644
|
||||
--- a/crypto/pbkdf-gcrypt.c
|
||||
+++ b/crypto/pbkdf-gcrypt.c
|
||||
@@ -33,6 +33,9 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
|
||||
case QCRYPTO_HASH_ALG_SHA384:
|
||||
case QCRYPTO_HASH_ALG_SHA512:
|
||||
case QCRYPTO_HASH_ALG_RIPEMD160:
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ case QCRYPTO_HASH_ALG_SM3:
|
||||
+#endif
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -54,6 +57,9 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
|
||||
[QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160,
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = GCRY_MD_SM3,
|
||||
+#endif
|
||||
};
|
||||
int ret;
|
||||
|
||||
diff --git a/crypto/pbkdf-nettle.c b/crypto/pbkdf-nettle.c
|
||||
index d6293c25a1..5fea570bd3 100644
|
||||
--- a/crypto/pbkdf-nettle.c
|
||||
+++ b/crypto/pbkdf-nettle.c
|
||||
@@ -34,6 +34,9 @@ bool qcrypto_pbkdf2_supports(QCryptoHashAlgorithm hash)
|
||||
case QCRYPTO_HASH_ALG_SHA384:
|
||||
case QCRYPTO_HASH_ALG_SHA512:
|
||||
case QCRYPTO_HASH_ALG_RIPEMD160:
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ case QCRYPTO_HASH_ALG_SM3:
|
||||
+#endif
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@@ -55,6 +58,9 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
|
||||
struct hmac_sha384_ctx sha384;
|
||||
struct hmac_sha512_ctx sha512;
|
||||
struct hmac_ripemd160_ctx ripemd160;
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ struct hmac_sm3_ctx sm3;
|
||||
+#endif
|
||||
} ctx;
|
||||
|
||||
if (iterations > UINT_MAX) {
|
||||
@@ -106,6 +112,13 @@ int qcrypto_pbkdf2(QCryptoHashAlgorithm hash,
|
||||
PBKDF2(&ctx.ripemd160, hmac_ripemd160_update, hmac_ripemd160_digest,
|
||||
RIPEMD160_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
|
||||
break;
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ case QCRYPTO_HASH_ALG_SM3:
|
||||
+ hmac_sm3_set_key(&ctx.sm3, nkey, key);
|
||||
+ PBKDF2(&ctx.sm3, hmac_sm3_update, hmac_sm3_digest,
|
||||
+ SM3_DIGEST_SIZE, iterations, nsalt, salt, nout, out);
|
||||
+ break;
|
||||
+#endif
|
||||
|
||||
default:
|
||||
error_setg_errno(errp, ENOSYS,
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 089f45d386..4024f9a4bb 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -1486,6 +1486,7 @@ gcrypt = not_found
|
||||
nettle = not_found
|
||||
hogweed = not_found
|
||||
crypto_sm4 = not_found
|
||||
+crypto_sm3 = not_found
|
||||
xts = 'none'
|
||||
|
||||
if get_option('nettle').enabled() and get_option('gcrypt').enabled()
|
||||
@@ -1522,6 +1523,17 @@ if not gnutls_crypto.found()
|
||||
}''', dependencies: gcrypt)
|
||||
crypto_sm4 = not_found
|
||||
endif
|
||||
+ crypto_sm3 = gcrypt
|
||||
+ # SM3 ALG is available in libgcrypt >= 1.8
|
||||
+ if gcrypt.found() and not cc.links('''
|
||||
+ #include <gcrypt.h>
|
||||
+ int main(void) {
|
||||
+ gcry_md_hd_t handler;
|
||||
+ gcry_md_open(&handler, GCRY_MD_SM3, 0);
|
||||
+ return 0;
|
||||
+ }''', dependencies: gcrypt)
|
||||
+ crypto_sm3 = not_found
|
||||
+ endif
|
||||
endif
|
||||
if (not get_option('nettle').auto() or have_system) and not gcrypt.found()
|
||||
nettle = dependency('nettle', version: '>=3.4',
|
||||
@@ -1542,6 +1554,31 @@ if not gnutls_crypto.found()
|
||||
}''', dependencies: nettle)
|
||||
crypto_sm4 = not_found
|
||||
endif
|
||||
+ crypto_sm3 = nettle
|
||||
+ # SM3 ALG is available in nettle >= 3.4
|
||||
+ if nettle.found() and not cc.links('''
|
||||
+ #include <nettle/sm3.h>
|
||||
+ #include <nettle/hmac.h>
|
||||
+ int main(void) {
|
||||
+ struct sm3_ctx ctx;
|
||||
+ struct hmac_sm3_ctx hmac_ctx;
|
||||
+ unsigned char data[64] = {0};
|
||||
+ unsigned char output[32];
|
||||
+
|
||||
+ // SM3 hash function test
|
||||
+ sm3_init(&ctx);
|
||||
+ sm3_update(&ctx, 64, data);
|
||||
+ sm3_digest(&ctx, 32, data);
|
||||
+
|
||||
+ // HMAC-SM3 test
|
||||
+ hmac_sm3_set_key(&hmac_ctx, 32, data);
|
||||
+ hmac_sm3_update(&hmac_ctx, 64, data);
|
||||
+ hmac_sm3_digest(&hmac_ctx, 32, output);
|
||||
+
|
||||
+ return 0;
|
||||
+ }''', dependencies: nettle)
|
||||
+ crypto_sm3 = not_found
|
||||
+ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
@@ -2229,6 +2266,7 @@ config_host_data.set('CONFIG_TASN1', tasn1.found())
|
||||
config_host_data.set('CONFIG_GCRYPT', gcrypt.found())
|
||||
config_host_data.set('CONFIG_NETTLE', nettle.found())
|
||||
config_host_data.set('CONFIG_CRYPTO_SM4', crypto_sm4.found())
|
||||
+config_host_data.set('CONFIG_CRYPTO_SM3', crypto_sm3.found())
|
||||
config_host_data.set('CONFIG_HOGWEED', hogweed.found())
|
||||
config_host_data.set('CONFIG_QEMU_PRIVATE_XTS', xts == 'private')
|
||||
config_host_data.set('CONFIG_MALLOC_TRIM', has_malloc_trim)
|
||||
@@ -4306,6 +4344,7 @@ if nettle.found()
|
||||
summary_info += {' XTS': xts != 'private'}
|
||||
endif
|
||||
summary_info += {'SM4 ALG support': crypto_sm4}
|
||||
+summary_info += {'SM3 ALG support': crypto_sm3}
|
||||
summary_info += {'AF_ALG support': have_afalg}
|
||||
summary_info += {'rng-none': get_option('rng_none')}
|
||||
summary_info += {'Linux keyring': have_keyring}
|
||||
diff --git a/qapi/crypto.json b/qapi/crypto.json
|
||||
index 2f2aeff5fd..af38f0a4bd 100644
|
||||
--- a/qapi/crypto.json
|
||||
+++ b/qapi/crypto.json
|
||||
@@ -58,11 +58,13 @@
|
||||
#
|
||||
# @ripemd160: RIPEMD-160. (since 2.7)
|
||||
#
|
||||
+# @sm3: SM3. (since 8.2.0)
|
||||
+#
|
||||
# Since: 2.6
|
||||
##
|
||||
{ 'enum': 'QCryptoHashAlgorithm',
|
||||
'prefix': 'QCRYPTO_HASH_ALG',
|
||||
- 'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160']}
|
||||
+ 'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160', 'sm3']}
|
||||
|
||||
##
|
||||
# @QCryptoCipherAlgorithm:
|
||||
diff --git a/tests/unit/test-crypto-hash.c b/tests/unit/test-crypto-hash.c
|
||||
index 1f4abb822b..61908e1769 100644
|
||||
--- a/tests/unit/test-crypto-hash.c
|
||||
+++ b/tests/unit/test-crypto-hash.c
|
||||
@@ -42,6 +42,9 @@
|
||||
"63b54e4cb2d2032b393994aa263c0dbb" \
|
||||
"e00a9f2fe9ef6037352232a1eec55ee7"
|
||||
#define OUTPUT_RIPEMD160 "f3d658fad3fdfb2b52c9369cf0d441249ddfa8a0"
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+#define OUTPUT_SM3 "d4a97db105b477b84c4f20ec9c31a6c814e2705a0b83a5a89748d75f0ef456a1"
|
||||
+#endif
|
||||
|
||||
#define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ=="
|
||||
#define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI="
|
||||
@@ -54,6 +57,10 @@
|
||||
"7sVe5w=="
|
||||
#define OUTPUT_RIPEMD160_B64 "89ZY+tP9+ytSyTac8NRBJJ3fqKA="
|
||||
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+#define OUTPUT_SM3_B64 "1Kl9sQW0d7hMTyDsnDGmyBTicFoLg6Wol0jXXw70VqE="
|
||||
+#endif
|
||||
+
|
||||
static const char *expected_outputs[] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5,
|
||||
[QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1,
|
||||
@@ -62,6 +69,9 @@ static const char *expected_outputs[] = {
|
||||
[QCRYPTO_HASH_ALG_SHA384] = OUTPUT_SHA384,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = OUTPUT_SHA512,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = OUTPUT_RIPEMD160,
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = OUTPUT_SM3,
|
||||
+#endif
|
||||
};
|
||||
static const char *expected_outputs_b64[] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5_B64,
|
||||
@@ -71,6 +81,9 @@ static const char *expected_outputs_b64[] = {
|
||||
[QCRYPTO_HASH_ALG_SHA384] = OUTPUT_SHA384_B64,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = OUTPUT_SHA512_B64,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = OUTPUT_RIPEMD160_B64,
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = OUTPUT_SM3_B64,
|
||||
+#endif
|
||||
};
|
||||
static const int expected_lens[] = {
|
||||
[QCRYPTO_HASH_ALG_MD5] = 16,
|
||||
@@ -80,6 +93,9 @@ static const int expected_lens[] = {
|
||||
[QCRYPTO_HASH_ALG_SHA384] = 48,
|
||||
[QCRYPTO_HASH_ALG_SHA512] = 64,
|
||||
[QCRYPTO_HASH_ALG_RIPEMD160] = 20,
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ [QCRYPTO_HASH_ALG_SM3] = 32,
|
||||
+#endif
|
||||
};
|
||||
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
diff --git a/tests/unit/test-crypto-hmac.c b/tests/unit/test-crypto-hmac.c
|
||||
index 23eb724d94..b1d04e9fcc 100644
|
||||
--- a/tests/unit/test-crypto-hmac.c
|
||||
+++ b/tests/unit/test-crypto-hmac.c
|
||||
@@ -76,6 +76,14 @@ static QCryptoHmacTestData test_data[] = {
|
||||
"94964ed4c1155b62b668c241d67279e5"
|
||||
"8a711676",
|
||||
},
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ {
|
||||
+ .alg = QCRYPTO_HASH_ALG_SM3,
|
||||
+ .hex_digest =
|
||||
+ "760e3799332bc913819b930085360ddb"
|
||||
+ "c05529261313d5b15b75bab4fd7ae91e",
|
||||
+ },
|
||||
+#endif
|
||||
};
|
||||
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
diff --git a/tests/unit/test-crypto-pbkdf.c b/tests/unit/test-crypto-pbkdf.c
|
||||
index 43c417f6b4..3d76593c86 100644
|
||||
--- a/tests/unit/test-crypto-pbkdf.c
|
||||
+++ b/tests/unit/test-crypto-pbkdf.c
|
||||
@@ -326,6 +326,22 @@ static QCryptoPbkdfTestData test_data[] = {
|
||||
"\xce\xbf\x91\x14\x8b\x5c\x48\x41",
|
||||
.nout = 32
|
||||
},
|
||||
+#ifdef CONFIG_CRYPTO_SM3
|
||||
+ {
|
||||
+ .path = "/crypto/pbkdf/nonrfc/sm3/iter2",
|
||||
+ .hash = QCRYPTO_HASH_ALG_SM3,
|
||||
+ .iterations = 2,
|
||||
+ .key = "password",
|
||||
+ .nkey = 8,
|
||||
+ .salt = "ATHENA.MIT.EDUraeburn",
|
||||
+ .nsalt = 21,
|
||||
+ .out = "\x48\x71\x1b\x58\xa3\xcb\xce\x06"
|
||||
+ "\xba\xad\x77\xa8\xb5\xb9\xd8\x07"
|
||||
+ "\x6a\xe2\xb3\x5b\x95\xce\xc8\xce"
|
||||
+ "\xe7\xb1\xcb\xee\x61\xdf\x04\xea",
|
||||
+ .nout = 32
|
||||
+ },
|
||||
+#endif
|
||||
#if 0
|
||||
{
|
||||
.path = "/crypto/pbkdf/nonrfc/whirlpool/iter1200",
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
78
crypto-tlscredspsk-Free-username-on-finalize.patch
Normal file
78
crypto-tlscredspsk-Free-username-on-finalize.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From ec07000764f578bb7cd21fe73c8e649a183d7674 Mon Sep 17 00:00:00 2001
|
||||
From: qihao <qihao_yewu@cmss.chinamobile.com>
|
||||
Date: Mon, 26 Aug 2024 10:56:57 +0800
|
||||
Subject: [PATCH] crypto/tlscredspsk: Free username on finalize
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cheery-pick from 87e012f29f2e47dcd8c385ff8bb8188f9e06d4ea
|
||||
|
||||
When the creds->username property is set we allocate memory
|
||||
for it in qcrypto_tls_creds_psk_prop_set_username(), but
|
||||
we never free this when the QCryptoTLSCredsPSK is destroyed.
|
||||
Free the memory in finalize.
|
||||
|
||||
This fixes a LeakSanitizer complaint in migration-test:
|
||||
|
||||
$ (cd build/asan; ASAN_OPTIONS="fast_unwind_on_malloc=0" QTEST_QEMU_BINARY=./qemu-system-x86_64 ./tests/qtest/migration-test --tap -k -p /x86_64/migration/precopy/unix/tls/psk)
|
||||
|
||||
=================================================================
|
||||
==3867512==ERROR: LeakSanitizer: detected memory leaks
|
||||
|
||||
Direct leak of 5 byte(s) in 1 object(s) allocated from:
|
||||
#0 0x5624e5c99dee in malloc (/mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/qemu-system-x86_64+0x218edee) (BuildId: a9e623fa1009a9435c0142c037cd7b8c1ad04ce3)
|
||||
#1 0x7fb199ae9738 in g_malloc debian/build/deb/../../../glib/gmem.c:128:13
|
||||
#2 0x7fb199afe583 in g_strdup debian/build/deb/../../../glib/gstrfuncs.c:361:17
|
||||
#3 0x5624e82ea919 in qcrypto_tls_creds_psk_prop_set_username /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../crypto/tlscredspsk.c:255:23
|
||||
#4 0x5624e812c6b5 in property_set_str /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object.c:2277:5
|
||||
#5 0x5624e8125ce5 in object_property_set /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object.c:1463:5
|
||||
#6 0x5624e8136e7c in object_set_properties_from_qdict /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object_interfaces.c:55:14
|
||||
#7 0x5624e81372d2 in user_creatable_add_type /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object_interfaces.c:112:5
|
||||
#8 0x5624e8137964 in user_creatable_add_qapi /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/object_interfaces.c:157:11
|
||||
#9 0x5624e891ba3c in qmp_object_add /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qom/qom-qmp-cmds.c:227:5
|
||||
#10 0x5624e8af9118 in qmp_marshal_object_add /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/qapi/qapi-commands-qom.c:337:5
|
||||
#11 0x5624e8bd1d49 in do_qmp_dispatch_bh /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../qapi/qmp-dispatch.c:128:5
|
||||
#12 0x5624e8cb2531 in aio_bh_call /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:171:5
|
||||
#13 0x5624e8cb340c in aio_bh_poll /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:218:13
|
||||
#14 0x5624e8c0be98 in aio_dispatch /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/aio-posix.c:423:5
|
||||
#15 0x5624e8cba3ce in aio_ctx_dispatch /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/async.c:360:5
|
||||
#16 0x7fb199ae0d3a in g_main_dispatch debian/build/deb/../../../glib/gmain.c:3419:28
|
||||
#17 0x7fb199ae0d3a in g_main_context_dispatch debian/build/deb/../../../glib/gmain.c:4137:7
|
||||
#18 0x5624e8cbe1d9 in glib_pollfds_poll /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:287:9
|
||||
#19 0x5624e8cbcb13 in os_host_main_loop_wait /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:310:5
|
||||
#20 0x5624e8cbc6dc in main_loop_wait /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../util/main-loop.c:589:11
|
||||
#21 0x5624e6f3f917 in qemu_main_loop /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/runstate.c:801:9
|
||||
#22 0x5624e893379c in qemu_default_main /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/main.c:37:14
|
||||
#23 0x5624e89337e7 in main /mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/../../system/main.c:48:12
|
||||
#24 0x7fb197972d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
|
||||
#25 0x7fb197972e3f in __libc_start_main csu/../csu/libc-start.c:392:3
|
||||
#26 0x5624e5c16fa4 in _start (/mnt/nvmedisk/linaro/qemu-from-laptop/qemu/build/asan/qemu-system-x86_64+0x210bfa4) (BuildId: a9e623fa1009a9435c0142c037cd7b8c1ad04ce3)
|
||||
|
||||
SUMMARY: AddressSanitizer: 5 byte(s) leaked in 1 allocation(s).
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Message-ID: <20240819145021.38524-1-peter.maydell@linaro.org>
|
||||
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
crypto/tlscredspsk.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/crypto/tlscredspsk.c b/crypto/tlscredspsk.c
|
||||
index 546cad1c5a..0d6b71a37c 100644
|
||||
--- a/crypto/tlscredspsk.c
|
||||
+++ b/crypto/tlscredspsk.c
|
||||
@@ -243,6 +243,7 @@ qcrypto_tls_creds_psk_finalize(Object *obj)
|
||||
QCryptoTLSCredsPSK *creds = QCRYPTO_TLS_CREDS_PSK(obj);
|
||||
|
||||
qcrypto_tls_creds_psk_unload(creds);
|
||||
+ g_free(creds->username);
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
118
cvm-Implement-command-blacklist-for-cvm-security-enh.patch
Normal file
118
cvm-Implement-command-blacklist-for-cvm-security-enh.patch
Normal file
@ -0,0 +1,118 @@
|
||||
From 384b3f41fd69ed6f5bf376ff1aac1a12deeea0fb Mon Sep 17 00:00:00 2001
|
||||
From: liupingwei <liupingwei0317@outlook.com>
|
||||
Date: Fri, 16 Aug 2024 18:06:10 +0800
|
||||
Subject: [PATCH] cvm : Implement command blacklist for cvm security
|
||||
enhancement
|
||||
|
||||
Added a new feature to intercept and block specific virsh commands(virsh
|
||||
save,virsh restore,virsh dump,virsh suspend,virsh resume)that can impact
|
||||
the security of cvm.
|
||||
|
||||
Signed-off-by: liupingwei <liupingwei0317@outlook.com>
|
||||
---
|
||||
dump/dump.c | 7 +++++++
|
||||
migration/migration-hmp-cmds.c | 6 ++++++
|
||||
migration/savevm.c | 6 ++++++
|
||||
monitor/qmp-cmds.c | 6 ++++++
|
||||
4 files changed, 25 insertions(+)
|
||||
|
||||
diff --git a/dump/dump.c b/dump/dump.c
|
||||
index 4819050764..787059ac2c 100644
|
||||
--- a/dump/dump.c
|
||||
+++ b/dump/dump.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "sysemu/dump.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/cpus.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-commands-dump.h"
|
||||
#include "qapi/qapi-events-dump.h"
|
||||
@@ -2065,6 +2066,12 @@ void qmp_dump_guest_memory(bool paging, const char *protocol,
|
||||
Error **errp)
|
||||
{
|
||||
ERRP_GUARD();
|
||||
+
|
||||
+ if (virtcca_cvm_enabled()) {
|
||||
+ error_setg(errp, "The dump-guest-memory command is temporarily unsupported in cvm.");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
const char *p;
|
||||
int fd;
|
||||
DumpState *s;
|
||||
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
|
||||
index 1fa6a5f478..386ba7fc98 100644
|
||||
--- a/migration/migration-hmp-cmds.c
|
||||
+++ b/migration/migration-hmp-cmds.c
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "ui/qemu-spice.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
#include "options.h"
|
||||
#include "migration.h"
|
||||
|
||||
@@ -406,6 +407,11 @@ void hmp_loadvm(Monitor *mon, const QDict *qdict)
|
||||
const char *name = qdict_get_str(qdict, "name");
|
||||
Error *err = NULL;
|
||||
|
||||
+ if (virtcca_cvm_enabled()) {
|
||||
+ error_setg(&err, "The loadvm command is temporarily unsupported in cvm.");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
vm_stop(RUN_STATE_RESTORE_VM);
|
||||
|
||||
if (load_snapshot(name, NULL, false, NULL, &err) && saved_vm_running) {
|
||||
diff --git a/migration/savevm.c b/migration/savevm.c
|
||||
index 477a19719f..cc65da605e 100644
|
||||
--- a/migration/savevm.c
|
||||
+++ b/migration/savevm.c
|
||||
@@ -61,6 +61,7 @@
|
||||
#include "sysemu/replay.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
#include "sysemu/xen.h"
|
||||
#include "migration/colo.h"
|
||||
#include "qemu/bitmap.h"
|
||||
@@ -3044,6 +3045,11 @@ int qemu_loadvm_approve_switchover(void)
|
||||
bool save_snapshot(const char *name, bool overwrite, const char *vmstate,
|
||||
bool has_devices, strList *devices, Error **errp)
|
||||
{
|
||||
+ if (virtcca_cvm_enabled()) {
|
||||
+ error_setg(errp, "The savevm command is temporarily unsupported in cvm.");
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
BlockDriverState *bs;
|
||||
QEMUSnapshotInfo sn1, *sn = &sn1;
|
||||
int ret = -1, ret2;
|
||||
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
|
||||
index e78462b857..c0b66f11bf 100644
|
||||
--- a/monitor/qmp-cmds.c
|
||||
+++ b/monitor/qmp-cmds.c
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/runstate-action.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qapi-init-commands.h"
|
||||
#include "qapi/qapi-commands-control.h"
|
||||
@@ -50,6 +51,11 @@ void qmp_quit(Error **errp)
|
||||
|
||||
void qmp_stop(Error **errp)
|
||||
{
|
||||
+ if (virtcca_cvm_enabled()) {
|
||||
+ error_setg(errp, "The stop command is temporarily unsupported in cvm.");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* if there is a dump in background, we should wait until the dump
|
||||
* finished */
|
||||
if (qemu_system_dump_in_progress()) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
69
doc-update-AMD-SEV-to-include-Live-migration-flow.patch
Normal file
69
doc-update-AMD-SEV-to-include-Live-migration-flow.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From 2da2e7ebea456360cc41881ff2e4a81a03b6d10c Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Thu, 7 May 2020 22:26:17 +0000
|
||||
Subject: [PATCH] doc: update AMD SEV to include Live migration flow
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/0e2b3d80e3.
|
||||
|
||||
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
docs/system/i386/amd-memory-encryption.rst | 40 +++++++++++++++++++++-
|
||||
1 file changed, 39 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/system/i386/amd-memory-encryption.rst b/docs/system/i386/amd-memory-encryption.rst
|
||||
index e9bc142bc1..b7e3f46ff6 100644
|
||||
--- a/docs/system/i386/amd-memory-encryption.rst
|
||||
+++ b/docs/system/i386/amd-memory-encryption.rst
|
||||
@@ -177,7 +177,45 @@ TODO
|
||||
Live Migration
|
||||
---------------
|
||||
|
||||
-TODO
|
||||
+AMD SEV encrypts the memory of VMs and because a different key is used
|
||||
+in each VM, the hypervisor will be unable to simply copy the
|
||||
+ciphertext from one VM to another to migrate the VM. Instead the AMD SEV Key
|
||||
+Management API provides sets of function which the hypervisor can use
|
||||
+to package a guest page for migration, while maintaining the confidentiality
|
||||
+provided by AMD SEV.
|
||||
+
|
||||
+SEV guest VMs have the concept of private and shared memory. The private
|
||||
+memory is encrypted with the guest-specific key, while shared memory may
|
||||
+be encrypted with the hypervisor key. The migration APIs provided by the
|
||||
+SEV API spec should be used for migrating the private pages. The
|
||||
+KVM_GET_PAGE_ENC_BITMAP ioctl can be used to get the guest page encryption
|
||||
+bitmap. The bitmap can be used to check if the given guest page is
|
||||
+private or shared.
|
||||
+
|
||||
+Before initiating the migration, we need to know the targets machine's public
|
||||
+Diffie-Hellman key (PDH) and certificate chain. It can be retrieved
|
||||
+with the 'query-sev-capabilities' QMP command or using the sev-tool. The
|
||||
+migrate-set-parameter can be used to pass the target machine's PDH and
|
||||
+certificate chain.
|
||||
+
|
||||
+During the migration flow, the SEND_START is called on the source hypervisor
|
||||
+to create an outgoing encryption context. The SEV guest policy dictates whether
|
||||
+the certificate passed through the migrate-sev-set-info command will be
|
||||
+validated. SEND_UPDATE_DATA is called to encrypt the guest private pages.
|
||||
+After migration is completed, SEND_FINISH is called to destroy the encryption
|
||||
+context and make the VM non-runnable to protect it against cloning.
|
||||
+
|
||||
+On the target machine, RECEIVE_START is called first to create an
|
||||
+incoming encryption context. The RECEIVE_UPDATE_DATA is called to copy
|
||||
+the received encrypted page into guest memory. After migration has
|
||||
+completed, RECEIVE_FINISH is called to make the VM runnable.
|
||||
+
|
||||
+For more information about the migration see SEV API Appendix A
|
||||
+Usage flow (Live migration section).
|
||||
+
|
||||
+NOTE:
|
||||
+To protect against the memory clone SEV APIs are designed to make the VM
|
||||
+unrunnable in case of the migration failure.
|
||||
|
||||
References
|
||||
----------
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
101
hw-core-ptimer-fix-timer-zero-period-condition-for-f.patch
Normal file
101
hw-core-ptimer-fix-timer-zero-period-condition-for-f.patch
Normal file
@ -0,0 +1,101 @@
|
||||
From fcd3ff011e62739b824c2e465e01b98c47e364f5 Mon Sep 17 00:00:00 2001
|
||||
From: qihao <qihao_yewu@cmss.chinamobile.com>
|
||||
Date: Fri, 16 Aug 2024 17:01:07 +0800
|
||||
Subject: [PATCH] hw/core/ptimer: fix timer zero period condition for freq >
|
||||
1GHz
|
||||
|
||||
cheery-pick from 446e5e8b4515e9a7be69ef6a29852975289bb6f0
|
||||
|
||||
The real period is zero when both period and period_frac are zero.
|
||||
Check the method ptimer_set_freq, if freq is larger than 1000 MHz,
|
||||
the period is zero, but the period_frac is not, in this case, the
|
||||
ptimer will work but the current code incorrectly recognizes that
|
||||
the ptimer is disabled.
|
||||
|
||||
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2306
|
||||
Signed-off-by: JianZhou Yue <JianZhou.Yue@verisilicon.com>
|
||||
Message-id: 3DA024AEA8B57545AF1B3CAA37077D0FB75E82C8@SHASXM03.verisilicon.com
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/core/ptimer.c | 4 ++--
|
||||
tests/unit/ptimer-test.c | 33 +++++++++++++++++++++++++++++++++
|
||||
2 files changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/core/ptimer.c b/hw/core/ptimer.c
|
||||
index e03165febf..7177ecfab0 100644
|
||||
--- a/hw/core/ptimer.c
|
||||
+++ b/hw/core/ptimer.c
|
||||
@@ -83,7 +83,7 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust)
|
||||
delta = s->delta = s->limit;
|
||||
}
|
||||
|
||||
- if (s->period == 0) {
|
||||
+ if (s->period == 0 && s->period_frac == 0) {
|
||||
if (!qtest_enabled()) {
|
||||
fprintf(stderr, "Timer with period zero, disabling\n");
|
||||
}
|
||||
@@ -309,7 +309,7 @@ void ptimer_run(ptimer_state *s, int oneshot)
|
||||
|
||||
assert(s->in_transaction);
|
||||
|
||||
- if (was_disabled && s->period == 0) {
|
||||
+ if (was_disabled && s->period == 0 && s->period_frac == 0) {
|
||||
if (!qtest_enabled()) {
|
||||
fprintf(stderr, "Timer with period zero, disabling\n");
|
||||
}
|
||||
diff --git a/tests/unit/ptimer-test.c b/tests/unit/ptimer-test.c
|
||||
index 04b5f4e3d0..08240594bb 100644
|
||||
--- a/tests/unit/ptimer-test.c
|
||||
+++ b/tests/unit/ptimer-test.c
|
||||
@@ -763,6 +763,33 @@ static void check_oneshot_with_load_0(gconstpointer arg)
|
||||
ptimer_free(ptimer);
|
||||
}
|
||||
|
||||
+static void check_freq_more_than_1000M(gconstpointer arg)
|
||||
+{
|
||||
+ const uint8_t *policy = arg;
|
||||
+ ptimer_state *ptimer = ptimer_init(ptimer_trigger, NULL, *policy);
|
||||
+ bool no_round_down = (*policy & PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
|
||||
+
|
||||
+ triggered = false;
|
||||
+
|
||||
+ ptimer_transaction_begin(ptimer);
|
||||
+ ptimer_set_freq(ptimer, 2000000000);
|
||||
+ ptimer_set_limit(ptimer, 8, 1);
|
||||
+ ptimer_run(ptimer, 1);
|
||||
+ ptimer_transaction_commit(ptimer);
|
||||
+
|
||||
+ qemu_clock_step(3);
|
||||
+
|
||||
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, no_round_down ? 3 : 2);
|
||||
+ g_assert_false(triggered);
|
||||
+
|
||||
+ qemu_clock_step(1);
|
||||
+
|
||||
+ g_assert_cmpuint(ptimer_get_count(ptimer), ==, 0);
|
||||
+ g_assert_true(triggered);
|
||||
+
|
||||
+ ptimer_free(ptimer);
|
||||
+}
|
||||
+
|
||||
static void add_ptimer_tests(uint8_t policy)
|
||||
{
|
||||
char policy_name[256] = "";
|
||||
@@ -857,6 +884,12 @@ static void add_ptimer_tests(uint8_t policy)
|
||||
policy_name),
|
||||
g_memdup2(&policy, 1), check_oneshot_with_load_0, g_free);
|
||||
g_free(tmp);
|
||||
+
|
||||
+ g_test_add_data_func_full(
|
||||
+ tmp = g_strdup_printf("/ptimer/freq_more_than_1000M policy=%s",
|
||||
+ policy_name),
|
||||
+ g_memdup2(&policy, 1), check_freq_more_than_1000M, g_free);
|
||||
+ g_free(tmp);
|
||||
}
|
||||
|
||||
static void add_all_ptimer_policies_comb_tests(void)
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
39
hw-display-vhost-user-gpu.c-fix-vhost_user_gpu_chr_r.patch
Normal file
39
hw-display-vhost-user-gpu.c-fix-vhost_user_gpu_chr_r.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From f2efa9729b4cb4ec98f93c1eafe38459fd82e7ae Mon Sep 17 00:00:00 2001
|
||||
From: qihao <qihao_yewu@cmss.chinamobile.com>
|
||||
Date: Mon, 26 Aug 2024 09:34:05 +0800
|
||||
Subject: [PATCH] hw/display/vhost-user-gpu.c: fix vhost_user_gpu_chr_read()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cheery-pick from d6192f3f7593536a4285e8ab6c6cf3f34973ce62
|
||||
|
||||
fix vhost_user_gpu_chr_read() where `size` was incorrectly passed to `msg->flags`.
|
||||
|
||||
Fixes: 267f664658 ("hw/display: add vhost-user-vga & gpu-pci")
|
||||
Signed-off-by: Haoran Zhang <wh1sper@zju.edu.cn>
|
||||
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/display/vhost-user-gpu.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c
|
||||
index 709c8a02a1..373f04a7b4 100644
|
||||
--- a/hw/display/vhost-user-gpu.c
|
||||
+++ b/hw/display/vhost-user-gpu.c
|
||||
@@ -385,7 +385,7 @@ vhost_user_gpu_chr_read(void *opaque)
|
||||
}
|
||||
|
||||
msg->request = request;
|
||||
- msg->flags = size;
|
||||
+ msg->flags = flags;
|
||||
msg->size = size;
|
||||
|
||||
if (request == VHOST_USER_GPU_CURSOR_UPDATE ||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
44
hw-loongarch-Fix-fdt-memory-node-wrong-reg.patch
Normal file
44
hw-loongarch-Fix-fdt-memory-node-wrong-reg.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From 073620787702404e2d71486c30967455c3c7904c Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 10:57:38 +0800
|
||||
Subject: [PATCH] hw/loongarch: Fix fdt memory node wrong 'reg'
|
||||
|
||||
cherry picked from commitd b11f9814526b833b3a052be2559457b1affad7f5
|
||||
|
||||
The right fdt memory node like [1], not [2]
|
||||
|
||||
[1]
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x00 0x00 0x00 0x10000000>;
|
||||
};
|
||||
[2]
|
||||
memory@0 {
|
||||
device_type = "memory";
|
||||
reg = <0x02 0x00 0x02 0x10000000>;
|
||||
};
|
||||
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-10-gaosong@loongson.cn>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/loongarch/virt.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 01e59f3a95..fc7b70ed4e 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -360,7 +360,7 @@ static void fdt_add_memory_node(MachineState *ms,
|
||||
char *nodename = g_strdup_printf("/memory@%" PRIx64, base);
|
||||
|
||||
qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
- qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, 0, size);
|
||||
qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
|
||||
|
||||
if (ms->numa_state && ms->numa_state->num_nodes) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
36
hw-loongarch-virt-Fix-FDT-memory-node-address-width.patch
Normal file
36
hw-loongarch-virt-Fix-FDT-memory-node-address-width.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From b9e94d97025251cfd13b3ad859b97002504285ce Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Fri, 13 Sep 2024 18:57:20 +0800
|
||||
Subject: [PATCH] hw/loongarch/virt: Fix FDT memory node address width
|
||||
|
||||
cherry picked from commitd 6204af704a071ea68d3af55c0502b112a7af9546
|
||||
|
||||
Higher bits for memory nodes were omitted at qemu_fdt_setprop_cells.
|
||||
|
||||
Cc: mailto:qemu-stable@nongnu.org
|
||||
Signed-off-by: Jiaxun Yang jiaxun.yang@flygoat.com
|
||||
Reviewed-by: Song Gao gaosong@loongson.cn
|
||||
Message-Id: 20240520-loongarch-fdt-memnode-v1-1-5ea9be93911e@flygoat.com
|
||||
Signed-off-by: Song Gao gaosong@loongson.cn
|
||||
Signed-off-by: Gao Jiazhen gaojiazhen_yewu@cmss.chinamobile.com
|
||||
---
|
||||
hw/loongarch/virt.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index fc7b70ed4e..5d4fcb7a55 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -360,7 +360,8 @@ static void fdt_add_memory_node(MachineState *ms,
|
||||
char *nodename = g_strdup_printf("/memory@%" PRIx64, base);
|
||||
|
||||
qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
- qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0, base, 0, size);
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", base >> 32, base,
|
||||
+ size >> 32, size);
|
||||
qemu_fdt_setprop_string(ms->fdt, nodename, "device_type", "memory");
|
||||
|
||||
if (ms->numa_state && ms->numa_state->num_nodes) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
92
hw-misc-bcm2835_property-Fix-handling-of-FRAMEBUFFER.patch
Normal file
92
hw-misc-bcm2835_property-Fix-handling-of-FRAMEBUFFER.patch
Normal file
@ -0,0 +1,92 @@
|
||||
From 93959a5378f57190fb79dd1ccdefb8d8cd095b58 Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 10:29:32 +0800
|
||||
Subject: [PATCH] hw/misc/bcm2835_property: Fix handling of
|
||||
FRAMEBUFFER_SET_PALETTE
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cherry picked from commit 0892fffc2abaadfb5d8b79bb0250ae1794862560
|
||||
|
||||
The documentation of the "Set palette" mailbox property at
|
||||
https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface#set-palette
|
||||
says it has the form:
|
||||
|
||||
Length: 24..1032
|
||||
Value:
|
||||
u32: offset: first palette index to set (0-255)
|
||||
u32: length: number of palette entries to set (1-256)
|
||||
u32...: RGBA palette values (offset to offset+length-1)
|
||||
|
||||
We get this wrong in a couple of ways:
|
||||
* we aren't checking the offset and length are in range, so the guest
|
||||
can make us spin for a long time by providing a large length
|
||||
* the bounds check on our loop is wrong: we should iterate through
|
||||
'length' palette entries, not 'length - offset' entries
|
||||
|
||||
Fix the loop to implement the bounds checks and get the loop
|
||||
condition right. In the process, make the variables local to
|
||||
this switch case, rather than function-global, so it's clearer
|
||||
what type they are when reading the code.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Message-id: 20240723131029.1159908-2-peter.maydell@linaro.org
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/misc/bcm2835_property.c | 27 ++++++++++++++++-----------
|
||||
1 file changed, 16 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c
|
||||
index ff55a4e2cd..12a1bc558a 100644
|
||||
--- a/hw/misc/bcm2835_property.c
|
||||
+++ b/hw/misc/bcm2835_property.c
|
||||
@@ -28,8 +28,6 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
|
||||
uint32_t tot_len;
|
||||
size_t resplen;
|
||||
uint32_t tmp;
|
||||
- int n;
|
||||
- uint32_t offset, length, color;
|
||||
|
||||
/*
|
||||
* Copy the current state of the framebuffer config; we will update
|
||||
@@ -264,18 +262,25 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
|
||||
resplen = 16;
|
||||
break;
|
||||
case RPI_FWREQ_FRAMEBUFFER_SET_PALETTE:
|
||||
- offset = ldl_le_phys(&s->dma_as, value + 12);
|
||||
- length = ldl_le_phys(&s->dma_as, value + 16);
|
||||
- n = 0;
|
||||
- while (n < length - offset) {
|
||||
- color = ldl_le_phys(&s->dma_as, value + 20 + (n << 2));
|
||||
- stl_le_phys(&s->dma_as,
|
||||
- s->fbdev->vcram_base + ((offset + n) << 2), color);
|
||||
- n++;
|
||||
+ {
|
||||
+ uint32_t offset = ldl_le_phys(&s->dma_as, value + 12);
|
||||
+ uint32_t length = ldl_le_phys(&s->dma_as, value + 16);
|
||||
+ int resp;
|
||||
+
|
||||
+ if (offset > 255 || length < 1 || length > 256) {
|
||||
+ resp = 1; /* invalid request */
|
||||
+ } else {
|
||||
+ for (uint32_t e = 0; e < length; e++) {
|
||||
+ uint32_t color = ldl_le_phys(&s->dma_as, value + 20 + (e << 2));
|
||||
+ stl_le_phys(&s->dma_as,
|
||||
+ s->fbdev->vcram_base + ((offset + e) << 2), color);
|
||||
+ }
|
||||
+ resp = 0;
|
||||
}
|
||||
- stl_le_phys(&s->dma_as, value + 12, 0);
|
||||
+ stl_le_phys(&s->dma_as, value + 12, resp);
|
||||
resplen = 4;
|
||||
break;
|
||||
+ }
|
||||
case RPI_FWREQ_FRAMEBUFFER_GET_NUM_DISPLAYS:
|
||||
stl_le_phys(&s->dma_as, value + 12, 1);
|
||||
resplen = 4;
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
190
hw-misc-support-vpsp.patch
Normal file
190
hw-misc-support-vpsp.patch
Normal file
@ -0,0 +1,190 @@
|
||||
From f74cee44cd57da213a790f7711a68da0f4de061a Mon Sep 17 00:00:00 2001
|
||||
From: xiongmengbiao <xiongmengbiao@hygon.cn>
|
||||
Date: Thu, 30 Nov 2023 13:47:21 +0800
|
||||
Subject: [PATCH] hw/misc: support vpsp
|
||||
|
||||
simulate a psp misc device for support tkm's key isolation
|
||||
|
||||
Signed-off-by: xiongmengbiao <xiongmengbiao@hygon.cn>
|
||||
---
|
||||
hw/misc/Kconfig | 4 ++
|
||||
hw/misc/meson.build | 1 +
|
||||
hw/misc/psp.c | 141 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 146 insertions(+)
|
||||
create mode 100644 hw/misc/psp.c
|
||||
|
||||
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
|
||||
index cc8a8c1418..2ea5c68eb5 100644
|
||||
--- a/hw/misc/Kconfig
|
||||
+++ b/hw/misc/Kconfig
|
||||
@@ -200,4 +200,8 @@ config IOSB
|
||||
config XLNX_VERSAL_TRNG
|
||||
bool
|
||||
|
||||
+config PSP_DEV
|
||||
+ bool
|
||||
+ default y
|
||||
+
|
||||
source macio/Kconfig
|
||||
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
|
||||
index 36c20d5637..28cba0ac28 100644
|
||||
--- a/hw/misc/meson.build
|
||||
+++ b/hw/misc/meson.build
|
||||
@@ -9,6 +9,7 @@ system_ss.add(when: 'CONFIG_UNIMP', if_true: files('unimp.c'))
|
||||
system_ss.add(when: 'CONFIG_EMPTY_SLOT', if_true: files('empty_slot.c'))
|
||||
system_ss.add(when: 'CONFIG_LED', if_true: files('led.c'))
|
||||
system_ss.add(when: 'CONFIG_PVPANIC_COMMON', if_true: files('pvpanic.c'))
|
||||
+system_ss.add(when: 'CONFIG_PSP_DEV', if_true: files('psp.c'))
|
||||
|
||||
# ARM devices
|
||||
system_ss.add(when: 'CONFIG_PL310', if_true: files('arm_l2x0.c'))
|
||||
diff --git a/hw/misc/psp.c b/hw/misc/psp.c
|
||||
new file mode 100644
|
||||
index 0000000000..6ff2ceec10
|
||||
--- /dev/null
|
||||
+++ b/hw/misc/psp.c
|
||||
@@ -0,0 +1,141 @@
|
||||
+/*
|
||||
+ * hygon psp device emulation
|
||||
+ *
|
||||
+ * Copyright 2024 HYGON Corp.
|
||||
+ *
|
||||
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
|
||||
+ * your option) any later version. See the COPYING file in the top-level
|
||||
+ * directory.
|
||||
+ */
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "qemu/compiler.h"
|
||||
+#include "qemu/error-report.h"
|
||||
+#include "qapi/error.h"
|
||||
+#include "migration/vmstate.h"
|
||||
+#include "hw/qdev-properties.h"
|
||||
+#include "sysemu/runstate.h"
|
||||
+#include <sys/ioctl.h>
|
||||
+
|
||||
+#define TYPE_PSP_DEV "psp"
|
||||
+OBJECT_DECLARE_SIMPLE_TYPE(PSPDevState, PSP_DEV)
|
||||
+
|
||||
+struct PSPDevState {
|
||||
+ /* Private */
|
||||
+ DeviceState pdev;
|
||||
+
|
||||
+ /* Public */
|
||||
+ Notifier shutdown_notifier;
|
||||
+ int dev_fd;
|
||||
+ bool enabled;
|
||||
+
|
||||
+ /**
|
||||
+ * vid is used to identify a virtual machine in qemu.
|
||||
+ * When a virtual machine accesses a tkm key,
|
||||
+ * the TKM module uses different key spaces based on different vids.
|
||||
+ */
|
||||
+ uint32_t vid;
|
||||
+};
|
||||
+
|
||||
+#define PSP_DEV_PATH "/dev/hygon_psp_config"
|
||||
+#define HYGON_PSP_IOC_TYPE 'H'
|
||||
+#define PSP_IOC_MUTEX_ENABLE _IOWR(HYGON_PSP_IOC_TYPE, 1, NULL)
|
||||
+#define PSP_IOC_MUTEX_DISABLE _IOWR(HYGON_PSP_IOC_TYPE, 2, NULL)
|
||||
+#define PSP_IOC_VPSP_OPT _IOWR(HYGON_PSP_IOC_TYPE, 3, NULL)
|
||||
+
|
||||
+enum VPSP_DEV_CTRL_OPCODE {
|
||||
+ VPSP_OP_VID_ADD,
|
||||
+ VPSP_OP_VID_DEL,
|
||||
+};
|
||||
+
|
||||
+struct psp_dev_ctrl {
|
||||
+ unsigned char op;
|
||||
+ union {
|
||||
+ unsigned int vid;
|
||||
+ unsigned char reserved[128];
|
||||
+ } data;
|
||||
+};
|
||||
+
|
||||
+static void psp_dev_destroy(PSPDevState *state)
|
||||
+{
|
||||
+ struct psp_dev_ctrl ctrl = { 0 };
|
||||
+ if (state && state->dev_fd) {
|
||||
+ if (state->enabled) {
|
||||
+ ctrl.op = VPSP_OP_VID_DEL;
|
||||
+ if (ioctl(state->dev_fd, PSP_IOC_VPSP_OPT, &ctrl) < 0) {
|
||||
+ error_report("VPSP_OP_VID_DEL: %d", -errno);
|
||||
+ } else {
|
||||
+ state->enabled = false;
|
||||
+ }
|
||||
+ }
|
||||
+ qemu_close(state->dev_fd);
|
||||
+ state->dev_fd = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * Guest OS performs shut down operations through 'shutdown' and 'powerdown' event.
|
||||
+ * The 'powerdown' event will also trigger 'shutdown' in the end,
|
||||
+ * so only attention to the 'shutdown' event.
|
||||
+ *
|
||||
+ * When Guest OS trigger 'reboot' or 'reset' event, to do nothing.
|
||||
+*/
|
||||
+static void psp_dev_shutdown_notify(Notifier *notifier, void *data)
|
||||
+{
|
||||
+ PSPDevState *state = container_of(notifier, PSPDevState, shutdown_notifier);
|
||||
+ psp_dev_destroy(state);
|
||||
+}
|
||||
+
|
||||
+static void psp_dev_realize(DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ struct psp_dev_ctrl ctrl = { 0 };
|
||||
+ PSPDevState *state = PSP_DEV(dev);
|
||||
+
|
||||
+ state->dev_fd = qemu_open_old(PSP_DEV_PATH, O_RDWR);
|
||||
+ if (state->dev_fd < 0) {
|
||||
+ error_setg(errp, "fail to open %s, errno %d.", PSP_DEV_PATH, errno);
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+ ctrl.op = VPSP_OP_VID_ADD;
|
||||
+ ctrl.data.vid = state->vid;
|
||||
+ if (ioctl(state->dev_fd, PSP_IOC_VPSP_OPT, &ctrl) < 0) {
|
||||
+ error_setg(errp, "psp_dev_realize VPSP_OP_VID_ADD vid %d, return %d", ctrl.data.vid, -errno);
|
||||
+ goto end;
|
||||
+ }
|
||||
+
|
||||
+ state->enabled = true;
|
||||
+ state->shutdown_notifier.notify = psp_dev_shutdown_notify;
|
||||
+ qemu_register_shutdown_notifier(&state->shutdown_notifier);
|
||||
+end:
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static struct Property psp_dev_properties[] = {
|
||||
+ DEFINE_PROP_UINT32("vid", PSPDevState, vid, 0),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+};
|
||||
+
|
||||
+static void psp_dev_class_init(ObjectClass *klass, void *data)
|
||||
+{
|
||||
+ DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
+
|
||||
+ dc->desc = "PSP Device";
|
||||
+ dc->realize = psp_dev_realize;
|
||||
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
+ device_class_set_props(dc, psp_dev_properties);
|
||||
+}
|
||||
+
|
||||
+static const TypeInfo psp_dev_info = {
|
||||
+ .name = TYPE_PSP_DEV,
|
||||
+ .parent = TYPE_DEVICE,
|
||||
+ .instance_size = sizeof(PSPDevState),
|
||||
+ .class_init = psp_dev_class_init,
|
||||
+};
|
||||
+
|
||||
+static void psp_dev_register_types(void)
|
||||
+{
|
||||
+ type_register_static(&psp_dev_info);
|
||||
+}
|
||||
+
|
||||
+type_init(psp_dev_register_types)
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
35
hw-nvme-fix-leak-of-uninitialized-memory-in-io_mgmt_.patch
Normal file
35
hw-nvme-fix-leak-of-uninitialized-memory-in-io_mgmt_.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From 80f4d02d7afa212fba4420a3af04f3a670b9a5d4 Mon Sep 17 00:00:00 2001
|
||||
From: qihao <qihao_yewu@cmss.chinamobile.com>
|
||||
Date: Mon, 26 Aug 2024 10:40:40 +0800
|
||||
Subject: [PATCH] hw/nvme: fix leak of uninitialized memory in io_mgmt_recv
|
||||
|
||||
cheery-pick from 6a22121c4f25b181e99479f65958ecde65da1c92
|
||||
|
||||
Yutaro Shimizu from the Cyber Defense Institute discovered a bug in the
|
||||
NVMe emulation that leaks contents of an uninitialized heap buffer if
|
||||
subsystem and FDP emulation are enabled.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Reported-by: Yutaro Shimizu <shimizu@cyberdefense.jp>
|
||||
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/nvme/ctrl.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c
|
||||
index aecf7c37bb..104aebc5ea 100644
|
||||
--- a/hw/nvme/ctrl.c
|
||||
+++ b/hw/nvme/ctrl.c
|
||||
@@ -4302,7 +4302,7 @@ static uint16_t nvme_io_mgmt_recv_ruhs(NvmeCtrl *n, NvmeRequest *req,
|
||||
|
||||
nruhsd = ns->fdp.nphs * endgrp->fdp.nrg;
|
||||
trans_len = sizeof(NvmeRuhStatus) + nruhsd * sizeof(NvmeRuhStatusDescr);
|
||||
- buf = g_malloc(trans_len);
|
||||
+ buf = g_malloc0(trans_len);
|
||||
|
||||
trans_len = MIN(trans_len, len);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
171
kvm-Add-support-for-CSV2-reboot.patch
Normal file
171
kvm-Add-support-for-CSV2-reboot.patch
Normal file
@ -0,0 +1,171 @@
|
||||
From 09934a231a513289caaae68e68912b735cb44b75 Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Thu, 15 Apr 2021 08:32:24 -0400
|
||||
Subject: [PATCH] kvm: Add support for CSV2 reboot
|
||||
|
||||
Linux will set vcpu.arch.guest_state_protected to true after execute
|
||||
LAUNCH_UPDATE_VMSA successfully, and then KVM will prevent any changes
|
||||
to VMCB State Save Area.
|
||||
|
||||
In order to support CSV2 guest reboot, calls cpus_control_pre_system_reset()
|
||||
to set vcpu.arch.guest_state_protected to false, and calls
|
||||
cpus_control_post_system_reset() to restore VMSA of guest's vcpu with
|
||||
data generated by LAUNCH_UPDATE_VMSA.
|
||||
|
||||
In addition, for memory encrypted guest, additional works may be
|
||||
required during system reset, such as flushing the cache. The function
|
||||
cpus_control_post_system_reset() hints linux to flush caches of guest
|
||||
memory.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
accel/kvm/kvm-accel-ops.c | 3 +++
|
||||
accel/kvm/kvm-all.c | 10 ++++++++++
|
||||
accel/kvm/kvm-cpus.h | 3 +++
|
||||
include/sysemu/accel-ops.h | 3 +++
|
||||
include/sysemu/cpus.h | 2 ++
|
||||
linux-headers/linux/kvm.h | 4 ++++
|
||||
system/cpus.c | 14 ++++++++++++++
|
||||
system/runstate.c | 5 +++++
|
||||
8 files changed, 44 insertions(+)
|
||||
|
||||
diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c
|
||||
index 6195150a0b..54f19028b8 100644
|
||||
--- a/accel/kvm/kvm-accel-ops.c
|
||||
+++ b/accel/kvm/kvm-accel-ops.c
|
||||
@@ -112,6 +112,9 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data)
|
||||
ops->remove_breakpoint = kvm_remove_breakpoint;
|
||||
ops->remove_all_breakpoints = kvm_remove_all_breakpoints;
|
||||
#endif
|
||||
+
|
||||
+ ops->control_pre_system_reset = kvm_cpus_control_pre_system_reset;
|
||||
+ ops->control_post_system_reset = kvm_cpus_control_post_system_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo kvm_accel_ops_type = {
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index dc3605e648..8077630825 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -2810,6 +2810,16 @@ void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu)
|
||||
run_on_cpu(cpu, do_kvm_cpu_synchronize_pre_loadvm, RUN_ON_CPU_NULL);
|
||||
}
|
||||
|
||||
+void kvm_cpus_control_pre_system_reset(void)
|
||||
+{
|
||||
+ kvm_vm_ioctl(kvm_state, KVM_CONTROL_VCPU_PRE_SYSTEM_RESET, NULL);
|
||||
+}
|
||||
+
|
||||
+void kvm_cpus_control_post_system_reset(void)
|
||||
+{
|
||||
+ kvm_vm_ioctl(kvm_state, KVM_CONTROL_VCPU_POST_SYSTEM_RESET, NULL);
|
||||
+}
|
||||
+
|
||||
#ifdef KVM_HAVE_MCE_INJECTION
|
||||
static __thread void *pending_sigbus_addr;
|
||||
static __thread int pending_sigbus_code;
|
||||
diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h
|
||||
index ca40add32c..27b9d0d9db 100644
|
||||
--- a/accel/kvm/kvm-cpus.h
|
||||
+++ b/accel/kvm/kvm-cpus.h
|
||||
@@ -23,4 +23,7 @@ int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len);
|
||||
int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr addr, vaddr len);
|
||||
void kvm_remove_all_breakpoints(CPUState *cpu);
|
||||
|
||||
+void kvm_cpus_control_pre_system_reset(void);
|
||||
+void kvm_cpus_control_post_system_reset(void);
|
||||
+
|
||||
#endif /* KVM_CPUS_H */
|
||||
diff --git a/include/sysemu/accel-ops.h b/include/sysemu/accel-ops.h
|
||||
index ef91fc28bb..7a32e7f820 100644
|
||||
--- a/include/sysemu/accel-ops.h
|
||||
+++ b/include/sysemu/accel-ops.h
|
||||
@@ -53,6 +53,9 @@ struct AccelOpsClass {
|
||||
int (*insert_breakpoint)(CPUState *cpu, int type, vaddr addr, vaddr len);
|
||||
int (*remove_breakpoint)(CPUState *cpu, int type, vaddr addr, vaddr len);
|
||||
void (*remove_all_breakpoints)(CPUState *cpu);
|
||||
+
|
||||
+ void (*control_pre_system_reset)(void);
|
||||
+ void (*control_post_system_reset)(void);
|
||||
};
|
||||
|
||||
#endif /* ACCEL_OPS_H */
|
||||
diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h
|
||||
index b4a566cfe7..f24d27daf5 100644
|
||||
--- a/include/sysemu/cpus.h
|
||||
+++ b/include/sysemu/cpus.h
|
||||
@@ -44,6 +44,8 @@ extern int icount_align_option;
|
||||
void qemu_cpu_kick_self(void);
|
||||
|
||||
bool cpus_are_resettable(void);
|
||||
+void cpus_control_pre_system_reset(void);
|
||||
+void cpus_control_post_system_reset(void);
|
||||
|
||||
void cpu_synchronize_all_states(void);
|
||||
void cpu_synchronize_all_post_reset(void);
|
||||
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||||
index e796105b76..eb30402c2d 100644
|
||||
--- a/linux-headers/linux/kvm.h
|
||||
+++ b/linux-headers/linux/kvm.h
|
||||
@@ -1626,6 +1626,10 @@ struct kvm_master_dev_info
|
||||
#define KVM_GET_DEVICE_ATTR _IOW(KVMIO, 0xe2, struct kvm_device_attr)
|
||||
#define KVM_HAS_DEVICE_ATTR _IOW(KVMIO, 0xe3, struct kvm_device_attr)
|
||||
|
||||
+/* ioctls for control vcpu setup during system reset */
|
||||
+#define KVM_CONTROL_VCPU_PRE_SYSTEM_RESET _IO(KVMIO, 0xe8)
|
||||
+#define KVM_CONTROL_VCPU_POST_SYSTEM_RESET _IO(KVMIO, 0xe9)
|
||||
+
|
||||
/*
|
||||
* ioctls for vcpu fds
|
||||
*/
|
||||
diff --git a/system/cpus.c b/system/cpus.c
|
||||
index f2289e9545..d9de09b9e8 100644
|
||||
--- a/system/cpus.c
|
||||
+++ b/system/cpus.c
|
||||
@@ -193,6 +193,20 @@ void cpu_synchronize_pre_loadvm(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
+void cpus_control_pre_system_reset(void)
|
||||
+{
|
||||
+ if (cpus_accel->control_pre_system_reset) {
|
||||
+ cpus_accel->control_pre_system_reset();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void cpus_control_post_system_reset(void)
|
||||
+{
|
||||
+ if (cpus_accel->control_post_system_reset) {
|
||||
+ cpus_accel->control_post_system_reset();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
bool cpus_are_resettable(void)
|
||||
{
|
||||
if (cpus_accel->cpus_are_resettable) {
|
||||
diff --git a/system/runstate.c b/system/runstate.c
|
||||
index 538c645326..7e41626bb1 100644
|
||||
--- a/system/runstate.c
|
||||
+++ b/system/runstate.c
|
||||
@@ -487,6 +487,8 @@ void qemu_system_reset(ShutdownCause reason)
|
||||
|
||||
mc = current_machine ? MACHINE_GET_CLASS(current_machine) : NULL;
|
||||
|
||||
+ cpus_control_pre_system_reset();
|
||||
+
|
||||
cpu_synchronize_all_states();
|
||||
|
||||
if (mc && mc->reset) {
|
||||
@@ -503,6 +505,9 @@ void qemu_system_reset(ShutdownCause reason)
|
||||
qapi_event_send_reset(shutdown_caused_by_guest(reason), reason);
|
||||
}
|
||||
cpu_synchronize_all_post_reset();
|
||||
+
|
||||
+ cpus_control_post_system_reset();
|
||||
+
|
||||
monitor_qapi_event_discard_io_error();
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
315
kvm-Add-support-for-SEV-shared-regions-list-and-KVM_.patch
Normal file
315
kvm-Add-support-for-SEV-shared-regions-list-and-KVM_.patch
Normal file
@ -0,0 +1,315 @@
|
||||
From 02e6bfc88ce5e944ce36b8ccb7d2af103a969980 Mon Sep 17 00:00:00 2001
|
||||
From: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Date: Tue, 27 Jul 2021 15:05:49 +0000
|
||||
Subject: [PATCH] kvm: Add support for SEV shared regions list and
|
||||
KVM_EXIT_HYPERCALL.
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/fcbbd9b19ac.
|
||||
|
||||
KVM_HC_MAP_GPA_RANGE hypercall is used by the SEV guest to notify a
|
||||
change in the page encryption status to the hypervisor. The hypercall
|
||||
should be invoked only when the encryption attribute is changed from
|
||||
encrypted -> decrypted and vice versa. By default all guest pages are
|
||||
considered encrypted.
|
||||
|
||||
The hypercall exits to userspace with KVM_EXIT_HYPERCALL exit code,
|
||||
currently this is used only by SEV guests for guest page encryptiion
|
||||
status tracking. Add support to handle this exit and invoke SEV
|
||||
shared regions list handlers.
|
||||
|
||||
Add support for SEV guest shared regions and implementation of the
|
||||
SEV shared regions list.
|
||||
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflicts. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
linux-headers/linux/kvm.h | 3 ++
|
||||
target/i386/kvm/kvm.c | 48 +++++++++++++++++
|
||||
target/i386/kvm/sev-stub.c | 11 ++++
|
||||
target/i386/sev.c | 106 +++++++++++++++++++++++++++++++++++++
|
||||
target/i386/sev.h | 3 ++
|
||||
5 files changed, 171 insertions(+)
|
||||
|
||||
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||||
index 8d12435e41..9489a20835 100644
|
||||
--- a/linux-headers/linux/kvm.h
|
||||
+++ b/linux-headers/linux/kvm.h
|
||||
@@ -348,6 +348,7 @@ struct kvm_run {
|
||||
} iocsr_io;
|
||||
/* KVM_EXIT_HYPERCALL */
|
||||
struct {
|
||||
+#define KVM_HC_MAP_GPA_RANGE 12
|
||||
__u64 nr;
|
||||
__u64 args[6];
|
||||
__u64 ret;
|
||||
@@ -1204,6 +1205,8 @@ struct kvm_ppc_resize_hpt {
|
||||
|
||||
#define KVM_CAP_ARM_VIRT_MSI_BYPASS 799
|
||||
|
||||
+#define KVM_EXIT_HYPERCALL_VALID_MASK (1 << KVM_HC_MAP_GPA_RANGE)
|
||||
+
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
struct kvm_irq_routing_irqchip {
|
||||
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||
index a0bc9ea7b1..82f6d3b048 100644
|
||||
--- a/target/i386/kvm/kvm.c
|
||||
+++ b/target/i386/kvm/kvm.c
|
||||
@@ -148,6 +148,7 @@ static int has_xcrs;
|
||||
static int has_sregs2;
|
||||
static int has_exception_payload;
|
||||
static int has_triple_fault_event;
|
||||
+static int has_map_gpa_range;
|
||||
|
||||
static bool has_msr_mcg_ext_ctl;
|
||||
|
||||
@@ -2191,6 +2192,17 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
c->eax = MAX(c->eax, KVM_CPUID_SIGNATURE | 0x10);
|
||||
}
|
||||
|
||||
+ if (sev_enabled()) {
|
||||
+ c = cpuid_find_entry(&cpuid_data.cpuid,
|
||||
+ KVM_CPUID_FEATURES | kvm_base, 0);
|
||||
+ if (c) {
|
||||
+ c->eax |= (1 << KVM_FEATURE_MIGRATION_CONTROL);
|
||||
+ if (has_map_gpa_range) {
|
||||
+ c->eax |= (1 << KVM_FEATURE_HC_MAP_GPA_RANGE);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
cpuid_data.cpuid.nent = cpuid_i;
|
||||
|
||||
cpuid_data.cpuid.padding = 0;
|
||||
@@ -2584,6 +2596,17 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
#endif
|
||||
}
|
||||
|
||||
+ has_map_gpa_range = kvm_check_extension(s, KVM_CAP_EXIT_HYPERCALL);
|
||||
+ if (has_map_gpa_range) {
|
||||
+ ret = kvm_vm_enable_cap(s, KVM_CAP_EXIT_HYPERCALL, 0,
|
||||
+ KVM_EXIT_HYPERCALL_VALID_MASK);
|
||||
+ if (ret < 0) {
|
||||
+ error_report("kvm: Failed to enable MAP_GPA_RANGE cap: %s",
|
||||
+ strerror(-ret));
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
ret = kvm_get_supported_msrs(s);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -4936,6 +4959,28 @@ static int kvm_handle_tpr_access(X86CPU *cpu)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static int kvm_handle_exit_hypercall(X86CPU *cpu, struct kvm_run *run)
|
||||
+{
|
||||
+ /*
|
||||
+ * Currently this exit is only used by SEV guests for
|
||||
+ * guest page encryption status tracking.
|
||||
+ */
|
||||
+ if (run->hypercall.nr == KVM_HC_MAP_GPA_RANGE) {
|
||||
+ unsigned long enc = run->hypercall.args[2];
|
||||
+ unsigned long gpa = run->hypercall.args[0];
|
||||
+ unsigned long npages = run->hypercall.args[1];
|
||||
+ unsigned long gfn_start = gpa >> TARGET_PAGE_BITS;
|
||||
+ unsigned long gfn_end = gfn_start + npages;
|
||||
+
|
||||
+ if (enc) {
|
||||
+ sev_remove_shared_regions_list(gfn_start, gfn_end);
|
||||
+ } else {
|
||||
+ sev_add_shared_regions_list(gfn_start, gfn_end);
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
|
||||
{
|
||||
static const uint8_t int3 = 0xcc;
|
||||
@@ -5359,6 +5404,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
ret = kvm_xen_handle_exit(cpu, &run->xen);
|
||||
break;
|
||||
#endif
|
||||
+ case KVM_EXIT_HYPERCALL:
|
||||
+ ret = kvm_handle_exit_hypercall(cpu, run);
|
||||
+ break;
|
||||
default:
|
||||
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
||||
ret = -1;
|
||||
diff --git a/target/i386/kvm/sev-stub.c b/target/i386/kvm/sev-stub.c
|
||||
index 1be5341e8a..1282d242a7 100644
|
||||
--- a/target/i386/kvm/sev-stub.c
|
||||
+++ b/target/i386/kvm/sev-stub.c
|
||||
@@ -19,3 +19,14 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
/* If we get here, cgs must be some non-SEV thing */
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+int sev_remove_shared_regions_list(unsigned long gfn_start,
|
||||
+ unsigned long gfn_end)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int sev_add_shared_regions_list(unsigned long gfn_start, unsigned long gfn_end)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index de1a4b271e..8525a7351f 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -44,6 +44,11 @@
|
||||
#define TYPE_SEV_GUEST "sev-guest"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
|
||||
|
||||
+struct shared_region {
|
||||
+ unsigned long gfn_start, gfn_end;
|
||||
+ QTAILQ_ENTRY(shared_region) list;
|
||||
+};
|
||||
+
|
||||
|
||||
/**
|
||||
* SevGuestState:
|
||||
@@ -87,6 +92,8 @@ struct SevGuestState {
|
||||
uint32_t reset_cs;
|
||||
uint32_t reset_ip;
|
||||
bool reset_data_valid;
|
||||
+
|
||||
+ QTAILQ_HEAD(, shared_region) shared_regions_list;
|
||||
};
|
||||
|
||||
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
|
||||
@@ -1136,6 +1143,7 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
migration_add_notifier(&sev_migration_state, sev_migration_state_notifier);
|
||||
|
||||
cgs_class->memory_encryption_ops = &sev_memory_encryption_ops;
|
||||
+ QTAILQ_INIT(&sev->shared_regions_list);
|
||||
|
||||
cgs->ready = true;
|
||||
|
||||
@@ -1671,6 +1679,104 @@ int sev_load_incoming_page(QEMUFile *f, uint8_t *ptr)
|
||||
return sev_receive_update_data(f, ptr);
|
||||
}
|
||||
|
||||
+int sev_remove_shared_regions_list(unsigned long start, unsigned long end)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+ struct shared_region *pos;
|
||||
+
|
||||
+ QTAILQ_FOREACH(pos, &s->shared_regions_list, list) {
|
||||
+ unsigned long l, r;
|
||||
+ unsigned long curr_gfn_end = pos->gfn_end;
|
||||
+
|
||||
+ /*
|
||||
+ * Find if any intersection exists ?
|
||||
+ * left bound for intersecting segment
|
||||
+ */
|
||||
+ l = MAX(start, pos->gfn_start);
|
||||
+ /* right bound for intersecting segment */
|
||||
+ r = MIN(end, pos->gfn_end);
|
||||
+ if (l <= r) {
|
||||
+ if (pos->gfn_start == l && pos->gfn_end == r) {
|
||||
+ QTAILQ_REMOVE(&s->shared_regions_list, pos, list);
|
||||
+ } else if (l == pos->gfn_start) {
|
||||
+ pos->gfn_start = r;
|
||||
+ } else if (r == pos->gfn_end) {
|
||||
+ pos->gfn_end = l;
|
||||
+ } else {
|
||||
+ /* Do a de-merge -- split linked list nodes */
|
||||
+ struct shared_region *shrd_region;
|
||||
+
|
||||
+ pos->gfn_end = l;
|
||||
+ shrd_region = g_malloc0(sizeof(*shrd_region));
|
||||
+ if (!shrd_region) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ shrd_region->gfn_start = r;
|
||||
+ shrd_region->gfn_end = curr_gfn_end;
|
||||
+ QTAILQ_INSERT_AFTER(&s->shared_regions_list, pos,
|
||||
+ shrd_region, list);
|
||||
+ }
|
||||
+ }
|
||||
+ if (end <= curr_gfn_end) {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int sev_add_shared_regions_list(unsigned long start, unsigned long end)
|
||||
+{
|
||||
+ struct shared_region *shrd_region;
|
||||
+ struct shared_region *pos;
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+
|
||||
+ if (QTAILQ_EMPTY(&s->shared_regions_list)) {
|
||||
+ shrd_region = g_malloc0(sizeof(*shrd_region));
|
||||
+ if (!shrd_region) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ shrd_region->gfn_start = start;
|
||||
+ shrd_region->gfn_end = end;
|
||||
+ QTAILQ_INSERT_TAIL(&s->shared_regions_list, shrd_region, list);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * shared regions list is a sorted list in ascending order
|
||||
+ * of guest PA's and also merges consecutive range of guest PA's
|
||||
+ */
|
||||
+ QTAILQ_FOREACH(pos, &s->shared_regions_list, list) {
|
||||
+ /* handle duplicate overlapping regions */
|
||||
+ if (start >= pos->gfn_start && end <= pos->gfn_end) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ if (pos->gfn_end < start) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ /* merge consecutive guest PA(s) -- forward merge */
|
||||
+ if (pos->gfn_start <= start && pos->gfn_end >= start) {
|
||||
+ pos->gfn_end = end;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+ /*
|
||||
+ * Add a new node
|
||||
+ */
|
||||
+ shrd_region = g_malloc0(sizeof(*shrd_region));
|
||||
+ if (!shrd_region) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ shrd_region->gfn_start = start;
|
||||
+ shrd_region->gfn_end = end;
|
||||
+ if (pos) {
|
||||
+ QTAILQ_INSERT_BEFORE(pos, shrd_region, list);
|
||||
+ } else {
|
||||
+ QTAILQ_INSERT_TAIL(&s->shared_regions_list, shrd_region, list);
|
||||
+ }
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
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 d94da2956b..acf69d4e6f 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -61,6 +61,9 @@ int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||
|
||||
int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size);
|
||||
void sev_es_set_reset_vector(CPUState *cpu);
|
||||
+int sev_remove_shared_regions_list(unsigned long gfn_start,
|
||||
+ unsigned long gfn_end);
|
||||
+int sev_add_shared_regions_list(unsigned long gfn_start, unsigned long gfn_end);
|
||||
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
123
kvm-Add-support-for-userspace-MSR-filtering-and-hand.patch
Normal file
123
kvm-Add-support-for-userspace-MSR-filtering-and-hand.patch
Normal file
@ -0,0 +1,123 @@
|
||||
From 7aced2a5fff91e0fcff97bb5eafddafece0cb983 Mon Sep 17 00:00:00 2001
|
||||
From: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Date: Tue, 27 Jul 2021 17:59:33 +0000
|
||||
Subject: [PATCH] kvm: Add support for userspace MSR filtering and handling of
|
||||
MSR_KVM_MIGRATION_CONTROL.
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/67935c3fd5f.
|
||||
|
||||
Add support for userspace MSR filtering using KVM_X86_SET_MSR_FILTER
|
||||
ioctl and handling of MSRs in userspace. Currently this is only used
|
||||
for SEV guests which use MSR_KVM_MIGRATION_CONTROL to indicate if the
|
||||
guest is enabled and ready for migration.
|
||||
|
||||
KVM arch code calls into SEV guest specific code to delete the
|
||||
SEV migrate blocker which has been setup at SEV_LAUNCH_FINISH.
|
||||
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflicts. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
target/i386/kvm/kvm.c | 35 +++++++++++++++++++++++++++++++++++
|
||||
target/i386/kvm/sev-stub.c | 4 ++++
|
||||
target/i386/sev.c | 6 ++++++
|
||||
target/i386/sev.h | 1 +
|
||||
4 files changed, 46 insertions(+)
|
||||
|
||||
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||
index 82f6d3b048..a5a755db01 100644
|
||||
--- a/target/i386/kvm/kvm.c
|
||||
+++ b/target/i386/kvm/kvm.c
|
||||
@@ -2488,6 +2488,32 @@ static bool kvm_rdmsr_core_thread_count(X86CPU *cpu, uint32_t msr,
|
||||
return true;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Currently this exit is only used by SEV guests for
|
||||
+ * MSR_KVM_MIGRATION_CONTROL to indicate if the guest
|
||||
+ * is ready for migration.
|
||||
+ */
|
||||
+static uint64_t msr_kvm_migration_control;
|
||||
+
|
||||
+static bool kvm_rdmsr_kvm_migration_control(X86CPU *cpu, uint32_t msr,
|
||||
+ uint64_t *val)
|
||||
+{
|
||||
+ *val = msr_kvm_migration_control;
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static bool kvm_wrmsr_kvm_migration_control(X86CPU *cpu, uint32_t msr,
|
||||
+ uint64_t val)
|
||||
+{
|
||||
+ msr_kvm_migration_control = val;
|
||||
+
|
||||
+ if (val == KVM_MIGRATION_READY)
|
||||
+ sev_del_migrate_blocker();
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
static Notifier smram_machine_done;
|
||||
static KVMMemoryListener smram_listener;
|
||||
static AddressSpace smram_address_space;
|
||||
@@ -2735,6 +2761,15 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
strerror(-ret));
|
||||
exit(1);
|
||||
}
|
||||
+
|
||||
+ r = kvm_filter_msr(s, MSR_KVM_MIGRATION_CONTROL,
|
||||
+ kvm_rdmsr_kvm_migration_control,
|
||||
+ kvm_wrmsr_kvm_migration_control);
|
||||
+ if (!r) {
|
||||
+ error_report("Could not install MSR_KVM_MIGRATION_CONTROL handler: %s",
|
||||
+ strerror(-ret));
|
||||
+ exit(1);
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
diff --git a/target/i386/kvm/sev-stub.c b/target/i386/kvm/sev-stub.c
|
||||
index 1282d242a7..99899688e4 100644
|
||||
--- a/target/i386/kvm/sev-stub.c
|
||||
+++ b/target/i386/kvm/sev-stub.c
|
||||
@@ -30,3 +30,7 @@ int sev_add_shared_regions_list(unsigned long gfn_start, unsigned long gfn_end)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
+
|
||||
+void sev_del_migrate_blocker(void)
|
||||
+{
|
||||
+}
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 47f41aefe7..98b0d3937a 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -925,6 +925,12 @@ sev_launch_finish(SevGuestState *sev)
|
||||
migrate_add_blocker(&sev_mig_blocker, &error_fatal);
|
||||
}
|
||||
|
||||
+void
|
||||
+sev_del_migrate_blocker(void)
|
||||
+{
|
||||
+ migrate_del_blocker(&sev_mig_blocker);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
sev_receive_finish(SevGuestState *s)
|
||||
{
|
||||
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||
index b9c2afb799..84e3bdf2df 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -70,6 +70,7 @@ int sev_add_shared_regions_list(unsigned long gfn_start, unsigned long gfn_end);
|
||||
int sev_save_outgoing_shared_regions_list(QEMUFile *f, uint64_t *bytes_sent);
|
||||
int sev_load_incoming_shared_regions_list(QEMUFile *f);
|
||||
bool sev_is_gfn_in_unshared_region(unsigned long gfn);
|
||||
+void sev_del_migrate_blocker(void);
|
||||
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
43
load_elf-fix-iterator-s-type-for-elf-file-processing.patch
Normal file
43
load_elf-fix-iterator-s-type-for-elf-file-processing.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From 2651409cf43002dc497483ae3ae227d4c602ca45 Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 17:02:38 +0800
|
||||
Subject: [PATCH] load_elf: fix iterator's type for elf file processing
|
||||
|
||||
cherry picked from commit 410c2a4d75f52f6a2fe978eda5a9b6f854afe5ea
|
||||
|
||||
j is used while loading an ELF file to byteswap segments'
|
||||
data. If data is larger than 2GB an overflow may happen.
|
||||
So j should be elf_word.
|
||||
|
||||
This commit fixes a minor bug: it's unlikely anybody is trying to
|
||||
load ELF files with 2GB+ segments for wrong-endianness targets,
|
||||
but if they did, it wouldn't work correctly.
|
||||
|
||||
Found by Linux Verification Center (linuxtesting.org) with SVACE.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Fixes: 7ef295e ("loader: Add data swap option to load-elf")
|
||||
Signed-off-by: Anastasia Belova <abelova@astralinux.ru>
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
include/hw/elf_ops.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
|
||||
index 0a5c258fe6..9c35d1b9da 100644
|
||||
--- a/include/hw/elf_ops.h
|
||||
+++ b/include/hw/elf_ops.h
|
||||
@@ -500,7 +500,7 @@ static ssize_t glue(load_elf, SZ)(const char *name, int fd,
|
||||
}
|
||||
|
||||
if (data_swab) {
|
||||
- int j;
|
||||
+ elf_word j;
|
||||
for (j = 0; j < file_size; j += (1 << data_swab)) {
|
||||
uint8_t *dp = data + j;
|
||||
switch (data_swab) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
120
migration-add-support-to-migrate-shared-regions-list.patch
Normal file
120
migration-add-support-to-migrate-shared-regions-list.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From 0f85e3a486c2d0130cb3be322900aa839d77d4bd Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Tue, 27 Jul 2021 16:31:36 +0000
|
||||
Subject: [PATCH] migration: add support to migrate shared regions list
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/9236f522e48b6.
|
||||
|
||||
When memory encryption is enabled, the hypervisor maintains a shared
|
||||
regions list which is referred by hypervisor during migration to check
|
||||
if page is private or shared. This list is built during the VM bootup and
|
||||
must be migrated to the target host so that hypervisor on target host can
|
||||
use it for future migration.
|
||||
|
||||
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Co-developed-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflicts. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
include/exec/confidential-guest-support.h | 2 +-
|
||||
target/i386/sev.c | 45 +++++++++++++++++++++++
|
||||
target/i386/sev.h | 2 +
|
||||
3 files changed, 48 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||
index 343f686fc2..dd4887f65f 100644
|
||||
--- a/include/exec/confidential-guest-support.h
|
||||
+++ b/include/exec/confidential-guest-support.h
|
||||
@@ -73,7 +73,7 @@ struct ConfidentialGuestMemoryEncryptionOps {
|
||||
bool (*is_gfn_in_unshared_region)(unsigned long gfn);
|
||||
|
||||
/* Write the shared regions list */
|
||||
- int (*save_outgoing_shared_regions_list)(QEMUFile *f);
|
||||
+ int (*save_outgoing_shared_regions_list)(QEMUFile *f, uint64_t *bytes_sent);
|
||||
|
||||
/* Load the shared regions list */
|
||||
int (*load_incoming_shared_regions_list)(QEMUFile *f);
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 8525a7351f..92aedf0503 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -176,10 +176,15 @@ static const char *const sev_fw_errlist[] = {
|
||||
|
||||
#define SEV_FW_BLOB_MAX_SIZE 0x4000 /* 16KB */
|
||||
|
||||
+#define SHARED_REGION_LIST_CONT 0x1
|
||||
+#define SHARED_REGION_LIST_END 0x2
|
||||
+
|
||||
static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.save_setup = sev_save_setup,
|
||||
.save_outgoing_page = sev_save_outgoing_page,
|
||||
.load_incoming_page = sev_load_incoming_page,
|
||||
+ .save_outgoing_shared_regions_list = sev_save_outgoing_shared_regions_list,
|
||||
+ .load_incoming_shared_regions_list = sev_load_incoming_shared_regions_list,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -1777,6 +1782,46 @@ int sev_add_shared_regions_list(unsigned long start, unsigned long end)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+int sev_save_outgoing_shared_regions_list(QEMUFile *f, uint64_t *bytes_sent)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+ struct shared_region *pos;
|
||||
+
|
||||
+ QTAILQ_FOREACH(pos, &s->shared_regions_list, list) {
|
||||
+ qemu_put_be32(f, SHARED_REGION_LIST_CONT);
|
||||
+ qemu_put_be32(f, pos->gfn_start);
|
||||
+ qemu_put_be32(f, pos->gfn_end);
|
||||
+ *bytes_sent += 12;
|
||||
+ }
|
||||
+
|
||||
+ qemu_put_be32(f, SHARED_REGION_LIST_END);
|
||||
+ *bytes_sent += 4;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int sev_load_incoming_shared_regions_list(QEMUFile *f)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+ struct shared_region *shrd_region;
|
||||
+ int status;
|
||||
+
|
||||
+ status = qemu_get_be32(f);
|
||||
+ while (status == SHARED_REGION_LIST_CONT) {
|
||||
+
|
||||
+ shrd_region = g_malloc0(sizeof(*shrd_region));
|
||||
+ if (!shrd_region) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ shrd_region->gfn_start = qemu_get_be32(f);
|
||||
+ shrd_region->gfn_end = qemu_get_be32(f);
|
||||
+
|
||||
+ QTAILQ_INSERT_TAIL(&s->shared_regions_list, shrd_region, list);
|
||||
+
|
||||
+ status = qemu_get_be32(f);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
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 acf69d4e6f..5b4231c859 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -64,6 +64,8 @@ void sev_es_set_reset_vector(CPUState *cpu);
|
||||
int sev_remove_shared_regions_list(unsigned long gfn_start,
|
||||
unsigned long gfn_end);
|
||||
int sev_add_shared_regions_list(unsigned long gfn_start, unsigned long gfn_end);
|
||||
+int sev_save_outgoing_shared_regions_list(QEMUFile *f, uint64_t *bytes_sent);
|
||||
+int sev_load_incoming_shared_regions_list(QEMUFile *f);
|
||||
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
87
migration-colo-Fix-bdrv_graph_rdlock_main_loop-Asser.patch
Normal file
87
migration-colo-Fix-bdrv_graph_rdlock_main_loop-Asser.patch
Normal file
@ -0,0 +1,87 @@
|
||||
From 015fc431353ae348e7e9cef2036b674a4e33eb1c Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 15:04:16 +0800
|
||||
Subject: [PATCH] =?UTF-8?q?migration/colo:=20Fix=20bdrv=5Fgraph=5Frdlock?=
|
||||
=?UTF-8?q?=5Fmain=5Floop:=20Assertion=20`!qemu=5Fin=5F=E2=80=A6?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cherry picked from commit 2cc637f1ea08d2a1b19fc5b1a30bc609f948de93
|
||||
|
||||
…coroutine()' failed.
|
||||
|
||||
bdrv_activate_all() should not be called from the coroutine context, move
|
||||
it to the QEMU thread colo_process_incoming_thread() with the bql_lock
|
||||
protected.
|
||||
|
||||
The backtrace is as follows:
|
||||
#4 0x0000561af7948362 in bdrv_graph_rdlock_main_loop () at ../block/graph-lock.c:260
|
||||
#5 0x0000561af7907a68 in graph_lockable_auto_lock_mainloop (x=0x7fd29810be7b) at /patch/to/qemu/include/block/graph-lock.h:259
|
||||
#6 0x0000561af79167d1 in bdrv_activate_all (errp=0x7fd29810bed0) at ../block.c:6906
|
||||
#7 0x0000561af762b4af in colo_incoming_co () at ../migration/colo.c:935
|
||||
#8 0x0000561af7607e57 in process_incoming_migration_co (opaque=0x0) at ../migration/migration.c:793
|
||||
#9 0x0000561af7adbeeb in coroutine_trampoline (i0=-106876144, i1=22042) at ../util/coroutine-ucontext.c:175
|
||||
#10 0x00007fd2a5cf21c0 in () at /lib64/libc.so.6
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Cc: Fabiano Rosas <farosas@suse.de>
|
||||
Closes: https://gitlab.com/qemu-project/qemu/-/issues/2277
|
||||
Fixes: 2b3912f ("block: Mark bdrv_first_blk() and bdrv_is_root_node() GRAPH_RDLOCK")
|
||||
Signed-off-by: Li Zhijian <lizhijian@fujitsu.com>
|
||||
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
|
||||
Tested-by: Zhang Chen <chen.zhang@intel.com>
|
||||
Reviewed-by: Fabiano Rosas <farosas@suse.de>
|
||||
Link: https://lore.kernel.org/r/20240417025634.1014582-1-lizhijian@fujitsu.com
|
||||
Signed-off-by: Peter Xu <peterx@redhat.com>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
migration/colo.c | 18 ++++++++++--------
|
||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/migration/colo.c b/migration/colo.c
|
||||
index 4447e34914..8f301b7e57 100644
|
||||
--- a/migration/colo.c
|
||||
+++ b/migration/colo.c
|
||||
@@ -830,6 +830,16 @@ static void *colo_process_incoming_thread(void *opaque)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ /* Make sure all file formats throw away their mutable metadata */
|
||||
+ qemu_mutex_lock_iothread();
|
||||
+ bdrv_activate_all(&local_err);
|
||||
+ if (local_err) {
|
||||
+ qemu_mutex_unlock_iothread();
|
||||
+ error_report_err(local_err);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ qemu_mutex_unlock_iothread();
|
||||
+
|
||||
failover_init_state();
|
||||
|
||||
mis->to_src_file = qemu_file_get_return_path(mis->from_src_file);
|
||||
@@ -917,7 +927,6 @@ out:
|
||||
int coroutine_fn colo_incoming_co(void)
|
||||
{
|
||||
MigrationIncomingState *mis = migration_incoming_get_current();
|
||||
- Error *local_err = NULL;
|
||||
QemuThread th;
|
||||
|
||||
assert(qemu_mutex_iothread_locked());
|
||||
@@ -926,13 +935,6 @@ int coroutine_fn colo_incoming_co(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- /* Make sure all file formats throw away their mutable metadata */
|
||||
- bdrv_activate_all(&local_err);
|
||||
- if (local_err) {
|
||||
- error_report_err(local_err);
|
||||
- return -EINVAL;
|
||||
- }
|
||||
-
|
||||
qemu_thread_create(&th, "COLO incoming", colo_process_incoming_thread,
|
||||
mis, QEMU_THREAD_JOINABLE);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
37
migration-ram-Accelerate-the-loading-of-CSV-guest-s-.patch
Normal file
37
migration-ram-Accelerate-the-loading-of-CSV-guest-s-.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From eac3cab8dcd005b33365b5196801268d696a11bc Mon Sep 17 00:00:00 2001
|
||||
From: fangbaoshun <fangbaoshun@hygon.cn>
|
||||
Date: Mon, 2 Aug 2021 14:49:45 +0800
|
||||
Subject: [PATCH] migration/ram: Accelerate the loading of CSV guest's
|
||||
encrypted pages
|
||||
|
||||
When memory encryption is enabled, the guest memory will be encrypted with
|
||||
the guest specific key. The patch introduces an accelerate solution which
|
||||
queued the pages into list and load them togather by COMMAND_BATCH.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
migration/ram.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index 7747f5af3a..790c0413c1 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -1297,6 +1297,14 @@ static int load_encrypted_data(QEMUFile *f, uint8_t *ptr)
|
||||
return ops->load_incoming_page(f, ptr);
|
||||
} else if (flag == RAM_SAVE_SHARED_REGIONS_LIST) {
|
||||
return ops->load_incoming_shared_regions_list(f);
|
||||
+ } else if (flag == RAM_SAVE_ENCRYPTED_PAGE_BATCH) {
|
||||
+ return ops->queue_incoming_page(f, ptr);
|
||||
+ } else if (flag == RAM_SAVE_ENCRYPTED_PAGE_BATCH_END) {
|
||||
+ if (ops->queue_incoming_page(f, ptr)) {
|
||||
+ error_report("Failed to queue incoming data");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ return ops->load_queued_incoming_pages(f);
|
||||
} else {
|
||||
error_report("unknown encrypted flag %x", flag);
|
||||
return 1;
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
208
migration-ram-Accelerate-the-transmission-of-CSV-gue.patch
Normal file
208
migration-ram-Accelerate-the-transmission-of-CSV-gue.patch
Normal file
@ -0,0 +1,208 @@
|
||||
From e2b3943bf75d34f5e913e05fbdf8116179812866 Mon Sep 17 00:00:00 2001
|
||||
From: fangbaoshun <fangbaoshun@hygon.cn>
|
||||
Date: Mon, 2 Aug 2021 14:35:51 +0800
|
||||
Subject: [PATCH] migration/ram: Accelerate the transmission of CSV guest's
|
||||
encrypted pages
|
||||
|
||||
When memory encryption is enabled, the guest memory will be encrypted with
|
||||
the guest specific key. The patch introduces an accelerate solution which
|
||||
queued the pages into list and send them togather by COMMAND_BATCH.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
configs/devices/i386-softmmu/default.mak | 1 +
|
||||
hw/i386/Kconfig | 5 +
|
||||
migration/ram.c | 119 +++++++++++++++++++++++
|
||||
target/i386/csv.h | 2 +
|
||||
4 files changed, 127 insertions(+)
|
||||
|
||||
diff --git a/configs/devices/i386-softmmu/default.mak b/configs/devices/i386-softmmu/default.mak
|
||||
index db83ffcab9..e948e54e4e 100644
|
||||
--- a/configs/devices/i386-softmmu/default.mak
|
||||
+++ b/configs/devices/i386-softmmu/default.mak
|
||||
@@ -24,6 +24,7 @@
|
||||
#CONFIG_VTD=n
|
||||
#CONFIG_SGX=n
|
||||
#CONFIG_CSV=n
|
||||
+#CONFIG_HYGON_CSV_MIG_ACCEL=n
|
||||
|
||||
# Boards:
|
||||
#
|
||||
diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig
|
||||
index 08f3ae43f8..682e324f1c 100644
|
||||
--- a/hw/i386/Kconfig
|
||||
+++ b/hw/i386/Kconfig
|
||||
@@ -12,8 +12,13 @@ config SGX
|
||||
|
||||
config CSV
|
||||
bool
|
||||
+ select HYGON_CSV_MIG_ACCEL
|
||||
depends on SEV
|
||||
|
||||
+config HYGON_CSV_MIG_ACCEL
|
||||
+ bool
|
||||
+ depends on CSV
|
||||
+
|
||||
config PC
|
||||
bool
|
||||
imply APPLESMC
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index 1abe8476f7..7747f5af3a 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -67,6 +67,7 @@
|
||||
|
||||
/* Defines RAM_SAVE_ENCRYPTED_PAGE and RAM_SAVE_SHARED_REGION_LIST */
|
||||
#include "target/i386/sev.h"
|
||||
+#include "target/i386/csv.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
#include "hw/boards.h" /* for machine_dump_guest_core() */
|
||||
@@ -2336,6 +2337,112 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_HYGON_CSV_MIG_ACCEL
|
||||
+/**
|
||||
+ * ram_save_encrypted_pages_in_batch: send the given encrypted pages to
|
||||
+ * the stream.
|
||||
+ *
|
||||
+ * Sending pages of 4K size in batch. The saving stops at the end of
|
||||
+ * the block.
|
||||
+ *
|
||||
+ * The caller must be with ram_state.bitmap_mutex held to call this
|
||||
+ * function.
|
||||
+ *
|
||||
+ * Returns the number of pages written or negative on error
|
||||
+ *
|
||||
+ * @rs: current RAM state
|
||||
+ * @pss: data about the page we want to send
|
||||
+ */
|
||||
+static int
|
||||
+ram_save_encrypted_pages_in_batch(RAMState *rs, PageSearchStatus *pss)
|
||||
+{
|
||||
+ bool page_dirty;
|
||||
+ int ret;
|
||||
+ int tmppages, pages = 0;
|
||||
+ uint8_t *p;
|
||||
+ uint32_t host_len = 0;
|
||||
+ uint64_t bytes_xmit = 0;
|
||||
+ ram_addr_t offset, start_offset = 0;
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ ConfidentialGuestSupportClass *cgs_class =
|
||||
+ (ConfidentialGuestSupportClass *)object_get_class(OBJECT(ms->cgs));
|
||||
+ struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||||
+ cgs_class->memory_encryption_ops;
|
||||
+
|
||||
+ do {
|
||||
+ page_dirty = migration_bitmap_clear_dirty(rs, pss->block, pss->page);
|
||||
+
|
||||
+ /* Check the pages is dirty and if it is send it */
|
||||
+ if (page_dirty) {
|
||||
+ /* Process the unencrypted page */
|
||||
+ if (!encrypted_test_list(rs, pss->block, pss->page)) {
|
||||
+ tmppages = migration_ops->ram_save_target_page(rs, pss);
|
||||
+ } else {
|
||||
+ /* Caculate the offset and host virtual address of the page */
|
||||
+ offset = ((ram_addr_t)pss->page) << TARGET_PAGE_BITS;
|
||||
+ p = pss->block->host + offset;
|
||||
+
|
||||
+ /* Record the offset and host virtual address of the first
|
||||
+ * page in this loop which will be used below.
|
||||
+ */
|
||||
+ if (host_len == 0) {
|
||||
+ start_offset = offset | RAM_SAVE_FLAG_ENCRYPTED_DATA;
|
||||
+ } else {
|
||||
+ offset |= (RAM_SAVE_FLAG_ENCRYPTED_DATA | RAM_SAVE_FLAG_CONTINUE);
|
||||
+ }
|
||||
+
|
||||
+ /* Queue the outgoing page if the page is not zero page.
|
||||
+ * If the queued pages are up to the outgoing page window size,
|
||||
+ * process them below.
|
||||
+ */
|
||||
+ if (ops->queue_outgoing_page(p, TARGET_PAGE_SIZE, offset))
|
||||
+ return -1;
|
||||
+
|
||||
+ tmppages = 1;
|
||||
+ host_len += TARGET_PAGE_SIZE;
|
||||
+
|
||||
+ stat64_add(&mig_stats.normal_pages, 1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ tmppages = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (tmppages >= 0) {
|
||||
+ pages += tmppages;
|
||||
+ } else {
|
||||
+ return tmppages;
|
||||
+ }
|
||||
+
|
||||
+ pss_find_next_dirty(pss);
|
||||
+ } while (offset_in_ramblock(pss->block,
|
||||
+ ((ram_addr_t)pss->page) << TARGET_PAGE_BITS) &&
|
||||
+ host_len < CSV_OUTGOING_PAGE_WINDOW_SIZE);
|
||||
+
|
||||
+ /* Check if there are any queued pages */
|
||||
+ if (host_len != 0) {
|
||||
+ ram_transferred_add(save_page_header(pss, pss->pss_channel,
|
||||
+ pss->block, start_offset));
|
||||
+ /* if only one page queued, flag is BATCH_END, else flag is BATCH */
|
||||
+ if (host_len > TARGET_PAGE_SIZE)
|
||||
+ qemu_put_be32(pss->pss_channel, RAM_SAVE_ENCRYPTED_PAGE_BATCH);
|
||||
+ else
|
||||
+ qemu_put_be32(pss->pss_channel, RAM_SAVE_ENCRYPTED_PAGE_BATCH_END);
|
||||
+ ram_transferred_add(4);
|
||||
+ /* Process the queued pages in batch */
|
||||
+ ret = ops->save_queued_outgoing_pages(pss->pss_channel, &bytes_xmit);
|
||||
+ if (ret) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ram_transferred_add(bytes_xmit);
|
||||
+ }
|
||||
+
|
||||
+ /* The offset we leave with is the last one we looked at */
|
||||
+ pss->page--;
|
||||
+
|
||||
+ return pages;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/**
|
||||
* ram_save_host_page: save a whole host page
|
||||
*
|
||||
@@ -2371,6 +2478,18 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+#ifdef CONFIG_HYGON_CSV_MIG_ACCEL
|
||||
+ /*
|
||||
+ * If command_batch function is enabled and memory encryption is enabled
|
||||
+ * then use command batch APIs to accelerate the sending process
|
||||
+ * to write the outgoing buffer to the wire. The encryption APIs
|
||||
+ * will re-encrypt the data with transport key so that data is prototect
|
||||
+ * on the wire.
|
||||
+ */
|
||||
+ if (memcrypt_enabled() && is_hygon_cpu() && !migration_in_postcopy())
|
||||
+ return ram_save_encrypted_pages_in_batch(rs, pss);
|
||||
+#endif
|
||||
+
|
||||
/* Update host page boundary information */
|
||||
pss_host_page_prepare(pss);
|
||||
|
||||
diff --git a/target/i386/csv.h b/target/i386/csv.h
|
||||
index 977f08b982..74a54f9b9c 100644
|
||||
--- a/target/i386/csv.h
|
||||
+++ b/target/i386/csv.h
|
||||
@@ -44,6 +44,8 @@ static bool __attribute__((unused)) is_hygon_cpu(void)
|
||||
|
||||
#endif
|
||||
|
||||
+#define CSV_OUTGOING_PAGE_WINDOW_SIZE (4094 * TARGET_PAGE_SIZE)
|
||||
+
|
||||
typedef struct CsvBatchCmdList CsvBatchCmdList;
|
||||
typedef void (*CsvDestroyCmdNodeFn) (void *data);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
57
migration-ram-Fix-calculation-of-gfn-correpond-to-a-.patch
Normal file
57
migration-ram-Fix-calculation-of-gfn-correpond-to-a-.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From ec2518709b8d461c3a165c1722ccd2e585cec161 Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Sun, 16 Jan 2022 20:05:02 -0500
|
||||
Subject: [PATCH] migration/ram: Fix calculation of gfn correpond to a page in
|
||||
ramblock
|
||||
|
||||
A RAMBlock contains a host memory region which may consist of many
|
||||
discontiguous MemoryRegion in AddressSpace of a Guest, so we cannot
|
||||
get gpa by MemoryRegion.addr. Since KVM memslot records the relationship
|
||||
between gpa and hva, so we can pass the hva of page in RAMBlock to
|
||||
kvm_phisical_memory_addr_from_host() to get the expected gpa.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
migration/ram.c | 12 +++++++++++-
|
||||
1 file changed, 11 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index 66a36736ad..1abe8476f7 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -67,6 +67,7 @@
|
||||
|
||||
/* Defines RAM_SAVE_ENCRYPTED_PAGE and RAM_SAVE_SHARED_REGION_LIST */
|
||||
#include "target/i386/sev.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
|
||||
#include "hw/boards.h" /* for machine_dump_guest_core() */
|
||||
|
||||
@@ -2145,6 +2146,8 @@ static bool encrypted_test_list(RAMState *rs, RAMBlock *block,
|
||||
struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||||
cgs_class->memory_encryption_ops;
|
||||
unsigned long gfn;
|
||||
+ hwaddr paddr = 0;
|
||||
+ int ret;
|
||||
|
||||
/* ROM devices contains the unencrypted data */
|
||||
if (memory_region_is_rom(block->mr)) {
|
||||
@@ -2167,7 +2170,14 @@ static bool encrypted_test_list(RAMState *rs, RAMBlock *block,
|
||||
* Translate page in ram_addr_t address space to GPA address
|
||||
* space using memory region.
|
||||
*/
|
||||
- gfn = page + (block->mr->addr >> TARGET_PAGE_BITS);
|
||||
+ if (kvm_enabled()) {
|
||||
+ ret = kvm_physical_memory_addr_from_host(kvm_state,
|
||||
+ block->host + (page << TARGET_PAGE_BITS), &paddr);
|
||||
+ if (ret == 0) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ gfn = paddr >> TARGET_PAGE_BITS;
|
||||
|
||||
return ops->is_gfn_in_unshared_region(gfn);
|
||||
}
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
32
migration-ram-Force-encrypted-status-for-VGA-vram.patch
Normal file
32
migration-ram-Force-encrypted-status-for-VGA-vram.patch
Normal file
@ -0,0 +1,32 @@
|
||||
From e6a20047ca9f61d7fc544e4f0b9b26aa268ccda7 Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Tue, 8 Dec 2020 22:57:46 -0500
|
||||
Subject: [PATCH] migration/ram: Force encrypted status for VGA vram
|
||||
|
||||
The VGA vram memory region act as frame buffer of VM. This memory
|
||||
is decrypted in the QEMU process. For CSV VM live migration, we
|
||||
should avoid memory encryption status check on VGA vram.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
migration/ram.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index 9ecd8580c5..66a36736ad 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -2159,6 +2159,10 @@ static bool encrypted_test_list(RAMState *rs, RAMBlock *block,
|
||||
return false;
|
||||
}
|
||||
|
||||
+ if (!strcmp(memory_region_name(block->mr), "vga.vram")) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Translate page in ram_addr_t address space to GPA address
|
||||
* space using memory region.
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
44
migration-ram-Force-encrypted-status-for-flash0-flas.patch
Normal file
44
migration-ram-Force-encrypted-status-for-flash0-flas.patch
Normal file
@ -0,0 +1,44 @@
|
||||
From cbbac2aa57d5609c254f99bf247d16e4b9fd7de3 Mon Sep 17 00:00:00 2001
|
||||
From: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Date: Tue, 27 Jul 2021 18:05:25 +0000
|
||||
Subject: [PATCH] migration/ram: Force encrypted status for flash0 & flash1
|
||||
devices.
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/803d6a4c8d.
|
||||
|
||||
Currently OVMF clears the C-bit and marks NonExistent memory space
|
||||
as decrypted in the page encryption bitmap. By marking the
|
||||
NonExistent memory space as decrypted it gurantees any future MMIO adds
|
||||
will work correctly, but this marks flash0 device space as decrypted.
|
||||
At reset the SEV core will be in forced encrypted state, so this
|
||||
decrypted marking of flash0 device space will cause VCPU reset to fail
|
||||
as flash0 device pages will be migrated incorrectly.
|
||||
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
migration/ram.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index beac7ea2c0..9ecd8580c5 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -2151,6 +2151,14 @@ static bool encrypted_test_list(RAMState *rs, RAMBlock *block,
|
||||
return false;
|
||||
}
|
||||
|
||||
+ if (!strcmp(memory_region_name(block->mr), "system.flash0")) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ if (!strcmp(memory_region_name(block->mr), "system.flash1")) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
/*
|
||||
* Translate page in ram_addr_t address space to GPA address
|
||||
* space using memory region.
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
343
migration-ram-add-support-to-send-encrypted-pages.patch
Normal file
343
migration-ram-add-support-to-send-encrypted-pages.patch
Normal file
@ -0,0 +1,343 @@
|
||||
From af3077a2f19f0604c4e7f8b94eb0338b7f1f85d6 Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Tue, 27 Jul 2021 16:53:19 +0000
|
||||
Subject: [PATCH] migration/ram: add support to send encrypted pages
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/2d6bda0d4cf.
|
||||
|
||||
When memory encryption is enabled, the guest memory will be encrypted with
|
||||
the guest specific key. The patch introduces RAM_SAVE_FLAG_ENCRYPTED_PAGE
|
||||
flag to distinguish the encrypted data from plaintext. Encrypted pages
|
||||
may need special handling. The sev_save_outgoing_page() is used
|
||||
by the sender to write the encrypted pages onto the socket, similarly the
|
||||
sev_load_incoming_page() is used by the target to read the
|
||||
encrypted pages from the socket and load into the guest memory.
|
||||
|
||||
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Co-developed-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflicts. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
migration/migration.h | 2 +
|
||||
migration/ram.c | 174 +++++++++++++++++++++++++++++++++++++++++-
|
||||
target/i386/sev.c | 14 ++++
|
||||
target/i386/sev.h | 4 +
|
||||
4 files changed, 192 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/migration/migration.h b/migration/migration.h
|
||||
index 2f26c9509b..eeddb7c0bd 100644
|
||||
--- a/migration/migration.h
|
||||
+++ b/migration/migration.h
|
||||
@@ -553,4 +553,6 @@ int migration_stop_vm(RunState state);
|
||||
|
||||
void migrate_fd_cancel(MigrationState *s);
|
||||
|
||||
+bool memcrypt_enabled(void);
|
||||
+
|
||||
#endif
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index f9b2b9b985..beac7ea2c0 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -63,6 +63,10 @@
|
||||
#include "options.h"
|
||||
#include "sysemu/dirtylimit.h"
|
||||
#include "sysemu/kvm.h"
|
||||
+#include "exec/confidential-guest-support.h"
|
||||
+
|
||||
+/* Defines RAM_SAVE_ENCRYPTED_PAGE and RAM_SAVE_SHARED_REGION_LIST */
|
||||
+#include "target/i386/sev.h"
|
||||
|
||||
#include "hw/boards.h" /* for machine_dump_guest_core() */
|
||||
|
||||
@@ -92,7 +96,16 @@
|
||||
/* 0x80 is reserved in rdma.h for RAM_SAVE_FLAG_HOOK */
|
||||
#define RAM_SAVE_FLAG_COMPRESS_PAGE 0x100
|
||||
#define RAM_SAVE_FLAG_MULTIFD_FLUSH 0x200
|
||||
-/* We can't use any flag that is bigger than 0x200 */
|
||||
+#define RAM_SAVE_FLAG_ENCRYPTED_DATA 0x400
|
||||
+
|
||||
+bool memcrypt_enabled(void)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ if(ms->cgs)
|
||||
+ return ms->cgs->ready;
|
||||
+ else
|
||||
+ return false;
|
||||
+}
|
||||
|
||||
XBZRLECacheStats xbzrle_counters;
|
||||
|
||||
@@ -1206,6 +1219,88 @@ static int save_normal_page(PageSearchStatus *pss, RAMBlock *block,
|
||||
return 1;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * ram_save_encrypted_page - send the given encrypted page to the stream
|
||||
+ */
|
||||
+static int ram_save_encrypted_page(RAMState *rs, PageSearchStatus *pss)
|
||||
+{
|
||||
+ QEMUFile *file = pss->pss_channel;
|
||||
+ int ret;
|
||||
+ uint8_t *p;
|
||||
+ RAMBlock *block = pss->block;
|
||||
+ ram_addr_t offset = ((ram_addr_t)pss->page) << TARGET_PAGE_BITS;
|
||||
+ uint64_t bytes_xmit = 0;
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ ConfidentialGuestSupportClass *cgs_class =
|
||||
+ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(ms->cgs));
|
||||
+ struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||||
+ cgs_class->memory_encryption_ops;
|
||||
+
|
||||
+ p = block->host + offset;
|
||||
+ trace_ram_save_page(block->idstr, (uint64_t)offset, p);
|
||||
+
|
||||
+ ram_transferred_add(save_page_header(pss, file, block,
|
||||
+ offset | RAM_SAVE_FLAG_ENCRYPTED_DATA));
|
||||
+ qemu_put_be32(file, RAM_SAVE_ENCRYPTED_PAGE);
|
||||
+ ret = ops->save_outgoing_page(file, p, TARGET_PAGE_SIZE, &bytes_xmit);
|
||||
+ if (ret) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ ram_transferred_add(4 + bytes_xmit);
|
||||
+ stat64_add(&mig_stats.normal_pages, 1);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * ram_save_shared_region_list: send the shared region list
|
||||
+ */
|
||||
+static int ram_save_shared_region_list(RAMState *rs, QEMUFile *f)
|
||||
+{
|
||||
+ int ret;
|
||||
+ uint64_t bytes_xmit = 0;
|
||||
+ PageSearchStatus *pss = &rs->pss[RAM_CHANNEL_PRECOPY];
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ ConfidentialGuestSupportClass *cgs_class =
|
||||
+ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(ms->cgs));
|
||||
+ struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||||
+ cgs_class->memory_encryption_ops;
|
||||
+
|
||||
+ ram_transferred_add(save_page_header(pss, f,
|
||||
+ pss->last_sent_block,
|
||||
+ RAM_SAVE_FLAG_ENCRYPTED_DATA));
|
||||
+ qemu_put_be32(f, RAM_SAVE_SHARED_REGIONS_LIST);
|
||||
+ ret = ops->save_outgoing_shared_regions_list(f, &bytes_xmit);
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ram_transferred_add(4 + bytes_xmit);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int load_encrypted_data(QEMUFile *f, uint8_t *ptr)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ ConfidentialGuestSupportClass *cgs_class =
|
||||
+ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(ms->cgs));
|
||||
+ struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||||
+ cgs_class->memory_encryption_ops;
|
||||
+
|
||||
+ int flag;
|
||||
+
|
||||
+ flag = qemu_get_be32(f);
|
||||
+
|
||||
+ if (flag == RAM_SAVE_ENCRYPTED_PAGE) {
|
||||
+ return ops->load_incoming_page(f, ptr);
|
||||
+ } else if (flag == RAM_SAVE_SHARED_REGIONS_LIST) {
|
||||
+ return ops->load_incoming_shared_regions_list(f);
|
||||
+ } else {
|
||||
+ error_report("unknown encrypted flag %x", flag);
|
||||
+ return 1;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* ram_save_page: send the given page to the stream
|
||||
*
|
||||
@@ -2036,6 +2131,35 @@ static bool save_compress_page(RAMState *rs, PageSearchStatus *pss,
|
||||
compress_send_queued_data);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * encrypted_test_list: check if the page is encrypted
|
||||
+ *
|
||||
+ * Returns a bool indicating whether the page is encrypted.
|
||||
+ */
|
||||
+static bool encrypted_test_list(RAMState *rs, RAMBlock *block,
|
||||
+ unsigned long page)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ ConfidentialGuestSupportClass *cgs_class =
|
||||
+ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(ms->cgs));
|
||||
+ struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||||
+ cgs_class->memory_encryption_ops;
|
||||
+ unsigned long gfn;
|
||||
+
|
||||
+ /* ROM devices contains the unencrypted data */
|
||||
+ if (memory_region_is_rom(block->mr)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Translate page in ram_addr_t address space to GPA address
|
||||
+ * space using memory region.
|
||||
+ */
|
||||
+ gfn = page + (block->mr->addr >> TARGET_PAGE_BITS);
|
||||
+
|
||||
+ return ops->is_gfn_in_unshared_region(gfn);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* ram_save_target_page_legacy: save one target page
|
||||
*
|
||||
@@ -2054,6 +2178,17 @@ static int ram_save_target_page_legacy(RAMState *rs, PageSearchStatus *pss)
|
||||
return res;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * If memory encryption is enabled then use memory encryption APIs
|
||||
+ * to write the outgoing buffer to the wire. The encryption APIs
|
||||
+ * will take care of accessing the guest memory and re-encrypt it
|
||||
+ * for the transport purposes.
|
||||
+ */
|
||||
+ if (memcrypt_enabled() &&
|
||||
+ encrypted_test_list(rs, pss->block, pss->page)) {
|
||||
+ return ram_save_encrypted_page(rs, pss);
|
||||
+ }
|
||||
+
|
||||
if (save_compress_page(rs, pss, offset)) {
|
||||
return 1;
|
||||
}
|
||||
@@ -2919,6 +3054,18 @@ void qemu_guest_free_page_hint(void *addr, size_t len)
|
||||
}
|
||||
}
|
||||
|
||||
+static int ram_encrypted_save_setup(void)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ ConfidentialGuestSupportClass *cgs_class =
|
||||
+ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(ms->cgs));
|
||||
+ struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||||
+ cgs_class->memory_encryption_ops;
|
||||
+ MigrationParameters *p = &migrate_get_current()->parameters;
|
||||
+
|
||||
+ return ops->save_setup(p->sev_pdh, p->sev_plat_cert, p->sev_amd_cert);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Each of ram_save_setup, ram_save_iterate and ram_save_complete has
|
||||
* long-running RCU critical section. When rcu-reclaims in the code
|
||||
@@ -2954,6 +3101,13 @@ static int ram_save_setup(QEMUFile *f, void *opaque)
|
||||
(*rsp)->pss[RAM_CHANNEL_PRECOPY].pss_channel = f;
|
||||
|
||||
WITH_RCU_READ_LOCK_GUARD() {
|
||||
+
|
||||
+ if (memcrypt_enabled()) {
|
||||
+ if (ram_encrypted_save_setup()) {
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
qemu_put_be64(f, ram_bytes_total_with_ignored()
|
||||
| RAM_SAVE_FLAG_MEM_SIZE);
|
||||
|
||||
@@ -3183,6 +3337,15 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
|
||||
qemu_file_set_error(f, ret);
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+ /* send the shared regions list */
|
||||
+ if (memcrypt_enabled()) {
|
||||
+ ret = ram_save_shared_region_list(rs, f);
|
||||
+ if (ret < 0) {
|
||||
+ qemu_file_set_error(f, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
ret = multifd_send_sync_main(rs->pss[RAM_CHANNEL_PRECOPY].pss_channel);
|
||||
@@ -3920,7 +4083,8 @@ static int ram_load_precopy(QEMUFile *f)
|
||||
}
|
||||
|
||||
if (flags & (RAM_SAVE_FLAG_ZERO | RAM_SAVE_FLAG_PAGE |
|
||||
- RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE)) {
|
||||
+ RAM_SAVE_FLAG_COMPRESS_PAGE | RAM_SAVE_FLAG_XBZRLE |
|
||||
+ RAM_SAVE_FLAG_ENCRYPTED_DATA)) {
|
||||
RAMBlock *block = ram_block_from_stream(mis, f, flags,
|
||||
RAM_CHANNEL_PRECOPY);
|
||||
|
||||
@@ -4013,6 +4177,12 @@ static int ram_load_precopy(QEMUFile *f)
|
||||
qemu_file_set_error(f, ret);
|
||||
}
|
||||
break;
|
||||
+ case RAM_SAVE_FLAG_ENCRYPTED_DATA:
|
||||
+ if (load_encrypted_data(f, host)) {
|
||||
+ error_report("Failed to load encrypted data");
|
||||
+ ret = -EINVAL;
|
||||
+ }
|
||||
+ break;
|
||||
default:
|
||||
error_report("Unknown combination of migration flags: 0x%x", flags);
|
||||
ret = -EINVAL;
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 92aedf0503..47f41aefe7 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -183,6 +183,7 @@ static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.save_setup = sev_save_setup,
|
||||
.save_outgoing_page = sev_save_outgoing_page,
|
||||
.load_incoming_page = sev_load_incoming_page,
|
||||
+ .is_gfn_in_unshared_region = sev_is_gfn_in_unshared_region,
|
||||
.save_outgoing_shared_regions_list = sev_save_outgoing_shared_regions_list,
|
||||
.load_incoming_shared_regions_list = sev_load_incoming_shared_regions_list,
|
||||
};
|
||||
@@ -1822,6 +1823,19 @@ int sev_load_incoming_shared_regions_list(QEMUFile *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+bool sev_is_gfn_in_unshared_region(unsigned long gfn)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+ struct shared_region *pos;
|
||||
+
|
||||
+ QTAILQ_FOREACH(pos, &s->shared_regions_list, list) {
|
||||
+ if (gfn >= pos->gfn_start && gfn < pos->gfn_end) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
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 5b4231c859..b9c2afb799 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -38,6 +38,9 @@ typedef struct SevKernelLoaderContext {
|
||||
size_t cmdline_size;
|
||||
} SevKernelLoaderContext;
|
||||
|
||||
+#define RAM_SAVE_ENCRYPTED_PAGE 0x1
|
||||
+#define RAM_SAVE_SHARED_REGIONS_LIST 0x2
|
||||
+
|
||||
#ifdef CONFIG_SEV
|
||||
bool sev_enabled(void);
|
||||
bool sev_es_enabled(void);
|
||||
@@ -66,6 +69,7 @@ int sev_remove_shared_regions_list(unsigned long gfn_start,
|
||||
int sev_add_shared_regions_list(unsigned long gfn_start, unsigned long gfn_end);
|
||||
int sev_save_outgoing_shared_regions_list(QEMUFile *f, uint64_t *bytes_sent);
|
||||
int sev_load_incoming_shared_regions_list(QEMUFile *f);
|
||||
+bool sev_is_gfn_in_unshared_region(unsigned long gfn);
|
||||
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
265
migration.json-add-AMD-SEV-specific-migration-parame.patch
Normal file
265
migration.json-add-AMD-SEV-specific-migration-parame.patch
Normal file
@ -0,0 +1,265 @@
|
||||
From 5ff59a5649385672da42097b24a2428bc2348d9b Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Tue, 27 Jul 2021 11:27:00 +0000
|
||||
Subject: [PATCH] migration.json: add AMD SEV specific migration parameters
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/d6a23bde6b6e.
|
||||
|
||||
AMD SEV migration flow requires that target machine's public Diffie-Hellman
|
||||
key (PDH) and certificate chain must be passed before initiating the guest
|
||||
migration. User can use QMP 'migrate-set-parameters' to pass the certificate
|
||||
chain. The certificate chain will be used while creating the outgoing
|
||||
encryption context.
|
||||
|
||||
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflicts and qapi errors. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
migration/migration-hmp-cmds.c | 28 ++++++++++++++++
|
||||
migration/options.c | 60 ++++++++++++++++++++++++++++++++++
|
||||
qapi/migration.json | 41 +++++++++++++++++++++--
|
||||
3 files changed, 126 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/migration/migration-hmp-cmds.c b/migration/migration-hmp-cmds.c
|
||||
index 1fa6a5f478..7ce0446d46 100644
|
||||
--- a/migration/migration-hmp-cmds.c
|
||||
+++ b/migration/migration-hmp-cmds.c
|
||||
@@ -395,6 +395,19 @@ void hmp_info_migrate_parameters(Monitor *mon, const QDict *qdict)
|
||||
monitor_printf(mon, "%s: %s\n",
|
||||
MigrationParameter_str(MIGRATION_PARAMETER_MODE),
|
||||
qapi_enum_lookup(&MigMode_lookup, params->mode));
|
||||
+
|
||||
+ assert(params->sev_pdh);
|
||||
+ monitor_printf(mon, "%s: %s\n",
|
||||
+ MigrationParameter_str(MIGRATION_PARAMETER_SEV_PDH),
|
||||
+ params->sev_pdh);
|
||||
+ assert(params->sev_plat_cert);
|
||||
+ monitor_printf(mon, "%s: %s\n",
|
||||
+ MigrationParameter_str(MIGRATION_PARAMETER_SEV_PLAT_CERT),
|
||||
+ params->sev_plat_cert);
|
||||
+ assert(params->sev_amd_cert);
|
||||
+ monitor_printf(mon, "%s: %s\n",
|
||||
+ MigrationParameter_str(MIGRATION_PARAMETER_SEV_AMD_CERT),
|
||||
+ params->sev_amd_cert);
|
||||
}
|
||||
|
||||
qapi_free_MigrationParameters(params);
|
||||
@@ -691,6 +704,21 @@ void hmp_migrate_set_parameter(Monitor *mon, const QDict *qdict)
|
||||
p->has_mode = true;
|
||||
visit_type_MigMode(v, param, &p->mode, &err);
|
||||
break;
|
||||
+ case MIGRATION_PARAMETER_SEV_PDH:
|
||||
+ p->sev_pdh = g_new0(StrOrNull, 1);
|
||||
+ p->sev_pdh->type = QTYPE_QSTRING;
|
||||
+ visit_type_str(v, param, &p->sev_pdh->u.s, &err);
|
||||
+ break;
|
||||
+ case MIGRATION_PARAMETER_SEV_PLAT_CERT:
|
||||
+ p->sev_plat_cert = g_new0(StrOrNull, 1);
|
||||
+ p->sev_plat_cert->type = QTYPE_QSTRING;
|
||||
+ visit_type_str(v, param, &p->sev_plat_cert->u.s, &err);
|
||||
+ break;
|
||||
+ case MIGRATION_PARAMETER_SEV_AMD_CERT:
|
||||
+ p->sev_amd_cert = g_new0(StrOrNull, 1);
|
||||
+ p->sev_amd_cert->type = QTYPE_QSTRING;
|
||||
+ visit_type_str(v, param, &p->sev_amd_cert->u.s, &err);
|
||||
+ break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
diff --git a/migration/options.c b/migration/options.c
|
||||
index 9b68962a65..71e71ea801 100644
|
||||
--- a/migration/options.c
|
||||
+++ b/migration/options.c
|
||||
@@ -183,6 +183,9 @@ Property migration_properties[] = {
|
||||
DEFINE_PROP_MIG_MODE("mode", MigrationState,
|
||||
parameters.mode,
|
||||
MIG_MODE_NORMAL),
|
||||
+ DEFINE_PROP_STRING("sev-pdh", MigrationState, parameters.sev_pdh),
|
||||
+ DEFINE_PROP_STRING("sev-plat-cert", MigrationState, parameters.sev_plat_cert),
|
||||
+ DEFINE_PROP_STRING("sev-amd-cert", MigrationState, parameters.sev_amd_cert),
|
||||
|
||||
/* Migration capabilities */
|
||||
DEFINE_PROP_MIG_CAP("x-xbzrle", MIGRATION_CAPABILITY_XBZRLE),
|
||||
@@ -1012,6 +1015,9 @@ MigrationParameters *qmp_query_migrate_parameters(Error **errp)
|
||||
params->announce_rounds = s->parameters.announce_rounds;
|
||||
params->has_announce_step = true;
|
||||
params->announce_step = s->parameters.announce_step;
|
||||
+ params->sev_pdh = g_strdup(s->parameters.sev_pdh);
|
||||
+ params->sev_plat_cert = g_strdup(s->parameters.sev_plat_cert);
|
||||
+ params->sev_amd_cert = g_strdup(s->parameters.sev_amd_cert);
|
||||
|
||||
if (s->parameters.has_block_bitmap_mapping) {
|
||||
params->has_block_bitmap_mapping = true;
|
||||
@@ -1063,6 +1069,10 @@ void migrate_params_init(MigrationParameters *params)
|
||||
params->has_x_vcpu_dirty_limit_period = true;
|
||||
params->has_vcpu_dirty_limit = true;
|
||||
params->has_mode = true;
|
||||
+
|
||||
+ params->sev_pdh = g_strdup("");
|
||||
+ params->sev_plat_cert = g_strdup("");
|
||||
+ params->sev_amd_cert = g_strdup("");
|
||||
}
|
||||
|
||||
static bool compress_level_check(MigrationParameters *params, Error **errp)
|
||||
@@ -1392,6 +1402,19 @@ static void migrate_params_test_apply(MigrateSetParameters *params,
|
||||
if (params->has_mode) {
|
||||
dest->mode = params->mode;
|
||||
}
|
||||
+
|
||||
+ if (params->sev_pdh) {
|
||||
+ assert(params->sev_pdh->type == QTYPE_QSTRING);
|
||||
+ dest->sev_pdh = params->sev_pdh->u.s;
|
||||
+ }
|
||||
+ if (params->sev_plat_cert) {
|
||||
+ assert(params->sev_plat_cert->type == QTYPE_QSTRING);
|
||||
+ dest->sev_plat_cert = params->sev_plat_cert->u.s;
|
||||
+ }
|
||||
+ if (params->sev_amd_cert) {
|
||||
+ assert(params->sev_amd_cert->type == QTYPE_QSTRING);
|
||||
+ dest->sev_amd_cert = params->sev_amd_cert->u.s;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
|
||||
@@ -1540,6 +1563,22 @@ static void migrate_params_apply(MigrateSetParameters *params, Error **errp)
|
||||
if (params->has_mode) {
|
||||
s->parameters.mode = params->mode;
|
||||
}
|
||||
+
|
||||
+ if (params->sev_pdh) {
|
||||
+ g_free(s->parameters.sev_pdh);
|
||||
+ assert(params->sev_pdh->type == QTYPE_QSTRING);
|
||||
+ s->parameters.sev_pdh = g_strdup(params->sev_pdh->u.s);
|
||||
+ }
|
||||
+ if (params->sev_plat_cert) {
|
||||
+ g_free(s->parameters.sev_plat_cert);
|
||||
+ assert(params->sev_plat_cert->type == QTYPE_QSTRING);
|
||||
+ s->parameters.sev_plat_cert = g_strdup(params->sev_plat_cert->u.s);
|
||||
+ }
|
||||
+ if (params->sev_amd_cert) {
|
||||
+ g_free(s->parameters.sev_amd_cert);
|
||||
+ assert(params->sev_amd_cert->type == QTYPE_QSTRING);
|
||||
+ s->parameters.sev_amd_cert = g_strdup(params->sev_amd_cert->u.s);
|
||||
+ }
|
||||
}
|
||||
|
||||
void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
|
||||
@@ -1565,6 +1604,27 @@ void qmp_migrate_set_parameters(MigrateSetParameters *params, Error **errp)
|
||||
params->tls_authz->type = QTYPE_QSTRING;
|
||||
params->tls_authz->u.s = strdup("");
|
||||
}
|
||||
+ /* TODO Rewrite "" to null instead */
|
||||
+ if (params->sev_pdh
|
||||
+ && params->sev_pdh->type == QTYPE_QNULL) {
|
||||
+ qobject_unref(params->sev_pdh->u.n);
|
||||
+ params->sev_pdh->type = QTYPE_QSTRING;
|
||||
+ params->sev_pdh->u.s = strdup("");
|
||||
+ }
|
||||
+ /* TODO Rewrite "" to null instead */
|
||||
+ if (params->sev_plat_cert
|
||||
+ && params->sev_plat_cert->type == QTYPE_QNULL) {
|
||||
+ qobject_unref(params->sev_plat_cert->u.n);
|
||||
+ params->sev_plat_cert->type = QTYPE_QSTRING;
|
||||
+ params->sev_plat_cert->u.s = strdup("");
|
||||
+ }
|
||||
+ /* TODO Rewrite "" to null instead */
|
||||
+ if (params->sev_amd_cert
|
||||
+ && params->sev_amd_cert->type == QTYPE_QNULL) {
|
||||
+ qobject_unref(params->sev_amd_cert->u.n);
|
||||
+ params->sev_amd_cert->type = QTYPE_QSTRING;
|
||||
+ params->sev_amd_cert->u.s = strdup("");
|
||||
+ }
|
||||
|
||||
migrate_params_test_apply(params, &tmp);
|
||||
|
||||
diff --git a/qapi/migration.json b/qapi/migration.json
|
||||
index 5d0855a1d8..038e99cba3 100644
|
||||
--- a/qapi/migration.json
|
||||
+++ b/qapi/migration.json
|
||||
@@ -891,6 +891,15 @@
|
||||
# @mode: Migration mode. See description in @MigMode. Default is 'normal'.
|
||||
# (Since 8.2)
|
||||
#
|
||||
+# @sev-pdh: The target host platform diffie-hellman key encoded in base64
|
||||
+# (Since 4.2)
|
||||
+#
|
||||
+# @sev-plat-cert: The target host platform certificate chain encoded in base64
|
||||
+# (Since 4.2)
|
||||
+#
|
||||
+# @sev-amd-cert: AMD certificate chain which include ASK and OCA encoded in
|
||||
+# base64 (Since 4.2)
|
||||
+#
|
||||
# Features:
|
||||
#
|
||||
# @deprecated: Member @block-incremental is deprecated. Use
|
||||
@@ -925,7 +934,8 @@
|
||||
'block-bitmap-mapping',
|
||||
{ 'name': 'x-vcpu-dirty-limit-period', 'features': ['unstable'] },
|
||||
'vcpu-dirty-limit',
|
||||
- 'mode'] }
|
||||
+ 'mode',
|
||||
+ 'sev-pdh', 'sev-plat-cert', 'sev-amd-cert'] }
|
||||
|
||||
##
|
||||
# @MigrateSetParameters:
|
||||
@@ -1083,6 +1093,15 @@
|
||||
# @mode: Migration mode. See description in @MigMode. Default is 'normal'.
|
||||
# (Since 8.2)
|
||||
#
|
||||
+# @sev-pdh: The target host platform diffie-hellman key encoded in base64
|
||||
+# (Since 4.2)
|
||||
+#
|
||||
+# @sev-plat-cert: The target host platform certificate chain encoded in base64
|
||||
+# (Since 4.2)
|
||||
+#
|
||||
+# @sev-amd-cert: AMD certificate chain which include ASK and OCA encoded in
|
||||
+# base64 (Since 4.2)
|
||||
+#
|
||||
# Features:
|
||||
#
|
||||
# @deprecated: Member @block-incremental is deprecated. Use
|
||||
@@ -1139,7 +1158,11 @@
|
||||
'*x-vcpu-dirty-limit-period': { 'type': 'uint64',
|
||||
'features': [ 'unstable' ] },
|
||||
'*vcpu-dirty-limit': 'uint64',
|
||||
- '*mode': 'MigMode'} }
|
||||
+ '*mode': 'MigMode',
|
||||
+ '*sev-pdh': 'StrOrNull',
|
||||
+ '*sev-plat-cert': 'StrOrNull',
|
||||
+ '*sev-amd-cert' : 'StrOrNull' } }
|
||||
+
|
||||
|
||||
##
|
||||
# @migrate-set-parameters:
|
||||
@@ -1317,6 +1340,15 @@
|
||||
# @mode: Migration mode. See description in @MigMode. Default is 'normal'.
|
||||
# (Since 8.2)
|
||||
#
|
||||
+# @sev-pdh: The target host platform diffie-hellman key encoded in base64
|
||||
+# (Since 4.2)
|
||||
+#
|
||||
+# @sev-plat-cert: The target host platform certificate chain encoded in base64
|
||||
+# (Since 4.2)
|
||||
+#
|
||||
+# @sev-amd-cert: AMD certificate chain which include ASK and OCA encoded in
|
||||
+# base64 (Since 4.2)
|
||||
+#
|
||||
# Features:
|
||||
#
|
||||
# @deprecated: Member @block-incremental is deprecated. Use
|
||||
@@ -1369,7 +1401,10 @@
|
||||
'*x-vcpu-dirty-limit-period': { 'type': 'uint64',
|
||||
'features': [ 'unstable' ] },
|
||||
'*vcpu-dirty-limit': 'uint64',
|
||||
- '*mode': 'MigMode'} }
|
||||
+ '*mode': 'MigMode',
|
||||
+ '*sev-pdh': 'str',
|
||||
+ '*sev-plat-cert': 'str',
|
||||
+ '*sev-amd-cert' : 'str'} }
|
||||
|
||||
##
|
||||
# @query-migrate-parameters:
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
90
nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch
Normal file
90
nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch
Normal file
@ -0,0 +1,90 @@
|
||||
From 5da793de60f37cf0daaffee3fe8300a1a20bf36b Mon Sep 17 00:00:00 2001
|
||||
From: Eric Blake <eblake@redhat.com>
|
||||
Date: Thu, 22 Aug 2024 09:35:29 -0500
|
||||
Subject: [PATCH] nbd/server: CVE-2024-7409: Avoid use-after-free when closing
|
||||
server
|
||||
|
||||
Commit 3e7ef738 plugged the use-after-free of the global nbd_server
|
||||
object, but overlooked a use-after-free of nbd_server->listener.
|
||||
Although this race is harder to hit, notice that our shutdown path
|
||||
first drops the reference count of nbd_server->listener, then triggers
|
||||
actions that can result in a pending client reaching the
|
||||
nbd_blockdev_client_closed() callback, which in turn calls
|
||||
qio_net_listener_set_client_func on a potentially stale object.
|
||||
|
||||
If we know we don't want any more clients to connect, and have already
|
||||
told the listener socket to shut down, then we should not be trying to
|
||||
update the listener socket's associated function.
|
||||
|
||||
Reproducer:
|
||||
|
||||
> #!/usr/bin/python3
|
||||
>
|
||||
> import os
|
||||
> from threading import Thread
|
||||
>
|
||||
> def start_stop():
|
||||
> while 1:
|
||||
> os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-start",
|
||||
+"arguments":{"addr":{"type":"unix","data":{"path":"/tmp/nbd-sock"}}}}\'')
|
||||
> os.system('virsh qemu-monitor-command VM \'{"execute": "nbd-server-stop"}\'')
|
||||
>
|
||||
> def nbd_list():
|
||||
> while 1:
|
||||
> os.system('/path/to/build/qemu-nbd -L -k /tmp/nbd-sock')
|
||||
>
|
||||
> def test():
|
||||
> sst = Thread(target=start_stop)
|
||||
> sst.start()
|
||||
> nlt = Thread(target=nbd_list)
|
||||
> nlt.start()
|
||||
>
|
||||
> sst.join()
|
||||
> nlt.join()
|
||||
>
|
||||
> test()
|
||||
|
||||
Fixes: CVE-2024-7409
|
||||
Fixes: 3e7ef738c8 ("nbd/server: CVE-2024-7409: Close stray clients at server-stop")
|
||||
CC: qemu-stable@nongnu.org
|
||||
Reported-by: Andrey Drobyshev <andrey.drobyshev@virtuozzo.com>
|
||||
Signed-off-by: Eric Blake <eblake@redhat.com>
|
||||
Message-ID: <20240822143617.800419-2-eblake@redhat.com>
|
||||
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
---
|
||||
blockdev-nbd.c | 12 ++++++++----
|
||||
1 file changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/blockdev-nbd.c b/blockdev-nbd.c
|
||||
index f73409ae49..b36f41b7c5 100644
|
||||
--- a/blockdev-nbd.c
|
||||
+++ b/blockdev-nbd.c
|
||||
@@ -92,10 +92,13 @@ static void nbd_accept(QIONetListener *listener, QIOChannelSocket *cioc,
|
||||
|
||||
static void nbd_update_server_watch(NBDServerData *s)
|
||||
{
|
||||
- if (!s->max_connections || s->connections < s->max_connections) {
|
||||
- qio_net_listener_set_client_func(s->listener, nbd_accept, NULL, NULL);
|
||||
- } else {
|
||||
- qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
|
||||
+ if (s->listener) {
|
||||
+ if (!s->max_connections || s->connections < s->max_connections) {
|
||||
+ qio_net_listener_set_client_func(s->listener, nbd_accept, NULL,
|
||||
+ NULL);
|
||||
+ } else {
|
||||
+ qio_net_listener_set_client_func(s->listener, NULL, NULL, NULL);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +116,7 @@ static void nbd_server_free(NBDServerData *server)
|
||||
*/
|
||||
qio_net_listener_disconnect(server->listener);
|
||||
object_unref(OBJECT(server->listener));
|
||||
+ server->listener = NULL;
|
||||
QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) {
|
||||
qio_channel_shutdown(QIO_CHANNEL(conn->cioc), QIO_CHANNEL_SHUTDOWN_BOTH,
|
||||
NULL);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
111
qemu.spec
111
qemu.spec
@ -3,7 +3,7 @@
|
||||
|
||||
Name: qemu
|
||||
Version: 8.2.0
|
||||
Release: 17
|
||||
Release: 18
|
||||
Epoch: 11
|
||||
Summary: QEMU is a generic and open source machine emulator and virtualizer
|
||||
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0
|
||||
@ -302,6 +302,60 @@ Patch0285: target-i386-add-support-for-LAM-in-CPUID-enumeration.patch
|
||||
Patch0286: target-i386-add-control-bits-support-for-LAM.patch
|
||||
Patch0287: cvm-bug-fix-for-incorrect-device-name-check-for-vhos.patch
|
||||
Patch0288: cvm-bug-fix-for-undefined-reference-to-virtcca_cvm_a.patch
|
||||
Patch0289: hw-misc-support-vpsp.patch
|
||||
Patch0290: hw-core-ptimer-fix-timer-zero-period-condition-for-f.patch
|
||||
Patch0291: vvfat-Fix-bug-in-writing-to-middle-of-file.patch
|
||||
Patch0292: virtio-net-Use-virtual-time-for-RSC-timers.patch
|
||||
Patch0293: crypto-Introduce-SM3-hash-hmac-pbkdf-algorithm.patch
|
||||
Patch0294: cvm-Implement-command-blacklist-for-cvm-security-enh.patch
|
||||
Patch0295: hw-display-vhost-user-gpu.c-fix-vhost_user_gpu_chr_r.patch
|
||||
Patch0296: hw-nvme-fix-leak-of-uninitialized-memory-in-io_mgmt_.patch
|
||||
Patch0297: crypto-tlscredspsk-Free-username-on-finalize.patch
|
||||
Patch0298: doc-update-AMD-SEV-to-include-Live-migration-flow.patch
|
||||
Patch0299: migration.json-add-AMD-SEV-specific-migration-parame.patch
|
||||
Patch0300: confidential-guest-support-introduce-ConfidentialGue.patch
|
||||
Patch0301: target-i386-sev-provide-callback-to-setup-outgoing-c.patch
|
||||
Patch0302: target-i386-sev-do-not-create-launch-context-for-an-.patch
|
||||
Patch0303: target-i386-sev-add-support-to-encrypt-the-outgoing-.patch
|
||||
Patch0304: target-i386-sev-add-support-to-load-incoming-encrypt.patch
|
||||
Patch0305: kvm-Add-support-for-SEV-shared-regions-list-and-KVM_.patch
|
||||
Patch0306: migration-add-support-to-migrate-shared-regions-list.patch
|
||||
Patch0307: migration-ram-add-support-to-send-encrypted-pages.patch
|
||||
Patch0308: migration-ram-Force-encrypted-status-for-flash0-flas.patch
|
||||
Patch0309: kvm-Add-support-for-userspace-MSR-filtering-and-hand.patch
|
||||
Patch0310: target-i386-sev-Return-0-if-sev_send_get_packet_len-.patch
|
||||
Patch0311: migration-ram-Force-encrypted-status-for-VGA-vram.patch
|
||||
Patch0312: target-i386-sev-Clear-shared_regions_list-when-reboo.patch
|
||||
Patch0313: migration-ram-Fix-calculation-of-gfn-correpond-to-a-.patch
|
||||
Patch0314: target-i386-Introduce-header-file-csv.h.patch
|
||||
Patch0315: target-i386-csv-Read-cert-chain-from-file-when-prepa.patch
|
||||
Patch0316: target-i386-csv-add-support-to-queue-the-outgoing-pa.patch
|
||||
Patch0317: target-i386-csv-add-support-to-encrypt-the-outgoing-.patch
|
||||
Patch0318: target-i386-csv-add-support-to-queue-the-incoming-pa.patch
|
||||
Patch0319: target-i386-csv-add-support-to-load-incoming-encrypt.patch
|
||||
Patch0320: migration-ram-Accelerate-the-transmission-of-CSV-gue.patch
|
||||
Patch0321: migration-ram-Accelerate-the-loading-of-CSV-guest-s-.patch
|
||||
Patch0322: target-i386-csv-Add-support-for-migrate-VMSA-for-CSV.patch
|
||||
Patch0323: target-i386-get-set-migrate-GHCB-state.patch
|
||||
Patch0324: target-i386-kvm-Fix-the-resettable-info-when-emulate.patch
|
||||
Patch0325: kvm-Add-support-for-CSV2-reboot.patch
|
||||
Patch0326: update-docs-tools-virtfs-proxy-helper.rst.patch
|
||||
Patch0327: update-io-trace-events.patch
|
||||
Patch0328: nbd-server-CVE-2024-7409-Avoid-use-after-free-when-c.patch
|
||||
Patch0329: virtio-net-Ensure-queue-index-fits-with-RSS-CVE-2024.patch
|
||||
Patch0330: target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch
|
||||
Patch0331: hw-misc-bcm2835_property-Fix-handling-of-FRAMEBUFFER.patch
|
||||
Patch0332: target-arm-Disable-SVE-extensions-when-SVE-is-disabl.patch
|
||||
Patch0333: virtio-pci-fix-use-of-a-released-vector.patch
|
||||
Patch0334: target-loongarch-fix-a-wrong-print-in-cpu-dump.patch
|
||||
Patch0335: backends-cryptodev-builtin-Fix-local_error-leaks.patch
|
||||
Patch0336: char-stdio-Restore-blocking-mode-of-stdout-on-exit.patch
|
||||
Patch0337: target-i386-no-single-step-exception-after-MOV-or-PO.patch
|
||||
Patch0338: migration-colo-Fix-bdrv_graph_rdlock_main_loop-Asser.patch
|
||||
Patch0339: load_elf-fix-iterator-s-type-for-elf-file-processing.patch
|
||||
Patch0340: hw-loongarch-Fix-fdt-memory-node-wrong-reg.patch
|
||||
Patch0341: hw-loongarch-virt-Fix-FDT-memory-node-address-width.patch
|
||||
|
||||
|
||||
BuildRequires: flex
|
||||
BuildRequires: gcc
|
||||
@ -899,6 +953,61 @@ getent passwd qemu >/dev/null || \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Sep 18 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-18
|
||||
- hw/loongarch/virt: Fix FDT memory node address width
|
||||
- hw/loongarch: Fix fdt memory node wrong 'reg'
|
||||
- load_elf: fix iterator's type for elf file processing
|
||||
- migration/colo: Fix bdrv_graph_rdlock_main_loop: Assertion `!qemu_in_…
|
||||
- target/i386: no single-step exception after MOV or POP SS
|
||||
- char-stdio: Restore blocking mode of stdout on exit
|
||||
- backends/cryptodev-builtin: Fix local_error leaks
|
||||
- target/loongarch: fix a wrong print in cpu dump
|
||||
- virtio-pci: fix use of a released vector
|
||||
- target/arm: Disable SVE extensions when SVE is disabled
|
||||
- hw/misc/bcm2835_property: Fix handling of FRAMEBUFFER_SET_PALETTE
|
||||
- target/i386: Introduce SapphireRapids-v3 to add missing features
|
||||
- virtio-net: Ensure queue index fits with RSS (CVE-2024-6505)
|
||||
- nbd/server: CVE-2024-7409: Avoid use-after-free when closing server
|
||||
- update io/trace-events. Parameters should remain consistent.
|
||||
- update docs/tools/virtfs-proxy-helper.rst. This place is spelled wrong.
|
||||
- kvm: Add support for CSV2 reboot
|
||||
- target/i386/kvm: Fix the resettable info when emulate Hygon CSV2 guest
|
||||
- target/i386: get/set/migrate GHCB state
|
||||
- target/i386: csv: Add support for migrate VMSA for CSV2 guest
|
||||
- migration/ram: Accelerate the loading of CSV guest's encrypted pages
|
||||
- migration/ram: Accelerate the transmission of CSV guest's encrypted pages
|
||||
- target/i386: csv: add support to load incoming encrypted pages queued in the CMD list
|
||||
- target/i386: csv: add support to queue the incoming page into a list
|
||||
- target/i386: csv: add support to encrypt the outgoing pages in the list queued before.
|
||||
- target/i386: csv: add support to queue the outgoing page into a list
|
||||
- target/i386: csv: Read cert chain from file when prepared for CSV live migration
|
||||
- target/i386: Introduce header file csv.h
|
||||
- migration/ram: Fix calculation of gfn correpond to a page in ramblock
|
||||
- target/i386: sev: Clear shared_regions_list when reboot CSV Guest
|
||||
- migration/ram: Force encrypted status for VGA vram
|
||||
- target/i386: sev: Return 0 if sev_send_get_packet_len() fails
|
||||
- kvm: Add support for userspace MSR filtering and handling of MSR_KVM_MIGRATION_CONTROL.
|
||||
- migration/ram: Force encrypted status for flash0 & flash1 devices.
|
||||
- migration/ram: add support to send encrypted pages
|
||||
- migration: add support to migrate shared regions list
|
||||
- kvm: Add support for SEV shared regions list and KVM_EXIT_HYPERCALL.
|
||||
- target/i386: sev: add support to load incoming encrypted page
|
||||
- target/i386: sev: add support to encrypt the outgoing page
|
||||
- target/i386: sev: do not create launch context for an incoming guest
|
||||
- target/i386: sev: provide callback to setup outgoing context
|
||||
- confidential guest support: introduce ConfidentialGuestMemoryEncryptionOps for encrypted VMs
|
||||
- migration.json: add AMD SEV specific migration parameters
|
||||
- doc: update AMD SEV to include Live migration flow
|
||||
- crypto/tlscredspsk: Free username on finalize
|
||||
- hw/nvme: fix leak of uninitialized memory in io_mgmt_recv
|
||||
- hw/display/vhost-user-gpu.c: fix vhost_user_gpu_chr_read()
|
||||
- cvm : Implement command blacklist for cvm security enhancement
|
||||
- crypto: Introduce SM3 hash hmac pbkdf algorithm
|
||||
- virtio-net: Use virtual time for RSC timers
|
||||
- vvfat: Fix bug in writing to middle of file
|
||||
- hw/core/ptimer: fix timer zero period condition for freq > 1GHz
|
||||
- hw/misc: support vpsp
|
||||
|
||||
* Thu Sep 5 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-17
|
||||
- cvm : bug fix for undefined reference to 'virtcca_cvm_allowed' while compiling
|
||||
- cvm : bug-fix for incorrect device name check for vhost-user-fs
|
||||
|
||||
39
target-arm-Disable-SVE-extensions-when-SVE-is-disabl.patch
Normal file
39
target-arm-Disable-SVE-extensions-when-SVE-is-disabl.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From a113ddc33b432c8b4d21160dccb54ba19580ab01 Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 11:22:56 +0800
|
||||
Subject: [PATCH] target/arm: Disable SVE extensions when SVE is disabled
|
||||
|
||||
cherry picked from commit daf9748ac002ec35258e5986b6257961fd04b565
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2304
|
||||
Reported-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
|
||||
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
|
||||
Message-id: 20240526204551.553282-1-richard.henderson@linaro.org
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
target/arm/cpu64.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
|
||||
index 5d28838175..6eca55ac29 100644
|
||||
--- a/target/arm/cpu64.c
|
||||
+++ b/target/arm/cpu64.c
|
||||
@@ -110,6 +110,11 @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
|
||||
*/
|
||||
if (!cpu_isar_feature(aa64_sve, cpu)) {
|
||||
/* SVE is disabled and so are all vector lengths. Good. */
|
||||
+ /*
|
||||
+ * SVE is disabled and so are all vector lengths. Good.
|
||||
+ * Disable all SVE extensions as well.
|
||||
+ */
|
||||
+ cpu->isar.id_aa64zfr0 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
48
target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch
Normal file
48
target-i386-Introduce-SapphireRapids-v3-to-add-missi.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From 3323c09d283e02c10bbf6e8dfc43ea9f41e746db Mon Sep 17 00:00:00 2001
|
||||
From: Lei Wang <lei4.wang@intel.com>
|
||||
Date: Wed, 24 Apr 2024 03:29:12 -0400
|
||||
Subject: [PATCH] target/i386: Introduce SapphireRapids-v3 to add missing
|
||||
features
|
||||
|
||||
commit b10b2481738304db13d28252e86c10555121a5b3 upstream.
|
||||
|
||||
Add the missing features(ss, tsc-adjust, cldemote, movdiri, movdir64b) in
|
||||
the SapphireRapids-v3 CPU model.
|
||||
|
||||
Intel-SIG: commit b10b24817383 target/i386: Introduce SapphireRapids-v3 to add missing features.
|
||||
8.2-SPR new model support
|
||||
|
||||
Signed-off-by: Lei Wang <lei4.wang@intel.com>
|
||||
Message-ID: <20240424072912.43188-1-lei4.wang@intel.com>
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
[ Quanxian Wang: amend commit log ]
|
||||
Signed-off-by: Quanxian Wang <quanxian.wang@intel.com>
|
||||
---
|
||||
target/i386/cpu.c | 11 +++++++++++
|
||||
1 file changed, 11 insertions(+)
|
||||
|
||||
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
|
||||
index 19ebd49e8c..ca7e5337b0 100644
|
||||
--- a/target/i386/cpu.c
|
||||
+++ b/target/i386/cpu.c
|
||||
@@ -4020,6 +4020,17 @@ static const X86CPUDefinition builtin_x86_defs[] = {
|
||||
{ /* end of list */ }
|
||||
}
|
||||
},
|
||||
+ {
|
||||
+ .version = 3,
|
||||
+ .props = (PropValue[]) {
|
||||
+ { "ss", "on" },
|
||||
+ { "tsc-adjust", "on" },
|
||||
+ { "cldemote", "on" },
|
||||
+ { "movdiri", "on" },
|
||||
+ { "movdir64b", "on" },
|
||||
+ { /* end of list */ }
|
||||
+ }
|
||||
+ },
|
||||
{ /* end of list */ }
|
||||
}
|
||||
},
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
107
target-i386-Introduce-header-file-csv.h.patch
Normal file
107
target-i386-Introduce-header-file-csv.h.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From 2bdf07593dbec66205f2f20fa5430595678ded89 Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Thu, 14 Mar 2024 19:21:11 +0800
|
||||
Subject: [PATCH] target/i386: Introduce header file csv.h
|
||||
|
||||
This header file is used to provide common helper functions
|
||||
and data structures for Hygon CSV.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
configs/devices/i386-softmmu/default.mak | 1 +
|
||||
hw/i386/Kconfig | 5 +++
|
||||
target/i386/csv.h | 47 ++++++++++++++++++++++++
|
||||
3 files changed, 53 insertions(+)
|
||||
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 55850791df..08f3ae43f8 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 TEST_DEVICES
|
||||
imply TPM_CRB
|
||||
imply TPM_TIS_ISA
|
||||
diff --git a/target/i386/csv.h b/target/i386/csv.h
|
||||
new file mode 100644
|
||||
index 0000000000..f935babe97
|
||||
--- /dev/null
|
||||
+++ b/target/i386/csv.h
|
||||
@@ -0,0 +1,47 @@
|
||||
+/*
|
||||
+ * QEMU CSV support
|
||||
+ *
|
||||
+ * Copyright: Hygon Info Technologies Ltd. 2022
|
||||
+ *
|
||||
+ * Author:
|
||||
+ * Jiang Xin <jiangxin@hygon.cn>
|
||||
+ *
|
||||
+ * 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 I386_CSV_H
|
||||
+#define I386_CSV_H
|
||||
+
|
||||
+#ifdef CONFIG_CSV
|
||||
+
|
||||
+#include "cpu.h"
|
||||
+
|
||||
+#define CPUID_VENDOR_HYGON_EBX 0x6f677948 /* "Hygo" */
|
||||
+#define CPUID_VENDOR_HYGON_ECX 0x656e6975 /* "uine" */
|
||||
+#define CPUID_VENDOR_HYGON_EDX 0x6e65476e /* "nGen" */
|
||||
+
|
||||
+static bool __attribute__((unused)) 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;
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+
|
||||
+#define is_hygon_cpu() (false)
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
433
target-i386-csv-Add-support-for-migrate-VMSA-for-CSV.patch
Normal file
433
target-i386-csv-Add-support-for-migrate-VMSA-for-CSV.patch
Normal file
@ -0,0 +1,433 @@
|
||||
From 940858a3ab39575a0c1d91d4aa5bb65607259a8f Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Tue, 7 Jun 2022 15:19:32 +0800
|
||||
Subject: [PATCH] target/i386: csv: Add support for migrate VMSA for CSV2 guest
|
||||
|
||||
CSV2 can protect guest's cpu state through memory encryption. Each
|
||||
vcpu has its corresponding memory, which is also called VMSA, and
|
||||
is encrypted by guest's specific encrytion key.
|
||||
|
||||
When CSV2 guest exit to host, the vcpu's state will be encrypted
|
||||
and saved to VMSA, and the VMSA will be decrypted and loaded to cpu
|
||||
when the guest's vcpu running at next time.
|
||||
|
||||
If user wants to migrate one CSV2 guest to target machine, the VMSA
|
||||
of the vcpus also should be migrated to target. CSV firmware provides
|
||||
SEND_UPDATE_VMSA/RECEIVE_UPDATE_VMSA API through which VMSA can be
|
||||
converted into secure data and transmitted to the remote end (for
|
||||
example, network transmission).
|
||||
|
||||
The migration of cpu state is identified by CPUState.cpu_index which
|
||||
may not equals to vcpu id from KVM's perspective.
|
||||
|
||||
When migrate the VMSA, the source QEMU will invoke SEND_UPDATE_VMSA to
|
||||
generate data correspond to VMSA, after target QEMU received the data,
|
||||
it will calc target vcpu id in the KVM by CPUState.cpu_index, and then
|
||||
invoke RECEIVE_UPDATE_VMSA to restore VMSA correspond to vcpu.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
include/exec/confidential-guest-support.h | 6 +
|
||||
linux-headers/linux/kvm.h | 16 ++
|
||||
migration/ram.c | 42 +++++
|
||||
target/i386/csv.h | 2 +
|
||||
target/i386/sev.c | 201 ++++++++++++++++++++++
|
||||
target/i386/sev.h | 1 +
|
||||
target/i386/trace-events | 2 +
|
||||
7 files changed, 270 insertions(+)
|
||||
|
||||
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||
index cb14b815cb..2cba27642f 100644
|
||||
--- a/include/exec/confidential-guest-support.h
|
||||
+++ b/include/exec/confidential-guest-support.h
|
||||
@@ -90,6 +90,12 @@ struct ConfidentialGuestMemoryEncryptionOps {
|
||||
|
||||
/* Load the incoming encrypted pages queued in list into guest memory */
|
||||
int (*load_queued_incoming_pages)(QEMUFile *f);
|
||||
+
|
||||
+ /* Write the encrypted cpu state */
|
||||
+ int (*save_outgoing_cpu_state)(QEMUFile *f, uint64_t *bytes_sent);
|
||||
+
|
||||
+ /* Load the encrypted cpu state */
|
||||
+ int (*load_incoming_cpu_state)(QEMUFile *f);
|
||||
};
|
||||
|
||||
typedef struct ConfidentialGuestSupportClass {
|
||||
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||||
index fcd09126a1..e9cd0ebaf1 100644
|
||||
--- a/linux-headers/linux/kvm.h
|
||||
+++ b/linux-headers/linux/kvm.h
|
||||
@@ -2052,6 +2052,14 @@ struct kvm_sev_send_update_data {
|
||||
__u32 trans_len;
|
||||
};
|
||||
|
||||
+struct kvm_sev_send_update_vmsa {
|
||||
+ __u32 vcpu_id;
|
||||
+ __u64 hdr_uaddr;
|
||||
+ __u32 hdr_len;
|
||||
+ __u64 trans_uaddr;
|
||||
+ __u32 trans_len;
|
||||
+};
|
||||
+
|
||||
struct kvm_sev_receive_start {
|
||||
__u32 handle;
|
||||
__u32 policy;
|
||||
@@ -2070,6 +2078,14 @@ struct kvm_sev_receive_update_data {
|
||||
__u32 trans_len;
|
||||
};
|
||||
|
||||
+struct kvm_sev_receive_update_vmsa {
|
||||
+ __u32 vcpu_id;
|
||||
+ __u64 hdr_uaddr;
|
||||
+ __u32 hdr_len;
|
||||
+ __u64 trans_uaddr;
|
||||
+ __u32 trans_len;
|
||||
+};
|
||||
+
|
||||
struct kvm_csv_batch_list_node {
|
||||
__u64 cmd_data_addr;
|
||||
__u64 addr;
|
||||
diff --git a/migration/ram.c b/migration/ram.c
|
||||
index 790c0413c1..1377b9eb37 100644
|
||||
--- a/migration/ram.c
|
||||
+++ b/migration/ram.c
|
||||
@@ -1281,6 +1281,33 @@ static int ram_save_shared_region_list(RAMState *rs, QEMUFile *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * ram_save_encrypted_cpu_state: send the encrypted cpu state
|
||||
+ */
|
||||
+static int ram_save_encrypted_cpu_state(RAMState *rs, QEMUFile *f)
|
||||
+{
|
||||
+ int ret;
|
||||
+ uint64_t bytes_xmit = 0;
|
||||
+ PageSearchStatus *pss = &rs->pss[RAM_CHANNEL_PRECOPY];
|
||||
+ MachineState *ms = MACHINE(qdev_get_machine());
|
||||
+ ConfidentialGuestSupportClass *cgs_class =
|
||||
+ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(ms->cgs));
|
||||
+ struct ConfidentialGuestMemoryEncryptionOps *ops =
|
||||
+ cgs_class->memory_encryption_ops;
|
||||
+
|
||||
+ ram_transferred_add(save_page_header(pss, f,
|
||||
+ pss->last_sent_block,
|
||||
+ RAM_SAVE_FLAG_ENCRYPTED_DATA));
|
||||
+ qemu_put_be32(f, RAM_SAVE_ENCRYPTED_CPU_STATE);
|
||||
+ ret = ops->save_outgoing_cpu_state(f, &bytes_xmit);
|
||||
+ if (ret < 0) {
|
||||
+ return ret;
|
||||
+ }
|
||||
+ ram_transferred_add(4 + bytes_xmit);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int load_encrypted_data(QEMUFile *f, uint8_t *ptr)
|
||||
{
|
||||
MachineState *ms = MACHINE(qdev_get_machine());
|
||||
@@ -1305,6 +1332,8 @@ static int load_encrypted_data(QEMUFile *f, uint8_t *ptr)
|
||||
return -EINVAL;
|
||||
}
|
||||
return ops->load_queued_incoming_pages(f);
|
||||
+ } else if (flag == RAM_SAVE_ENCRYPTED_CPU_STATE) {
|
||||
+ return ops->load_incoming_cpu_state(f);
|
||||
} else {
|
||||
error_report("unknown encrypted flag %x", flag);
|
||||
return 1;
|
||||
@@ -3494,6 +3523,19 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
|
||||
qemu_file_set_error(f, ret);
|
||||
return ret;
|
||||
}
|
||||
+
|
||||
+ /*
|
||||
+ * send the encrypted cpu state, for example, CSV2 guest's
|
||||
+ * vmsa for each vcpu.
|
||||
+ */
|
||||
+ if (is_hygon_cpu()) {
|
||||
+ ret = ram_save_encrypted_cpu_state(rs, f);
|
||||
+ if (ret < 0) {
|
||||
+ error_report("Failed to save encrypted cpu state");
|
||||
+ qemu_file_set_error(f, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/target/i386/csv.h b/target/i386/csv.h
|
||||
index 74a54f9b9c..47741a0a4f 100644
|
||||
--- a/target/i386/csv.h
|
||||
+++ b/target/i386/csv.h
|
||||
@@ -59,5 +59,7 @@ 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);
|
||||
int csv_queue_incoming_page(QEMUFile *f, uint8_t *ptr);
|
||||
int csv_load_queued_incoming_pages(QEMUFile *f);
|
||||
+int csv_save_outgoing_cpu_state(QEMUFile *f, uint64_t *bytes_sent);
|
||||
+int csv_load_incoming_cpu_state(QEMUFile *f);
|
||||
|
||||
#endif
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 2dee46d852..6ba71c91d7 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -90,6 +90,10 @@ struct SevGuestState {
|
||||
gchar *send_packet_hdr;
|
||||
size_t send_packet_hdr_len;
|
||||
|
||||
+ /* needed by live migration of HYGON CSV2 guest */
|
||||
+ gchar *send_vmsa_packet_hdr;
|
||||
+ size_t send_vmsa_packet_hdr_len;
|
||||
+
|
||||
uint32_t reset_cs;
|
||||
uint32_t reset_ip;
|
||||
bool reset_data_valid;
|
||||
@@ -183,6 +187,9 @@ static const char *const sev_fw_errlist[] = {
|
||||
#define SHARED_REGION_LIST_CONT 0x1
|
||||
#define SHARED_REGION_LIST_END 0x2
|
||||
|
||||
+#define ENCRYPTED_CPU_STATE_CONT 0x1
|
||||
+#define ENCRYPTED_CPU_STATE_END 0x2
|
||||
+
|
||||
static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.save_setup = sev_save_setup,
|
||||
.save_outgoing_page = sev_save_outgoing_page,
|
||||
@@ -194,6 +201,8 @@ static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.save_queued_outgoing_pages = csv_save_queued_outgoing_pages,
|
||||
.queue_incoming_page = csv_queue_incoming_page,
|
||||
.load_queued_incoming_pages = csv_load_queued_incoming_pages,
|
||||
+ .save_outgoing_cpu_state = csv_save_outgoing_cpu_state,
|
||||
+ .load_incoming_cpu_state = csv_load_incoming_cpu_state,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -1047,6 +1056,9 @@ sev_send_finish(void)
|
||||
}
|
||||
|
||||
g_free(sev_guest->send_packet_hdr);
|
||||
+ if (sev_es_enabled() && is_hygon_cpu()) {
|
||||
+ g_free(sev_guest->send_vmsa_packet_hdr);
|
||||
+ }
|
||||
sev_set_guest_state(sev_guest, SEV_STATE_RUNNING);
|
||||
}
|
||||
|
||||
@@ -2238,6 +2250,195 @@ int csv_load_queued_incoming_pages(QEMUFile *f)
|
||||
return csv_receive_update_data_batch(s);
|
||||
}
|
||||
|
||||
+static int
|
||||
+sev_send_vmsa_get_packet_len(int *fw_err)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct kvm_sev_send_update_vmsa update = { 0, };
|
||||
+
|
||||
+ ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_SEND_UPDATE_VMSA,
|
||||
+ &update, fw_err);
|
||||
+ if (*fw_err != SEV_RET_INVALID_LEN) {
|
||||
+ ret = 0;
|
||||
+ error_report("%s: failed to get session length ret=%d fw_error=%d '%s'",
|
||||
+ __func__, ret, *fw_err, fw_error_to_str(*fw_err));
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = update.hdr_len;
|
||||
+
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sev_send_update_vmsa(SevGuestState *s, QEMUFile *f, uint32_t cpu_id,
|
||||
+ uint32_t cpu_index, uint32_t size, uint64_t *bytes_sent)
|
||||
+{
|
||||
+ int ret, fw_error;
|
||||
+ guchar *trans = NULL;
|
||||
+ struct kvm_sev_send_update_vmsa update = {};
|
||||
+
|
||||
+ /*
|
||||
+ * If this is first call then query the packet header bytes and allocate
|
||||
+ * the packet buffer.
|
||||
+ */
|
||||
+ if (!s->send_vmsa_packet_hdr) {
|
||||
+ s->send_vmsa_packet_hdr_len = sev_send_vmsa_get_packet_len(&fw_error);
|
||||
+ if (s->send_vmsa_packet_hdr_len < 1) {
|
||||
+ error_report("%s: SEND_UPDATE_VMSA fw_error=%d '%s'",
|
||||
+ __func__, fw_error, fw_error_to_str(fw_error));
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ s->send_vmsa_packet_hdr = g_new(gchar, s->send_vmsa_packet_hdr_len);
|
||||
+ }
|
||||
+
|
||||
+ /* allocate transport buffer */
|
||||
+ trans = g_new(guchar, size);
|
||||
+
|
||||
+ update.vcpu_id = cpu_id;
|
||||
+ update.hdr_uaddr = (uintptr_t)s->send_vmsa_packet_hdr;
|
||||
+ update.hdr_len = s->send_vmsa_packet_hdr_len;
|
||||
+ update.trans_uaddr = (uintptr_t)trans;
|
||||
+ update.trans_len = size;
|
||||
+
|
||||
+ trace_kvm_sev_send_update_vmsa(cpu_id, cpu_index, trans, size);
|
||||
+
|
||||
+ ret = sev_ioctl(s->sev_fd, KVM_SEV_SEND_UPDATE_VMSA, &update, &fw_error);
|
||||
+ if (ret) {
|
||||
+ error_report("%s: SEND_UPDATE_VMSA ret=%d fw_error=%d '%s'",
|
||||
+ __func__, ret, fw_error, fw_error_to_str(fw_error));
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Migration of vCPU's VMState according to the instance_id
|
||||
+ * (i.e. CPUState.cpu_index)
|
||||
+ */
|
||||
+ qemu_put_be32(f, sizeof(uint32_t));
|
||||
+ qemu_put_buffer(f, (uint8_t *)&cpu_index, sizeof(uint32_t));
|
||||
+ *bytes_sent += 4 + sizeof(uint32_t);
|
||||
+
|
||||
+ 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:
|
||||
+ g_free(trans);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int csv_save_outgoing_cpu_state(QEMUFile *f, uint64_t *bytes_sent)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+ CPUState *cpu;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /* Only support migrate VMSAs for HYGON CSV2 guest */
|
||||
+ if (!sev_es_enabled() || !is_hygon_cpu()) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ CPU_FOREACH(cpu) {
|
||||
+ qemu_put_be32(f, ENCRYPTED_CPU_STATE_CONT);
|
||||
+ *bytes_sent += 4;
|
||||
+ ret = sev_send_update_vmsa(s, f, kvm_arch_vcpu_id(cpu),
|
||||
+ cpu->cpu_index, TARGET_PAGE_SIZE, bytes_sent);
|
||||
+ if (ret) {
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ qemu_put_be32(f, ENCRYPTED_CPU_STATE_END);
|
||||
+ *bytes_sent += 4;
|
||||
+
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int sev_receive_update_vmsa(QEMUFile *f)
|
||||
+{
|
||||
+ int ret = 1, fw_error = 0;
|
||||
+ CPUState *cpu;
|
||||
+ uint32_t cpu_index, cpu_id = 0;
|
||||
+ gchar *hdr = NULL, *trans = NULL;
|
||||
+ struct kvm_sev_receive_update_vmsa update = {};
|
||||
+
|
||||
+ /* get cpu index buffer */
|
||||
+ assert(qemu_get_be32(f) == sizeof(uint32_t));
|
||||
+ qemu_get_buffer(f, (uint8_t *)&cpu_index, sizeof(uint32_t));
|
||||
+
|
||||
+ CPU_FOREACH(cpu) {
|
||||
+ if (cpu->cpu_index == cpu_index) {
|
||||
+ cpu_id = kvm_arch_vcpu_id(cpu);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ update.vcpu_id = cpu_id;
|
||||
+
|
||||
+ /* get packet header */
|
||||
+ update.hdr_len = qemu_get_be32(f);
|
||||
+ if (!check_blob_length(update.hdr_len)) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ hdr = g_new(gchar, update.hdr_len);
|
||||
+ qemu_get_buffer(f, (uint8_t *)hdr, update.hdr_len);
|
||||
+ update.hdr_uaddr = (uintptr_t)hdr;
|
||||
+
|
||||
+ /* get transport buffer */
|
||||
+ update.trans_len = qemu_get_be32(f);
|
||||
+ if (!check_blob_length(update.trans_len)) {
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ trans = g_new(gchar, update.trans_len);
|
||||
+ update.trans_uaddr = (uintptr_t)trans;
|
||||
+ qemu_get_buffer(f, (uint8_t *)update.trans_uaddr, update.trans_len);
|
||||
+
|
||||
+ trace_kvm_sev_receive_update_vmsa(cpu_id, cpu_index,
|
||||
+ trans, update.trans_len, hdr, update.hdr_len);
|
||||
+
|
||||
+ ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_RECEIVE_UPDATE_VMSA,
|
||||
+ &update, &fw_error);
|
||||
+ if (ret) {
|
||||
+ error_report("Error RECEIVE_UPDATE_VMSA ret=%d fw_error=%d '%s'",
|
||||
+ ret, fw_error, fw_error_to_str(fw_error));
|
||||
+ }
|
||||
+
|
||||
+err:
|
||||
+ g_free(trans);
|
||||
+ g_free(hdr);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int csv_load_incoming_cpu_state(QEMUFile *f)
|
||||
+{
|
||||
+ int status, ret = 0;
|
||||
+
|
||||
+ /* Only support migrate VMSAs for HYGON CSV2 guest */
|
||||
+ if (!sev_es_enabled() || !is_hygon_cpu()) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ status = qemu_get_be32(f);
|
||||
+ while (status == ENCRYPTED_CPU_STATE_CONT) {
|
||||
+ ret = sev_receive_update_vmsa(f);
|
||||
+ if (ret) {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ status = qemu_get_be32(f);
|
||||
+ }
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
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 f7886116e7..209c92fd6f 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -43,6 +43,7 @@ typedef struct SevKernelLoaderContext {
|
||||
|
||||
#define RAM_SAVE_ENCRYPTED_PAGE_BATCH 0x4
|
||||
#define RAM_SAVE_ENCRYPTED_PAGE_BATCH_END 0x5
|
||||
+#define RAM_SAVE_ENCRYPTED_CPU_STATE 0x6
|
||||
|
||||
#ifdef CONFIG_SEV
|
||||
bool sev_enabled(void);
|
||||
diff --git a/target/i386/trace-events b/target/i386/trace-events
|
||||
index 475de65ad4..87b765c73c 100644
|
||||
--- a/target/i386/trace-events
|
||||
+++ b/target/i386/trace-events
|
||||
@@ -17,3 +17,5 @@ kvm_sev_send_finish(void) ""
|
||||
kvm_sev_receive_start(int policy, void *session, void *pdh) "policy 0x%x session %p pdh %p"
|
||||
kvm_sev_receive_update_data(void *src, void *dst, int len, void *hdr, int hdr_len) "guest %p trans %p len %d hdr %p hdr_len %d"
|
||||
kvm_sev_receive_finish(void) ""
|
||||
+kvm_sev_send_update_vmsa(uint32_t cpu_id, uint32_t cpu_index, void *dst, int len) "cpu_id %d cpu_index %d trans %p len %d"
|
||||
+kvm_sev_receive_update_vmsa(uint32_t cpu_id, uint32_t cpu_index, void *src, int len, void *hdr, int hdr_len) "cpu_id %d cpu_index %d trans %p len %d hdr %p hdr_len %d"
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
140
target-i386-csv-Read-cert-chain-from-file-when-prepa.patch
Normal file
140
target-i386-csv-Read-cert-chain-from-file-when-prepa.patch
Normal file
@ -0,0 +1,140 @@
|
||||
From d23c6a2bcc836587620bd35726ca4d5f71c0a844 Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Mon, 13 Nov 2023 21:55:33 +0000
|
||||
Subject: [PATCH] target/i386: csv: Read cert chain from file when prepared for
|
||||
CSV live migration
|
||||
|
||||
The cert chain is too long when encoded with base64, use the filename
|
||||
of cert chain instead of the encoded string when prepared for CSV live
|
||||
migration.
|
||||
|
||||
[ Fix conflicts. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
qapi/migration.json | 24 +++++++++++++++---------
|
||||
target/i386/sev.c | 30 ++++++++++++++++++++++++++----
|
||||
2 files changed, 41 insertions(+), 13 deletions(-)
|
||||
|
||||
diff --git a/qapi/migration.json b/qapi/migration.json
|
||||
index 038e99cba3..3aed216c3b 100644
|
||||
--- a/qapi/migration.json
|
||||
+++ b/qapi/migration.json
|
||||
@@ -891,14 +891,16 @@
|
||||
# @mode: Migration mode. See description in @MigMode. Default is 'normal'.
|
||||
# (Since 8.2)
|
||||
#
|
||||
-# @sev-pdh: The target host platform diffie-hellman key encoded in base64
|
||||
+# @sev-pdh: The target host platform diffie-hellman key encoded in base64, or
|
||||
+# pdh filename for hygon
|
||||
# (Since 4.2)
|
||||
#
|
||||
-# @sev-plat-cert: The target host platform certificate chain encoded in base64
|
||||
+# @sev-plat-cert: The target host platform certificate chain encoded in base64,
|
||||
+# or plat cert filename for hygon
|
||||
# (Since 4.2)
|
||||
#
|
||||
# @sev-amd-cert: AMD certificate chain which include ASK and OCA encoded in
|
||||
-# base64 (Since 4.2)
|
||||
+# base64, or vendor cert filename for hygon (Since 4.2)
|
||||
#
|
||||
# Features:
|
||||
#
|
||||
@@ -1093,14 +1095,16 @@
|
||||
# @mode: Migration mode. See description in @MigMode. Default is 'normal'.
|
||||
# (Since 8.2)
|
||||
#
|
||||
-# @sev-pdh: The target host platform diffie-hellman key encoded in base64
|
||||
+# @sev-pdh: The target host platform diffie-hellman key encoded in base64, or
|
||||
+# pdh filename for hygon
|
||||
# (Since 4.2)
|
||||
#
|
||||
-# @sev-plat-cert: The target host platform certificate chain encoded in base64
|
||||
+# @sev-plat-cert: The target host platform certificate chain encoded in base64,
|
||||
+# or plat cert filename for hygon
|
||||
# (Since 4.2)
|
||||
#
|
||||
# @sev-amd-cert: AMD certificate chain which include ASK and OCA encoded in
|
||||
-# base64 (Since 4.2)
|
||||
+# base64, or vendor cert filename for hygon (Since 4.2)
|
||||
#
|
||||
# Features:
|
||||
#
|
||||
@@ -1340,14 +1344,16 @@
|
||||
# @mode: Migration mode. See description in @MigMode. Default is 'normal'.
|
||||
# (Since 8.2)
|
||||
#
|
||||
-# @sev-pdh: The target host platform diffie-hellman key encoded in base64
|
||||
+# @sev-pdh: The target host platform diffie-hellman key encoded in base64, or
|
||||
+# pdh filename for hygon
|
||||
# (Since 4.2)
|
||||
#
|
||||
-# @sev-plat-cert: The target host platform certificate chain encoded in base64
|
||||
+# @sev-plat-cert: The target host platform certificate chain encoded in base64,
|
||||
+# or plat cert filename for hygon
|
||||
# (Since 4.2)
|
||||
#
|
||||
# @sev-amd-cert: AMD certificate chain which include ASK and OCA encoded in
|
||||
-# base64 (Since 4.2)
|
||||
+# base64, or vendor cert filename for hygon (Since 4.2)
|
||||
#
|
||||
# Features:
|
||||
#
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 0b0f589aee..331dfa4516 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -27,6 +27,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"
|
||||
@@ -979,18 +980,39 @@ int sev_save_setup(const char *pdh, const char *plat_cert,
|
||||
{
|
||||
SevGuestState *s = sev_guest;
|
||||
|
||||
- s->remote_pdh = g_base64_decode(pdh, &s->remote_pdh_len);
|
||||
+ if (is_hygon_cpu()) {
|
||||
+ if (sev_read_file_base64(pdh, &s->remote_pdh,
|
||||
+ &s->remote_pdh_len) < 0) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+ } else {
|
||||
+ s->remote_pdh = g_base64_decode(pdh, &s->remote_pdh_len);
|
||||
+ }
|
||||
if (!check_blob_length(s->remote_pdh_len)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
- s->remote_plat_cert = g_base64_decode(plat_cert,
|
||||
- &s->remote_plat_cert_len);
|
||||
+ if (is_hygon_cpu()) {
|
||||
+ if (sev_read_file_base64(plat_cert, &s->remote_plat_cert,
|
||||
+ &s->remote_plat_cert_len) < 0) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+ } else {
|
||||
+ s->remote_plat_cert = g_base64_decode(plat_cert,
|
||||
+ &s->remote_plat_cert_len);
|
||||
+ }
|
||||
if (!check_blob_length(s->remote_plat_cert_len)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
- s->amd_cert = g_base64_decode(amd_cert, &s->amd_cert_len);
|
||||
+ if (is_hygon_cpu()) {
|
||||
+ if (sev_read_file_base64(amd_cert, &s->amd_cert,
|
||||
+ &s->amd_cert_len) < 0) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+ } else {
|
||||
+ s->amd_cert = g_base64_decode(amd_cert, &s->amd_cert_len);
|
||||
+ }
|
||||
if (!check_blob_length(s->amd_cert_len)) {
|
||||
goto error;
|
||||
}
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
207
target-i386-csv-add-support-to-encrypt-the-outgoing-.patch
Normal file
207
target-i386-csv-add-support-to-encrypt-the-outgoing-.patch
Normal file
@ -0,0 +1,207 @@
|
||||
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
|
||||
|
||||
107
target-i386-csv-add-support-to-load-incoming-encrypt.patch
Normal file
107
target-i386-csv-add-support-to-load-incoming-encrypt.patch
Normal file
@ -0,0 +1,107 @@
|
||||
From cb5c1c9c70110639eda0ff50c8dfcf24b0be561d Mon Sep 17 00:00:00 2001
|
||||
From: fangbaoshun <fangbaoshun@hygon.cn>
|
||||
Date: Mon, 2 Aug 2021 14:11:43 +0800
|
||||
Subject: [PATCH] target/i386: csv: add support to load incoming encrypted
|
||||
pages queued in the CMD list
|
||||
|
||||
The csv_load_queued_incoming_pages() provide the implementation to read the
|
||||
incoming guest private pages from the socket queued in the CMD list and load
|
||||
them into the guest memory. The routines uses the RECEIVE_START command to
|
||||
create the incoming encryption context on the first call then uses the
|
||||
COMMAND_BATCH carried with RECEIEVE_UPDATE_DATA commands to load the encrypted
|
||||
pages into the guest memory. After migration is completed, we issue the
|
||||
RECEIVE_FINISH command to transition the SEV guest to the runnable state
|
||||
so that it can be executed.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
include/exec/confidential-guest-support.h | 3 +++
|
||||
target/i386/csv.h | 1 +
|
||||
target/i386/sev.c | 32 +++++++++++++++++++++++
|
||||
3 files changed, 36 insertions(+)
|
||||
|
||||
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||
index 101cc5220a..cb14b815cb 100644
|
||||
--- a/include/exec/confidential-guest-support.h
|
||||
+++ b/include/exec/confidential-guest-support.h
|
||||
@@ -87,6 +87,9 @@ struct ConfidentialGuestMemoryEncryptionOps {
|
||||
|
||||
/* Queue the incoming encrypted page into a list */
|
||||
int (*queue_incoming_page)(QEMUFile *f, uint8_t *ptr);
|
||||
+
|
||||
+ /* Load the incoming encrypted pages queued in list into guest memory */
|
||||
+ int (*load_queued_incoming_pages)(QEMUFile *f);
|
||||
};
|
||||
|
||||
typedef struct ConfidentialGuestSupportClass {
|
||||
diff --git a/target/i386/csv.h b/target/i386/csv.h
|
||||
index d1bcc8bc16..977f08b982 100644
|
||||
--- a/target/i386/csv.h
|
||||
+++ b/target/i386/csv.h
|
||||
@@ -56,5 +56,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);
|
||||
int csv_queue_incoming_page(QEMUFile *f, uint8_t *ptr);
|
||||
+int csv_load_queued_incoming_pages(QEMUFile *f);
|
||||
|
||||
#endif
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 606aaad328..2dee46d852 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -193,6 +193,7 @@ static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.queue_outgoing_page = csv_queue_outgoing_page,
|
||||
.save_queued_outgoing_pages = csv_save_queued_outgoing_pages,
|
||||
.queue_incoming_page = csv_queue_incoming_page,
|
||||
+ .load_queued_incoming_pages = csv_load_queued_incoming_pages,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -2146,6 +2147,24 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int
|
||||
+csv_receive_update_data_batch(SevGuestState *s)
|
||||
+{
|
||||
+ int ret;
|
||||
+ int fw_error;
|
||||
+
|
||||
+ ret = csv_command_batch(KVM_SEV_RECEIVE_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));
|
||||
+ }
|
||||
+
|
||||
+ 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)
|
||||
{
|
||||
@@ -2206,6 +2225,19 @@ csv_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent)
|
||||
return csv_send_update_data_batch(s, f, bytes_sent);
|
||||
}
|
||||
|
||||
+int csv_load_queued_incoming_pages(QEMUFile *f)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+
|
||||
+ /* Only support for HYGON CSV */
|
||||
+ if (!is_hygon_cpu()) {
|
||||
+ error_report("Only support load queued pages for HYGON CSV");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return csv_receive_update_data_batch(s);
|
||||
+}
|
||||
+
|
||||
static const QemuUUID sev_hash_table_header_guid = {
|
||||
.data = UUID_LE(0x9438d606, 0x4f22, 0x4cc9, 0xb4, 0x79, 0xa7, 0x93,
|
||||
0xd4, 0x11, 0xfd, 0x21)
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
170
target-i386-csv-add-support-to-queue-the-incoming-pa.patch
Normal file
170
target-i386-csv-add-support-to-queue-the-incoming-pa.patch
Normal file
@ -0,0 +1,170 @@
|
||||
From 8125145bcd3b8348e69686e26f482cf16b16ec98 Mon Sep 17 00:00:00 2001
|
||||
From: fangbaoshun <fangbaoshun@hygon.cn>
|
||||
Date: Mon, 2 Aug 2021 13:49:48 +0800
|
||||
Subject: [PATCH] target/i386: csv: add support to queue the incoming page into
|
||||
a list
|
||||
|
||||
The csv_queue_incoming_page() provide the implementation to queue the
|
||||
guest private pages during transmission. The routines queues the incoming
|
||||
socket which contains the guest private pages into a list then uses the
|
||||
COMMAND_BATCH command to load the encrypted pages into the guest memory.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
include/exec/confidential-guest-support.h | 3 +
|
||||
target/i386/csv.h | 1 +
|
||||
target/i386/sev.c | 92 +++++++++++++++++++++++
|
||||
3 files changed, 96 insertions(+)
|
||||
|
||||
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||
index c84f8c1efc..101cc5220a 100644
|
||||
--- a/include/exec/confidential-guest-support.h
|
||||
+++ b/include/exec/confidential-guest-support.h
|
||||
@@ -84,6 +84,9 @@ struct ConfidentialGuestMemoryEncryptionOps {
|
||||
/* Write the list queued with encrypted pages and metadata associated
|
||||
* with them */
|
||||
int (*save_queued_outgoing_pages)(QEMUFile *f, uint64_t *bytes_sent);
|
||||
+
|
||||
+ /* Queue the incoming encrypted page into a list */
|
||||
+ int (*queue_incoming_page)(QEMUFile *f, uint8_t *ptr);
|
||||
};
|
||||
|
||||
typedef struct ConfidentialGuestSupportClass {
|
||||
diff --git a/target/i386/csv.h b/target/i386/csv.h
|
||||
index 2a3a3119d9..d1bcc8bc16 100644
|
||||
--- a/target/i386/csv.h
|
||||
+++ b/target/i386/csv.h
|
||||
@@ -55,5 +55,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);
|
||||
+int csv_queue_incoming_page(QEMUFile *f, uint8_t *ptr);
|
||||
|
||||
#endif
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 1e2bbafe36..606aaad328 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -192,6 +192,7 @@ static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.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,
|
||||
+ .queue_incoming_page = csv_queue_incoming_page,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -1941,6 +1942,15 @@ static void send_update_data_free(void *data)
|
||||
g_free(update);
|
||||
}
|
||||
|
||||
+static void receive_update_data_free(void *data)
|
||||
+{
|
||||
+ struct kvm_sev_receive_update_data *update =
|
||||
+ (struct kvm_sev_receive_update_data *)data;
|
||||
+ g_free((guchar *)update->hdr_uaddr);
|
||||
+ g_free((guchar *)update->trans_uaddr);
|
||||
+ g_free(update);
|
||||
+}
|
||||
+
|
||||
static int
|
||||
csv_send_queue_data(SevGuestState *s, uint8_t *ptr,
|
||||
uint32_t size, uint64_t addr)
|
||||
@@ -2013,6 +2023,66 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static int
|
||||
+csv_receive_queue_data(SevGuestState *s, QEMUFile *f, uint8_t *ptr)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ gchar *hdr = NULL, *trans = NULL;
|
||||
+ struct kvm_sev_receive_update_data *update;
|
||||
+ struct kvm_csv_batch_list_node *new_node = NULL;
|
||||
+
|
||||
+ update = g_new0(struct kvm_sev_receive_update_data, 1);
|
||||
+ /* get packet header */
|
||||
+ update->hdr_len = qemu_get_be32(f);
|
||||
+ hdr = g_new(gchar, update->hdr_len);
|
||||
+ qemu_get_buffer(f, (uint8_t *)hdr, update->hdr_len);
|
||||
+ update->hdr_uaddr = (unsigned long)hdr;
|
||||
+
|
||||
+ /* get transport buffer */
|
||||
+ update->trans_len = qemu_get_be32(f);
|
||||
+ trans = g_new(gchar, update->trans_len);
|
||||
+ update->trans_uaddr = (unsigned long)trans;
|
||||
+ qemu_get_buffer(f, (uint8_t *)update->trans_uaddr, update->trans_len);
|
||||
+
|
||||
+ /* set guest address,guest len is page_size */
|
||||
+ update->guest_uaddr = (uint64_t)ptr;
|
||||
+ update->guest_len = TARGET_PAGE_SIZE;
|
||||
+
|
||||
+ new_node = csv_batch_cmd_list_node_create((uint64_t)update, 0);
|
||||
+ if (!new_node) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (s->csv_batch_cmd_list == NULL) {
|
||||
+ s->csv_batch_cmd_list = csv_batch_cmd_list_create(new_node,
|
||||
+ receive_update_data_free);
|
||||
+ if (s->csv_batch_cmd_list == NULL) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Add new_node's command address to the last_node */
|
||||
+ csv_batch_cmd_list_add_after(s->csv_batch_cmd_list, new_node);
|
||||
+ }
|
||||
+
|
||||
+ trace_kvm_sev_receive_update_data(trans, (void *)ptr, update->guest_len,
|
||||
+ (void *)hdr, update->hdr_len);
|
||||
+
|
||||
+ return ret;
|
||||
+
|
||||
+err:
|
||||
+ g_free(trans);
|
||||
+ g_free(update);
|
||||
+ g_free(hdr);
|
||||
+ g_free(new_node);
|
||||
+ if (s->csv_batch_cmd_list) {
|
||||
+ csv_batch_cmd_list_destroy(s->csv_batch_cmd_list);
|
||||
+ s->csv_batch_cmd_list = NULL;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
csv_command_batch(uint32_t cmd_id, uint64_t head_uaddr, int *fw_err)
|
||||
{
|
||||
@@ -2090,6 +2160,28 @@ csv_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr)
|
||||
return csv_send_queue_data(s, ptr, sz, addr);
|
||||
}
|
||||
|
||||
+int csv_queue_incoming_page(QEMUFile *f, uint8_t *ptr)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+
|
||||
+ /* Only support for HYGON CSV */
|
||||
+ if (!is_hygon_cpu()) {
|
||||
+ error_report("Only support enqueue received pages for HYGON CSV");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * If this is first buffer and SEV is not in recieiving state then
|
||||
+ * use RECEIVE_START command to create a encryption context.
|
||||
+ */
|
||||
+ if (!sev_check_state(s, SEV_STATE_RECEIVE_UPDATE) &&
|
||||
+ sev_receive_start(s, f)) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return csv_receive_queue_data(s, f, ptr);
|
||||
+}
|
||||
+
|
||||
int
|
||||
csv_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent)
|
||||
{
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
259
target-i386-csv-add-support-to-queue-the-outgoing-pa.patch
Normal file
259
target-i386-csv-add-support-to-queue-the-outgoing-pa.patch
Normal file
@ -0,0 +1,259 @@
|
||||
From e6d587b63c3950f5d5af9002a8ae14e0904d62c3 Mon Sep 17 00:00:00 2001
|
||||
From: fangbaoshun <fangbaoshun@hygon.cn>
|
||||
Date: Mon, 2 Aug 2021 11:00:07 +0800
|
||||
Subject: [PATCH] target/i386: csv: add support to queue the outgoing page into
|
||||
a list
|
||||
|
||||
The csv_queue_outgoing_page() provide the implementation to queue the
|
||||
guest private pages during transmission. The routines queues the outgoing
|
||||
pages into a listi, and then issues the KVM_CSV_COMMAND_BATCH command to
|
||||
encrypt the pages togather before writing them to the socket.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
include/exec/confidential-guest-support.h | 3 +
|
||||
linux-headers/linux/kvm.h | 6 +
|
||||
target/i386/csv.h | 11 ++
|
||||
target/i386/sev.c | 161 ++++++++++++++++++++++
|
||||
4 files changed, 181 insertions(+)
|
||||
|
||||
diff --git a/include/exec/confidential-guest-support.h b/include/exec/confidential-guest-support.h
|
||||
index dd4887f65f..8949568acc 100644
|
||||
--- a/include/exec/confidential-guest-support.h
|
||||
+++ b/include/exec/confidential-guest-support.h
|
||||
@@ -77,6 +77,9 @@ struct ConfidentialGuestMemoryEncryptionOps {
|
||||
|
||||
/* Load the shared regions list */
|
||||
int (*load_incoming_shared_regions_list)(QEMUFile *f);
|
||||
+
|
||||
+ /* 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);
|
||||
};
|
||||
|
||||
typedef struct ConfidentialGuestSupportClass {
|
||||
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||||
index 9489a20835..ca78fdc8b6 100644
|
||||
--- a/linux-headers/linux/kvm.h
|
||||
+++ b/linux-headers/linux/kvm.h
|
||||
@@ -2067,6 +2067,12 @@ struct kvm_sev_receive_update_data {
|
||||
__u32 trans_len;
|
||||
};
|
||||
|
||||
+struct kvm_csv_batch_list_node {
|
||||
+ __u64 cmd_data_addr;
|
||||
+ __u64 addr;
|
||||
+ __u64 next_cmd_addr;
|
||||
+};
|
||||
+
|
||||
#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 f935babe97..4c1ef20029 100644
|
||||
--- a/target/i386/csv.h
|
||||
+++ b/target/i386/csv.h
|
||||
@@ -44,4 +44,15 @@ static bool __attribute__((unused)) is_hygon_cpu(void)
|
||||
|
||||
#endif
|
||||
|
||||
+typedef struct CsvBatchCmdList CsvBatchCmdList;
|
||||
+typedef void (*CsvDestroyCmdNodeFn) (void *data);
|
||||
+
|
||||
+struct CsvBatchCmdList {
|
||||
+ struct kvm_csv_batch_list_node *head;
|
||||
+ struct kvm_csv_batch_list_node *tail;
|
||||
+ CsvDestroyCmdNodeFn destroy_fn;
|
||||
+};
|
||||
+
|
||||
+int csv_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr);
|
||||
+
|
||||
#endif
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 331dfa4516..7dd35d64ee 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -95,6 +95,9 @@ struct SevGuestState {
|
||||
bool reset_data_valid;
|
||||
|
||||
QTAILQ_HEAD(, shared_region) shared_regions_list;
|
||||
+
|
||||
+ /* link list used for HYGON CSV */
|
||||
+ CsvBatchCmdList *csv_batch_cmd_list;
|
||||
};
|
||||
|
||||
#define DEFAULT_GUEST_POLICY 0x1 /* disable debug */
|
||||
@@ -187,6 +190,7 @@ static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.is_gfn_in_unshared_region = sev_is_gfn_in_unshared_region,
|
||||
.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,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -1865,6 +1869,163 @@ bool sev_is_gfn_in_unshared_region(unsigned long gfn)
|
||||
return true;
|
||||
}
|
||||
|
||||
+static CsvBatchCmdList *
|
||||
+csv_batch_cmd_list_create(struct kvm_csv_batch_list_node *head,
|
||||
+ CsvDestroyCmdNodeFn func)
|
||||
+{
|
||||
+ CsvBatchCmdList *csv_batch_cmd_list =
|
||||
+ g_malloc0(sizeof(*csv_batch_cmd_list));
|
||||
+
|
||||
+ if (!csv_batch_cmd_list) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ csv_batch_cmd_list->head = head;
|
||||
+ csv_batch_cmd_list->tail = head;
|
||||
+ csv_batch_cmd_list->destroy_fn = func;
|
||||
+
|
||||
+ return csv_batch_cmd_list;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+csv_batch_cmd_list_add_after(CsvBatchCmdList *list,
|
||||
+ struct kvm_csv_batch_list_node *new_node)
|
||||
+{
|
||||
+ list->tail->next_cmd_addr = (__u64)new_node;
|
||||
+ list->tail = new_node;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct kvm_csv_batch_list_node *
|
||||
+csv_batch_cmd_list_node_create(uint64_t cmd_data_addr, uint64_t addr)
|
||||
+{
|
||||
+ struct kvm_csv_batch_list_node *new_node =
|
||||
+ g_malloc0(sizeof(struct kvm_csv_batch_list_node));
|
||||
+
|
||||
+ if (!new_node) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ new_node->cmd_data_addr = cmd_data_addr;
|
||||
+ new_node->addr = addr;
|
||||
+ new_node->next_cmd_addr = 0;
|
||||
+
|
||||
+ return new_node;
|
||||
+}
|
||||
+
|
||||
+static int csv_batch_cmd_list_destroy(CsvBatchCmdList *list)
|
||||
+{
|
||||
+ struct kvm_csv_batch_list_node *node = list->head;
|
||||
+
|
||||
+ while (node != NULL) {
|
||||
+ if (list->destroy_fn != NULL)
|
||||
+ list->destroy_fn((void *)node->cmd_data_addr);
|
||||
+
|
||||
+ list->head = (struct kvm_csv_batch_list_node *)node->next_cmd_addr;
|
||||
+ g_free(node);
|
||||
+ node = list->head;
|
||||
+ }
|
||||
+
|
||||
+ g_free(list);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void send_update_data_free(void *data)
|
||||
+{
|
||||
+ struct kvm_sev_send_update_data *update =
|
||||
+ (struct kvm_sev_send_update_data *)data;
|
||||
+ g_free((guchar *)update->hdr_uaddr);
|
||||
+ g_free((guchar *)update->trans_uaddr);
|
||||
+ g_free(update);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+csv_send_queue_data(SevGuestState *s, uint8_t *ptr,
|
||||
+ uint32_t size, uint64_t addr)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ int fw_error;
|
||||
+ guchar *trans;
|
||||
+ guchar *packet_hdr;
|
||||
+ struct kvm_sev_send_update_data *update;
|
||||
+ struct kvm_csv_batch_list_node *new_node = NULL;
|
||||
+
|
||||
+ /* If this is first call then query the packet header bytes and allocate
|
||||
+ * the packet buffer.
|
||||
+ */
|
||||
+ if (s->send_packet_hdr_len < 1) {
|
||||
+ s->send_packet_hdr_len = sev_send_get_packet_len(&fw_error);
|
||||
+ if (s->send_packet_hdr_len < 1) {
|
||||
+ error_report("%s: SEND_UPDATE fw_error=%d '%s'",
|
||||
+ __func__, fw_error, fw_error_to_str(fw_error));
|
||||
+ return 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ packet_hdr = g_new(guchar, s->send_packet_hdr_len);
|
||||
+ memset(packet_hdr, 0, s->send_packet_hdr_len);
|
||||
+
|
||||
+ update = g_new0(struct kvm_sev_send_update_data, 1);
|
||||
+
|
||||
+ /* allocate transport buffer */
|
||||
+ trans = g_new(guchar, size);
|
||||
+
|
||||
+ update->hdr_uaddr = (unsigned long)packet_hdr;
|
||||
+ update->hdr_len = s->send_packet_hdr_len;
|
||||
+ update->guest_uaddr = (unsigned long)ptr;
|
||||
+ update->guest_len = size;
|
||||
+ update->trans_uaddr = (unsigned long)trans;
|
||||
+ update->trans_len = size;
|
||||
+
|
||||
+ new_node = csv_batch_cmd_list_node_create((uint64_t)update, addr);
|
||||
+ if (!new_node) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (s->csv_batch_cmd_list == NULL) {
|
||||
+ s->csv_batch_cmd_list = csv_batch_cmd_list_create(new_node,
|
||||
+ send_update_data_free);
|
||||
+ if (s->csv_batch_cmd_list == NULL) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* Add new_node's command address to the last_node */
|
||||
+ csv_batch_cmd_list_add_after(s->csv_batch_cmd_list, new_node);
|
||||
+ }
|
||||
+
|
||||
+ trace_kvm_sev_send_update_data(ptr, trans, size);
|
||||
+
|
||||
+ return ret;
|
||||
+
|
||||
+err:
|
||||
+ g_free(trans);
|
||||
+ g_free(update);
|
||||
+ g_free(packet_hdr);
|
||||
+ g_free(new_node);
|
||||
+ if (s->csv_batch_cmd_list) {
|
||||
+ 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)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+
|
||||
+ /* Only support for HYGON CSV */
|
||||
+ if (!is_hygon_cpu()) {
|
||||
+ error_report("Only support enqueue pages for HYGON CSV");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ return csv_send_queue_data(s, ptr, sz, addr);
|
||||
+}
|
||||
+
|
||||
static const QemuUUID sev_hash_table_header_guid = {
|
||||
.data = UUID_LE(0x9438d606, 0x4f22, 0x4cc9, 0xb4, 0x79, 0xa7, 0x93,
|
||||
0xd4, 0x11, 0xfd, 0x21)
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
190
target-i386-get-set-migrate-GHCB-state.patch
Normal file
190
target-i386-get-set-migrate-GHCB-state.patch
Normal file
@ -0,0 +1,190 @@
|
||||
From 6a8b58a3ce6dc162cae4b74ca8f39392672e6cba Mon Sep 17 00:00:00 2001
|
||||
From: panpingsheng <panpingsheng@hygon.cn>
|
||||
Date: Sat, 12 Jun 2021 15:15:29 +0800
|
||||
Subject: [PATCH] target/i386: get/set/migrate GHCB state
|
||||
|
||||
GHCB state is necessary to CSV2 guest when migrating to target.
|
||||
|
||||
Add GHCB related definition, it also adds corresponding part
|
||||
to kvm_get/put, and vmstate.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
linux-headers/linux/kvm.h | 2 ++
|
||||
target/i386/cpu.h | 5 +++++
|
||||
target/i386/kvm/kvm.c | 11 +++++++++++
|
||||
target/i386/kvm/sev-stub.c | 2 ++
|
||||
target/i386/machine.c | 24 ++++++++++++++++++++++++
|
||||
target/i386/sev.c | 10 ++++++++++
|
||||
target/i386/sev.h | 2 ++
|
||||
7 files changed, 56 insertions(+)
|
||||
|
||||
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||||
index e9cd0ebaf1..e796105b76 100644
|
||||
--- a/linux-headers/linux/kvm.h
|
||||
+++ b/linux-headers/linux/kvm.h
|
||||
@@ -1203,6 +1203,8 @@ struct kvm_ppc_resize_hpt {
|
||||
|
||||
#define KVM_CAP_ARM_TMM 300
|
||||
|
||||
+#define KVM_CAP_SEV_ES_GHCB 500
|
||||
+
|
||||
#define KVM_CAP_ARM_VIRT_MSI_BYPASS 799
|
||||
|
||||
#define KVM_EXIT_HYPERCALL_VALID_MASK (1 << KVM_HC_MAP_GPA_RANGE)
|
||||
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
|
||||
index 6993552cd9..a9a646bba2 100644
|
||||
--- a/target/i386/cpu.h
|
||||
+++ b/target/i386/cpu.h
|
||||
@@ -520,6 +520,8 @@ typedef enum X86Seg {
|
||||
|
||||
#define MSR_VM_HSAVE_PA 0xc0010117
|
||||
|
||||
+#define MSR_AMD64_SEV_ES_GHCB 0xc0010130
|
||||
+
|
||||
#define MSR_IA32_XFD 0x000001c4
|
||||
#define MSR_IA32_XFD_ERR 0x000001c5
|
||||
|
||||
@@ -1885,6 +1887,9 @@ typedef struct CPUArchState {
|
||||
|
||||
/* Number of dies within this CPU package. */
|
||||
unsigned nr_dies;
|
||||
+
|
||||
+ /* GHCB guest physical address info */
|
||||
+ uint64_t ghcb_gpa;
|
||||
} CPUX86State;
|
||||
|
||||
struct kvm_msrs;
|
||||
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||
index 5730d0e0c0..9e65242739 100644
|
||||
--- a/target/i386/kvm/kvm.c
|
||||
+++ b/target/i386/kvm/kvm.c
|
||||
@@ -3625,6 +3625,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
}
|
||||
}
|
||||
|
||||
+ if (sev_kvm_has_msr_ghcb) {
|
||||
+ kvm_msr_entry_add(cpu, MSR_AMD64_SEV_ES_GHCB, env->ghcb_gpa);
|
||||
+ }
|
||||
+
|
||||
return kvm_buf_set_msrs(cpu);
|
||||
}
|
||||
|
||||
@@ -3999,6 +4003,10 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
+ if (sev_kvm_has_msr_ghcb) {
|
||||
+ kvm_msr_entry_add(cpu, MSR_AMD64_SEV_ES_GHCB, 0);
|
||||
+ }
|
||||
+
|
||||
ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, cpu->kvm_msr_buf);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
@@ -4319,6 +4327,9 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
case MSR_ARCH_LBR_INFO_0 ... MSR_ARCH_LBR_INFO_0 + 31:
|
||||
env->lbr_records[index - MSR_ARCH_LBR_INFO_0].info = msrs[i].data;
|
||||
break;
|
||||
+ case MSR_AMD64_SEV_ES_GHCB:
|
||||
+ env->ghcb_gpa = msrs[i].data;
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/target/i386/kvm/sev-stub.c b/target/i386/kvm/sev-stub.c
|
||||
index 99899688e4..a0aac1117f 100644
|
||||
--- a/target/i386/kvm/sev-stub.c
|
||||
+++ b/target/i386/kvm/sev-stub.c
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sev.h"
|
||||
|
||||
+bool sev_kvm_has_msr_ghcb;
|
||||
+
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
{
|
||||
/* If we get here, cgs must be some non-SEV thing */
|
||||
diff --git a/target/i386/machine.c b/target/i386/machine.c
|
||||
index a1041ef828..9a1cb8f3b8 100644
|
||||
--- a/target/i386/machine.c
|
||||
+++ b/target/i386/machine.c
|
||||
@@ -1605,6 +1605,27 @@ static const VMStateDescription vmstate_triple_fault = {
|
||||
}
|
||||
};
|
||||
|
||||
+#if defined(CONFIG_KVM) && defined(TARGET_X86_64)
|
||||
+static bool msr_ghcb_gpa_needed(void *opaque)
|
||||
+{
|
||||
+ X86CPU *cpu = opaque;
|
||||
+ CPUX86State *env = &cpu->env;
|
||||
+
|
||||
+ return env->ghcb_gpa != 0;
|
||||
+}
|
||||
+
|
||||
+static const VMStateDescription vmstate_msr_ghcb_gpa = {
|
||||
+ .name = "cpu/svm_msr_ghcb_gpa",
|
||||
+ .version_id = 1,
|
||||
+ .minimum_version_id = 1,
|
||||
+ .needed = msr_ghcb_gpa_needed,
|
||||
+ .fields = (VMStateField[]) {
|
||||
+ VMSTATE_UINT64(env.ghcb_gpa, X86CPU),
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ }
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
const VMStateDescription vmstate_x86_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 12,
|
||||
@@ -1751,6 +1772,9 @@ const VMStateDescription vmstate_x86_cpu = {
|
||||
#endif
|
||||
&vmstate_arch_lbr,
|
||||
&vmstate_triple_fault,
|
||||
+#if defined(CONFIG_KVM) && defined(TARGET_X86_64)
|
||||
+ &vmstate_msr_ghcb_gpa,
|
||||
+#endif
|
||||
NULL
|
||||
}
|
||||
};
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 6ba71c91d7..7744378112 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -152,6 +152,8 @@ QEMU_BUILD_BUG_ON(sizeof(PaddedSevHashTable) % 16 != 0);
|
||||
static SevGuestState *sev_guest;
|
||||
static Error *sev_mig_blocker;
|
||||
|
||||
+bool sev_kvm_has_msr_ghcb;
|
||||
+
|
||||
static const char *const sev_fw_errlist[] = {
|
||||
[SEV_RET_SUCCESS] = "",
|
||||
[SEV_RET_INVALID_PLATFORM_STATE] = "Platform state is invalid",
|
||||
@@ -1198,6 +1200,14 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
cgs_class->memory_encryption_ops = &sev_memory_encryption_ops;
|
||||
QTAILQ_INIT(&sev->shared_regions_list);
|
||||
|
||||
+ /* Determine whether support MSR_AMD64_SEV_ES_GHCB */
|
||||
+ if (sev_es_enabled()) {
|
||||
+ sev_kvm_has_msr_ghcb =
|
||||
+ kvm_vm_check_extension(kvm_state, KVM_CAP_SEV_ES_GHCB);
|
||||
+ } else {
|
||||
+ sev_kvm_has_msr_ghcb = false;
|
||||
+ }
|
||||
+
|
||||
cgs->ready = true;
|
||||
|
||||
return 0;
|
||||
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||
index 209c92fd6f..0bfe3879ef 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -78,4 +78,6 @@ void sev_del_migrate_blocker(void);
|
||||
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp);
|
||||
|
||||
+extern bool sev_kvm_has_msr_ghcb;
|
||||
+
|
||||
#endif
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
179
target-i386-kvm-Fix-the-resettable-info-when-emulate.patch
Normal file
179
target-i386-kvm-Fix-the-resettable-info-when-emulate.patch
Normal file
@ -0,0 +1,179 @@
|
||||
From 366c11c56875ae053043c48c8b93349c6e3125cc Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Sun, 19 Jun 2022 16:49:45 +0800
|
||||
Subject: [PATCH] target/i386/kvm: Fix the resettable info when emulate Hygon
|
||||
CSV2 guest
|
||||
|
||||
SEV-ES guest will be terminated by QEMU when receive reboot request.
|
||||
In order to support reboot for CSV2 guest, report resettable in
|
||||
kvm_arch_cpu_check_are_resettable(). But the CSV2 guest is still not
|
||||
resettable if it was migrated to target machine.
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
target/i386/csv-sysemu-stub.c | 16 ++++++++++++++++
|
||||
target/i386/csv.c | 20 ++++++++++++++++++++
|
||||
target/i386/csv.h | 2 ++
|
||||
target/i386/kvm/csv-stub.c | 17 +++++++++++++++++
|
||||
target/i386/kvm/kvm.c | 4 ++++
|
||||
target/i386/kvm/meson.build | 1 +
|
||||
target/i386/meson.build | 1 +
|
||||
target/i386/sev.c | 9 +++++++++
|
||||
8 files changed, 70 insertions(+)
|
||||
create mode 100644 target/i386/csv-sysemu-stub.c
|
||||
create mode 100644 target/i386/csv.c
|
||||
create mode 100644 target/i386/kvm/csv-stub.c
|
||||
|
||||
diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c
|
||||
new file mode 100644
|
||||
index 0000000000..5874e4cc1d
|
||||
--- /dev/null
|
||||
+++ b/target/i386/csv-sysemu-stub.c
|
||||
@@ -0,0 +1,16 @@
|
||||
+/*
|
||||
+ * QEMU CSV system stub
|
||||
+ *
|
||||
+ * Copyright: Hygon Info Technologies Ltd. 2022
|
||||
+ *
|
||||
+ * Author:
|
||||
+ * Jiang Xin <jiangxin@hygon.cn>
|
||||
+ *
|
||||
+ * 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..88fb05ac37
|
||||
--- /dev/null
|
||||
+++ b/target/i386/csv.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+/*
|
||||
+ * QEMU CSV support
|
||||
+ *
|
||||
+ * Copyright: Hygon Info Technologies Ltd. 2022
|
||||
+ *
|
||||
+ * Author:
|
||||
+ * Jiang Xin <jiangxin@hygon.cn>
|
||||
+ *
|
||||
+ * 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"
|
||||
+
|
||||
+bool csv_kvm_cpu_reset_inhibit;
|
||||
diff --git a/target/i386/csv.h b/target/i386/csv.h
|
||||
index 47741a0a4f..ac4bb5bee1 100644
|
||||
--- a/target/i386/csv.h
|
||||
+++ b/target/i386/csv.h
|
||||
@@ -46,6 +46,8 @@ static bool __attribute__((unused)) is_hygon_cpu(void)
|
||||
|
||||
#define CSV_OUTGOING_PAGE_WINDOW_SIZE (4094 * TARGET_PAGE_SIZE)
|
||||
|
||||
+extern bool csv_kvm_cpu_reset_inhibit;
|
||||
+
|
||||
typedef struct CsvBatchCmdList CsvBatchCmdList;
|
||||
typedef void (*CsvDestroyCmdNodeFn) (void *data);
|
||||
|
||||
diff --git a/target/i386/kvm/csv-stub.c b/target/i386/kvm/csv-stub.c
|
||||
new file mode 100644
|
||||
index 0000000000..4d1376f268
|
||||
--- /dev/null
|
||||
+++ b/target/i386/kvm/csv-stub.c
|
||||
@@ -0,0 +1,17 @@
|
||||
+/*
|
||||
+ * QEMU CSV stub
|
||||
+ *
|
||||
+ * Copyright Hygon Info Technologies Ltd. 2024
|
||||
+ *
|
||||
+ * Authors:
|
||||
+ * Han Liyang <hanliyang@hygon.cn>
|
||||
+ *
|
||||
+ * 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 "csv.h"
|
||||
+
|
||||
+bool csv_kvm_cpu_reset_inhibit;
|
||||
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||
index 9e65242739..2866a6d0ec 100644
|
||||
--- a/target/i386/kvm/kvm.c
|
||||
+++ b/target/i386/kvm/kvm.c
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "kvm_i386.h"
|
||||
#include "sev.h"
|
||||
+#include "csv.h"
|
||||
#include "xen-emu.h"
|
||||
#include "hyperv.h"
|
||||
#include "hyperv-proto.h"
|
||||
@@ -5710,6 +5711,9 @@ bool kvm_has_waitpkg(void)
|
||||
|
||||
bool kvm_arch_cpu_check_are_resettable(void)
|
||||
{
|
||||
+ if (is_hygon_cpu())
|
||||
+ return !csv_kvm_cpu_reset_inhibit;
|
||||
+
|
||||
return !sev_es_enabled();
|
||||
}
|
||||
|
||||
diff --git a/target/i386/kvm/meson.build b/target/i386/kvm/meson.build
|
||||
index 84d9143e60..3c3f8cf93c 100644
|
||||
--- a/target/i386/kvm/meson.build
|
||||
+++ b/target/i386/kvm/meson.build
|
||||
@@ -8,6 +8,7 @@ i386_kvm_ss.add(files(
|
||||
i386_kvm_ss.add(when: 'CONFIG_XEN_EMU', if_true: files('xen-emu.c'))
|
||||
|
||||
i386_kvm_ss.add(when: 'CONFIG_SEV', if_false: files('sev-stub.c'))
|
||||
+i386_kvm_ss.add(when: 'CONFIG_CSV', if_false: files('csv-stub.c'))
|
||||
|
||||
i386_system_ss.add(when: 'CONFIG_HYPERV', if_true: files('hyperv.c'), if_false: files('hyperv-stub.c'))
|
||||
|
||||
diff --git a/target/i386/meson.build b/target/i386/meson.build
|
||||
index 7c74bfa859..594a0a6abf 100644
|
||||
--- a/target/i386/meson.build
|
||||
+++ b/target/i386/meson.build
|
||||
@@ -21,6 +21,7 @@ i386_system_ss.add(files(
|
||||
'cpu-sysemu.c',
|
||||
))
|
||||
i386_system_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-sysemu-stub.c'))
|
||||
+i386_system_ss.add(when: 'CONFIG_CSV', if_true: files('csv.c'), if_false: files('csv-sysemu-stub.c'))
|
||||
|
||||
i386_user_ss = ss.source_set()
|
||||
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 7744378112..2c6aecd1a3 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -1190,6 +1190,15 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
error_setg(errp, "%s: failed to create encryption context", __func__);
|
||||
goto err;
|
||||
}
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * The CSV2 guest is not resettable after migrated to target machine,
|
||||
+ * set csv_kvm_cpu_reset_inhibit to true to indicate the CSV2 guest is
|
||||
+ * not resettable.
|
||||
+ */
|
||||
+ if (is_hygon_cpu() && sev_es_enabled()) {
|
||||
+ csv_kvm_cpu_reset_inhibit = true;
|
||||
+ }
|
||||
}
|
||||
|
||||
ram_block_notifier_add(&sev_ram_notifier);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
34
target-i386-no-single-step-exception-after-MOV-or-PO.patch
Normal file
34
target-i386-no-single-step-exception-after-MOV-or-PO.patch
Normal file
@ -0,0 +1,34 @@
|
||||
From 004e0a984118380ff89ceaabb6ace1ebbfb1eb6d Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 11:08:13 +0800
|
||||
Subject: [PATCH] target/i386: no single-step exception after MOV or POP SS
|
||||
|
||||
cherry picked from commitd f0f0136abba688a6516647a79cc91e03fad6d5d7
|
||||
|
||||
Intel SDM 18.3.1.4 "If an occurrence of the MOV or POP instruction
|
||||
loads the SS register executes with EFLAGS.TF = 1, no single-step debug
|
||||
exception occurs following the MOV or POP instruction."
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
target/i386/tcg/translate.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
|
||||
index 037bc47e7c..dc672d7995 100644
|
||||
--- a/target/i386/tcg/translate.c
|
||||
+++ b/target/i386/tcg/translate.c
|
||||
@@ -2790,7 +2790,7 @@ do_gen_eob_worker(DisasContext *s, bool inhibit, bool recheck_tf, bool jr)
|
||||
if (recheck_tf) {
|
||||
gen_helper_rechecking_single_step(tcg_env);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
- } else if (s->flags & HF_TF_MASK) {
|
||||
+ } else if ((s->flags & HF_TF_MASK) && !inhibit) {
|
||||
gen_helper_single_step(tcg_env);
|
||||
} else if (jr) {
|
||||
tcg_gen_lookup_and_goto_ptr();
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
57
target-i386-sev-Clear-shared_regions_list-when-reboo.patch
Normal file
57
target-i386-sev-Clear-shared_regions_list-when-reboo.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From e98147762cb47645c590ee000dbc12c654a6cc2d Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Sun, 16 Jan 2022 19:57:58 -0500
|
||||
Subject: [PATCH] target/i386: sev: Clear shared_regions_list when reboot CSV
|
||||
Guest
|
||||
|
||||
Also fix memory leak in sev_remove_shared_regions_list().
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
target/i386/kvm/kvm.c | 5 +++++
|
||||
target/i386/sev.c | 5 +++--
|
||||
2 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
|
||||
index a5a755db01..5730d0e0c0 100644
|
||||
--- a/target/i386/kvm/kvm.c
|
||||
+++ b/target/i386/kvm/kvm.c
|
||||
@@ -2270,6 +2270,11 @@ void kvm_arch_reset_vcpu(X86CPU *cpu)
|
||||
env->mp_state = KVM_MP_STATE_RUNNABLE;
|
||||
}
|
||||
|
||||
+ if (cpu_is_bsp(cpu) &&
|
||||
+ sev_enabled() && has_map_gpa_range) {
|
||||
+ sev_remove_shared_regions_list(0, -1);
|
||||
+ }
|
||||
+
|
||||
/* enabled by default */
|
||||
env->poll_control_msr = 1;
|
||||
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 6ccb22c00a..0b0f589aee 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -1694,9 +1694,9 @@ int sev_load_incoming_page(QEMUFile *f, uint8_t *ptr)
|
||||
int sev_remove_shared_regions_list(unsigned long start, unsigned long end)
|
||||
{
|
||||
SevGuestState *s = sev_guest;
|
||||
- struct shared_region *pos;
|
||||
+ struct shared_region *pos, *next_pos;
|
||||
|
||||
- QTAILQ_FOREACH(pos, &s->shared_regions_list, list) {
|
||||
+ QTAILQ_FOREACH_SAFE(pos, &s->shared_regions_list, list, next_pos) {
|
||||
unsigned long l, r;
|
||||
unsigned long curr_gfn_end = pos->gfn_end;
|
||||
|
||||
@@ -1710,6 +1710,7 @@ int sev_remove_shared_regions_list(unsigned long start, unsigned long end)
|
||||
if (l <= r) {
|
||||
if (pos->gfn_start == l && pos->gfn_end == r) {
|
||||
QTAILQ_REMOVE(&s->shared_regions_list, pos, list);
|
||||
+ g_free(pos);
|
||||
} else if (l == pos->gfn_start) {
|
||||
pos->gfn_start = r;
|
||||
} else if (r == pos->gfn_end) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
59
target-i386-sev-Return-0-if-sev_send_get_packet_len-.patch
Normal file
59
target-i386-sev-Return-0-if-sev_send_get_packet_len-.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From ccca5618025567c4168630459b90bf11bf96cca4 Mon Sep 17 00:00:00 2001
|
||||
From: hanliyang <hanliyang@hygon.cn>
|
||||
Date: Wed, 31 Jan 2024 07:26:57 +0800
|
||||
Subject: [PATCH] target/i386: sev: Return 0 if sev_send_get_packet_len() fails
|
||||
|
||||
The send_packet_hdr_len of struct SEVState is of type size_t
|
||||
which is an unsigned class type. If the send_packet_hdr_len
|
||||
is assigned as -1, then it will be a huge number and the QEMU
|
||||
process will crash when allocating packet buffer with the
|
||||
huge size.
|
||||
|
||||
For example, the following code could cause crash described
|
||||
above.
|
||||
|
||||
```
|
||||
static int
|
||||
sev_send_update_data(SEVState *s, QEMUFile *f, uint8_t *ptr, uint32_t size,
|
||||
uint64_t *bytes_sent)
|
||||
{
|
||||
|
||||
......
|
||||
|
||||
if (!s->send_packet_hdr) {
|
||||
s->send_packet_hdr_len = sev_send_get_packet_len(&fw_error);
|
||||
if (s->send_packet_hdr_len < 1) {
|
||||
error_report("%s: SEND_UPDATE fw_error=%d '%s'",
|
||||
__func__, fw_error, fw_error_to_str(fw_error));
|
||||
return 1;
|
||||
}
|
||||
|
||||
s->send_packet_hdr = g_new(gchar, s->send_packet_hdr_len);
|
||||
}
|
||||
|
||||
......
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
target/i386/sev.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 98b0d3937a..6ccb22c00a 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -1492,7 +1492,7 @@ sev_send_get_packet_len(int *fw_err)
|
||||
ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_SEND_UPDATE_DATA,
|
||||
&update, fw_err);
|
||||
if (*fw_err != SEV_RET_INVALID_LEN) {
|
||||
- ret = -1;
|
||||
+ ret = 0;
|
||||
error_report("%s: failed to get session length ret=%d fw_error=%d '%s'",
|
||||
__func__, ret, *fw_err, fw_error_to_str(*fw_err));
|
||||
goto err;
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
319
target-i386-sev-add-support-to-encrypt-the-outgoing-.patch
Normal file
319
target-i386-sev-add-support-to-encrypt-the-outgoing-.patch
Normal file
@ -0,0 +1,319 @@
|
||||
From 0a7dde8450d9b6a6d0c75cef11e4bbff65e95edc Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Tue, 27 Jul 2021 12:55:25 +0000
|
||||
Subject: [PATCH] target/i386: sev: add support to encrypt the outgoing page
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/5187c6f86bd.
|
||||
|
||||
The sev_save_outgoing_page() provide the implementation to encrypt the
|
||||
guest private pages during the transit. The routines uses the SEND_START
|
||||
command to create the outgoing encryption context on the first call then
|
||||
uses the SEND_UPDATE_DATA command 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: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Co-developed-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflict. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
target/i386/sev.c | 219 +++++++++++++++++++++++++++++++++++++++
|
||||
target/i386/sev.h | 2 +
|
||||
target/i386/trace-events | 3 +
|
||||
3 files changed, 224 insertions(+)
|
||||
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 65984f013a..e1fa0ec5e5 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "sysemu/runstate.h"
|
||||
#include "trace.h"
|
||||
#include "migration/blocker.h"
|
||||
+#include "migration/qemu-file.h"
|
||||
+#include "migration/misc.h"
|
||||
#include "qom/object.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "monitor/hmp-target.h"
|
||||
@@ -79,6 +81,8 @@ struct SevGuestState {
|
||||
size_t remote_plat_cert_len;
|
||||
guchar *amd_cert;
|
||||
size_t amd_cert_len;
|
||||
+ gchar *send_packet_hdr;
|
||||
+ size_t send_packet_hdr_len;
|
||||
|
||||
uint32_t reset_cs;
|
||||
uint32_t reset_ip;
|
||||
@@ -167,6 +171,7 @@ static const char *const sev_fw_errlist[] = {
|
||||
|
||||
static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.save_setup = sev_save_setup,
|
||||
+ .save_outgoing_page = sev_save_outgoing_page,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -960,6 +965,38 @@ error:
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static void
|
||||
+sev_send_finish(void)
|
||||
+{
|
||||
+ int ret, error;
|
||||
+
|
||||
+ trace_kvm_sev_send_finish();
|
||||
+ ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_SEND_FINISH, 0, &error);
|
||||
+ if (ret) {
|
||||
+ error_report("%s: SEND_FINISH ret=%d fw_error=%d '%s'",
|
||||
+ __func__, ret, error, fw_error_to_str(error));
|
||||
+ }
|
||||
+
|
||||
+ g_free(sev_guest->send_packet_hdr);
|
||||
+ sev_set_guest_state(sev_guest, SEV_STATE_RUNNING);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+sev_migration_state_notifier(Notifier *notifier, void *data)
|
||||
+{
|
||||
+ MigrationState *s = data;
|
||||
+
|
||||
+ if (migration_has_finished(s) ||
|
||||
+ migration_in_postcopy_after_devices(s) ||
|
||||
+ migration_has_failed(s)) {
|
||||
+ if (sev_check_state(sev_guest, SEV_STATE_SEND_UPDATE)) {
|
||||
+ sev_send_finish();
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static Notifier sev_migration_state;
|
||||
+
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
{
|
||||
SevGuestState *sev
|
||||
@@ -1075,6 +1112,7 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
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);
|
||||
+ migration_add_notifier(&sev_migration_state, sev_migration_state_notifier);
|
||||
|
||||
cgs_class->memory_encryption_ops = &sev_memory_encryption_ops;
|
||||
|
||||
@@ -1317,6 +1355,187 @@ int sev_es_save_reset_vector(void *flash_ptr, uint64_t flash_size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int
|
||||
+sev_get_send_session_length(void)
|
||||
+{
|
||||
+ int ret, fw_err = 0;
|
||||
+ struct kvm_sev_send_start start = {};
|
||||
+
|
||||
+ ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_SEND_START, &start, &fw_err);
|
||||
+ if (fw_err != SEV_RET_INVALID_LEN) {
|
||||
+ ret = -1;
|
||||
+ error_report("%s: failed to get session length ret=%d fw_error=%d '%s'",
|
||||
+ __func__, ret, fw_err, fw_error_to_str(fw_err));
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = start.session_len;
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sev_send_start(SevGuestState *s, QEMUFile *f, uint64_t *bytes_sent)
|
||||
+{
|
||||
+ gsize pdh_len = 0, plat_cert_len;
|
||||
+ int session_len, ret, fw_error;
|
||||
+ struct kvm_sev_send_start start = { };
|
||||
+ guchar *pdh = NULL, *plat_cert = NULL, *session = NULL;
|
||||
+ Error *local_err = NULL;
|
||||
+
|
||||
+ if (!s->remote_pdh || !s->remote_plat_cert || !s->amd_cert_len) {
|
||||
+ error_report("%s: missing remote PDH or PLAT_CERT", __func__);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ start.pdh_cert_uaddr = (uintptr_t) s->remote_pdh;
|
||||
+ start.pdh_cert_len = s->remote_pdh_len;
|
||||
+
|
||||
+ start.plat_certs_uaddr = (uintptr_t)s->remote_plat_cert;
|
||||
+ start.plat_certs_len = s->remote_plat_cert_len;
|
||||
+
|
||||
+ start.amd_certs_uaddr = (uintptr_t)s->amd_cert;
|
||||
+ start.amd_certs_len = s->amd_cert_len;
|
||||
+
|
||||
+ /* get the session length */
|
||||
+ session_len = sev_get_send_session_length();
|
||||
+ if (session_len < 0) {
|
||||
+ ret = 1;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ session = g_new0(guchar, session_len);
|
||||
+ start.session_uaddr = (unsigned long)session;
|
||||
+ start.session_len = session_len;
|
||||
+
|
||||
+ /* Get our PDH certificate */
|
||||
+ ret = sev_get_pdh_info(s->sev_fd, &pdh, &pdh_len,
|
||||
+ &plat_cert, &plat_cert_len, &local_err);
|
||||
+ if (ret) {
|
||||
+ error_report("Failed to get our PDH cert");
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ trace_kvm_sev_send_start(start.pdh_cert_uaddr, start.pdh_cert_len,
|
||||
+ start.plat_certs_uaddr, start.plat_certs_len,
|
||||
+ start.amd_certs_uaddr, start.amd_certs_len);
|
||||
+
|
||||
+ ret = sev_ioctl(s->sev_fd, KVM_SEV_SEND_START, &start, &fw_error);
|
||||
+ if (ret < 0) {
|
||||
+ error_report("%s: SEND_START ret=%d fw_error=%d '%s'",
|
||||
+ __func__, ret, fw_error, fw_error_to_str(fw_error));
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ qemu_put_be32(f, start.policy);
|
||||
+ qemu_put_be32(f, pdh_len);
|
||||
+ qemu_put_buffer(f, (uint8_t *)pdh, pdh_len);
|
||||
+ qemu_put_be32(f, start.session_len);
|
||||
+ qemu_put_buffer(f, (uint8_t *)start.session_uaddr, start.session_len);
|
||||
+ *bytes_sent = 12 + pdh_len + start.session_len;
|
||||
+
|
||||
+ sev_set_guest_state(s, SEV_STATE_SEND_UPDATE);
|
||||
+
|
||||
+err:
|
||||
+ g_free(pdh);
|
||||
+ g_free(plat_cert);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sev_send_get_packet_len(int *fw_err)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct kvm_sev_send_update_data update = { 0, };
|
||||
+
|
||||
+ ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_SEND_UPDATE_DATA,
|
||||
+ &update, fw_err);
|
||||
+ if (*fw_err != SEV_RET_INVALID_LEN) {
|
||||
+ ret = -1;
|
||||
+ error_report("%s: failed to get session length ret=%d fw_error=%d '%s'",
|
||||
+ __func__, ret, *fw_err, fw_error_to_str(*fw_err));
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ret = update.hdr_len;
|
||||
+
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+sev_send_update_data(SevGuestState *s, QEMUFile *f, uint8_t *ptr, uint32_t size,
|
||||
+ uint64_t *bytes_sent)
|
||||
+{
|
||||
+ int ret, fw_error;
|
||||
+ guchar *trans;
|
||||
+ struct kvm_sev_send_update_data update = { };
|
||||
+
|
||||
+ /*
|
||||
+ * If this is first call then query the packet header bytes and allocate
|
||||
+ * the packet buffer.
|
||||
+ */
|
||||
+ if (!s->send_packet_hdr) {
|
||||
+ s->send_packet_hdr_len = sev_send_get_packet_len(&fw_error);
|
||||
+ if (s->send_packet_hdr_len < 1) {
|
||||
+ error_report("%s: SEND_UPDATE fw_error=%d '%s'",
|
||||
+ __func__, fw_error, fw_error_to_str(fw_error));
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ s->send_packet_hdr = g_new(gchar, s->send_packet_hdr_len);
|
||||
+ }
|
||||
+
|
||||
+ /* allocate transport buffer */
|
||||
+ trans = g_new(guchar, size);
|
||||
+
|
||||
+ update.hdr_uaddr = (uintptr_t)s->send_packet_hdr;
|
||||
+ update.hdr_len = s->send_packet_hdr_len;
|
||||
+ update.guest_uaddr = (uintptr_t)ptr;
|
||||
+ update.guest_len = size;
|
||||
+ update.trans_uaddr = (uintptr_t)trans;
|
||||
+ update.trans_len = size;
|
||||
+
|
||||
+ trace_kvm_sev_send_update_data(ptr, trans, size);
|
||||
+
|
||||
+ ret = sev_ioctl(s->sev_fd, KVM_SEV_SEND_UPDATE_DATA, &update, &fw_error);
|
||||
+ if (ret) {
|
||||
+ error_report("%s: SEND_UPDATE_DATA ret=%d fw_error=%d '%s'",
|
||||
+ __func__, ret, fw_error, fw_error_to_str(fw_error));
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ 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:
|
||||
+ g_free(trans);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int sev_save_outgoing_page(QEMUFile *f, uint8_t *ptr,
|
||||
+ uint32_t sz, uint64_t *bytes_sent)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+
|
||||
+ /*
|
||||
+ * 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 sev_send_update_data(s, f, ptr, sz, 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 e96de021f5..463e94bb81 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -53,6 +53,8 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp);
|
||||
int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp);
|
||||
int sev_save_setup(const char *pdh, const char *plat_cert,
|
||||
const char *amd_cert);
|
||||
+int sev_save_outgoing_page(QEMUFile *f, uint8_t *ptr,
|
||||
+ uint32_t size, uint64_t *bytes_sent);
|
||||
int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||
uint64_t gpa, Error **errp);
|
||||
|
||||
diff --git a/target/i386/trace-events b/target/i386/trace-events
|
||||
index 2cd8726eeb..e8d4aec125 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"
|
||||
+kvm_sev_send_start(uint64_t pdh, int l1, uint64_t plat, int l2, uint64_t amd, int l3) "pdh 0x%" PRIx64 " len %d plat 0x%" PRIx64 " len %d amd 0x%" PRIx64 " len %d"
|
||||
+kvm_sev_send_update_data(void *src, void *dst, int len) "guest %p trans %p len %d"
|
||||
+kvm_sev_send_finish(void) ""
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
221
target-i386-sev-add-support-to-load-incoming-encrypt.patch
Normal file
221
target-i386-sev-add-support-to-load-incoming-encrypt.patch
Normal file
@ -0,0 +1,221 @@
|
||||
From 778457c2f0f91b6a52e5db02dd3dc1f35ae64526 Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Tue, 27 Jul 2021 13:00:50 +0000
|
||||
Subject: [PATCH] target/i386: sev: add support to load incoming encrypted page
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/e86e5dccb045.
|
||||
|
||||
The sev_load_incoming_page() provide the implementation to read the
|
||||
incoming guest private pages from the socket and load it into the guest
|
||||
memory. The routines uses the RECEIVE_START command to create the
|
||||
incoming encryption context on the first call then uses the
|
||||
RECEIEVE_UPDATE_DATA command to load the encrypted pages into the guest
|
||||
memory. After migration is completed, we issue the RECEIVE_FINISH command
|
||||
to transition the SEV guest to the runnable state so that it can be
|
||||
executed.
|
||||
|
||||
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Co-developed-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflicts. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
target/i386/sev.c | 137 ++++++++++++++++++++++++++++++++++++++-
|
||||
target/i386/sev.h | 1 +
|
||||
target/i386/trace-events | 3 +
|
||||
3 files changed, 140 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index e1fa0ec5e5..de1a4b271e 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -172,6 +172,7 @@ static const char *const sev_fw_errlist[] = {
|
||||
static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
.save_setup = sev_save_setup,
|
||||
.save_outgoing_page = sev_save_outgoing_page,
|
||||
+ .load_incoming_page = sev_load_incoming_page,
|
||||
};
|
||||
|
||||
static int
|
||||
@@ -911,13 +912,33 @@ sev_launch_finish(SevGuestState *sev)
|
||||
migrate_add_blocker(&sev_mig_blocker, &error_fatal);
|
||||
}
|
||||
|
||||
+static int
|
||||
+sev_receive_finish(SevGuestState *s)
|
||||
+{
|
||||
+ int error, ret = 1;
|
||||
+
|
||||
+ trace_kvm_sev_receive_finish();
|
||||
+ ret = sev_ioctl(s->sev_fd, KVM_SEV_RECEIVE_FINISH, 0, &error);
|
||||
+ if (ret) {
|
||||
+ error_report("%s: RECEIVE_FINISH ret=%d fw_error=%d '%s'",
|
||||
+ __func__, ret, error, fw_error_to_str(error));
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ sev_set_guest_state(s, SEV_STATE_RUNNING);
|
||||
+err:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||
{
|
||||
SevGuestState *sev = opaque;
|
||||
|
||||
if (running) {
|
||||
- if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
|
||||
+ if (sev_check_state(sev, SEV_STATE_RECEIVE_UPDATE)) {
|
||||
+ sev_receive_finish(sev);
|
||||
+ } else if (!sev_check_state(sev, SEV_STATE_RUNNING)) {
|
||||
sev_launch_finish(sev);
|
||||
}
|
||||
}
|
||||
@@ -1536,6 +1557,120 @@ int sev_save_outgoing_page(QEMUFile *f, uint8_t *ptr,
|
||||
return sev_send_update_data(s, f, ptr, sz, bytes_sent);
|
||||
}
|
||||
|
||||
+static int
|
||||
+sev_receive_start(SevGuestState *sev, QEMUFile *f)
|
||||
+{
|
||||
+ int ret = 1;
|
||||
+ int fw_error;
|
||||
+ struct kvm_sev_receive_start start = { };
|
||||
+ gchar *session = NULL, *pdh_cert = NULL;
|
||||
+
|
||||
+ /* get SEV guest handle */
|
||||
+ start.handle = object_property_get_int(OBJECT(sev), "handle",
|
||||
+ &error_abort);
|
||||
+
|
||||
+ /* get the source policy */
|
||||
+ start.policy = qemu_get_be32(f);
|
||||
+
|
||||
+ /* get source PDH key */
|
||||
+ start.pdh_len = qemu_get_be32(f);
|
||||
+ if (!check_blob_length(start.pdh_len)) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ pdh_cert = g_new(gchar, start.pdh_len);
|
||||
+ qemu_get_buffer(f, (uint8_t *)pdh_cert, start.pdh_len);
|
||||
+ start.pdh_uaddr = (uintptr_t)pdh_cert;
|
||||
+
|
||||
+ /* get source session data */
|
||||
+ start.session_len = qemu_get_be32(f);
|
||||
+ if (!check_blob_length(start.session_len)) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+ session = g_new(gchar, start.session_len);
|
||||
+ qemu_get_buffer(f, (uint8_t *)session, start.session_len);
|
||||
+ start.session_uaddr = (uintptr_t)session;
|
||||
+
|
||||
+ trace_kvm_sev_receive_start(start.policy, session, pdh_cert);
|
||||
+
|
||||
+ ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_RECEIVE_START,
|
||||
+ &start, &fw_error);
|
||||
+ if (ret < 0) {
|
||||
+ error_report("Error RECEIVE_START ret=%d fw_error=%d '%s'",
|
||||
+ ret, fw_error, fw_error_to_str(fw_error));
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ object_property_set_int(OBJECT(sev), "handle", start.handle, &error_abort);
|
||||
+ sev_set_guest_state(sev, SEV_STATE_RECEIVE_UPDATE);
|
||||
+err:
|
||||
+ g_free(session);
|
||||
+ g_free(pdh_cert);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int sev_receive_update_data(QEMUFile *f, uint8_t *ptr)
|
||||
+{
|
||||
+ int ret = 1, fw_error = 0;
|
||||
+ gchar *hdr = NULL, *trans = NULL;
|
||||
+ struct kvm_sev_receive_update_data update = {};
|
||||
+
|
||||
+ /* get packet header */
|
||||
+ update.hdr_len = qemu_get_be32(f);
|
||||
+ if (!check_blob_length(update.hdr_len)) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ hdr = g_new(gchar, update.hdr_len);
|
||||
+ qemu_get_buffer(f, (uint8_t *)hdr, update.hdr_len);
|
||||
+ update.hdr_uaddr = (uintptr_t)hdr;
|
||||
+
|
||||
+ /* get transport buffer */
|
||||
+ update.trans_len = qemu_get_be32(f);
|
||||
+ if (!check_blob_length(update.trans_len)) {
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ trans = g_new(gchar, update.trans_len);
|
||||
+ update.trans_uaddr = (uintptr_t)trans;
|
||||
+ qemu_get_buffer(f, (uint8_t *)update.trans_uaddr, update.trans_len);
|
||||
+
|
||||
+ update.guest_uaddr = (uintptr_t) ptr;
|
||||
+ update.guest_len = update.trans_len;
|
||||
+
|
||||
+ trace_kvm_sev_receive_update_data(trans, ptr, update.guest_len,
|
||||
+ hdr, update.hdr_len);
|
||||
+
|
||||
+ ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_RECEIVE_UPDATE_DATA,
|
||||
+ &update, &fw_error);
|
||||
+ if (ret) {
|
||||
+ error_report("Error RECEIVE_UPDATE_DATA ret=%d fw_error=%d '%s'",
|
||||
+ ret, fw_error, fw_error_to_str(fw_error));
|
||||
+ goto err;
|
||||
+ }
|
||||
+err:
|
||||
+ g_free(trans);
|
||||
+ g_free(hdr);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int sev_load_incoming_page(QEMUFile *f, uint8_t *ptr)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+
|
||||
+ /*
|
||||
+ * If this is first buffer and SEV is not in recieiving state then
|
||||
+ * use RECEIVE_START command to create a encryption context.
|
||||
+ */
|
||||
+ if (!sev_check_state(s, SEV_STATE_RECEIVE_UPDATE) &&
|
||||
+ sev_receive_start(s, f)) {
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ return sev_receive_update_data(f, ptr);
|
||||
+}
|
||||
+
|
||||
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 463e94bb81..d94da2956b 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -55,6 +55,7 @@ int sev_save_setup(const char *pdh, const char *plat_cert,
|
||||
const char *amd_cert);
|
||||
int sev_save_outgoing_page(QEMUFile *f, uint8_t *ptr,
|
||||
uint32_t size, uint64_t *bytes_sent);
|
||||
+int sev_load_incoming_page(QEMUFile *f, uint8_t *ptr);
|
||||
int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||
uint64_t gpa, Error **errp);
|
||||
|
||||
diff --git a/target/i386/trace-events b/target/i386/trace-events
|
||||
index e8d4aec125..475de65ad4 100644
|
||||
--- a/target/i386/trace-events
|
||||
+++ b/target/i386/trace-events
|
||||
@@ -14,3 +14,6 @@ kvm_sev_attestation_report(const char *mnonce, const char *data) "mnonce %s data
|
||||
kvm_sev_send_start(uint64_t pdh, int l1, uint64_t plat, int l2, uint64_t amd, int l3) "pdh 0x%" PRIx64 " len %d plat 0x%" PRIx64 " len %d amd 0x%" PRIx64 " len %d"
|
||||
kvm_sev_send_update_data(void *src, void *dst, int len) "guest %p trans %p len %d"
|
||||
kvm_sev_send_finish(void) ""
|
||||
+kvm_sev_receive_start(int policy, void *session, void *pdh) "policy 0x%x session %p pdh %p"
|
||||
+kvm_sev_receive_update_data(void *src, void *dst, int len, void *hdr, int hdr_len) "guest %p trans %p len %d hdr %p hdr_len %d"
|
||||
+kvm_sev_receive_finish(void) ""
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
49
target-i386-sev-do-not-create-launch-context-for-an-.patch
Normal file
49
target-i386-sev-do-not-create-launch-context-for-an-.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From c8a6d5f18c45079575b707db8f017cce22acc970 Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Tue, 27 Jul 2021 12:16:09 +0000
|
||||
Subject: [PATCH] target/i386: sev: do not create launch context for an
|
||||
incoming guest
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/b85694233495.
|
||||
|
||||
The LAUNCH_START is used for creating an encryption context to encrypt
|
||||
newly created guest, for an incoming guest the RECEIVE_START should be
|
||||
used.
|
||||
|
||||
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
|
||||
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflict. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
target/i386/sev.c | 14 ++++++++++----
|
||||
1 file changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 10233511cf..65984f013a 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -1060,10 +1060,16 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
goto err;
|
||||
}
|
||||
|
||||
- ret = sev_launch_start(sev);
|
||||
- if (ret) {
|
||||
- error_setg(errp, "%s: failed to create encryption context", __func__);
|
||||
- goto err;
|
||||
+ /*
|
||||
+ * The LAUNCH context is used for new guest, if its an incoming guest
|
||||
+ * then RECEIVE context will be created after the connection is established.
|
||||
+ */
|
||||
+ if (!runstate_check(RUN_STATE_INMIGRATE)) {
|
||||
+ ret = sev_launch_start(sev);
|
||||
+ if (ret) {
|
||||
+ error_setg(errp, "%s: failed to create encryption context", __func__);
|
||||
+ goto err;
|
||||
+ }
|
||||
}
|
||||
|
||||
ram_block_notifier_add(&sev_ram_notifier);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
135
target-i386-sev-provide-callback-to-setup-outgoing-c.patch
Normal file
135
target-i386-sev-provide-callback-to-setup-outgoing-c.patch
Normal file
@ -0,0 +1,135 @@
|
||||
From f6753191237118294d04193908db503bb87619f7 Mon Sep 17 00:00:00 2001
|
||||
From: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Date: Tue, 27 Jul 2021 12:10:23 +0000
|
||||
Subject: [PATCH] target/i386: sev: provide callback to setup outgoing context
|
||||
|
||||
cherry-picked from https://github.com/AMDESE/qemu/commit/7521883afc0.
|
||||
|
||||
The user provides the target machine's Platform Diffie-Hellman key (PDH)
|
||||
and certificate chain before starting the SEV guest migration. Cache the
|
||||
certificate chain as we need them while creating the outgoing context.
|
||||
|
||||
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
|
||||
Co-developed-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
|
||||
[ Fix conflict. ]
|
||||
Signed-off-by: hanliyang <hanliyang@hygon.cn>
|
||||
---
|
||||
target/i386/sev.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
target/i386/sev.h | 2 ++
|
||||
2 files changed, 61 insertions(+)
|
||||
|
||||
diff --git a/target/i386/sev.c b/target/i386/sev.c
|
||||
index 1a9d1db7a8..10233511cf 100644
|
||||
--- a/target/i386/sev.c
|
||||
+++ b/target/i386/sev.c
|
||||
@@ -73,6 +73,12 @@ struct SevGuestState {
|
||||
int sev_fd;
|
||||
SevState state;
|
||||
gchar *measurement;
|
||||
+ guchar *remote_pdh;
|
||||
+ size_t remote_pdh_len;
|
||||
+ guchar *remote_plat_cert;
|
||||
+ size_t remote_plat_cert_len;
|
||||
+ guchar *amd_cert;
|
||||
+ size_t amd_cert_len;
|
||||
|
||||
uint32_t reset_cs;
|
||||
uint32_t reset_ip;
|
||||
@@ -157,6 +163,12 @@ static const char *const sev_fw_errlist[] = {
|
||||
|
||||
#define SEV_FW_MAX_ERROR ARRAY_SIZE(sev_fw_errlist)
|
||||
|
||||
+#define SEV_FW_BLOB_MAX_SIZE 0x4000 /* 16KB */
|
||||
+
|
||||
+static struct ConfidentialGuestMemoryEncryptionOps sev_memory_encryption_ops = {
|
||||
+ .save_setup = sev_save_setup,
|
||||
+};
|
||||
+
|
||||
static int
|
||||
sev_ioctl(int fd, int cmd, void *data, int *error)
|
||||
{
|
||||
@@ -906,6 +918,48 @@ sev_vm_state_change(void *opaque, bool running, RunState state)
|
||||
}
|
||||
}
|
||||
|
||||
+static inline bool check_blob_length(size_t value)
|
||||
+{
|
||||
+ if (value > SEV_FW_BLOB_MAX_SIZE) {
|
||||
+ error_report("invalid length max=%d got=%ld",
|
||||
+ SEV_FW_BLOB_MAX_SIZE, value);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+int sev_save_setup(const char *pdh, const char *plat_cert,
|
||||
+ const char *amd_cert)
|
||||
+{
|
||||
+ SevGuestState *s = sev_guest;
|
||||
+
|
||||
+ s->remote_pdh = g_base64_decode(pdh, &s->remote_pdh_len);
|
||||
+ if (!check_blob_length(s->remote_pdh_len)) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ s->remote_plat_cert = g_base64_decode(plat_cert,
|
||||
+ &s->remote_plat_cert_len);
|
||||
+ if (!check_blob_length(s->remote_plat_cert_len)) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ s->amd_cert = g_base64_decode(amd_cert, &s->amd_cert_len);
|
||||
+ if (!check_blob_length(s->amd_cert_len)) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+error:
|
||||
+ g_free(s->remote_pdh);
|
||||
+ g_free(s->remote_plat_cert);
|
||||
+ g_free(s->amd_cert);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
{
|
||||
SevGuestState *sev
|
||||
@@ -920,6 +974,9 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ ConfidentialGuestSupportClass *cgs_class =
|
||||
+ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(cgs));
|
||||
+
|
||||
ret = ram_block_discard_disable(true);
|
||||
if (ret) {
|
||||
error_report("%s: cannot disable RAM discard", __func__);
|
||||
@@ -1013,6 +1070,8 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
|
||||
qemu_add_machine_init_done_notifier(&sev_machine_done_notify);
|
||||
qemu_add_vm_change_state_handler(sev_vm_state_change, sev);
|
||||
|
||||
+ cgs_class->memory_encryption_ops = &sev_memory_encryption_ops;
|
||||
+
|
||||
cgs->ready = true;
|
||||
|
||||
return 0;
|
||||
diff --git a/target/i386/sev.h b/target/i386/sev.h
|
||||
index e7499c95b1..e96de021f5 100644
|
||||
--- a/target/i386/sev.h
|
||||
+++ b/target/i386/sev.h
|
||||
@@ -51,6 +51,8 @@ uint32_t sev_get_reduced_phys_bits(void);
|
||||
bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp);
|
||||
|
||||
int sev_encrypt_flash(uint8_t *ptr, uint64_t len, Error **errp);
|
||||
+int sev_save_setup(const char *pdh, const char *plat_cert,
|
||||
+ const char *amd_cert);
|
||||
int sev_inject_launch_secret(const char *hdr, const char *secret,
|
||||
uint64_t gpa, Error **errp);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
39
target-loongarch-fix-a-wrong-print-in-cpu-dump.patch
Normal file
39
target-loongarch-fix-a-wrong-print-in-cpu-dump.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 4f76ccdc5bdad57b9c70da7a4fc00502cc335060 Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 11:27:12 +0800
|
||||
Subject: [PATCH] target/loongarch: fix a wrong print in cpu dump
|
||||
|
||||
cherry picked from commit 78f932ea1f7b3b9b0ac628dc2a91281318fe51fa
|
||||
|
||||
description:
|
||||
loongarch_cpu_dump_state() want to dump all loongarch cpu
|
||||
state registers, but there is a tiny typographical error when
|
||||
printing "PRCFG2".
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: lanyanzhi <lanyanzhi22b@ict.ac.cn>
|
||||
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240604073831.666690-1-lanyanzhi22b@ict.ac.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
target/loongarch/cpu.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
|
||||
index 8e7c8332da..f7b5dae7ed 100644
|
||||
--- a/target/loongarch/cpu.c
|
||||
+++ b/target/loongarch/cpu.c
|
||||
@@ -802,7 +802,7 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
|
||||
qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
|
||||
" PRCFG3=%016" PRIx64 "\n",
|
||||
- env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
|
||||
+ env->CSR_PRCFG1, env->CSR_PRCFG2, env->CSR_PRCFG3);
|
||||
qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
|
||||
qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
|
||||
qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
27
update-docs-tools-virtfs-proxy-helper.rst.patch
Normal file
27
update-docs-tools-virtfs-proxy-helper.rst.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From c31f85b015326ad6619c707ada5cea2713970741 Mon Sep 17 00:00:00 2001
|
||||
From: lixiang_yewu <lixiang_yewu@cmss.chinamobile.com>
|
||||
Date: Mon, 2 Sep 2024 07:35:57 +0000
|
||||
Subject: [PATCH] update docs/tools/virtfs-proxy-helper.rst. This place is
|
||||
spelled wrong.
|
||||
|
||||
Signed-off-by: lixiang_yewu <lixiang_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
docs/tools/virtfs-proxy-helper.rst | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/tools/virtfs-proxy-helper.rst b/docs/tools/virtfs-proxy-helper.rst
|
||||
index bd310ebb07..175b480926 100644
|
||||
--- a/docs/tools/virtfs-proxy-helper.rst
|
||||
+++ b/docs/tools/virtfs-proxy-helper.rst
|
||||
@@ -55,7 +55,7 @@ The following options are supported:
|
||||
.. option:: -f, --fd SOCKET_ID
|
||||
|
||||
Use given file descriptor as socket descriptor for communicating with
|
||||
- qemu proxy fs drier. Usually a helper like libvirt will create
|
||||
+ qemu proxy fs driver. Usually a helper like libvirt will create
|
||||
socketpair and pass one of the fds as parameter to this option.
|
||||
|
||||
.. option:: -s, --socket SOCKET_FILE
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
26
update-io-trace-events.patch
Normal file
26
update-io-trace-events.patch
Normal file
@ -0,0 +1,26 @@
|
||||
From c6b96a0e10db061c9ab790b443f0bfd8220d7d3c Mon Sep 17 00:00:00 2001
|
||||
From: lixiang_yewu <lixiang_yewu@cmss.chinamobile.com>
|
||||
Date: Mon, 2 Sep 2024 07:39:00 +0000
|
||||
Subject: [PATCH] update io/trace-events. Parameters should remain consistent.
|
||||
|
||||
Signed-off-by: lixiang_yewu <lixiang_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
io/trace-events | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/io/trace-events b/io/trace-events
|
||||
index 3cc5cf1efd..79e1a19af7 100644
|
||||
--- a/io/trace-events
|
||||
+++ b/io/trace-events
|
||||
@@ -38,7 +38,7 @@ qio_channel_file_new_path(void *ioc, const char *path, int flags, int mode, int
|
||||
|
||||
# channel-tls.c
|
||||
qio_channel_tls_new_client(void *ioc, void *master, void *creds, const char *hostname) "TLS new client ioc=%p master=%p creds=%p hostname=%s"
|
||||
-qio_channel_tls_new_server(void *ioc, void *master, void *creds, const char *aclname) "TLS new client ioc=%p master=%p creds=%p acltname=%s"
|
||||
+qio_channel_tls_new_server(void *ioc, void *master, void *creds, const char *aclname) "TLS new client ioc=%p master=%p creds=%p aclname=%s"
|
||||
qio_channel_tls_handshake_start(void *ioc) "TLS handshake start ioc=%p"
|
||||
qio_channel_tls_handshake_pending(void *ioc, int status) "TLS handshake pending ioc=%p status=%d"
|
||||
qio_channel_tls_handshake_fail(void *ioc) "TLS handshake fail ioc=%p"
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
36
virtio-net-Ensure-queue-index-fits-with-RSS-CVE-2024.patch
Normal file
36
virtio-net-Ensure-queue-index-fits-with-RSS-CVE-2024.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From a8bc17bf7f94f684ba518c56e56b41974c50305e Mon Sep 17 00:00:00 2001
|
||||
From: Akihiko Odaki <akihiko.odaki@daynix.com>
|
||||
Date: Mon, 1 Jul 2024 20:58:04 +0900
|
||||
Subject: [PATCH] virtio-net: Ensure queue index fits with RSS (CVE-2024-6505)
|
||||
|
||||
Ensure the queue index points to a valid queue when software RSS
|
||||
enabled. The new calculation matches with the behavior of Linux's TAP
|
||||
device with the RSS eBPF program.
|
||||
|
||||
Fixes: 4474e37a5b3a ("virtio-net: implement RX RSS processing")
|
||||
Reported-by: Zhibin Hu <huzhibin5@huawei.com>
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
---
|
||||
hw/net/virtio-net.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
|
||||
index 91c1504544..432c433540 100644
|
||||
--- a/hw/net/virtio-net.c
|
||||
+++ b/hw/net/virtio-net.c
|
||||
@@ -1931,7 +1931,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||
if (!no_rss && n->rss_data.enabled && n->rss_data.enabled_software_rss) {
|
||||
int index = virtio_net_process_rss(nc, buf, size);
|
||||
if (index >= 0) {
|
||||
- NetClientState *nc2 = qemu_get_subqueue(n->nic, index);
|
||||
+ NetClientState *nc2 =
|
||||
+ qemu_get_subqueue(n->nic, index % n->curr_queue_pairs);
|
||||
return virtio_net_receive_rcu(nc2, buf, size, true);
|
||||
}
|
||||
}
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
58
virtio-net-Use-virtual-time-for-RSC-timers.patch
Normal file
58
virtio-net-Use-virtual-time-for-RSC-timers.patch
Normal file
@ -0,0 +1,58 @@
|
||||
From 8f6c35e3acb54208564fcb773cf79809d7412cf5 Mon Sep 17 00:00:00 2001
|
||||
From: qihao <qihao_yewu@cmss.chinamobile.com>
|
||||
Date: Tue, 20 Aug 2024 09:48:42 +0800
|
||||
Subject: [PATCH] virtio-net: Use virtual time for RSC timers
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cheery-pick from 44bc14fa1e78f01bfddcb265fc41c29204ebbfd8
|
||||
|
||||
Receive coalescing is visible to the target machine, so its timers
|
||||
should use virtual time like other timers in virtio-net, to be
|
||||
compatible with record-replay.
|
||||
|
||||
Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
|
||||
Message-Id: <20240813050638.446172-10-npiggin@gmail.com>
|
||||
Acked-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
|
||||
Message-Id: <20240813202329.1237572-18-alex.bennee@linaro.org>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/net/virtio-net.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
|
||||
index c0a54f2d61..91c1504544 100644
|
||||
--- a/hw/net/virtio-net.c
|
||||
+++ b/hw/net/virtio-net.c
|
||||
@@ -2141,7 +2141,7 @@ static void virtio_net_rsc_purge(void *opq)
|
||||
chain->stat.timer++;
|
||||
if (!QTAILQ_EMPTY(&chain->buffers)) {
|
||||
timer_mod(chain->drain_timer,
|
||||
- qemu_clock_get_ns(QEMU_CLOCK_HOST) + chain->n->rsc_timeout);
|
||||
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + chain->n->rsc_timeout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2377,7 +2377,7 @@ static size_t virtio_net_rsc_do_coalesce(VirtioNetRscChain *chain,
|
||||
chain->stat.empty_cache++;
|
||||
virtio_net_rsc_cache_buf(chain, nc, buf, size);
|
||||
timer_mod(chain->drain_timer,
|
||||
- qemu_clock_get_ns(QEMU_CLOCK_HOST) + chain->n->rsc_timeout);
|
||||
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + chain->n->rsc_timeout);
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -2615,7 +2615,7 @@ static VirtioNetRscChain *virtio_net_rsc_lookup_chain(VirtIONet *n,
|
||||
chain->max_payload = VIRTIO_NET_MAX_IP6_PAYLOAD;
|
||||
chain->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
|
||||
}
|
||||
- chain->drain_timer = timer_new_ns(QEMU_CLOCK_HOST,
|
||||
+ chain->drain_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||
virtio_net_rsc_purge, chain);
|
||||
memset(&chain->stat, 0, sizeof(chain->stat));
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
156
virtio-pci-fix-use-of-a-released-vector.patch
Normal file
156
virtio-pci-fix-use-of-a-released-vector.patch
Normal file
@ -0,0 +1,156 @@
|
||||
From 11e71bc99d8811644ddf1a854e556170bb8f5db3 Mon Sep 17 00:00:00 2001
|
||||
From: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 12 Sep 2024 16:01:04 +0800
|
||||
Subject: [PATCH] virtio-pci: fix use of a released vector
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cherry picked from commit 2ce6cff94df2650c460f809e5ad263f1d22507c0
|
||||
|
||||
During the booting process of the non-standard image, the behavior of the
|
||||
called function in qemu is as follows:
|
||||
|
||||
1. vhost_net_stop() was triggered by guest image. This will call the function
|
||||
virtio_pci_set_guest_notifiers() with assgin= false,
|
||||
virtio_pci_set_guest_notifiers() will release the irqfd for vector 0
|
||||
|
||||
2. virtio_reset() was triggered, this will set configure vector to VIRTIO_NO_VECTOR
|
||||
|
||||
3.vhost_net_start() was called (at this time, the configure vector is
|
||||
still VIRTIO_NO_VECTOR) and then call virtio_pci_set_guest_notifiers() with
|
||||
assgin=true, so the irqfd for vector 0 is still not "init" during this process
|
||||
|
||||
4. The system continues to boot and sets the vector back to 0. After that
|
||||
msix_fire_vector_notifier() was triggered to unmask the vector 0 and meet the crash
|
||||
|
||||
To fix the issue, we need to support changing the vector after VIRTIO_CONFIG_S_DRIVER_OK is set.
|
||||
|
||||
(gdb) bt
|
||||
0 __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0)
|
||||
at pthread_kill.c:44
|
||||
1 0x00007fc87148ec53 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at pthread_kill.c:78
|
||||
2 0x00007fc87143e956 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
|
||||
3 0x00007fc8714287f4 in __GI_abort () at abort.c:79
|
||||
4 0x00007fc87142871b in __assert_fail_base
|
||||
(fmt=0x7fc8715bbde0 "%s%s%s:%u: %s%sAssertion `%s' failed.\n%n", assertion=0x5606413efd53 "ret == 0", file=0x5606413ef87d "../accel/kvm/kvm-all.c", line=1837, function=<optimized out>) at assert.c:92
|
||||
5 0x00007fc871437536 in __GI___assert_fail
|
||||
(assertion=0x5606413efd53 "ret == 0", file=0x5606413ef87d "../accel/kvm/kvm-all.c", line=1837, function=0x5606413f06f0 <__PRETTY_FUNCTION__.19> "kvm_irqchip_commit_routes") at assert.c:101
|
||||
6 0x0000560640f884b5 in kvm_irqchip_commit_routes (s=0x560642cae1f0) at ../accel/kvm/kvm-all.c:1837
|
||||
7 0x0000560640c98f8e in virtio_pci_one_vector_unmask
|
||||
(proxy=0x560643c65f00, queue_no=4294967295, vector=0, msg=..., n=0x560643c6e4c8)
|
||||
at ../hw/virtio/virtio-pci.c:1005
|
||||
8 0x0000560640c99201 in virtio_pci_vector_unmask (dev=0x560643c65f00, vector=0, msg=...)
|
||||
at ../hw/virtio/virtio-pci.c:1070
|
||||
9 0x0000560640bc402e in msix_fire_vector_notifier (dev=0x560643c65f00, vector=0, is_masked=false)
|
||||
at ../hw/pci/msix.c:120
|
||||
10 0x0000560640bc40f1 in msix_handle_mask_update (dev=0x560643c65f00, vector=0, was_masked=true)
|
||||
at ../hw/pci/msix.c:140
|
||||
11 0x0000560640bc4503 in msix_table_mmio_write (opaque=0x560643c65f00, addr=12, val=0, size=4)
|
||||
at ../hw/pci/msix.c:231
|
||||
12 0x0000560640f26d83 in memory_region_write_accessor
|
||||
(mr=0x560643c66540, addr=12, value=0x7fc86b7bc628, size=4, shift=0, mask=4294967295, attrs=...)
|
||||
at ../system/memory.c:497
|
||||
13 0x0000560640f270a6 in access_with_adjusted_size
|
||||
|
||||
(addr=12, value=0x7fc86b7bc628, size=4, access_size_min=1, access_size_max=4, access_fn=0x560640f26c8d <memory_region_write_accessor>, mr=0x560643c66540, attrs=...) at ../system/memory.c:573
|
||||
14 0x0000560640f2a2b5 in memory_region_dispatch_write (mr=0x560643c66540, addr=12, data=0, op=MO_32, attrs=...)
|
||||
at ../system/memory.c:1521
|
||||
15 0x0000560640f37bac in flatview_write_continue
|
||||
(fv=0x7fc65805e0b0, addr=4273803276, attrs=..., ptr=0x7fc871e9c028, len=4, addr1=12, l=4, mr=0x560643c66540)
|
||||
at ../system/physmem.c:2714
|
||||
16 0x0000560640f37d0f in flatview_write
|
||||
(fv=0x7fc65805e0b0, addr=4273803276, attrs=..., buf=0x7fc871e9c028, len=4) at ../system/physmem.c:2756
|
||||
17 0x0000560640f380bf in address_space_write
|
||||
(as=0x560642161ae0 <address_space_memory>, addr=4273803276, attrs=..., buf=0x7fc871e9c028, len=4)
|
||||
at ../system/physmem.c:2863
|
||||
18 0x0000560640f3812c in address_space_rw
|
||||
(as=0x560642161ae0 <address_space_memory>, addr=4273803276, attrs=..., buf=0x7fc871e9c028, len=4, is_write=true) at ../system/physmem.c:2873
|
||||
--Type <RET> for more, q to quit, c to continue without paging--
|
||||
19 0x0000560640f8aa55 in kvm_cpu_exec (cpu=0x560642f205e0) at ../accel/kvm/kvm-all.c:2915
|
||||
20 0x0000560640f8d731 in kvm_vcpu_thread_fn (arg=0x560642f205e0) at ../accel/kvm/kvm-accel-ops.c:51
|
||||
21 0x00005606411949f4 in qemu_thread_start (args=0x560642f292b0) at ../util/qemu-thread-posix.c:541
|
||||
22 0x00007fc87148cdcd in start_thread (arg=<optimized out>) at pthread_create.c:442
|
||||
23 0x00007fc871512630 in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:81
|
||||
(gdb)
|
||||
|
||||
MST: coding style and typo fixups
|
||||
|
||||
Fixes: f9a09ca ("vhost: add support for configure interrupt")
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Signed-off-by: Cindy Lu <lulu@redhat.com>
|
||||
Message-ID: <2321ade5f601367efe7380c04e3f61379c59b48f.1713173550.git.mst@redhat.com>
|
||||
Cc: Lei Yang <leiyang@redhat.com>
|
||||
Cc: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Tested-by: Cindy Lu <lulu@redhat.com>
|
||||
Signed-off-by: Gao Jiazhen <gaojiazhen_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/virtio/virtio-pci.c | 37 +++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 35 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
|
||||
index f8adb0520a..3ad7487411 100644
|
||||
--- a/hw/virtio/virtio-pci.c
|
||||
+++ b/hw/virtio/virtio-pci.c
|
||||
@@ -1456,6 +1456,38 @@ static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy,
|
||||
return offset;
|
||||
}
|
||||
|
||||
+static void virtio_pci_set_vector(VirtIODevice *vdev,
|
||||
+ VirtIOPCIProxy *proxy,
|
||||
+ int queue_no, uint16_t old_vector,
|
||||
+ uint16_t new_vector)
|
||||
+{
|
||||
+ bool kvm_irqfd = (vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
|
||||
+ msix_enabled(&proxy->pci_dev) && kvm_msi_via_irqfd_enabled();
|
||||
+
|
||||
+ if (new_vector == old_vector) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * If the device uses irqfd and the vector changes after DRIVER_OK is
|
||||
+ * set, we need to release the old vector and set up the new one.
|
||||
+ * Otherwise just need to set the new vector on the device.
|
||||
+ */
|
||||
+ if (kvm_irqfd && old_vector != VIRTIO_NO_VECTOR) {
|
||||
+ kvm_virtio_pci_vector_release_one(proxy, queue_no);
|
||||
+ }
|
||||
+ /* Set the new vector on the device. */
|
||||
+ if (queue_no == VIRTIO_CONFIG_IRQ_IDX) {
|
||||
+ vdev->config_vector = new_vector;
|
||||
+ } else {
|
||||
+ virtio_queue_set_vector(vdev, queue_no, new_vector);
|
||||
+ }
|
||||
+ /* If the new vector changed need to set it up. */
|
||||
+ if (kvm_irqfd && new_vector != VIRTIO_NO_VECTOR) {
|
||||
+ kvm_virtio_pci_vector_use_one(proxy, queue_no);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy,
|
||||
uint8_t bar, uint64_t offset, uint64_t length,
|
||||
uint8_t id)
|
||||
@@ -1602,7 +1634,8 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
|
||||
} else {
|
||||
val = VIRTIO_NO_VECTOR;
|
||||
}
|
||||
- vdev->config_vector = val;
|
||||
+ virtio_pci_set_vector(vdev, proxy, VIRTIO_CONFIG_IRQ_IDX,
|
||||
+ vdev->config_vector, val);
|
||||
break;
|
||||
case VIRTIO_PCI_COMMON_STATUS:
|
||||
if (!(val & VIRTIO_CONFIG_S_DRIVER_OK)) {
|
||||
@@ -1642,7 +1675,7 @@ static void virtio_pci_common_write(void *opaque, hwaddr addr,
|
||||
} else {
|
||||
val = VIRTIO_NO_VECTOR;
|
||||
}
|
||||
- virtio_queue_set_vector(vdev, vdev->queue_sel, val);
|
||||
+ virtio_pci_set_vector(vdev, proxy, vdev->queue_sel, vector, val);
|
||||
break;
|
||||
case VIRTIO_PCI_COMMON_Q_ENABLE:
|
||||
if (val == 1) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
41
vvfat-Fix-bug-in-writing-to-middle-of-file.patch
Normal file
41
vvfat-Fix-bug-in-writing-to-middle-of-file.patch
Normal file
@ -0,0 +1,41 @@
|
||||
From db722158867b3b7541ed788b0a0f42a29a839ee4 Mon Sep 17 00:00:00 2001
|
||||
From: qihao <qihao_yewu@cmss.chinamobile.com>
|
||||
Date: Fri, 16 Aug 2024 17:51:45 +0800
|
||||
Subject: [PATCH] vvfat: Fix bug in writing to middle of file
|
||||
|
||||
cheery-pick from b881cf00c99e03bc8a3648581f97736ff275b18b
|
||||
|
||||
Before this commit, the behavior when calling `commit_one_file` for
|
||||
example with `offset=0x2000` (second cluster), what will happen is that
|
||||
we won't fetch the next cluster from the fat, and instead use the first
|
||||
cluster for the read operation.
|
||||
|
||||
This is due to off-by-one error here, where `i=0x2000 !< offset=0x2000`,
|
||||
thus not fetching the next cluster.
|
||||
|
||||
Signed-off-by: Amjad Alsharafi <amjadsharafi10@gmail.com>
|
||||
Reviewed-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Tested-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Message-ID: <b97c1e1f1bc2f776061ae914f95d799d124fcd73.1721470238.git.amjadsharafi10@gmail.com>
|
||||
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
block/vvfat.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/block/vvfat.c b/block/vvfat.c
|
||||
index 9d050ba3ae..9010f3f33f 100644
|
||||
--- a/block/vvfat.c
|
||||
+++ b/block/vvfat.c
|
||||
@@ -2525,7 +2525,7 @@ commit_one_file(BDRVVVFATState* s, int dir_index, uint32_t offset)
|
||||
return -1;
|
||||
}
|
||||
|
||||
- for (i = s->cluster_size; i < offset; i += s->cluster_size)
|
||||
+ for (i = 0; i < offset; i += s->cluster_size)
|
||||
c = modified_fat_get(s, c);
|
||||
|
||||
fd = qemu_open_old(mapping->path, O_RDWR | O_CREAT | O_BINARY, 0666);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user