diff --git a/9pfs-fix-crash-on-Treaddir-request.patch b/9pfs-fix-crash-on-Treaddir-request.patch new file mode 100644 index 0000000000000000000000000000000000000000..160943104c2fb976b5e81cdab5bb2202c74418a9 --- /dev/null +++ b/9pfs-fix-crash-on-Treaddir-request.patch @@ -0,0 +1,64 @@ +From 93e7987cb5a7b33c2d2e0a02b7f310955ca11851 Mon Sep 17 00:00:00 2001 +From: Christian Schoenebeck +Date: Tue, 5 Nov 2024 11:25:26 +0100 +Subject: [PATCH] 9pfs: fix crash on 'Treaddir' request + +A bad (broken or malicious) 9p client (guest) could cause QEMU host to +crash by sending a 9p 'Treaddir' request with a numeric file ID (FID) that +was previously opened for a file instead of an expected directory: + + #0 0x0000762aff8f4919 in __GI___rewinddir (dirp=0xf) at + ../sysdeps/unix/sysv/linux/rewinddir.c:29 + #1 0x0000557b7625fb40 in do_readdir_many (pdu=0x557bb67d2eb0, + fidp=0x557bb67955b0, entries=0x762afe9fff58, offset=0, maxsize=131072, + dostat=) at ../hw/9pfs/codir.c:101 + #2 v9fs_co_readdir_many (pdu=pdu@entry=0x557bb67d2eb0, + fidp=fidp@entry=0x557bb67955b0, entries=entries@entry=0x762afe9fff58, + offset=0, maxsize=131072, dostat=false) at ../hw/9pfs/codir.c:226 + #3 0x0000557b7625c1f9 in v9fs_do_readdir (pdu=0x557bb67d2eb0, + fidp=0x557bb67955b0, offset=, + max_count=) at ../hw/9pfs/9p.c:2488 + #4 v9fs_readdir (opaque=0x557bb67d2eb0) at ../hw/9pfs/9p.c:2602 + +That's because V9fsFidOpenState was declared as union type. So the +same memory region is used for either an open POSIX file handle (int), +or a POSIX DIR* pointer, etc., so 9p server incorrectly used the +previously opened (valid) POSIX file handle (0xf) as DIR* pointer, +eventually causing a crash in glibc's rewinddir() function. + +Root cause was therefore a missing check in 9p server's 'Treaddir' +request handler, which must ensure that the client supplied FID was +really opened as directory stream before trying to access the +aforementioned union and its DIR* member. + +Cc: qemu-stable@nongnu.org +Fixes: d62dbb51f7 ("virtio-9p: Add fidtype so that we can do type ...") +Reported-by: Akihiro Suda +Tested-by: Akihiro Suda +Signed-off-by: Christian Schoenebeck +Reviewed-by: Greg Kurz +Message-Id: +Signed-off-by: Zhongrui Tang +--- + hw/9pfs/9p.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c +index af636cfb2d..9a291d1b51 100644 +--- a/hw/9pfs/9p.c ++++ b/hw/9pfs/9p.c +@@ -2587,6 +2587,11 @@ static void coroutine_fn v9fs_readdir(void *opaque) + retval = -EINVAL; + goto out_nofid; + } ++ if (fidp->fid_type != P9_FID_DIR) { ++ warn_report_once("9p: bad client: T_readdir on non-directory stream"); ++ retval = -ENOTDIR; ++ goto out; ++ } + if (!fidp->fs.dir.stream) { + retval = -EINVAL; + goto out; +-- +2.41.0.windows.1 + diff --git a/accel-tcg-Fix-typo-causing-tb-page_addr-1-to-not-be-.patch b/accel-tcg-Fix-typo-causing-tb-page_addr-1-to-not-be-.patch new file mode 100644 index 0000000000000000000000000000000000000000..382187c5b46eabc3ebfd68b37aa4cd5aee41f38b --- /dev/null +++ b/accel-tcg-Fix-typo-causing-tb-page_addr-1-to-not-be-.patch @@ -0,0 +1,52 @@ +From 378d79fa6b9410af702776ffa93865219f273380 Mon Sep 17 00:00:00 2001 +From: Anton Johansson +Date: Wed, 12 Jun 2024 15:30:31 +0200 +Subject: [PATCH] accel/tcg: Fix typo causing tb->page_addr[1] to not be + recorded +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +For TBs crossing page boundaries, the 2nd page will never be +recorded/removed, as the index of the 2nd page is computed from the +address of the 1st page. This is due to a typo, fix it. + +Cc: qemu-stable@nongnu.org +Fixes: deba78709a ("accel/tcg: Always lock pages before translation") +Signed-off-by: Anton Johansson +Reviewed-by: Manos Pitsidianakis +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alex Bennée +Message-Id: <20240612133031.15298-1-anjo@rev.ng> +Signed-off-by: Richard Henderson +(cherry picked from commit 3b279f73fa37bec8d3ba04a15f5153d6491cffaf) +Signed-off-by: zhujun2 +--- + accel/tcg/tb-maint.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/accel/tcg/tb-maint.c b/accel/tcg/tb-maint.c +index 3d2a896220..eb37f9e8a8 100644 +--- a/accel/tcg/tb-maint.c ++++ b/accel/tcg/tb-maint.c +@@ -712,7 +712,7 @@ static void tb_record(TranslationBlock *tb) + tb_page_addr_t paddr0 = tb_page_addr0(tb); + tb_page_addr_t paddr1 = tb_page_addr1(tb); + tb_page_addr_t pindex0 = paddr0 >> TARGET_PAGE_BITS; +- tb_page_addr_t pindex1 = paddr0 >> TARGET_PAGE_BITS; ++ tb_page_addr_t pindex1 = paddr1 >> TARGET_PAGE_BITS; + + assert(paddr0 != -1); + if (unlikely(paddr1 != -1) && pindex0 != pindex1) { +@@ -744,7 +744,7 @@ static void tb_remove(TranslationBlock *tb) + tb_page_addr_t paddr0 = tb_page_addr0(tb); + tb_page_addr_t paddr1 = tb_page_addr1(tb); + tb_page_addr_t pindex0 = paddr0 >> TARGET_PAGE_BITS; +- tb_page_addr_t pindex1 = paddr0 >> TARGET_PAGE_BITS; ++ tb_page_addr_t pindex1 = paddr1 >> TARGET_PAGE_BITS; + + assert(paddr0 != -1); + if (unlikely(paddr1 != -1) && pindex0 != pindex1) { +-- +2.41.0.windows.1 + diff --git a/exec-memop-Remove-unused-memop_big_endian-helper.patch b/exec-memop-Remove-unused-memop_big_endian-helper.patch new file mode 100644 index 0000000000000000000000000000000000000000..8e4176f089fb555f256d69f2db44542974df04fe --- /dev/null +++ b/exec-memop-Remove-unused-memop_big_endian-helper.patch @@ -0,0 +1,39 @@ +From 9a12c439cb9d1e59175be4b96adf0732dca39db3 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Tue, 12 Nov 2024 13:30:29 +0800 +Subject: [PATCH] exec/memop: Remove unused memop_big_endian() helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 5caa0e1b1bf8597ea7277391b0e17e8584fad18f + +Last use of memop_big_endian() was removed in commit 592134617c9 +("accel/tcg: Reorg system mode store helpers"). + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Thomas Huth +Message-Id: <20241003234211.53644-3-philmd@linaro.org> +Signed-off-by: Zhang Jiao +--- + include/exec/memop.h | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/include/exec/memop.h b/include/exec/memop.h +index a86dc6743a..5b9064819c 100644 +--- a/include/exec/memop.h ++++ b/include/exec/memop.h +@@ -164,10 +164,4 @@ static inline MemOp size_memop(unsigned size) + return ctz32(size); + } + +-/* Big endianness from MemOp. */ +-static inline bool memop_big_endian(MemOp op) +-{ +- return (op & MO_BSWAP) == MO_BE; +-} +- + #endif +-- +2.41.0.windows.1 + diff --git a/hvf-arm-Fix-encodings-for-ID_AA64PFR1_EL1-and-debug-.patch b/hvf-arm-Fix-encodings-for-ID_AA64PFR1_EL1-and-debug-.patch new file mode 100644 index 0000000000000000000000000000000000000000..a7f2fde7e7a2e4eb3fcc03c75e14b678fae74d2c --- /dev/null +++ b/hvf-arm-Fix-encodings-for-ID_AA64PFR1_EL1-and-debug-.patch @@ -0,0 +1,211 @@ +From ab7c657e05f896600c310c74e7584fc345ff235c Mon Sep 17 00:00:00 2001 +From: Zenghui Yu +Date: Thu, 23 May 2024 16:06:19 +0100 +Subject: [PATCH] hvf: arm: Fix encodings for ID_AA64PFR1_EL1 and debug System + registers + +We wrongly encoded ID_AA64PFR1_EL1 using {3,0,0,4,2} in hvf_sreg_match[] so +we fail to get the expected ARMCPRegInfo from cp_regs hash table with the +wrong key. + +Fix it with the correct encoding {3,0,0,4,1}. With that fixed, the Linux +guest can properly detect FEAT_SSBS2 on my M1 HW. + +All DBG{B,W}{V,C}R_EL1 registers are also wrongly encoded with op0 == 14. +It happens to work because HVF_SYSREG(CRn, CRm, 14, op1, op2) equals to +HVF_SYSREG(CRn, CRm, 2, op1, op2), by definition. But we shouldn't rely on +it. + +Cc: qemu-stable@nongnu.org +Fixes: a1477da3ddeb ("hvf: Add Apple Silicon support") +Signed-off-by: Zenghui Yu +Reviewed-by: Alexander Graf +Message-id: 20240503153453.54389-1-zenghui.yu@linux.dev +Signed-off-by: Peter Maydell +(cherry picked from commit 19ed42e8adc87a3c739f61608b66a046bb9237e2) +Signed-off-by: zhujun2 +--- + target/arm/hvf/hvf.c | 160 +++++++++++++++++++++---------------------- + 1 file changed, 80 insertions(+), 80 deletions(-) + +diff --git a/target/arm/hvf/hvf.c b/target/arm/hvf/hvf.c +index b4e98a99e2..d7cc00a084 100644 +--- a/target/arm/hvf/hvf.c ++++ b/target/arm/hvf/hvf.c +@@ -392,85 +392,85 @@ struct hvf_sreg_match { + }; + + static struct hvf_sreg_match hvf_sreg_match[] = { +- { HV_SYS_REG_DBGBVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR0_EL1, HVF_SYSREG(0, 0, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR0_EL1, HVF_SYSREG(0, 0, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR1_EL1, HVF_SYSREG(0, 1, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR1_EL1, HVF_SYSREG(0, 1, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR2_EL1, HVF_SYSREG(0, 2, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR2_EL1, HVF_SYSREG(0, 2, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR3_EL1, HVF_SYSREG(0, 3, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR3_EL1, HVF_SYSREG(0, 3, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR4_EL1, HVF_SYSREG(0, 4, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR4_EL1, HVF_SYSREG(0, 4, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR5_EL1, HVF_SYSREG(0, 5, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR5_EL1, HVF_SYSREG(0, 5, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR6_EL1, HVF_SYSREG(0, 6, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR6_EL1, HVF_SYSREG(0, 6, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR7_EL1, HVF_SYSREG(0, 7, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR7_EL1, HVF_SYSREG(0, 7, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR8_EL1, HVF_SYSREG(0, 8, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR8_EL1, HVF_SYSREG(0, 8, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR9_EL1, HVF_SYSREG(0, 9, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR9_EL1, HVF_SYSREG(0, 9, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR10_EL1, HVF_SYSREG(0, 10, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR10_EL1, HVF_SYSREG(0, 10, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR11_EL1, HVF_SYSREG(0, 11, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR11_EL1, HVF_SYSREG(0, 11, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR12_EL1, HVF_SYSREG(0, 12, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR12_EL1, HVF_SYSREG(0, 12, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR13_EL1, HVF_SYSREG(0, 13, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR13_EL1, HVF_SYSREG(0, 13, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR14_EL1, HVF_SYSREG(0, 14, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR14_EL1, HVF_SYSREG(0, 14, 14, 0, 7) }, +- +- { HV_SYS_REG_DBGBVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 4) }, +- { HV_SYS_REG_DBGBCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 5) }, +- { HV_SYS_REG_DBGWVR15_EL1, HVF_SYSREG(0, 15, 14, 0, 6) }, +- { HV_SYS_REG_DBGWCR15_EL1, HVF_SYSREG(0, 15, 14, 0, 7) }, ++ { HV_SYS_REG_DBGBVR0_EL1, HVF_SYSREG(0, 0, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR0_EL1, HVF_SYSREG(0, 0, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR0_EL1, HVF_SYSREG(0, 0, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR0_EL1, HVF_SYSREG(0, 0, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR1_EL1, HVF_SYSREG(0, 1, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR1_EL1, HVF_SYSREG(0, 1, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR1_EL1, HVF_SYSREG(0, 1, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR1_EL1, HVF_SYSREG(0, 1, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR2_EL1, HVF_SYSREG(0, 2, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR2_EL1, HVF_SYSREG(0, 2, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR2_EL1, HVF_SYSREG(0, 2, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR2_EL1, HVF_SYSREG(0, 2, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR3_EL1, HVF_SYSREG(0, 3, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR3_EL1, HVF_SYSREG(0, 3, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR3_EL1, HVF_SYSREG(0, 3, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR3_EL1, HVF_SYSREG(0, 3, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR4_EL1, HVF_SYSREG(0, 4, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR4_EL1, HVF_SYSREG(0, 4, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR4_EL1, HVF_SYSREG(0, 4, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR4_EL1, HVF_SYSREG(0, 4, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR5_EL1, HVF_SYSREG(0, 5, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR5_EL1, HVF_SYSREG(0, 5, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR5_EL1, HVF_SYSREG(0, 5, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR5_EL1, HVF_SYSREG(0, 5, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR6_EL1, HVF_SYSREG(0, 6, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR6_EL1, HVF_SYSREG(0, 6, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR6_EL1, HVF_SYSREG(0, 6, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR6_EL1, HVF_SYSREG(0, 6, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR7_EL1, HVF_SYSREG(0, 7, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR7_EL1, HVF_SYSREG(0, 7, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR7_EL1, HVF_SYSREG(0, 7, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR7_EL1, HVF_SYSREG(0, 7, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR8_EL1, HVF_SYSREG(0, 8, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR8_EL1, HVF_SYSREG(0, 8, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR8_EL1, HVF_SYSREG(0, 8, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR8_EL1, HVF_SYSREG(0, 8, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR9_EL1, HVF_SYSREG(0, 9, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR9_EL1, HVF_SYSREG(0, 9, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR9_EL1, HVF_SYSREG(0, 9, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR9_EL1, HVF_SYSREG(0, 9, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR10_EL1, HVF_SYSREG(0, 10, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR10_EL1, HVF_SYSREG(0, 10, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR10_EL1, HVF_SYSREG(0, 10, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR10_EL1, HVF_SYSREG(0, 10, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR11_EL1, HVF_SYSREG(0, 11, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR11_EL1, HVF_SYSREG(0, 11, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR11_EL1, HVF_SYSREG(0, 11, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR11_EL1, HVF_SYSREG(0, 11, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR12_EL1, HVF_SYSREG(0, 12, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR12_EL1, HVF_SYSREG(0, 12, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR12_EL1, HVF_SYSREG(0, 12, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR12_EL1, HVF_SYSREG(0, 12, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR13_EL1, HVF_SYSREG(0, 13, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR13_EL1, HVF_SYSREG(0, 13, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR13_EL1, HVF_SYSREG(0, 13, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR13_EL1, HVF_SYSREG(0, 13, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR14_EL1, HVF_SYSREG(0, 14, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR14_EL1, HVF_SYSREG(0, 14, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR14_EL1, HVF_SYSREG(0, 14, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR14_EL1, HVF_SYSREG(0, 14, 2, 0, 7) }, ++ ++ { HV_SYS_REG_DBGBVR15_EL1, HVF_SYSREG(0, 15, 2, 0, 4) }, ++ { HV_SYS_REG_DBGBCR15_EL1, HVF_SYSREG(0, 15, 2, 0, 5) }, ++ { HV_SYS_REG_DBGWVR15_EL1, HVF_SYSREG(0, 15, 2, 0, 6) }, ++ { HV_SYS_REG_DBGWCR15_EL1, HVF_SYSREG(0, 15, 2, 0, 7) }, + + #ifdef SYNC_NO_RAW_REGS + /* +@@ -482,7 +482,7 @@ static struct hvf_sreg_match hvf_sreg_match[] = { + { HV_SYS_REG_MPIDR_EL1, HVF_SYSREG(0, 0, 3, 0, 5) }, + { HV_SYS_REG_ID_AA64PFR0_EL1, HVF_SYSREG(0, 4, 3, 0, 0) }, + #endif +- { HV_SYS_REG_ID_AA64PFR1_EL1, HVF_SYSREG(0, 4, 3, 0, 2) }, ++ { HV_SYS_REG_ID_AA64PFR1_EL1, HVF_SYSREG(0, 4, 3, 0, 1) }, + { HV_SYS_REG_ID_AA64DFR0_EL1, HVF_SYSREG(0, 5, 3, 0, 0) }, + { HV_SYS_REG_ID_AA64DFR1_EL1, HVF_SYSREG(0, 5, 3, 0, 1) }, + { HV_SYS_REG_ID_AA64ISAR0_EL1, HVF_SYSREG(0, 6, 3, 0, 0) }, +-- +2.41.0.windows.1 + diff --git a/hw-arm-mps2-tz.c-fix-RX-TX-interrupts-order.patch b/hw-arm-mps2-tz.c-fix-RX-TX-interrupts-order.patch new file mode 100644 index 0000000000000000000000000000000000000000..aa349bfd331e87b3637b8af6c4e68f63fa41973c --- /dev/null +++ b/hw-arm-mps2-tz.c-fix-RX-TX-interrupts-order.patch @@ -0,0 +1,50 @@ +From 322f39889ff60a6fda87d7d95a6f233efb558e8a Mon Sep 17 00:00:00 2001 +From: Marco Palumbi +Date: Thu, 1 Aug 2024 10:15:02 +0100 +Subject: [PATCH] hw/arm/mps2-tz.c: fix RX/TX interrupts order + +The order of the RX and TX interrupts are swapped. +This commit fixes the order as per the following documents: + * https://developer.arm.com/documentation/dai0505/latest/ + * https://developer.arm.com/documentation/dai0521/latest/ + * https://developer.arm.com/documentation/dai0524/latest/ + * https://developer.arm.com/documentation/dai0547/latest/ + +Cc: qemu-stable@nongnu.org +Signed-off-by: Marco Palumbi +Message-id: 20240730073123.72992-1-marco@palumbi.it +Reviewed-by: Peter Maydell +Signed-off-by: Peter Maydell +(cherry picked from commit 5a558be93ad628e5bed6e0ee062870f49251725c) +Signed-off-by: zhujun2 +--- + hw/arm/mps2-tz.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c +index 668db5ed61..9d9c263ef8 100644 +--- a/hw/arm/mps2-tz.c ++++ b/hw/arm/mps2-tz.c +@@ -435,7 +435,7 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque, + const char *name, hwaddr size, + const int *irqs, const PPCExtraData *extradata) + { +- /* The irq[] array is tx, rx, combined, in that order */ ++ /* The irq[] array is rx, tx, combined, in that order */ + MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms); + CMSDKAPBUART *uart = opaque; + int i = uart - &mms->uart[0]; +@@ -447,8 +447,8 @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque, + qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->apb_periph_frq); + sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal); + s = SYS_BUS_DEVICE(uart); +- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0])); +- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1])); ++ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[1])); ++ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[0])); + sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2)); + sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1)); + sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqs[2])); +-- +2.41.0.windows.1 + diff --git a/hw-i386-add-mem2-option-for-qemu.patch b/hw-i386-add-mem2-option-for-qemu.patch new file mode 100644 index 0000000000000000000000000000000000000000..eef09e89fe4164910e2c667fbd318d867216f02d --- /dev/null +++ b/hw-i386-add-mem2-option-for-qemu.patch @@ -0,0 +1,324 @@ +From d29bc8738131dcaaa1a1ae2870ea29b59a137f30 Mon Sep 17 00:00:00 2001 +From: xiongmengbiao +Date: Wed, 29 May 2024 00:05:44 +0800 +Subject: [PATCH] hw/i386: add mem2 option for qemu + +The '-mem2' option is used to create a set of hugepages +of memory and map them to a fixed address range of the guest. + +This allows some devices to easily obtain continuous host +physical address ranges for performing DMA operations. + +Signed-off-by: xiongmengbiao +--- + hw/i386/pc.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ + include/hw/boards.h | 2 + + qemu-options.hx | 12 +++++ + system/vl.c | 76 ++++++++++++++++++++++++++++ + 4 files changed, 211 insertions(+) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 29b9964733..204e34db86 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -743,6 +743,111 @@ void xen_load_linux(PCMachineState *pcms) + x86ms->fw_cfg = fw_cfg; + } + ++static int try_create_2MB_page(uint32_t page_num) ++{ ++ char nr_hp_num_s[256] = {0}; ++ char free_hp_num_s[256] = {0}; ++ const char *nr_hugepages_dir = "/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages"; ++ const char *free_hugepages_dir = "/sys/kernel/mm/hugepages/hugepages-2048kB/free_hugepages"; ++ int nr_hp_num = -1, free_hp_num = -1, ret = -1; ++ int nr_fd = qemu_open_old(nr_hugepages_dir, O_RDWR); ++ int free_fd = qemu_open_old(free_hugepages_dir, O_RDONLY); ++ ++ if (nr_fd < 0 || free_fd < 0) { ++ error_report("%s: qemu_open failed: %s\n", __func__, strerror(errno)); ++ goto end; ++ } ++ ++ if (read(nr_fd, nr_hp_num_s, 256) < 0) ++ goto end; ++ if (read(free_fd, free_hp_num_s, 256) < 0) ++ goto end; ++ ++ nr_hp_num = atoi(nr_hp_num_s); ++ free_hp_num = atoi(free_hp_num_s); ++ if (nr_hp_num < 0 || free_hp_num < 0) ++ goto end; ++ ++ if (page_num <= free_hp_num) { ++ ret = 0; ++ goto end; ++ } ++ ++ nr_hp_num += (page_num - free_hp_num); ++ snprintf (nr_hp_num_s, 256, "%d", nr_hp_num); ++ if (write(nr_fd, nr_hp_num_s, strlen(nr_hp_num_s)) < 0) ++ goto end; ++ ++ ret = 0; ++end: ++ if (nr_fd >= 0) ++ close(nr_fd); ++ if (free_fd >= 0) ++ close(free_fd); ++ return ret; ++} ++ ++#define HUGEPAGE_NUM_MAX 128 ++#define HUGEPAGE_SIZE (1024*1024*2) ++static void mem2_init(MachineState *ms, MemoryRegion *system_memory) ++{ ++ MemoryRegion *mem2_mr; ++ char mr_name[128] = {0}; ++ void *ram = NULL; ++ int ret = 0, lock_fd; ++ const char *lock_file = "/sys/kernel/mm/hugepages/hugepages-2048kB/nr_overcommit_hugepages"; ++ uint32_t page_num = ms->ram2_size / HUGEPAGE_SIZE, i; ++ ++ if (HUGEPAGE_NUM_MAX < page_num) { ++ error_report("\"-mem2 'size='\" needs to Less than %dM\n", ++ (HUGEPAGE_SIZE * HUGEPAGE_NUM_MAX) / (1024 * 1024)); ++ exit(EXIT_FAILURE); ++ } ++ ++ // Apply for hugepages from OS and use them, which needs to be synchronized ++ lock_fd = qemu_open_old(lock_file, O_WRONLY); ++ if (lock_fd < 0) { ++ error_report("%s: open %s failed: %s\n", __func__, lock_file, strerror(errno)); ++ exit(EXIT_FAILURE); ++ } ++ ++ while (qemu_lock_fd(lock_fd, 0, 0, true)) { ++ if (errno != EACCES && errno != EAGAIN) { ++ error_report("qemu_lock_fd failed: %s\n", strerror(errno)); ++ exit(EXIT_FAILURE); ++ } ++ } ++ ++ /** try to create hugepage. ++ * If there are enough free hugepages, then do nothing. ++ */ ++ ret = try_create_2MB_page(page_num); ++ if (ret) { ++ error_report("%s: Failed to allocate hugepage\n", __func__); ++ goto unlock; ++ } ++ ++ for (i = 0; i < page_num; ++i) { ++ mem2_mr = g_malloc(sizeof(*mem2_mr)); ++ ram = mmap(NULL, HUGEPAGE_SIZE, PROT_READ | PROT_WRITE, ++ MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE | MAP_HUGETLB, -1, 0); ++ if (ram == MAP_FAILED) { ++ error_report("%s: mmap failed: %s", __func__, strerror(errno)); ++ goto unlock; ++ } ++ ++ sprintf(mr_name, "mem2-%d", i); ++ memory_region_init_ram_ptr(mem2_mr, NULL, mr_name, HUGEPAGE_SIZE, ram); ++ memory_region_add_subregion(system_memory, ms->ram2_base + (i * HUGEPAGE_SIZE), mem2_mr); ++ } ++ ++ ret = 0; ++unlock: ++ qemu_unlock_fd(lock_fd, 0, 0); ++ if (ret) ++ exit(EXIT_FAILURE); ++} ++ + #define PC_ROM_MIN_VGA 0xc0000 + #define PC_ROM_MIN_OPTION 0xc8000 + #define PC_ROM_MAX 0xe0000 +@@ -965,6 +1070,22 @@ void pc_memory_init(PCMachineState *pcms, + E820_RAM); + } + ++ if (machine->ram2_size && machine->ram2_base) { ++ if (0x100000000ULL + x86ms->above_4g_mem_size > machine->ram2_base) { ++ error_report("\"-mem2 'base'\" needs to greater 0x%llx\n", ++ 0x100000000ULL + x86ms->above_4g_mem_size); ++ exit(EXIT_FAILURE); ++ } ++ if (machine->ram2_base & (HUGEPAGE_SIZE - 1) || ++ machine->ram2_size & (HUGEPAGE_SIZE - 1)) { ++ error_report("\"-mem2 'base|size'\" needs to aligned to 0x%x\n", HUGEPAGE_SIZE); ++ exit(EXIT_FAILURE); ++ } ++ ++ mem2_init(machine, system_memory); ++ e820_add_entry(machine->ram2_base, machine->ram2_size, E820_RAM); ++ } ++ + if (pcms->sgx_epc.size != 0) { + e820_add_entry(pcms->sgx_epc.base, pcms->sgx_epc.size, E820_RESERVED); + } +diff --git a/include/hw/boards.h b/include/hw/boards.h +index da85f86efb..8ac8cad2a2 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -389,6 +389,8 @@ struct MachineState { + + ram_addr_t ram_size; + ram_addr_t maxram_size; ++ ram_addr_t ram2_base; ++ ram_addr_t ram2_size; + uint64_t ram_slots; + BootConfiguration boot_config; + char *kernel_filename; +diff --git a/qemu-options.hx b/qemu-options.hx +index 42fd09e4de..bc8e66a037 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -5845,6 +5845,18 @@ SRST + (qemu) qom-set /objects/iothread1 poll-max-ns 100000 + ERST + ++DEF("mem2", HAS_ARG, QEMU_OPTION_mem2, ++ "-mem2 base=addr[G],size=n[MG]\n" ++ " Map guest memory using host hugepages\n" ++ " base: starting position of guest physical address\n" ++ " size: the size of mmaped memory\n" ++ "NOTE: Both `base` and `size` need to be aligned according to 2MB\n", ++ QEMU_ARCH_I386) ++SRST ++``-mem2 base=addr[G],size=n[MG]`` ++ Map the host's large page memory at the specified guest address ++ so that some devices can use larger contiguous physical memory. ++ERST + + HXCOMM This is the last statement. Insert new options before this line! + +diff --git a/system/vl.c b/system/vl.c +index 8e3357c578..a1e5e68773 100644 +--- a/system/vl.c ++++ b/system/vl.c +@@ -173,6 +173,8 @@ static QemuPluginList plugin_list = QTAILQ_HEAD_INITIALIZER(plugin_list); + static BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); + static bool nographic = false; + static int mem_prealloc; /* force preallocation of physical target memory */ ++static ram_addr_t ram2_base; ++static ram_addr_t ram2_size; + static const char *vga_model = NULL; + static DisplayOptions dpy; + static int num_serial_hds; +@@ -504,6 +506,23 @@ static QemuOptsList qemu_action_opts = { + }, + }; + ++static QemuOptsList qemu_mem2_opts = { ++ .name = "mem2", ++ .merge_lists = true, ++ .head = QTAILQ_HEAD_INITIALIZER(qemu_mem2_opts.head), ++ .desc = { ++ { ++ .name = "base", ++ .type = QEMU_OPT_SIZE, ++ }, ++ { ++ .name = "size", ++ .type = QEMU_OPT_SIZE, ++ }, ++ { /* end of list */ } ++ }, ++}; ++ + const char *qemu_get_vm_name(void) + { + return qemu_name; +@@ -1932,6 +1951,9 @@ static void qemu_apply_machine_options(QDict *qdict) + { + object_set_properties_from_keyval(OBJECT(current_machine), qdict, false, &error_fatal); + ++ current_machine->ram2_size = ram2_size; ++ current_machine->ram2_base = ram2_base; ++ + if (semihosting_enabled(false) && !semihosting_get_argc()) { + /* fall back to the -kernel/-append */ + semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline); +@@ -2094,11 +2116,57 @@ static void parse_memory_options(void) + loc_pop(&loc); + } + ++static void set_mem2_options(void) ++{ ++ uint64_t sz, base; ++ const char *mem_str; ++ QemuOpts *opts = qemu_find_opts_singleton("mem2"); ++ Location loc; ++ ++ loc_push_none(&loc); ++ qemu_opts_loc_restore(opts); ++ ++ mem_str = qemu_opt_get(opts, "base"); ++ if (mem_str) { ++ if (!*mem_str) { ++ error_report("missing 'base' option value"); ++ exit(EXIT_FAILURE); ++ } ++ ++ base = qemu_opt_get_size(opts, "base", ram2_base); ++ ram2_base = base; ++ } ++ ++ mem_str = qemu_opt_get(opts, "size"); ++ if (mem_str) { ++ if (!*mem_str) { ++ error_report("missing 'base' option value"); ++ exit(EXIT_FAILURE); ++ } ++ ++ sz = qemu_opt_get_size(opts, "size", ram2_size); ++ ram2_size = sz; ++ } ++ ++ if (ram2_base && !ram2_size){ ++ error_report("missing 'size' option value"); ++ exit(EXIT_FAILURE); ++ } ++ if (!ram2_base && ram2_size){ ++ error_report("missing 'base' option value"); ++ exit(EXIT_FAILURE); ++ } ++ ++ loc_pop(&loc); ++} ++ + static void qemu_create_machine(QDict *qdict) + { + MachineClass *machine_class = select_machine(qdict, &error_fatal); + object_set_machine_compat_props(machine_class->compat_props); + ++ set_mem2_options(); ++ + current_machine = MACHINE(object_new_with_class(OBJECT_CLASS(machine_class))); + object_property_add_child(object_get_root(), "machine", + OBJECT(current_machine)); +@@ -2777,6 +2845,7 @@ void qemu_init(int argc, char **argv) + qemu_add_opts(&qemu_semihosting_config_opts); + qemu_add_opts(&qemu_fw_cfg_opts); + qemu_add_opts(&qemu_action_opts); ++ qemu_add_opts(&qemu_mem2_opts); + qemu_add_run_with_opts(); + module_call_init(MODULE_INIT_OPTS); + +@@ -3596,6 +3665,13 @@ void qemu_init(int argc, char **argv) + case QEMU_OPTION_nouserconfig: + /* Nothing to be parsed here. Especially, do not error out below. */ + break; ++ case QEMU_OPTION_mem2: ++ opts = qemu_opts_parse_noisily(qemu_find_opts("mem2"), ++ optarg, false); ++ if (!opts) { ++ exit(EXIT_FAILURE); ++ } ++ break; + #if defined(CONFIG_POSIX) + case QEMU_OPTION_runas: + if (!os_set_runas(optarg)) { +-- +2.41.0.windows.1 + diff --git a/hw-i386-amd_iommu-Don-t-leak-memory-in-amdvi_update_.patch b/hw-i386-amd_iommu-Don-t-leak-memory-in-amdvi_update_.patch new file mode 100644 index 0000000000000000000000000000000000000000..b6e73f02be6b54c61f6cc57d2ff58c1630c98745 --- /dev/null +++ b/hw-i386-amd_iommu-Don-t-leak-memory-in-amdvi_update_.patch @@ -0,0 +1,50 @@ +From 1b0d08faf1daaed39809ed1a3516eaa0f7d61534 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Wed, 31 Jul 2024 18:00:19 +0100 +Subject: [PATCH] hw/i386/amd_iommu: Don't leak memory in amdvi_update_iotlb() + +In amdvi_update_iotlb() we will only put a new entry in the hash +table if to_cache.perm is not IOMMU_NONE. However we allocate the +memory for the new AMDVIIOTLBEntry and for the hash table key +regardless. This means that in the IOMMU_NONE case we will leak the +memory we alloacted. + +Move the allocations into the if() to the point where we know we're +going to add the item to the hash table. + +Cc: qemu-stable@nongnu.org +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2452 +Signed-off-by: Peter Maydell +Message-Id: <20240731170019.3590563-1-peter.maydell@linaro.org> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 9a45b0761628cc59267b3283a85d15294464ac31) +Signed-off-by: zhujun2 +--- + hw/i386/amd_iommu.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/hw/i386/amd_iommu.c b/hw/i386/amd_iommu.c +index 4203144da9..12742b1433 100644 +--- a/hw/i386/amd_iommu.c ++++ b/hw/i386/amd_iommu.c +@@ -346,12 +346,12 @@ static void amdvi_update_iotlb(AMDVIState *s, uint16_t devid, + uint64_t gpa, IOMMUTLBEntry to_cache, + uint16_t domid) + { +- AMDVIIOTLBEntry *entry = g_new(AMDVIIOTLBEntry, 1); +- uint64_t *key = g_new(uint64_t, 1); +- uint64_t gfn = gpa >> AMDVI_PAGE_SHIFT_4K; +- + /* don't cache erroneous translations */ + if (to_cache.perm != IOMMU_NONE) { ++ AMDVIIOTLBEntry *entry = g_new(AMDVIIOTLBEntry, 1); ++ uint64_t *key = g_new(uint64_t, 1); ++ uint64_t gfn = gpa >> AMDVI_PAGE_SHIFT_4K; ++ + trace_amdvi_cache_update(domid, PCI_BUS_NUM(devid), PCI_SLOT(devid), + PCI_FUNC(devid), gpa, to_cache.translated_addr); + +-- +2.41.0.windows.1 + diff --git a/hw-intc-arm_gic-Fix-handling-of-NS-view-of-GICC_APR-.patch b/hw-intc-arm_gic-Fix-handling-of-NS-view-of-GICC_APR-.patch new file mode 100644 index 0000000000000000000000000000000000000000..6f311c4c127e90ee8c38b2c65ff0c5fdce207fa8 --- /dev/null +++ b/hw-intc-arm_gic-Fix-handling-of-NS-view-of-GICC_APR-.patch @@ -0,0 +1,61 @@ +From 20541823659dc78a6a7be427f8fc03ccc58c88d1 Mon Sep 17 00:00:00 2001 +From: Andrey Shumilin +Date: Thu, 23 May 2024 16:06:20 +0100 +Subject: [PATCH] hw/intc/arm_gic: Fix handling of NS view of GICC_APR +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In gic_cpu_read() and gic_cpu_write(), we delegate the handling of +reading and writing the Non-Secure view of the GICC_APR registers +to functions gic_apr_ns_view() and gic_apr_write_ns_view(). +Unfortunately we got the order of the arguments wrong, swapping the +CPU number and the register number (which the compiler doesn't catch +because they're both integers). + +Most guests probably didn't notice this bug because directly +accessing the APR registers is typically something only done by +firmware when it is doing state save for going into a sleep mode. + +Correct the mismatched call arguments. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Cc: qemu-stable@nongnu.org +Fixes: 51fd06e0ee ("hw/intc/arm_gic: Fix handling of GICC_APR, GICC_NSAPR registers") +Signed-off-by: Andrey Shumilin +[PMM: Rewrote commit message] +Signed-off-by: Peter Maydell +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: Alex Bennée +(cherry picked from commit daafa78b297291fea36fb4daeed526705fa7c035) +Signed-off-by: zhujun2 +--- + hw/intc/arm_gic.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c +index dfe7a0a729..f0582f7a49 100644 +--- a/hw/intc/arm_gic.c ++++ b/hw/intc/arm_gic.c +@@ -1663,7 +1663,7 @@ static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset, + *data = s->h_apr[gic_get_vcpu_real_id(cpu)]; + } else if (gic_cpu_ns_access(s, cpu, attrs)) { + /* NS view of GICC_APR is the top half of GIC_NSAPR */ +- *data = gic_apr_ns_view(s, regno, cpu); ++ *data = gic_apr_ns_view(s, cpu, regno); + } else { + *data = s->apr[regno][cpu]; + } +@@ -1751,7 +1751,7 @@ static MemTxResult gic_cpu_write(GICState *s, int cpu, int offset, + s->h_apr[gic_get_vcpu_real_id(cpu)] = value; + } else if (gic_cpu_ns_access(s, cpu, attrs)) { + /* NS view of GICC_APR is the top half of GIC_NSAPR */ +- gic_apr_write_ns_view(s, regno, cpu, value); ++ gic_apr_write_ns_view(s, cpu, regno, value); + } else { + s->apr[regno][cpu] = value; + } +-- +2.41.0.windows.1 + diff --git a/hw-misc-psp-Pin-the-hugepage-memory-specified-by-mem.patch b/hw-misc-psp-Pin-the-hugepage-memory-specified-by-mem.patch new file mode 100644 index 0000000000000000000000000000000000000000..bf29af81203e7e0c9bb6a198cbd9ed14eaf036ca --- /dev/null +++ b/hw-misc-psp-Pin-the-hugepage-memory-specified-by-mem.patch @@ -0,0 +1,212 @@ +From ddaa38853d386e5b9f9fa1c3813048872c8ad687 Mon Sep 17 00:00:00 2001 +From: niuyongwen +Date: Sun, 29 Sep 2024 09:45:15 +0800 +Subject: [PATCH] hw/misc/psp: Pin the hugepage memory specified by mem2 during + use for psp + +Signed-off-by: niuyongwen +--- + hw/misc/psp.c | 138 +++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 121 insertions(+), 17 deletions(-) + +diff --git a/hw/misc/psp.c b/hw/misc/psp.c +index 4eb5ca0e0b..03e8663027 100644 +--- a/hw/misc/psp.c ++++ b/hw/misc/psp.c +@@ -17,6 +17,7 @@ + #include "sysemu/runstate.h" + #include "exec/memory.h" + #include "exec/address-spaces.h" ++#include "exec/ramblock.h" + #include "hw/i386/e820_memory_layout.h" + #include + +@@ -38,6 +39,8 @@ struct PSPDevState { + * the TKM module uses different key spaces based on different vids. + */ + uint32_t vid; ++ /* pinned hugepage numbers */ ++ int hp_num; + }; + + #define PSP_DEV_PATH "/dev/hygon_psp_config" +@@ -45,6 +48,8 @@ struct PSPDevState { + #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) ++#define PSP_IOC_PIN_USER_PAGE _IOWR(HYGON_PSP_IOC_TYPE, 4, NULL) ++#define PSP_IOC_UNPIN_USER_PAGE _IOWR(HYGON_PSP_IOC_TYPE, 5, NULL) + + enum VPSP_DEV_CTRL_OPCODE { + VPSP_OP_VID_ADD, +@@ -69,6 +74,109 @@ struct psp_dev_ctrl { + } __attribute__ ((packed)) data; + }; + ++static MemoryRegion *find_memory_region_by_name(MemoryRegion *root, const char *name) { ++ MemoryRegion *subregion; ++ MemoryRegion *result; ++ ++ if (strcmp(root->name, name) == 0) ++ return root; ++ ++ QTAILQ_FOREACH(subregion, &root->subregions, subregions_link) { ++ result = find_memory_region_by_name(subregion, name); ++ if (result) { ++ return result; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int pin_user_hugepage(int fd, uint64_t vaddr) ++{ ++ int ret; ++ ++ ret = ioctl(fd, PSP_IOC_PIN_USER_PAGE, vaddr); ++ /* 22: Invalid argument, some old kernel doesn't support this ioctl command */ ++ if (ret != 0 && errno == EINVAL) { ++ ret = 0; ++ } ++ return ret; ++} ++ ++static int unpin_user_hugepage(int fd, uint64_t vaddr) ++{ ++ int ret; ++ ++ ret = ioctl(fd, PSP_IOC_UNPIN_USER_PAGE, vaddr); ++ /* 22: Invalid argument, some old kernel doesn't support this ioctl command */ ++ if (ret != 0 && errno == EINVAL) { ++ ret = 0; ++ } ++ return ret; ++} ++ ++static int pin_psp_user_hugepages(struct PSPDevState *state, MemoryRegion *root) ++{ ++ int ret = 0; ++ char mr_name[128] = {0}; ++ int i, pinned_num; ++ MemoryRegion *find_mr = NULL; ++ ++ for (i = 0 ; i < state->hp_num; ++i) { ++ sprintf(mr_name, "mem2-%d", i); ++ find_mr = find_memory_region_by_name(root, mr_name); ++ if (!find_mr) { ++ error_report("fail to find memory region by name %s.", mr_name); ++ ret = -ENOMEM; ++ goto end; ++ } ++ ++ ret = pin_user_hugepage(state->dev_fd, (uint64_t)find_mr->ram_block->host); ++ if (ret) { ++ error_report("fail to pin_user_hugepage, ret: %d.", ret); ++ goto end; ++ } ++ } ++end: ++ if (ret) { ++ pinned_num = i; ++ for (i = 0 ; i < pinned_num; ++i) { ++ sprintf(mr_name, "mem2-%d", i); ++ find_mr = find_memory_region_by_name(root, mr_name); ++ if (!find_mr) { ++ continue; ++ } ++ unpin_user_hugepage(state->dev_fd, (uint64_t)find_mr->ram_block->host); ++ } ++ ++ } ++ return ret; ++} ++ ++static int unpin_psp_user_hugepages(struct PSPDevState *state, MemoryRegion *root) ++{ ++ int ret = 0; ++ char mr_name[128] = {0}; ++ int i; ++ MemoryRegion *find_mr = NULL; ++ ++ for (i = 0 ; i < state->hp_num; ++i) { ++ sprintf(mr_name, "mem2-%d", i); ++ find_mr = find_memory_region_by_name(root, mr_name); ++ if (!find_mr) { ++ continue; ++ } ++ ++ ret = unpin_user_hugepage(state->dev_fd, (uint64_t)find_mr->ram_block->host); ++ if (ret) { ++ error_report("fail to unpin_user_hugepage, ret: %d.", ret); ++ goto end; ++ } ++ } ++end: ++ return ret; ++} ++ + static void psp_dev_destroy(PSPDevState *state) + { + struct psp_dev_ctrl ctrl = { 0 }; +@@ -77,6 +185,11 @@ static void psp_dev_destroy(PSPDevState *state) + 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); ++ } ++ ++ /* Unpin hugepage memory */ ++ if (unpin_psp_user_hugepages(state, get_system_memory())) { ++ error_report("unpin_psp_user_hugepages failed"); + } else { + state->enabled = false; + } +@@ -99,23 +212,6 @@ static void psp_dev_shutdown_notify(Notifier *notifier, void *data) + psp_dev_destroy(state); + } + +-static MemoryRegion *find_memory_region_by_name(MemoryRegion *root, const char *name) { +- MemoryRegion *subregion; +- MemoryRegion *result; +- +- if (strcmp(root->name, name) == 0) +- return root; +- +- QTAILQ_FOREACH(subregion, &root->subregions, subregions_link) { +- result = find_memory_region_by_name(subregion, name); +- if (result) { +- return result; +- } +- } +- +- return NULL; +-} +- + static void psp_dev_realize(DeviceState *dev, Error **errp) + { + int i; +@@ -150,6 +246,8 @@ static void psp_dev_realize(DeviceState *dev, Error **errp) + ram2_end = find_mr->addr + find_mr->size - 1; + } + ++ state->hp_num = i; ++ + if (ram2_start != ram2_end) { + ctrl.op = VPSP_OP_SET_GPA; + ctrl.data.gpa.gpa_start = ram2_start; +@@ -159,6 +257,12 @@ static void psp_dev_realize(DeviceState *dev, Error **errp) + ram2_start, ram2_end, -errno); + goto del_vid; + } ++ ++ /* Pin hugepage memory */ ++ if(pin_psp_user_hugepages(state, root_mr)) { ++ error_setg(errp, "pin_psp_user_hugepages failed."); ++ goto del_vid; ++ } + } + + state->enabled = true; +-- +2.41.0.windows.1 + diff --git a/hw-misc-support-tkm-use-mem2-memory.patch b/hw-misc-support-tkm-use-mem2-memory.patch new file mode 100644 index 0000000000000000000000000000000000000000..eb9329b69776e54184de0f9a809385d1ada32afa --- /dev/null +++ b/hw-misc-support-tkm-use-mem2-memory.patch @@ -0,0 +1,123 @@ +From 884c4d6bc101454f0e0f3c779bc1155024b056c3 Mon Sep 17 00:00:00 2001 +From: xiongmengbiao +Date: Wed, 29 May 2024 15:18:55 +0800 +Subject: [PATCH] hw/misc: support tkm use mem2 memory + +Signed-off-by: xiongmengbiao +--- + hw/misc/psp.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 63 insertions(+), 1 deletion(-) + +diff --git a/hw/misc/psp.c b/hw/misc/psp.c +index 6ff2ceec10..4eb5ca0e0b 100644 +--- a/hw/misc/psp.c ++++ b/hw/misc/psp.c +@@ -15,6 +15,9 @@ + #include "migration/vmstate.h" + #include "hw/qdev-properties.h" + #include "sysemu/runstate.h" ++#include "exec/memory.h" ++#include "exec/address-spaces.h" ++#include "hw/i386/e820_memory_layout.h" + #include + + #define TYPE_PSP_DEV "psp" +@@ -46,14 +49,24 @@ struct PSPDevState { + enum VPSP_DEV_CTRL_OPCODE { + VPSP_OP_VID_ADD, + VPSP_OP_VID_DEL, ++ VPSP_OP_SET_DEFAULT_VID_PERMISSION, ++ VPSP_OP_GET_DEFAULT_VID_PERMISSION, ++ VPSP_OP_SET_GPA, + }; + + struct psp_dev_ctrl { + unsigned char op; ++ unsigned char resv[3]; + union { + unsigned int vid; ++ // Set or check the permissions for the default VID ++ unsigned int def_vid_perm; ++ struct { ++ uint64_t gpa_start; ++ uint64_t gpa_end; ++ } gpa; + unsigned char reserved[128]; +- } data; ++ } __attribute__ ((packed)) data; + }; + + static void psp_dev_destroy(PSPDevState *state) +@@ -86,10 +99,32 @@ static void psp_dev_shutdown_notify(Notifier *notifier, void *data) + psp_dev_destroy(state); + } + ++static MemoryRegion *find_memory_region_by_name(MemoryRegion *root, const char *name) { ++ MemoryRegion *subregion; ++ MemoryRegion *result; ++ ++ if (strcmp(root->name, name) == 0) ++ return root; ++ ++ QTAILQ_FOREACH(subregion, &root->subregions, subregions_link) { ++ result = find_memory_region_by_name(subregion, name); ++ if (result) { ++ return result; ++ } ++ } ++ ++ return NULL; ++} ++ + static void psp_dev_realize(DeviceState *dev, Error **errp) + { ++ int i; ++ char mr_name[128] = {0}; + struct psp_dev_ctrl ctrl = { 0 }; + PSPDevState *state = PSP_DEV(dev); ++ MemoryRegion *root_mr = get_system_memory(); ++ MemoryRegion *find_mr = NULL; ++ uint64_t ram2_start = 0, ram2_end = 0; + + state->dev_fd = qemu_open_old(PSP_DEV_PATH, O_RDWR); + if (state->dev_fd < 0) { +@@ -104,9 +139,36 @@ static void psp_dev_realize(DeviceState *dev, Error **errp) + goto end; + } + ++ for (i = 0 ;; ++i) { ++ sprintf(mr_name, "mem2-%d", i); ++ find_mr = find_memory_region_by_name(root_mr, mr_name); ++ if (!find_mr) ++ break; ++ ++ if (!ram2_start) ++ ram2_start = find_mr->addr; ++ ram2_end = find_mr->addr + find_mr->size - 1; ++ } ++ ++ if (ram2_start != ram2_end) { ++ ctrl.op = VPSP_OP_SET_GPA; ++ ctrl.data.gpa.gpa_start = ram2_start; ++ ctrl.data.gpa.gpa_end = ram2_end; ++ if (ioctl(state->dev_fd, PSP_IOC_VPSP_OPT, &ctrl) < 0) { ++ error_setg(errp, "psp_dev_realize VPSP_OP_SET_GPA (start 0x%lx, end 0x%lx), return %d", ++ ram2_start, ram2_end, -errno); ++ goto del_vid; ++ } ++ } ++ + state->enabled = true; + state->shutdown_notifier.notify = psp_dev_shutdown_notify; + qemu_register_shutdown_notifier(&state->shutdown_notifier); ++ ++ return; ++del_vid: ++ ctrl.op = VPSP_OP_VID_DEL; ++ ioctl(state->dev_fd, PSP_IOC_VPSP_OPT, &ctrl); + end: + return; + } +-- +2.41.0.windows.1 + diff --git a/hw-nvme-fix-handling-of-over-committed-queues.patch b/hw-nvme-fix-handling-of-over-committed-queues.patch new file mode 100644 index 0000000000000000000000000000000000000000..f4db2e75e1dfda31c74779369ff68ddc35a78319 --- /dev/null +++ b/hw-nvme-fix-handling-of-over-committed-queues.patch @@ -0,0 +1,102 @@ +From c4423b70160eb7ae91dac9f2cf61513758ee017d Mon Sep 17 00:00:00 2001 +From: Klaus Jensen +Date: Tue, 29 Oct 2024 13:15:19 +0100 +Subject: [PATCH] hw/nvme: fix handling of over-committed queues + +If a host chooses to use the SQHD "hint" in the CQE to know if there is +room in the submission queue for additional commands, it may result in a +situation where there are not enough internal resources (struct +NvmeRequest) available to process the command. For a lack of a better +term, the host may "over-commit" the device (i.e., it may have more +inflight commands than the queue size). + +For example, assume a queue with N entries. The host submits N commands +and all are picked up for processing, advancing the head and emptying +the queue. Regardless of which of these N commands complete first, the +SQHD field of that CQE will indicate to the host that the queue is +empty, which allows the host to issue N commands again. However, if the +device has not posted CQEs for all the previous commands yet, the device +will have less than N resources available to process the commands, so +queue processing is suspended. + +And here lies an 11 year latent bug. In the absense of any additional +tail updates on the submission queue, we never schedule the processing +bottom-half again unless we observe a head update on an associated full +completion queue. This has been sufficient to handle N-to-1 SQ/CQ setups +(in the absense of over-commit of course). Incidentially, that "kick all +associated SQs" mechanism can now be killed since we now just schedule +queue processing when we return a processing resource to a non-empty +submission queue, which happens to cover both edge cases. However, we +must retain kicking the CQ if it was previously full. + +So, apparently, no previous driver tested with hw/nvme has ever used +SQHD (e.g., neither the Linux NVMe driver or SPDK uses it). But then OSv +shows up with the driver that actually does. I salute you. + +Fixes: f3c507adcd7b ("NVMe: Initial commit for new storage interface") +Cc: qemu-stable@nongnu.org +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2388 +Reported-by: Waldemar Kozaczuk +Reviewed-by: Keith Busch +Signed-off-by: Klaus Jensen +Signed-off-by: Zhongrui Tang +--- + hw/nvme/ctrl.c | 21 ++++++++++++--------- + 1 file changed, 12 insertions(+), 9 deletions(-) + +diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c +index 104aebc5ea..29445938d5 100644 +--- a/hw/nvme/ctrl.c ++++ b/hw/nvme/ctrl.c +@@ -1516,9 +1516,16 @@ static void nvme_post_cqes(void *opaque) + stl_le_p(&n->bar.csts, NVME_CSTS_FAILED); + break; + } ++ + QTAILQ_REMOVE(&cq->req_list, req, entry); ++ + nvme_inc_cq_tail(cq); + nvme_sg_unmap(&req->sg); ++ ++ if (QTAILQ_EMPTY(&sq->req_list) && !nvme_sq_empty(sq)) { ++ qemu_bh_schedule(sq->bh); ++ } ++ + QTAILQ_INSERT_TAIL(&sq->req_list, req, entry); + } + if (cq->tail != cq->head) { +@@ -7575,7 +7582,6 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) + /* Completion queue doorbell write */ + + uint16_t new_head = val & 0xffff; +- int start_sqs; + NvmeCQueue *cq; + + qid = (addr - (0x1000 + (1 << 2))) >> 3; +@@ -7626,18 +7632,15 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val) + + trace_pci_nvme_mmio_doorbell_cq(cq->cqid, new_head); + +- start_sqs = nvme_cq_full(cq) ? 1 : 0; ++ /* scheduled deferred cqe posting if queue was previously full */ ++ if (nvme_cq_full(cq)) { ++ qemu_bh_schedule(cq->bh); ++ } ++ + cq->head = new_head; + if (!qid && n->dbbuf_enabled) { + stl_le_pci_dma(pci, cq->db_addr, cq->head, MEMTXATTRS_UNSPECIFIED); + } +- if (start_sqs) { +- NvmeSQueue *sq; +- QTAILQ_FOREACH(sq, &cq->sq_list, entry) { +- qemu_bh_schedule(sq->bh); +- } +- qemu_bh_schedule(cq->bh); +- } + + if (cq->tail == cq->head) { + if (cq->irq_enabled) { +-- +2.41.0.windows.1 + diff --git a/hw-ppc-e500-Add-missing-device-tree-properties-to-i2.patch b/hw-ppc-e500-Add-missing-device-tree-properties-to-i2.patch new file mode 100644 index 0000000000000000000000000000000000000000..267e5406d5f2bdeb7ed031d1a5f92aeca2964f75 --- /dev/null +++ b/hw-ppc-e500-Add-missing-device-tree-properties-to-i2.patch @@ -0,0 +1,44 @@ +From e025c40fac7d6cc5b4752c392a9c66a074dcaa0b Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Thu, 14 Nov 2024 14:24:58 +0800 +Subject: [PATCH] hw/ppc/e500: Add missing device tree properties to i2c + controller node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from b5d65592d931d07d4f4bcb915d018ec9598058b4 + +When compiling a decompiled device tree blob created with dumpdtb, dtc complains +with: + + /soc@e0000000/i2c@3000: incorrect #address-cells for I2C bus + /soc@e0000000/i2c@3000: incorrect #size-cells for I2C bus + +Fix this by adding the missing device tree properties. + +Reviewed-by: Cédric Le Goater +Signed-off-by: Bernhard Beschow +Message-ID: <20241103133412.73536-6-shentey@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Zhang Jiao +--- + hw/ppc/e500.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c +index 384226296b..8d394d749a 100644 +--- a/hw/ppc/e500.c ++++ b/hw/ppc/e500.c +@@ -203,6 +203,8 @@ static void dt_i2c_create(void *fdt, const char *soc, const char *mpic, + qemu_fdt_setprop_cells(fdt, i2c, "cell-index", 0); + qemu_fdt_setprop_cells(fdt, i2c, "interrupts", irq0, 0x2); + qemu_fdt_setprop_phandle(fdt, i2c, "interrupt-parent", mpic); ++ qemu_fdt_setprop_cell(fdt, i2c, "#size-cells", 0); ++ qemu_fdt_setprop_cell(fdt, i2c, "#address-cells", 1); + qemu_fdt_setprop_string(fdt, "/aliases", alias, i2c); + + g_free(i2c); +-- +2.41.0.windows.1 + diff --git a/hw-ppc-e500-Prefer-QOM-cast.patch b/hw-ppc-e500-Prefer-QOM-cast.patch new file mode 100644 index 0000000000000000000000000000000000000000..3008c3053135b237d600e5dcba2bb030f0094a9b --- /dev/null +++ b/hw-ppc-e500-Prefer-QOM-cast.patch @@ -0,0 +1,44 @@ +From b85c8374d8b78a6ec1c250bb7562423e6f5d89a0 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Thu, 14 Nov 2024 15:12:32 +0800 +Subject: [PATCH] hw/ppc/e500: Prefer QOM cast +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from c620b4ee92ed3664a3d98e0fbb0b651e19fba5b6 + +Reviewed-by: BALATON Zoltan +Signed-off-by: Bernhard Beschow +Message-ID: <20241103133412.73536-4-shentey@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Zhang Jiao +--- + hw/ppc/e500.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c +index 384226296b..df5a20d3ec 100644 +--- a/hw/ppc/e500.c ++++ b/hw/ppc/e500.c +@@ -1024,7 +1024,7 @@ void ppce500_init(MachineState *machine) + sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8544_I2C_IRQ)); + memory_region_add_subregion(ccsr_addr_space, MPC8544_I2C_REGS_OFFSET, + sysbus_mmio_get_region(s, 0)); +- i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); ++ i2c = I2C_BUS(qdev_get_child_bus(dev, "i2c")); + i2c_slave_create_simple(i2c, "ds1338", RTC_REGS_OFFSET); + + /* eSDHC */ +@@ -1073,7 +1073,7 @@ void ppce500_init(MachineState *machine) + memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET, + sysbus_mmio_get_region(s, 0)); + +- pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0"); ++ pci_bus = PCI_BUS(qdev_get_child_bus(dev, "pci.0")); + if (!pci_bus) + printf("couldn't create PCI controller!\n"); + +-- +2.41.0.windows.1 + diff --git a/hw-ppc-e500-Remove-unused-irqs-parameter.patch b/hw-ppc-e500-Remove-unused-irqs-parameter.patch new file mode 100644 index 0000000000000000000000000000000000000000..4b881490ea5c97ba06a82aac8ead470499aea7e2 --- /dev/null +++ b/hw-ppc-e500-Remove-unused-irqs-parameter.patch @@ -0,0 +1,44 @@ +From 239e256d5510b9aaa3e099359dcda54970e2f08a Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Thu, 14 Nov 2024 14:40:02 +0800 +Subject: [PATCH] hw/ppc/e500: Remove unused "irqs" parameter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 2a309354ac5decf78763c9de999bfb42c8612069 + +Reviewed-by: BALATON Zoltan +Signed-off-by: Bernhard Beschow +Message-ID: <20241103133412.73536-5-shentey@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Zhang Jiao +--- + hw/ppc/e500.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c +index 384226296b..8ab1ccc969 100644 +--- a/hw/ppc/e500.c ++++ b/hw/ppc/e500.c +@@ -832,7 +832,7 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500MachineState *pms, + } + + static DeviceState *ppce500_init_mpic_kvm(const PPCE500MachineClass *pmc, +- IrqLines *irqs, Error **errp) ++ Error **errp) + { + #ifdef CONFIG_KVM + DeviceState *dev; +@@ -872,7 +872,7 @@ static DeviceState *ppce500_init_mpic(PPCE500MachineState *pms, + Error *err = NULL; + + if (kvm_kernel_irqchip_allowed()) { +- dev = ppce500_init_mpic_kvm(pmc, irqs, &err); ++ dev = ppce500_init_mpic_kvm(pmc, &err); + } + if (kvm_kernel_irqchip_required() && !dev) { + error_reportf_err(err, +-- +2.41.0.windows.1 + diff --git a/kvm-add-support-for-guest-physical-bits.patch b/kvm-add-support-for-guest-physical-bits.patch new file mode 100644 index 0000000000000000000000000000000000000000..ce70df945a731b337369df0e5c9f63ce67d0974b --- /dev/null +++ b/kvm-add-support-for-guest-physical-bits.patch @@ -0,0 +1,111 @@ +From a2383a2a0537750794223f21156241b1b1e78d2e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 18 Mar 2024 16:53:35 +0100 +Subject: [PATCH] kvm: add support for guest physical bits + +commit 0d08c423688edcca857f88dab20f1fc56de2b281 upstream. + +Query kvm for supported guest physical address bits, in cpuid +function 80000008, eax[23:16]. Usually this is identical to host +physical address bits. With NPT or EPT being used this might be +restricted to 48 (max 4-level paging address space size) even if +the host cpu supports more physical address bits. + +When set pass this to the guest, using cpuid too. Guest firmware +can use this to figure how big the usable guest physical address +space is, so PCI bar mapping are actually reachable. + +Intel-SIG: commit 0d08c423688e kvm: add support for guest physical bits + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Xiaoyao Li +Reviewed-by: Zhao Liu +Message-ID: <20240318155336.156197-2-kraxel@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Jason Zeng +--- + target/i386/kvm/kvm-cpu.c | 50 ++++++++++++++++++++++++++++++++------- + 1 file changed, 42 insertions(+), 8 deletions(-) + +diff --git a/target/i386/kvm/kvm-cpu.c b/target/i386/kvm/kvm-cpu.c +index 9c791b7b05..f76972e47e 100644 +--- a/target/i386/kvm/kvm-cpu.c ++++ b/target/i386/kvm/kvm-cpu.c +@@ -18,10 +18,32 @@ + #include "kvm_i386.h" + #include "hw/core/accel-cpu.h" + ++static void kvm_set_guest_phys_bits(CPUState *cs) ++{ ++ X86CPU *cpu = X86_CPU(cs); ++ uint32_t eax, guest_phys_bits; ++ ++ eax = kvm_arch_get_supported_cpuid(cs->kvm_state, 0x80000008, 0, R_EAX); ++ guest_phys_bits = (eax >> 16) & 0xff; ++ if (!guest_phys_bits) { ++ return; ++ } ++ cpu->guest_phys_bits = guest_phys_bits; ++ if (cpu->guest_phys_bits > cpu->phys_bits) { ++ cpu->guest_phys_bits = cpu->phys_bits; ++ } ++ ++ if (cpu->host_phys_bits && cpu->host_phys_bits_limit && ++ cpu->guest_phys_bits > cpu->host_phys_bits_limit) { ++ cpu->guest_phys_bits = cpu->host_phys_bits_limit; ++ } ++} ++ + static bool kvm_cpu_realizefn(CPUState *cs, Error **errp) + { + X86CPU *cpu = X86_CPU(cs); + CPUX86State *env = &cpu->env; ++ bool ret; + + /* + * The realize order is important, since x86_cpu_realize() checks if +@@ -32,13 +54,15 @@ static bool kvm_cpu_realizefn(CPUState *cs, Error **errp) + * + * realize order: + * +- * x86_cpu_realize(): +- * -> x86_cpu_expand_features() +- * -> cpu_exec_realizefn(): +- * -> accel_cpu_common_realize() +- * kvm_cpu_realizefn() -> host_cpu_realizefn() +- * -> cpu_common_realizefn() +- * -> check/update ucode_rev, phys_bits, mwait ++ * x86_cpu_realizefn(): ++ * x86_cpu_expand_features() ++ * cpu_exec_realizefn(): ++ * accel_cpu_common_realize() ++ * kvm_cpu_realizefn() ++ * host_cpu_realizefn() ++ * kvm_set_guest_phys_bits() ++ * check/update ucode_rev, phys_bits, guest_phys_bits, mwait ++ * cpu_common_realizefn() (via xcc->parent_realize) + */ + if (cpu->max_features) { + if (enable_cpu_pm && kvm_has_waitpkg()) { +@@ -50,7 +74,17 @@ static bool kvm_cpu_realizefn(CPUState *cs, Error **errp) + MSR_IA32_UCODE_REV); + } + } +- return host_cpu_realizefn(cs, errp); ++ ret = host_cpu_realizefn(cs, errp); ++ if (!ret) { ++ return ret; ++ } ++ ++ if ((env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) && ++ cpu->guest_phys_bits == -1) { ++ kvm_set_guest_phys_bits(cs); ++ } ++ ++ return true; + } + + static bool lmce_supported(void) +-- +2.41.0.windows.1 + diff --git a/linux-headers-update-kernel-headers-to-include-CSV3-.patch b/linux-headers-update-kernel-headers-to-include-CSV3-.patch new file mode 100644 index 0000000000000000000000000000000000000000..24af3210ec0e9c202b00518ff8b43998f75630f1 --- /dev/null +++ b/linux-headers-update-kernel-headers-to-include-CSV3-.patch @@ -0,0 +1,79 @@ +From 454079664e1492eeb9b90d1d05598e84dc436f11 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Fri, 17 Jun 2022 09:25:19 +0800 +Subject: [PATCH] linux-headers: update kernel headers to include CSV3 + migration cmds + +Four new migration commands are added to support CSV3 migration. + +KVM_CSV3_SEND_ENCRYPT_DATA/KVM_CSV3_RECEIVE_ENCRYPT_DATA cmds are +used to migrate guest's pages. + +KVM_CSV3_SEND_ENCRYPT_CONTEXT/KVM_CSV3_RECEIVE_ENCRYPT_CONTEXT cmds +are used to migration guest's runtime context. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + linux-headers/linux/kvm.h | 38 ++++++++++++++++++++++++++++++++++++++ + 1 file changed, 38 insertions(+) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 8487d0889b..8543db844e 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -2115,6 +2115,12 @@ enum csv3_cmd_id { + KVM_CSV3_INIT = KVM_CSV3_NR_MIN, + KVM_CSV3_LAUNCH_ENCRYPT_DATA, + KVM_CSV3_LAUNCH_ENCRYPT_VMCB, ++ KVM_CSV3_SEND_ENCRYPT_DATA, ++ KVM_CSV3_SEND_ENCRYPT_CONTEXT, ++ KVM_CSV3_RECEIVE_ENCRYPT_DATA, ++ KVM_CSV3_RECEIVE_ENCRYPT_CONTEXT, ++ ++ KVM_CSV3_NR_MAX, + }; + + struct kvm_csv3_launch_encrypt_data { +@@ -2127,6 +2133,38 @@ struct kvm_csv3_init_data { + __u64 nodemask; + }; + ++struct kvm_csv3_send_encrypt_data { ++ __u64 hdr_uaddr; ++ __u32 hdr_len; ++ __u64 guest_addr_data; ++ __u32 guest_addr_len; ++ __u64 trans_uaddr; ++ __u32 trans_len; ++}; ++ ++struct kvm_csv3_send_encrypt_context { ++ __u64 hdr_uaddr; ++ __u32 hdr_len; ++ __u64 trans_uaddr; ++ __u32 trans_len; ++}; ++ ++struct kvm_csv3_receive_encrypt_data { ++ __u64 hdr_uaddr; ++ __u32 hdr_len; ++ __u64 guest_addr_data; ++ __u32 guest_addr_len; ++ __u64 trans_uaddr; ++ __u32 trans_len; ++}; ++ ++struct kvm_csv3_receive_encrypt_context { ++ __u64 hdr_uaddr; ++ __u32 hdr_len; ++ __u64 trans_uaddr; ++ __u32 trans_len; ++}; ++ + #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) +-- +2.41.0.windows.1 + diff --git a/migration-Fix-file-migration-with-fdset.patch b/migration-Fix-file-migration-with-fdset.patch new file mode 100644 index 0000000000000000000000000000000000000000..f8f9c95aeff5874945ff5ea392239713bf660b34 --- /dev/null +++ b/migration-Fix-file-migration-with-fdset.patch @@ -0,0 +1,65 @@ +From 6c76354fdfbebca55e080fea5ae6bfc8a3db2d91 Mon Sep 17 00:00:00 2001 +From: Fabiano Rosas +Date: Mon, 17 Jun 2024 15:57:17 -0300 +Subject: [PATCH] migration: Fix file migration with fdset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When the "file:" migration support was added we missed the special +case in the qemu_open_old implementation that allows for a particular +file name format to be used to refer to a set of file descriptors that +have been previously provided to QEMU via the add-fd QMP command. + +When using this fdset feature, we should not truncate the migration +file because being given an fd means that the management layer is in +control of the file and will likely already have some data written to +it. This is further indicated by the presence of the 'offset' +argument, which indicates the start of the region where QEMU is +allowed to write. + +Fix the issue by replacing the O_TRUNC flag on open by an ftruncate +call, which will take the offset into consideration. + +Fixes: 385f510df5 ("migration: file URI offset") +Suggested-by: Daniel P. Berrangé +Reviewed-by: Prasad Pandit +Reviewed-by: Peter Xu +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Fabiano Rosas +(cherry picked from commit 6d3279655ac49b806265f08415165f471d33e032) +Signed-off-by: Michael Tokarev +Signed-off-by: zhujun2 +--- + migration/file.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/migration/file.c b/migration/file.c +index 5d4975f43e..fb3f743e54 100644 +--- a/migration/file.c ++++ b/migration/file.c +@@ -46,12 +46,19 @@ void file_start_outgoing_migration(MigrationState *s, + + trace_migration_file_outgoing(filename); + +- fioc = qio_channel_file_new_path(filename, O_CREAT | O_WRONLY | O_TRUNC, +- 0600, errp); ++ fioc = qio_channel_file_new_path(filename, O_CREAT | O_WRONLY, 0600, errp); + if (!fioc) { + return; + } + ++ if (ftruncate(fioc->fd, offset)) { ++ error_setg_errno(errp, errno, ++ "failed to truncate migration file to offset %" PRIx64, ++ offset); ++ object_unref(OBJECT(fioc)); ++ return; ++ } ++ + ioc = QIO_CHANNEL(fioc); + if (offset && qio_channel_io_seek(ioc, offset, SEEK_SET, errp) < 0) { + return; +-- +2.41.0.windows.1 + diff --git a/migration-fix-possible-int-overflow.patch b/migration-fix-possible-int-overflow.patch new file mode 100644 index 0000000000000000000000000000000000000000..71b7875395c9a61be28a4f7e4d27076290d06e1d --- /dev/null +++ b/migration-fix-possible-int-overflow.patch @@ -0,0 +1,35 @@ +From 254c67a88ab54fdfe1eb55d7efaf4386a9597cd0 Mon Sep 17 00:00:00 2001 +From: tangzhongrui +Date: Sat, 16 Nov 2024 17:38:50 +0800 +Subject: [PATCH] migration: fix-possible-int-overflow + +stat64_add() takes uint64_t as 2nd argument, but both +"p->next_packet_size" and "p->packet_len" are uint32_t. +Thus, theyr sum may overflow uint32_t. + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Signed-off-by: Dmitry Frolov +Link: https://lore.kernel.org/r/20241113140509.325732-2-frolov@swemel.ru +Signed-off-by: Peter Xu +Signed-off-by: Zhongrui Tang +--- + migration/multifd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/migration/multifd.c b/migration/multifd.c +index 7d373a245e..f3bf6888c0 100644 +--- a/migration/multifd.c ++++ b/migration/multifd.c +@@ -735,7 +735,7 @@ static void *multifd_send_thread(void *opaque) + } + + stat64_add(&mig_stats.multifd_bytes, +- p->next_packet_size + p->packet_len); ++ (uint64_t)p->next_packet_size + p->packet_len); + p->next_packet_size = 0; + qemu_mutex_lock(&p->mutex); + p->pending_job--; +-- +2.41.0.windows.1 + diff --git a/next-kbd-convert-to-use-qemu_input_handler_register.patch b/next-kbd-convert-to-use-qemu_input_handler_register.patch new file mode 100644 index 0000000000000000000000000000000000000000..5c601fd4064c83ee52cb87554d8a77c194f43b58 --- /dev/null +++ b/next-kbd-convert-to-use-qemu_input_handler_register.patch @@ -0,0 +1,224 @@ +From 91e07a78026caafa181134beeb8c5b79157718ad Mon Sep 17 00:00:00 2001 +From: Mark Cave-Ayland +Date: Wed, 6 Nov 2024 12:09:27 +0000 +Subject: [PATCH] next-kbd: convert to use qemu_input_handler_register() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Convert the next-kbd device from the legacy UI qemu_add_kbd_event_handler() +function to use qemu_input_handler_register(). + +Signed-off-by: Mark Cave-Ayland +Reviewed-by: Thomas Huth +Reviewed-by: Daniel P. Berrangé +Message-ID: <20241106120928.242443-2-mark.cave-ayland@ilande.co.uk> +[thuth: Removed the NEXTKBD_NO_KEY definition - replaced by 0 now] +Signed-off-by: Thomas Huth +Signed-off-by: Zhongrui Tang +--- + hw/m68k/next-kbd.c | 158 +++++++++++++++++++++++++++++---------------- + 1 file changed, 103 insertions(+), 55 deletions(-) + +diff --git a/hw/m68k/next-kbd.c b/hw/m68k/next-kbd.c +index 0c348c18cf..880ebe3602 100644 +--- a/hw/m68k/next-kbd.c ++++ b/hw/m68k/next-kbd.c +@@ -68,7 +68,6 @@ struct NextKBDState { + uint16_t shift; + }; + +-static void queue_code(void *opaque, int code); + + /* lots of magic numbers here */ + static uint32_t kbd_read_byte(void *opaque, hwaddr addr) +@@ -166,68 +165,70 @@ static const MemoryRegionOps kbd_ops = { + .endianness = DEVICE_NATIVE_ENDIAN, + }; + +-static void nextkbd_event(void *opaque, int ch) +-{ +- /* +- * Will want to set vars for caps/num lock +- * if (ch & 0x80) -> key release +- * there's also e0 escaped scancodes that might need to be handled +- */ +- queue_code(opaque, ch); +-} +- +-static const unsigned char next_keycodes[128] = { +- 0x00, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x50, 0x4F, +- 0x4E, 0x1E, 0x1F, 0x20, 0x1D, 0x1C, 0x1B, 0x00, +- 0x42, 0x43, 0x44, 0x45, 0x48, 0x47, 0x46, 0x06, +- 0x07, 0x08, 0x00, 0x00, 0x2A, 0x00, 0x39, 0x3A, +- 0x3B, 0x3C, 0x3D, 0x40, 0x3F, 0x3E, 0x2D, 0x2C, +- 0x2B, 0x26, 0x00, 0x00, 0x31, 0x32, 0x33, 0x34, +- 0x35, 0x37, 0x36, 0x2e, 0x2f, 0x30, 0x00, 0x00, +- 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ++static const int qcode_to_nextkbd_keycode[] = { ++ [Q_KEY_CODE_ESC] = 0x49, ++ [Q_KEY_CODE_1] = 0x4a, ++ [Q_KEY_CODE_2] = 0x4b, ++ [Q_KEY_CODE_3] = 0x4c, ++ [Q_KEY_CODE_4] = 0x4d, ++ [Q_KEY_CODE_5] = 0x50, ++ [Q_KEY_CODE_6] = 0x4f, ++ [Q_KEY_CODE_7] = 0x4e, ++ [Q_KEY_CODE_8] = 0x1e, ++ [Q_KEY_CODE_9] = 0x1f, ++ [Q_KEY_CODE_0] = 0x20, ++ [Q_KEY_CODE_MINUS] = 0x1d, ++ [Q_KEY_CODE_EQUAL] = 0x1c, ++ [Q_KEY_CODE_BACKSPACE] = 0x1b, ++ ++ [Q_KEY_CODE_Q] = 0x42, ++ [Q_KEY_CODE_W] = 0x43, ++ [Q_KEY_CODE_E] = 0x44, ++ [Q_KEY_CODE_R] = 0x45, ++ [Q_KEY_CODE_T] = 0x48, ++ [Q_KEY_CODE_Y] = 0x47, ++ [Q_KEY_CODE_U] = 0x46, ++ [Q_KEY_CODE_I] = 0x06, ++ [Q_KEY_CODE_O] = 0x07, ++ [Q_KEY_CODE_P] = 0x08, ++ [Q_KEY_CODE_RET] = 0x2a, ++ [Q_KEY_CODE_A] = 0x39, ++ [Q_KEY_CODE_S] = 0x3a, ++ ++ [Q_KEY_CODE_D] = 0x3b, ++ [Q_KEY_CODE_F] = 0x3c, ++ [Q_KEY_CODE_G] = 0x3d, ++ [Q_KEY_CODE_H] = 0x40, ++ [Q_KEY_CODE_J] = 0x3f, ++ [Q_KEY_CODE_K] = 0x3e, ++ [Q_KEY_CODE_L] = 0x2d, ++ [Q_KEY_CODE_SEMICOLON] = 0x2c, ++ [Q_KEY_CODE_APOSTROPHE] = 0x2b, ++ [Q_KEY_CODE_GRAVE_ACCENT] = 0x26, ++ [Q_KEY_CODE_Z] = 0x31, ++ [Q_KEY_CODE_X] = 0x32, ++ [Q_KEY_CODE_C] = 0x33, ++ [Q_KEY_CODE_V] = 0x34, ++ ++ [Q_KEY_CODE_B] = 0x35, ++ [Q_KEY_CODE_N] = 0x37, ++ [Q_KEY_CODE_M] = 0x36, ++ [Q_KEY_CODE_COMMA] = 0x2e, ++ [Q_KEY_CODE_DOT] = 0x2f, ++ [Q_KEY_CODE_SLASH] = 0x30, ++ ++ [Q_KEY_CODE_SPC] = 0x38, + }; + +-static void queue_code(void *opaque, int code) ++static void nextkbd_put_keycode(NextKBDState *s, int keycode) + { +- NextKBDState *s = NEXTKBD(opaque); + KBDQueue *q = &s->queue; +- int key = code & KD_KEYMASK; +- int release = code & 0x80; +- static int ext; +- +- if (code == 0xE0) { +- ext = 1; +- } +- +- if (code == 0x2A || code == 0x1D || code == 0x36) { +- if (code == 0x2A) { +- s->shift = KD_LSHIFT; +- } else if (code == 0x36) { +- s->shift = KD_RSHIFT; +- ext = 0; +- } else if (code == 0x1D && !ext) { +- s->shift = KD_LCOMM; +- } else if (code == 0x1D && ext) { +- ext = 0; +- s->shift = KD_RCOMM; +- } +- return; +- } else if (code == (0x2A | 0x80) || code == (0x1D | 0x80) || +- code == (0x36 | 0x80)) { +- s->shift = 0; +- return; +- } + + if (q->count >= KBD_QUEUE_SIZE) { + return; + } + +- q->data[q->wptr] = next_keycodes[key] | release; +- ++ q->data[q->wptr] = keycode; + if (++q->wptr == KBD_QUEUE_SIZE) { + q->wptr = 0; + } +@@ -241,6 +242,53 @@ static void queue_code(void *opaque, int code) + /* s->update_irq(s->update_arg, 1); */ + } + ++static void nextkbd_event(DeviceState *dev, QemuConsole *src, InputEvent *evt) ++{ ++ NextKBDState *s = NEXTKBD(dev); ++ int qcode, keycode; ++ bool key_down = evt->u.key.data->down; ++ ++ qcode = qemu_input_key_value_to_qcode(evt->u.key.data->key); ++ if (qcode >= ARRAY_SIZE(qcode_to_nextkbd_keycode)) { ++ return; ++ } ++ ++ /* Shift key currently has no keycode, so handle separately */ ++ if (qcode == Q_KEY_CODE_SHIFT) { ++ if (key_down) { ++ s->shift |= KD_LSHIFT; ++ } else { ++ s->shift &= ~KD_LSHIFT; ++ } ++ } ++ ++ if (qcode == Q_KEY_CODE_SHIFT_R) { ++ if (key_down) { ++ s->shift |= KD_RSHIFT; ++ } else { ++ s->shift &= ~KD_RSHIFT; ++ } ++ } ++ ++ keycode = qcode_to_nextkbd_keycode[qcode]; ++ if (!keycode) { ++ return; ++ } ++ ++ /* If key release event, create keyboard break code */ ++ if (!key_down) { ++ keycode |= 0x80; ++ } ++ ++ nextkbd_put_keycode(s, keycode); ++} ++ ++static const QemuInputHandler nextkbd_handler = { ++ .name = "QEMU NeXT Keyboard", ++ .mask = INPUT_EVENT_MASK_KEY, ++ .event = nextkbd_event, ++}; ++ + static void nextkbd_reset(DeviceState *dev) + { + NextKBDState *nks = NEXTKBD(dev); +@@ -256,7 +304,7 @@ static void nextkbd_realize(DeviceState *dev, Error **errp) + memory_region_init_io(&s->mr, OBJECT(dev), &kbd_ops, s, "next.kbd", 0x1000); + sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr); + +- qemu_add_kbd_event_handler(nextkbd_event, s); ++ qemu_input_handler_register(dev, &nextkbd_handler); + } + + static const VMStateDescription nextkbd_vmstate = { +-- +2.41.0.windows.1 + diff --git a/qemu-bswap-Undefine-CPU_CONVERT-once-done.patch b/qemu-bswap-Undefine-CPU_CONVERT-once-done.patch new file mode 100644 index 0000000000000000000000000000000000000000..7240ff24b2bf294ded17d3771d3e1267a72076fe --- /dev/null +++ b/qemu-bswap-Undefine-CPU_CONVERT-once-done.patch @@ -0,0 +1,37 @@ +From 4fc36060bec2ac7de500068211b1282c38e3e073 Mon Sep 17 00:00:00 2001 +From: Zhang Jiao +Date: Tue, 12 Nov 2024 14:05:45 +0800 +Subject: [PATCH] qemu/bswap: Undefine CPU_CONVERT() once done +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +cheery-pick from 1d73353f236209e9b5987d7c6b30b2a32b739210 + +Better undefined macros once we are done with them, +like we do few lines later with DO_STN_LDN_P(). + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Thomas Huth +Message-Id: <20241003234211.53644-2-philmd@linaro.org> +Signed-off-by: Zhang Jiao +--- + include/qemu/bswap.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h +index 933a66ee87..49e4944457 100644 +--- a/include/qemu/bswap.h ++++ b/include/qemu/bswap.h +@@ -138,6 +138,8 @@ CPU_CONVERT(le, 16, uint16_t) + CPU_CONVERT(le, 32, uint32_t) + CPU_CONVERT(le, 64, uint64_t) + ++#undef CPU_CONVERT ++ + /* + * Same as cpu_to_le{16,32,64}, except that gcc will figure the result is + * a compile-time constant if you pass in a constant. So this can be +-- +2.41.0.windows.1 + diff --git a/qemu-options-Fix-CXL-Fixed-Memory-Window-interleave-.patch b/qemu-options-Fix-CXL-Fixed-Memory-Window-interleave-.patch new file mode 100644 index 0000000000000000000000000000000000000000..bdc8e67f70e9aca37ee8b2cfc2172822ea46971c --- /dev/null +++ b/qemu-options-Fix-CXL-Fixed-Memory-Window-interleave-.patch @@ -0,0 +1,48 @@ +From 34fc72b12cc4887cb2b551b171f6a76c860b6997 Mon Sep 17 00:00:00 2001 +From: Yuquan Wang +Date: Sun, 7 Apr 2024 16:35:39 +0800 +Subject: [PATCH] qemu-options: Fix CXL Fixed Memory Window + interleave-granularity typo +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Fix the unit typo of interleave-granularity of CXL Fixed Memory +Window in qemu-option.hx. + +Fixes: 03b39fcf64 ("hw/cxl: Make the CFMW a machine parameter.") +Signed-off-by: Yuquan Wang wangyuquan1236@phytium.com.cn +Message-ID: <20240407083539.1488172-2-wangyuquan1236@phytium.com.cn> +[PMD: Reworded] +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit aa88f99c87c0e5d195d6d96190374650553ea61f) +Signed-off-by: zhujun2 +--- + qemu-options.hx | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/qemu-options.hx b/qemu-options.hx +index 9829b1020a..4df4dcea21 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -149,14 +149,14 @@ SRST + platform and configuration dependent. + + ``interleave-granularity=granularity`` sets the granularity of +- interleave. Default 256KiB. Only 256KiB, 512KiB, 1024KiB, 2048KiB +- 4096KiB, 8192KiB and 16384KiB granularities supported. ++ interleave. Default 256 (bytes). Only 256, 512, 1k, 2k, ++ 4k, 8k and 16k granularities supported. + + Example: + + :: + +- -machine cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=128G,cxl-fmw.0.interleave-granularity=512k ++ -machine cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=128G,cxl-fmw.0.interleave-granularity=512 + ERST + + DEF("M", HAS_ARG, QEMU_OPTION_M, +-- +2.41.0.windows.1 + diff --git a/qemu.spec b/qemu.spec index ae2bdd343ba8fcbe93cdb757d75e08e898c4ebe4..316b3062cca3d89ff7c22626f70b6a053b074fff 100644 --- a/qemu.spec +++ b/qemu.spec @@ -3,7 +3,7 @@ Name: qemu Version: 8.2.0 -Release: 25 +Release: 26 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 @@ -441,6 +441,50 @@ Patch0424: target-i386-sev-Add-support-for-reuse-ASID-for-diffe.patch Patch0425: Add-virtCCA-Coda-annotation.patch Patch0426: cvm-Add-support-for-TEE-based-national-encryption-ac.patch Patch0427: hw-arm-virt-Keep-Guest-L1-cache-type-consistent-with.patch +Patch0428: target-i386-add-guest-phys-bits-cpu-property.patch +Patch0429: kvm-add-support-for-guest-physical-bits.patch +Patch0430: hw-i386-add-mem2-option-for-qemu.patch +Patch0431: hw-misc-support-tkm-use-mem2-memory.patch +Patch0432: hw-misc-psp-Pin-the-hugepage-memory-specified-by-mem.patch +Patch0433: 9pfs-fix-crash-on-Treaddir-request.patch +Patch0434: hw-nvme-fix-handling-of-over-committed-queues.patch +Patch0435: exec-memop-Remove-unused-memop_big_endian-helper.patch +Patch0436: qemu-bswap-Undefine-CPU_CONVERT-once-done.patch +Patch0437: next-kbd-convert-to-use-qemu_input_handler_register.patch +Patch0438: target-i386-csv-Add-CSV3-context.patch +Patch0439: target-i386-csv-Add-command-to-initialize-CSV3-conte.patch +Patch0440: target-i386-csv-Add-command-to-load-data-to-CSV3-gue.patch +Patch0441: target-i386-csv-Add-command-to-load-vmcb-to-CSV3-gue.patch +Patch0442: target-i386-cpu-Populate-CPUID-0x8000_001F-when-CSV3.patch +Patch0443: target-i386-csv-Do-not-register-unregister-guest-sec.patch +Patch0444: target-i386-csv-Load-initial-image-to-private-memory.patch +Patch0445: vga-Force-full-update-for-CSV3-guest.patch +Patch0446: vfio-Only-map-shared-region-for-CSV3-virtual-machine.patch +Patch0447: linux-headers-update-kernel-headers-to-include-CSV3-.patch +Patch0448: target-i386-csv-Add-support-to-migrate-the-outgoing-.patch +Patch0449: target-i386-csv-Add-support-to-migrate-the-incoming-.patch +Patch0450: target-i386-csv-Add-support-to-migrate-the-outgoing--new.patch +Patch0451: target-i386-csv-Add-support-to-migrate-the-incoming--new.patch +Patch0452: hw-arm-mps2-tz.c-fix-RX-TX-interrupts-order.patch +Patch0453: hw-i386-amd_iommu-Don-t-leak-memory-in-amdvi_update_.patch +Patch0454: hw-ppc-e500-Add-missing-device-tree-properties-to-i2.patch +Patch0455: hw-ppc-e500-Remove-unused-irqs-parameter.patch +Patch0456: sphinx-qapidoc-Fix-to-generate-doc-for-explicit-unbo.patch +Patch0457: hw-ppc-e500-Prefer-QOM-cast.patch +Patch0458: target-arm-Fix-FJCVTZS-vs-flush-to-zero.patch +Patch0459: ui-vnc-don-t-return-an-empty-SASL-mechlist-to-the-cl.patch +Patch0460: migration-Fix-file-migration-with-fdset.patch +Patch0461: tcg-loongarch64-Fix-tcg_out_movi-vs-some-pcrel-point.patch +Patch0462: accel-tcg-Fix-typo-causing-tb-page_addr-1-to-not-be-.patch +Patch0463: target-riscv-Fix-the-element-agnostic-function-probl.patch +Patch0464: qio-Inherit-follow_coroutine_ctx-across-TLS.patch +Patch0465: hw-intc-arm_gic-Fix-handling-of-NS-view-of-GICC_APR-.patch +Patch0466: hvf-arm-Fix-encodings-for-ID_AA64PFR1_EL1-and-debug-.patch +Patch0467: qemu-options-Fix-CXL-Fixed-Memory-Window-interleave-.patch +Patch0468: target-m68k-Map-FPU-exceptions-to-FPSR-register.patch +Patch0469: migration-fix-possible-int-overflow.patch +Patch0470: tcg-Allow-top-bit-of-SIMD_DATA_BITS-to-be-set-in-sim.patch +Patch0471: vdpa-dev-Fix-initialisation-order-to-restore-VDUSE-c.patch BuildRequires: flex BuildRequires: gcc @@ -1038,6 +1082,52 @@ getent passwd qemu >/dev/null || \ %endif %changelog +* Thu Dec 12 2024 Jiabo Feng - 11:8.2.0-26 +- vdpa-dev: Fix initialisation order to restore VDUSE compatibility +- tcg: Allow top bit of SIMD_DATA_BITS to be set in simd_desc() +- migration: fix-possible-int-overflow +- target/m68k: Map FPU exceptions to FPSR register +- qemu-options: Fix CXL Fixed Memory Window interleave-granularity typo +- hvf: arm: Fix encodings for ID_AA64PFR1_EL1 and debug System registers +- hw/intc/arm_gic: Fix handling of NS view of GICC_APR +- qio: Inherit follow_coroutine_ctx across TLS +- target/riscv: Fix the element agnostic function problem +- accel/tcg: Fix typo causing tb->page_addr[1] to not be recorded +- tcg/loongarch64: Fix tcg_out_movi vs some pcrel pointers +- migration: Fix file migration with fdset +- ui/vnc: don't return an empty SASL mechlist to the client +- target/arm: Fix FJCVTZS vs flush-to-zero +- hw/ppc/e500: Prefer QOM cast +- sphinx/qapidoc: Fix to generate doc for explicit, unboxed arguments +- hw/ppc/e500: Remove unused "irqs" parameter +- hw/ppc/e500: Add missing device tree properties to i2c controller node +- hw/i386/amd_iommu: Don't leak memory in amdvi_update_iotlb() +- hw/arm/mps2-tz.c: fix RX/TX interrupts order +- target/i386: csv: Add support to migrate the incoming context for CSV3 guest +- target/i386: csv: Add support to migrate the outgoing context for CSV3 guest +- target/i386: csv: Add support to migrate the incoming page for CSV3 guest +- target/i386: csv: Add support to migrate the outgoing page for CSV3 guest +- linux-headers: update kernel headers to include CSV3 migration cmds +- vfio: Only map shared region for CSV3 virtual machine +- vga: Force full update for CSV3 guest +- target/i386: csv: Load initial image to private memory for CSV3 guest +- target/i386: csv: Do not register/unregister guest secure memory for CSV3 guest +- target/i386: cpu: Populate CPUID 0x8000_001F when CSV3 is active +- target/i386: csv: Add command to load vmcb to CSV3 guest memory +- target/i386: csv: Add command to load data to CSV3 guest memory +- target/i386: csv: Add command to initialize CSV3 context +- target/i386: csv: Add CSV3 context +- next-kbd: convert to use qemu_input_handler_register() +- qemu/bswap: Undefine CPU_CONVERT() once done +- exec/memop: Remove unused memop_big_endian() helper +- hw/nvme: fix handling of over-committed queues +- 9pfs: fix crash on 'Treaddir' request +- hw/misc/psp: Pin the hugepage memory specified by mem2 during use for psp +- hw/misc: support tkm use mem2 memory +- hw/i386: add mem2 option for qemu +- kvm: add support for guest physical bits +- target/i386: add guest-phys-bits cpu property + * Sat Nov 30 2024 Jiabo Feng - 11:8.2.0-25 - hw/arm/virt:Keep Guest L1 cache type consistent with KVM - cvm : Add support for TEE-based national encryption acceleration. diff --git a/qio-Inherit-follow_coroutine_ctx-across-TLS.patch b/qio-Inherit-follow_coroutine_ctx-across-TLS.patch new file mode 100644 index 0000000000000000000000000000000000000000..81909d57f9eb98f127c98128a2776da8b7a9933c --- /dev/null +++ b/qio-Inherit-follow_coroutine_ctx-across-TLS.patch @@ -0,0 +1,121 @@ +From 4dccc6603af2cd3deefb6ac94c3e7aec4b60485d Mon Sep 17 00:00:00 2001 +From: Eric Blake +Date: Fri, 17 May 2024 21:50:14 -0500 +Subject: [PATCH] qio: Inherit follow_coroutine_ctx across TLS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Since qemu 8.2, the combination of NBD + TLS + iothread crashes on an +assertion failure: + +qemu-kvm: ../io/channel.c:534: void qio_channel_restart_read(void *): Assertion `qemu_get_current_aio_context() == qemu_coroutine_get_aio_context(co)' failed. + +It turns out that when we removed AioContext locking, we did so by +having NBD tell its qio channels that it wanted to opt in to +qio_channel_set_follow_coroutine_ctx(); but while we opted in on the +main channel, we did not opt in on the TLS wrapper channel. +qemu-iotests has coverage of NBD+iothread and NBD+TLS, but apparently +no coverage of NBD+TLS+iothread, or we would have noticed this +regression sooner. (I'll add that in the next patch) + +But while we could manually opt in to the TLS channel in nbd/server.c +(a one-line change), it is more generic if all qio channels that wrap +other channels inherit the follow status, in the same way that they +inherit feature bits. + +CC: Stefan Hajnoczi +CC: Daniel P. Berrangé +CC: qemu-stable@nongnu.org +Fixes: https://issues.redhat.com/browse/RHEL-34786 +Fixes: 06e0f098 ("io: follow coroutine AioContext in qio_channel_yield()", v8.2.0) +Signed-off-by: Eric Blake +Reviewed-by: Stefan Hajnoczi +Reviewed-by: Daniel P. Berrangé +Message-ID: <20240518025246.791593-5-eblake@redhat.com> +(cherry picked from commit 199e84de1c903ba5aa1f7256310bbc4a20dd930b) +Signed-off-by: zhujun2 +--- + io/channel-tls.c | 26 +++++++++++++++----------- + io/channel-websock.c | 1 + + 2 files changed, 16 insertions(+), 11 deletions(-) + +diff --git a/io/channel-tls.c b/io/channel-tls.c +index 58fe1aceee..a8ad89c3d1 100644 +--- a/io/channel-tls.c ++++ b/io/channel-tls.c +@@ -69,37 +69,40 @@ qio_channel_tls_new_server(QIOChannel *master, + const char *aclname, + Error **errp) + { +- QIOChannelTLS *ioc; ++ QIOChannelTLS *tioc; ++ QIOChannel *ioc; + +- ioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS)); ++ tioc = QIO_CHANNEL_TLS(object_new(TYPE_QIO_CHANNEL_TLS)); ++ ioc = QIO_CHANNEL(tioc); + +- ioc->master = master; ++ tioc->master = master; ++ ioc->follow_coroutine_ctx = master->follow_coroutine_ctx; + if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) { +- qio_channel_set_feature(QIO_CHANNEL(ioc), QIO_CHANNEL_FEATURE_SHUTDOWN); ++ qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN); + } + object_ref(OBJECT(master)); + +- ioc->session = qcrypto_tls_session_new( ++ tioc->session = qcrypto_tls_session_new( + creds, + NULL, + aclname, + QCRYPTO_TLS_CREDS_ENDPOINT_SERVER, + errp); +- if (!ioc->session) { ++ if (!tioc->session) { + goto error; + } + + qcrypto_tls_session_set_callbacks( +- ioc->session, ++ tioc->session, + qio_channel_tls_write_handler, + qio_channel_tls_read_handler, +- ioc); ++ tioc); + +- trace_qio_channel_tls_new_server(ioc, master, creds, aclname); +- return ioc; ++ trace_qio_channel_tls_new_server(tioc, master, creds, aclname); ++ return tioc; + + error: +- object_unref(OBJECT(ioc)); ++ object_unref(OBJECT(tioc)); + return NULL; + } + +@@ -116,6 +119,7 @@ qio_channel_tls_new_client(QIOChannel *master, + ioc = QIO_CHANNEL(tioc); + + tioc->master = master; ++ ioc->follow_coroutine_ctx = master->follow_coroutine_ctx; + if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) { + qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN); + } +diff --git a/io/channel-websock.c b/io/channel-websock.c +index a12acc27cf..de39f0d182 100644 +--- a/io/channel-websock.c ++++ b/io/channel-websock.c +@@ -883,6 +883,7 @@ qio_channel_websock_new_server(QIOChannel *master) + ioc = QIO_CHANNEL(wioc); + + wioc->master = master; ++ ioc->follow_coroutine_ctx = master->follow_coroutine_ctx; + if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) { + qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN); + } +-- +2.41.0.windows.1 + diff --git a/sphinx-qapidoc-Fix-to-generate-doc-for-explicit-unbo.patch b/sphinx-qapidoc-Fix-to-generate-doc-for-explicit-unbo.patch new file mode 100644 index 0000000000000000000000000000000000000000..9388ea10dd71baebbe8a516b9234034a202c6c7f --- /dev/null +++ b/sphinx-qapidoc-Fix-to-generate-doc-for-explicit-unbo.patch @@ -0,0 +1,156 @@ +From c7fe47e4aab35c1817c4c53f0025a741a9e2ad57 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Fri, 28 Jun 2024 13:27:56 +0200 +Subject: [PATCH] sphinx/qapidoc: Fix to generate doc for explicit, unboxed + arguments + +When a command's arguments are specified as an explicit type T, +generated documentation points to the members of T. + +Example: + + ## + # @announce-self: + # + # Trigger generation of broadcast RARP frames to update network + [...] + ## + { 'command': 'announce-self', 'boxed': true, + 'data' : 'AnnounceParameters'} + +generates + + "announce-self" (Command) + ------------------------- + + Trigger generation of broadcast RARP frames to update network + [...] + + Arguments + ~~~~~~~~~ + + The members of "AnnounceParameters" + +Except when the command takes its arguments unboxed , i.e. it doesn't +have 'boxed': true, we generate *nothing*. A few commands have a +reference in their doc comment to compensate, but most don't. + +Example: + + ## + # @blockdev-snapshot-sync: + # + # Takes a synchronous snapshot of a block device. + # + # For the arguments, see the documentation of BlockdevSnapshotSync. + [...] + ## + { 'command': 'blockdev-snapshot-sync', + 'data': 'BlockdevSnapshotSync', + 'allow-preconfig': true } + +generates + + "blockdev-snapshot-sync" (Command) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Takes a synchronous snapshot of a block device. + + For the arguments, see the documentation of BlockdevSnapshotSync. + [...] + +Same for event data. + +Fix qapidoc.py to generate the reference regardless of boxing. Delete +now redundant references in the doc comments. + +Fixes: 4078ee5469e5 (docs/sphinx: Add new qapi-doc Sphinx extension) +Cc: qemu-stable@nongnu.org +Signed-off-by: Markus Armbruster +Message-ID: <20240628112756.794237-1-armbru@redhat.com> +Reviewed-by: John Snow +(cherry picked from commit e389929d19a543ea5b34d02553b355f9f1c03162) +Signed-off-by: zhujun2 +--- + docs/sphinx/qapidoc.py | 12 +++++------- + qapi/block-core.json | 7 ------- + 2 files changed, 5 insertions(+), 14 deletions(-) + +diff --git a/docs/sphinx/qapidoc.py b/docs/sphinx/qapidoc.py +index 658c288f8f..3d19853444 100644 +--- a/docs/sphinx/qapidoc.py ++++ b/docs/sphinx/qapidoc.py +@@ -229,15 +229,15 @@ def _nodes_for_enum_values(self, doc): + section += dlnode + return [section] + +- def _nodes_for_arguments(self, doc, boxed_arg_type): ++ def _nodes_for_arguments(self, doc, arg_type): + """Return list of doctree nodes for the arguments section""" +- if boxed_arg_type: ++ if arg_type and not arg_type.is_implicit(): + assert not doc.args + section = self._make_section('Arguments') + dlnode = nodes.definition_list() + dlnode += self._make_dlitem( + [nodes.Text('The members of '), +- nodes.literal('', boxed_arg_type.name)], ++ nodes.literal('', arg_type.name)], + None) + section += dlnode + return [section] +@@ -341,8 +341,7 @@ def visit_command(self, name, info, ifcond, features, arg_type, + allow_preconfig, coroutine): + doc = self._cur_doc + self._add_doc('Command', +- self._nodes_for_arguments(doc, +- arg_type if boxed else None) ++ self._nodes_for_arguments(doc, arg_type) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) +@@ -350,8 +349,7 @@ def visit_command(self, name, info, ifcond, features, arg_type, + def visit_event(self, name, info, ifcond, features, arg_type, boxed): + doc = self._cur_doc + self._add_doc('Event', +- self._nodes_for_arguments(doc, +- arg_type if boxed else None) ++ self._nodes_for_arguments(doc, arg_type) + + self._nodes_for_features(doc) + + self._nodes_for_sections(doc) + + self._nodes_for_if_section(ifcond)) +diff --git a/qapi/block-core.json b/qapi/block-core.json +index ded6f0f6d2..0fa184698a 100644 +--- a/qapi/block-core.json ++++ b/qapi/block-core.json +@@ -1662,8 +1662,6 @@ + # + # Takes a synchronous snapshot of a block device. + # +-# For the arguments, see the documentation of BlockdevSnapshotSync. +-# + # Returns: + # - nothing on success + # - If @device is not a valid block device, DeviceNotFound +@@ -1693,8 +1691,6 @@ + # device, the block device changes to using 'overlay' as its new + # active image. + # +-# For the arguments, see the documentation of BlockdevSnapshot. +-# + # Features: + # + # @allow-write-only-overlay: If present, the check whether this +@@ -6037,9 +6033,6 @@ + # string, or a snapshot with name already exists, the operation will + # fail. + # +-# For the arguments, see the documentation of +-# BlockdevSnapshotInternal. +-# + # Returns: + # - nothing on success + # - If @device is not a valid block device, GenericError +-- +2.41.0.windows.1 + diff --git a/target-arm-Fix-FJCVTZS-vs-flush-to-zero.patch b/target-arm-Fix-FJCVTZS-vs-flush-to-zero.patch new file mode 100644 index 0000000000000000000000000000000000000000..9bd34d7cfed7e7891c3663ddd3f5b058f9db74de --- /dev/null +++ b/target-arm-Fix-FJCVTZS-vs-flush-to-zero.patch @@ -0,0 +1,106 @@ +From 148e01eba8041bad93081a19a240034bb8138988 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Tue, 25 Jun 2024 11:35:26 -0700 +Subject: [PATCH] target/arm: Fix FJCVTZS vs flush-to-zero + +Input denormals cause the Javascript inexact bit +(output to Z) to be set. + +Cc: qemu-stable@nongnu.org +Fixes: 6c1f6f2733a ("target/arm: Implement ARMv8.3-JSConv") +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2375 +Reviewed-by: Peter Maydell +Signed-off-by: Richard Henderson +Message-id: 20240625183536.1672454-4-richard.henderson@linaro.org +[PMM: fixed hardcoded tab in test case] +Signed-off-by: Peter Maydell +(cherry picked from commit 7619129f0d4a14d918227c5c47ad7433662e9ccc) +Signed-off-by: zhujun2 +--- + target/arm/vfp_helper.c | 18 +++++++++--------- + tests/tcg/aarch64/Makefile.target | 3 ++- + tests/tcg/aarch64/test-2375.c | 21 +++++++++++++++++++++ + 3 files changed, 32 insertions(+), 10 deletions(-) + create mode 100644 tests/tcg/aarch64/test-2375.c + +diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c +index 3e5e37abbe..ff59bc5522 100644 +--- a/target/arm/vfp_helper.c ++++ b/target/arm/vfp_helper.c +@@ -1121,8 +1121,8 @@ const FloatRoundMode arm_rmode_to_sf_map[] = { + uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus) + { + float_status *status = vstatus; +- uint32_t inexact, frac; +- uint32_t e_old, e_new; ++ uint32_t frac, e_old, e_new; ++ bool inexact; + + e_old = get_float_exception_flags(status); + set_float_exception_flags(0, status); +@@ -1130,13 +1130,13 @@ uint64_t HELPER(fjcvtzs)(float64 value, void *vstatus) + e_new = get_float_exception_flags(status); + set_float_exception_flags(e_old | e_new, status); + +- if (value == float64_chs(float64_zero)) { +- /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */ +- inexact = 1; +- } else { +- /* Normal inexact or overflow or NaN */ +- inexact = e_new & (float_flag_inexact | float_flag_invalid); +- } ++ /* Normal inexact, denormal with flush-to-zero, or overflow or NaN */ ++ inexact = e_new & (float_flag_inexact | ++ float_flag_input_denormal | ++ float_flag_invalid); ++ ++ /* While not inexact for IEEE FP, -0.0 is inexact for JavaScript. */ ++ inexact |= value == float64_chs(float64_zero); + + /* Pack the result and the env->ZF representation of Z together. */ + return deposit64(frac, 32, 32, inexact); +diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target +index cded1d01fc..6d593c6392 100644 +--- a/tests/tcg/aarch64/Makefile.target ++++ b/tests/tcg/aarch64/Makefile.target +@@ -40,8 +40,9 @@ endif + + # Pauth Tests + ifneq ($(CROSS_CC_HAS_ARMV8_3),) +-AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5 ++AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5 test-2375 + pauth-%: CFLAGS += -march=armv8.3-a ++test-2375: CFLAGS += -march=armv8.3-a + run-pauth-1: QEMU_OPTS += -cpu max + run-pauth-2: QEMU_OPTS += -cpu max + # Choose a cpu with FEAT_Pauth but without FEAT_FPAC for pauth-[45]. +diff --git a/tests/tcg/aarch64/test-2375.c b/tests/tcg/aarch64/test-2375.c +new file mode 100644 +index 0000000000..84c7e7de71 +--- /dev/null ++++ b/tests/tcg/aarch64/test-2375.c +@@ -0,0 +1,21 @@ ++/* SPDX-License-Identifier: GPL-2.0-or-later */ ++/* Copyright (c) 2024 Linaro Ltd */ ++/* See https://gitlab.com/qemu-project/qemu/-/issues/2375 */ ++ ++#include ++ ++int main(void) ++{ ++ int r, z; ++ ++ asm("msr fpcr, %2\n\t" ++ "fjcvtzs %w0, %d3\n\t" ++ "cset %1, eq" ++ : "=r"(r), "=r"(z) ++ : "r"(0x01000000L), /* FZ = 1 */ ++ "w"(0xfcff00L)); /* denormal */ ++ ++ assert(r == 0); ++ assert(z == 0); ++ return 0; ++} +-- +2.41.0.windows.1 + diff --git a/target-i386-add-guest-phys-bits-cpu-property.patch b/target-i386-add-guest-phys-bits-cpu-property.patch new file mode 100644 index 0000000000000000000000000000000000000000..c2f5b0e7e37dfc175f683ffe511f22b551349ed3 --- /dev/null +++ b/target-i386-add-guest-phys-bits-cpu-property.patch @@ -0,0 +1,106 @@ +From b6bfee023b15f25c1db077df7bfd2e9212cda762 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Mon, 18 Mar 2024 16:53:36 +0100 +Subject: [PATCH] target/i386: add guest-phys-bits cpu property + +commit 513ba32dccc659c80722b3a43233b26eaa50309a upstream. + +Allows to set guest-phys-bits (cpuid leaf 80000008, eax[23:16]) +via -cpu $model,guest-phys-bits=$nr. + +Intel-SIG: commit 513ba32dccc6 target/i386: add guest-phys-bits cpu property + +Signed-off-by: Gerd Hoffmann +Message-ID: <20240318155336.156197-3-kraxel@redhat.com> +Reviewed-by: Zhao Liu +Signed-off-by: Paolo Bonzini +[jz: compatible property for 9.0 machines not included] +Signed-off-by: Jason Zeng +--- + target/i386/cpu.c | 22 ++++++++++++++++++++++ + target/i386/cpu.h | 8 ++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index ca7e5337b0..93f88b7bf8 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -6827,6 +6827,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) { + /* 64 bit processor */ + *eax |= (cpu_x86_virtual_addr_width(env) << 8); ++ *eax |= (cpu->guest_phys_bits << 16); + } + *ebx = env->features[FEAT_8000_0008_EBX]; + if (cs->nr_cores * cs->nr_threads > 1) { +@@ -7603,6 +7604,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + goto out; + } + ++ if (cpu->guest_phys_bits == -1) { ++ /* ++ * If it was not set by the user, or by the accelerator via ++ * cpu_exec_realizefn, clear. ++ */ ++ cpu->guest_phys_bits = 0; ++ } ++ + if (cpu->ucode_rev == 0) { + /* + * The default is the same as KVM's. Note that this check +@@ -7653,6 +7662,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + if (cpu->phys_bits == 0) { + cpu->phys_bits = TCG_PHYS_ADDR_BITS; + } ++ if (cpu->guest_phys_bits && ++ (cpu->guest_phys_bits > cpu->phys_bits || ++ cpu->guest_phys_bits < 32)) { ++ error_setg(errp, "guest-phys-bits should be between 32 and %u " ++ " (but is %u)", ++ cpu->phys_bits, cpu->guest_phys_bits); ++ return; ++ } + } else { + /* For 32 bit systems don't use the user set value, but keep + * phys_bits consistent with what we tell the guest. +@@ -7661,6 +7678,10 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + error_setg(errp, "phys-bits is not user-configurable in 32 bit"); + return; + } ++ if (cpu->guest_phys_bits != 0) { ++ error_setg(errp, "guest-phys-bits is not user-configurable in 32 bit"); ++ return; ++ } + + if (env->features[FEAT_1_EDX] & (CPUID_PSE36 | CPUID_PAE)) { + cpu->phys_bits = 36; +@@ -8167,6 +8188,7 @@ static Property x86_cpu_properties[] = { + DEFINE_PROP_BOOL("x-force-features", X86CPU, force_features, false), + DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), + DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0), ++ DEFINE_PROP_UINT32("guest-phys-bits", X86CPU, guest_phys_bits, -1), + DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false), + DEFINE_PROP_UINT8("host-phys-bits-limit", X86CPU, host_phys_bits_limit, 0), + DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, false), +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 34f9615b98..d6fdcc04ca 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -2029,6 +2029,14 @@ struct ArchCPU { + /* Number of physical address bits supported */ + uint32_t phys_bits; + ++ /* ++ * Number of guest physical address bits available. Usually this is ++ * identical to host physical address bits. With NPT or EPT 4-level ++ * paging, guest physical address space might be restricted to 48 bits ++ * even if the host cpu supports more physical address bits. ++ */ ++ uint32_t guest_phys_bits; ++ + /* in order to simplify APIC support, we leave this pointer to the + user */ + struct DeviceState *apic_state; +-- +2.41.0.windows.1 + diff --git a/target-i386-cpu-Populate-CPUID-0x8000_001F-when-CSV3.patch b/target-i386-cpu-Populate-CPUID-0x8000_001F-when-CSV3.patch new file mode 100644 index 0000000000000000000000000000000000000000..73362342ccdc1d967fc44c38d8f07fcc0c4211be --- /dev/null +++ b/target-i386-cpu-Populate-CPUID-0x8000_001F-when-CSV3.patch @@ -0,0 +1,41 @@ +From 120d0b9e5c92de91c69fb9fbea038b51c820013d Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Tue, 24 Aug 2021 17:31:28 +0800 +Subject: [PATCH] target/i386: cpu: Populate CPUID 0x8000_001F when CSV3 is + active + +On Hygon platform, bit 30 of EAX indicates whether +this feature is supported in hardware. + +When CSV3 is active, CPUID 0x8000_001F provides +information for it. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + target/i386/cpu.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index ca7e5337b0..36f7ad6460 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -29,6 +29,7 @@ + #include "hvf/hvf-i386.h" + #include "kvm/kvm_i386.h" + #include "sev.h" ++#include "csv.h" + #include "qapi/error.h" + #include "qemu/error-report.h" + #include "qapi/qapi-visit-machine.h" +@@ -6943,6 +6944,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + if (sev_enabled()) { + *eax = 0x2; + *eax |= sev_es_enabled() ? 0x8 : 0; ++ *eax |= csv3_enabled() ? 0x40000000 : 0; /* bit 30 for CSV3 */ + *ebx = sev_get_cbit_position() & 0x3f; /* EBX[5:0] */ + *ebx |= (sev_get_reduced_phys_bits() & 0x3f) << 6; /* EBX[11:6] */ + } +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Add-CSV3-context.patch b/target-i386-csv-Add-CSV3-context.patch new file mode 100644 index 0000000000000000000000000000000000000000..3e12a6961fcc2cf91cd355457126f59ded87e31b --- /dev/null +++ b/target-i386-csv-Add-CSV3-context.patch @@ -0,0 +1,85 @@ +From 54648e0e5a45acf2e472430ee83bb8dfa057fb30 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Tue, 24 Aug 2021 14:57:28 +0800 +Subject: [PATCH] target/i386: csv: Add CSV3 context + +CSV/CSV2/CSV3 are the secure virtualization features on Hygon CPUs. +The CSV and CSV2 are compatible with the AMD SEV and SEV-ES, +respectively. From CSV3, we introduced more secure features to +protect the guest, users can bit 6 of the guest policy to run a +CSV3 guest. + +Add the context and the build option. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + target/i386/csv.c | 11 +++++++++++ + target/i386/csv.h | 17 +++++++++++++++++ + 2 files changed, 28 insertions(+) + +diff --git a/target/i386/csv.c b/target/i386/csv.c +index 88fb05ac37..9a1de04db7 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -18,3 +18,14 @@ + #include "csv.h" + + bool csv_kvm_cpu_reset_inhibit; ++ ++Csv3GuestState csv3_guest = { 0 }; ++ ++bool ++csv3_enabled(void) ++{ ++ if (!is_hygon_cpu()) ++ return false; ++ ++ return sev_es_enabled() && (csv3_guest.policy & GUEST_POLICY_CSV3_BIT); ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 05e7fd8dc1..ea87c1ba27 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -14,6 +14,9 @@ + #ifndef I386_CSV_H + #define I386_CSV_H + ++#include "qapi/qapi-commands-misc-target.h" ++ ++#define GUEST_POLICY_CSV3_BIT (1 << 6) + #define GUEST_POLICY_REUSE_ASID (1 << 7) + + #ifdef CONFIG_CSV +@@ -40,9 +43,12 @@ static bool __attribute__((unused)) is_hygon_cpu(void) + return false; + } + ++bool csv3_enabled(void); ++ + #else + + #define is_hygon_cpu() (false) ++#define csv3_enabled() (false) + + #endif + +@@ -66,4 +72,15 @@ 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); + ++/* CSV3 */ ++struct Csv3GuestState { ++ uint32_t policy; ++ int sev_fd; ++ void *state; ++}; ++ ++typedef struct Csv3GuestState Csv3GuestState; ++ ++extern struct Csv3GuestState csv3_guest; ++ + #endif +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Add-command-to-initialize-CSV3-conte.patch b/target-i386-csv-Add-command-to-initialize-CSV3-conte.patch new file mode 100644 index 0000000000000000000000000000000000000000..04aea45c55b0be6c1fc10378fad8718c0ca12ec9 --- /dev/null +++ b/target-i386-csv-Add-command-to-initialize-CSV3-conte.patch @@ -0,0 +1,201 @@ +From 4ce59de673b1b190cde76c458ac9e92a6413172d Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 11:07:41 +0800 +Subject: [PATCH] target/i386: csv: Add command to initialize CSV3 context + +When CSV3 is enabled, KVM_CSV3_INIT command is used to initialize +the platform, which is implemented by reusing the SEV API framework +and extending the functionality. + +The KVM_CSV3_INIT command should be performed earlier than +any other command. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + linux-headers/linux/kvm.h | 11 +++++++++ + target/i386/csv-sysemu-stub.c | 5 ++++ + target/i386/csv.c | 45 +++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 4 ++++ + target/i386/sev.c | 17 +++++++++++++ + target/i386/sev.h | 7 ++++++ + 6 files changed, 89 insertions(+) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 8dc00808ec..90869068c8 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -2108,6 +2108,17 @@ struct kvm_csv_init { + __u32 len; + }; + ++/* CSV3 command */ ++enum csv3_cmd_id { ++ KVM_CSV3_NR_MIN = 0xc0, ++ ++ KVM_CSV3_INIT = KVM_CSV3_NR_MIN, ++}; ++ ++struct kvm_csv3_init_data { ++ __u64 nodemask; ++}; ++ + #define KVM_DEV_ASSIGN_ENABLE_IOMMU (1 << 0) + #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) + #define KVM_DEV_ASSIGN_MASK_INTX (1 << 2) +diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c +index 5874e4cc1d..72f0f5c772 100644 +--- a/target/i386/csv-sysemu-stub.c ++++ b/target/i386/csv-sysemu-stub.c +@@ -14,3 +14,8 @@ + #include "qemu/osdep.h" + #include "sev.h" + #include "csv.h" ++ ++int csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) ++{ ++ return 0; ++} +diff --git a/target/i386/csv.c b/target/i386/csv.c +index 9a1de04db7..fd3ea291ca 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -12,6 +12,13 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/error-report.h" ++ ++#include ++ ++#ifdef CONFIG_NUMA ++#include ++#endif + + #include "cpu.h" + #include "sev.h" +@@ -21,6 +28,44 @@ bool csv_kvm_cpu_reset_inhibit; + + Csv3GuestState csv3_guest = { 0 }; + ++int ++csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) ++{ ++ int fw_error; ++ int ret; ++ struct kvm_csv3_init_data data = { 0 }; ++ ++#ifdef CONFIG_NUMA ++ int mode; ++ unsigned long nodemask; ++ ++ /* Set flags as 0 to retrieve the default NUMA policy. */ ++ ret = get_mempolicy(&mode, &nodemask, sizeof(nodemask) * 8, NULL, 0); ++ if (ret == 0 && mode == MPOL_BIND) ++ data.nodemask = nodemask; ++#endif ++ ++ if (!ops || !ops->sev_ioctl || !ops->fw_error_to_str) ++ return -1; ++ ++ csv3_guest.policy = policy; ++ if (csv3_enabled()) { ++ ret = ops->sev_ioctl(fd, KVM_CSV3_INIT, &data, &fw_error); ++ if (ret) { ++ csv3_guest.policy = 0; ++ error_report("%s: Fail to initialize ret=%d fw_error=%d '%s'", ++ __func__, ret, fw_error, ops->fw_error_to_str(fw_error)); ++ return -1; ++ } ++ ++ csv3_guest.sev_fd = fd; ++ csv3_guest.state = state; ++ csv3_guest.sev_ioctl = ops->sev_ioctl; ++ csv3_guest.fw_error_to_str = ops->fw_error_to_str; ++ } ++ return 0; ++} ++ + bool + csv3_enabled(void) + { +diff --git a/target/i386/csv.h b/target/i386/csv.h +index ea87c1ba27..4096e8658b 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -15,6 +15,7 @@ + #define I386_CSV_H + + #include "qapi/qapi-commands-misc-target.h" ++#include "sev.h" + + #define GUEST_POLICY_CSV3_BIT (1 << 6) + #define GUEST_POLICY_REUSE_ASID (1 << 7) +@@ -77,10 +78,13 @@ struct Csv3GuestState { + uint32_t policy; + int sev_fd; + void *state; ++ int (*sev_ioctl)(int fd, int cmd, void *data, int *error); ++ const char *(*fw_error_to_str)(int code); + }; + + typedef struct Csv3GuestState Csv3GuestState; + + extern struct Csv3GuestState csv3_guest; ++extern int csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops); + + #endif +diff --git a/target/i386/sev.c b/target/i386/sev.c +index af61ca5ba8..1c453b3148 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -1225,6 +1225,18 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) + goto err; + } + ++ /* Support CSV3 */ ++ if (!ret && cmd == KVM_SEV_ES_INIT) { ++ ret = csv3_init(sev_guest->policy, sev->sev_fd, (void *)&sev->state, &sev_ops); ++ if (ret) { ++ error_setg(errp, "%s: failed to init csv3 context", __func__); ++ goto err; ++ } ++ /* The CSV3 guest is not resettable */ ++ if (csv3_enabled()) ++ csv_kvm_cpu_reset_inhibit = true; ++ } ++ + /* + * The LAUNCH context is used for new guest, if its an incoming guest + * then RECEIVE context will be created after the connection is established. +@@ -2635,6 +2647,11 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) + return ret; + } + ++struct sev_ops sev_ops = { ++ .sev_ioctl = sev_ioctl, ++ .fw_error_to_str = fw_error_to_str, ++}; ++ + static void + sev_register_types(void) + { +diff --git a/target/i386/sev.h b/target/i386/sev.h +index 0bfe3879ef..e91431e0f7 100644 +--- a/target/i386/sev.h ++++ b/target/i386/sev.h +@@ -80,4 +80,11 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp); + + extern bool sev_kvm_has_msr_ghcb; + ++struct sev_ops { ++ int (*sev_ioctl)(int fd, int cmd, void *data, int *error); ++ const char *(*fw_error_to_str)(int code); ++}; ++ ++extern struct sev_ops sev_ops; ++ + #endif +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Add-command-to-load-data-to-CSV3-gue.patch b/target-i386-csv-Add-command-to-load-data-to-CSV3-gue.patch new file mode 100644 index 0000000000000000000000000000000000000000..3923d48f260fbb623351db24b0ffc55e9d21503a --- /dev/null +++ b/target-i386-csv-Add-command-to-load-data-to-CSV3-gue.patch @@ -0,0 +1,166 @@ +From 53cba8da8fb18cc9a463ec1f57990e8558cd4008 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 09:59:16 +0800 +Subject: [PATCH] target/i386: csv: Add command to load data to CSV3 guest + memory + +The KVM_CSV3_LAUNCH_ENCRYPT_DATA command is used to load data to an +encrypted guest memory in an isolated memory region that guest owns. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + linux-headers/linux/kvm.h | 7 ++++ + target/i386/csv-sysemu-stub.c | 5 +++ + target/i386/csv.c | 69 +++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 2 + + target/i386/trace-events | 3 ++ + 5 files changed, 86 insertions(+) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 90869068c8..dd6d9c2e07 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -2113,6 +2113,13 @@ enum csv3_cmd_id { + KVM_CSV3_NR_MIN = 0xc0, + + KVM_CSV3_INIT = KVM_CSV3_NR_MIN, ++ KVM_CSV3_LAUNCH_ENCRYPT_DATA, ++}; ++ ++struct kvm_csv3_launch_encrypt_data { ++ __u64 gpa; ++ __u64 uaddr; ++ __u32 len; + }; + + struct kvm_csv3_init_data { +diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c +index 72f0f5c772..b0ccbd2f18 100644 +--- a/target/i386/csv-sysemu-stub.c ++++ b/target/i386/csv-sysemu-stub.c +@@ -19,3 +19,8 @@ int csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) + { + return 0; + } ++ ++int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp) ++{ ++ g_assert_not_reached(); ++} +diff --git a/target/i386/csv.c b/target/i386/csv.c +index fd3ea291ca..2a596681b8 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -13,6 +13,7 @@ + + #include "qemu/osdep.h" + #include "qemu/error-report.h" ++#include "qapi/error.h" + + #include + +@@ -20,6 +21,7 @@ + #include + #endif + ++#include "trace.h" + #include "cpu.h" + #include "sev.h" + #include "csv.h" +@@ -74,3 +76,70 @@ csv3_enabled(void) + + return sev_es_enabled() && (csv3_guest.policy & GUEST_POLICY_CSV3_BIT); + } ++ ++static bool ++csv3_check_state(SevState state) ++{ ++ return *((SevState *)csv3_guest.state) == state; ++} ++ ++static int ++csv3_ioctl(int cmd, void *data, int *error) ++{ ++ if (csv3_guest.sev_ioctl) ++ return csv3_guest.sev_ioctl(csv3_guest.sev_fd, cmd, data, error); ++ else ++ return -1; ++} ++ ++static const char * ++fw_error_to_str(int code) ++{ ++ if (csv3_guest.fw_error_to_str) ++ return csv3_guest.fw_error_to_str(code); ++ else ++ return NULL; ++} ++ ++static int ++csv3_launch_encrypt_data(uint64_t gpa, uint8_t *addr, uint64_t len) ++{ ++ int ret, fw_error; ++ struct kvm_csv3_launch_encrypt_data update; ++ ++ if (!addr || !len) { ++ return 1; ++ } ++ ++ update.gpa = (__u64)gpa; ++ update.uaddr = (__u64)(unsigned long)addr; ++ update.len = len; ++ trace_kvm_csv3_launch_encrypt_data(gpa, addr, len); ++ ret = csv3_ioctl(KVM_CSV3_LAUNCH_ENCRYPT_DATA, &update, &fw_error); ++ if (ret) { ++ error_report("%s: CSV3 LAUNCH_ENCRYPT_DATA ret=%d fw_error=%d '%s'", ++ __func__, ret, fw_error, fw_error_to_str(fw_error)); ++ } ++ ++ return ret; ++} ++ ++int ++csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp) ++{ ++ int ret = 0; ++ ++ if (!csv3_enabled()) { ++ error_setg(errp, "%s: CSV3 is not enabled", __func__); ++ return -1; ++ } ++ ++ /* if CSV3 is in update state then load the data to secure memory */ ++ if (csv3_check_state(SEV_STATE_LAUNCH_UPDATE)) { ++ ret = csv3_launch_encrypt_data(gpa, ptr, len); ++ if (ret) ++ error_setg(errp, "%s: CSV3 fail to encrypt data", __func__); ++ } ++ ++ return ret; ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 4096e8658b..27b66f7857 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -87,4 +87,6 @@ typedef struct Csv3GuestState Csv3GuestState; + extern struct Csv3GuestState csv3_guest; + extern int csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops); + ++int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); ++ + #endif +diff --git a/target/i386/trace-events b/target/i386/trace-events +index 87b765c73c..34c205ffda 100644 +--- a/target/i386/trace-events ++++ b/target/i386/trace-events +@@ -19,3 +19,6 @@ kvm_sev_receive_update_data(void *src, void *dst, int len, void *hdr, int hdr_le + 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" ++ ++# csv.c ++kvm_csv3_launch_encrypt_data(uint64_t gpa, void *addr, uint64_t len) "gpa 0x%" PRIx64 "addr %p len 0x%" PRIx64 +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Add-command-to-load-vmcb-to-CSV3-gue.patch b/target-i386-csv-Add-command-to-load-vmcb-to-CSV3-gue.patch new file mode 100644 index 0000000000000000000000000000000000000000..b57c352017b2a96759cf4de143ab6917c0b3982c --- /dev/null +++ b/target-i386-csv-Add-command-to-load-vmcb-to-CSV3-gue.patch @@ -0,0 +1,108 @@ +From 368bf2c044fcdd21f10545de103af7cd2a5986f9 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 12:25:05 +0800 +Subject: [PATCH] target/i386: csv: Add command to load vmcb to CSV3 guest + memory + +The KVM_CSV3_LAUNCH_ENCRYPT_VMCB command is used to load and encrypt +the initial VMCB data to secure memory in an isolated region that +guest owns. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + linux-headers/linux/kvm.h | 1 + + target/i386/csv-sysemu-stub.c | 5 +++++ + target/i386/csv.c | 21 +++++++++++++++++++++ + target/i386/csv.h | 1 + + target/i386/sev.c | 8 ++++++-- + 5 files changed, 34 insertions(+), 2 deletions(-) + +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index dd6d9c2e07..8487d0889b 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -2114,6 +2114,7 @@ enum csv3_cmd_id { + + KVM_CSV3_INIT = KVM_CSV3_NR_MIN, + KVM_CSV3_LAUNCH_ENCRYPT_DATA, ++ KVM_CSV3_LAUNCH_ENCRYPT_VMCB, + }; + + struct kvm_csv3_launch_encrypt_data { +diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c +index b0ccbd2f18..23d885f0f3 100644 +--- a/target/i386/csv-sysemu-stub.c ++++ b/target/i386/csv-sysemu-stub.c +@@ -24,3 +24,8 @@ int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp) + { + g_assert_not_reached(); + } ++ ++int csv3_launch_encrypt_vmcb(void) ++{ ++ g_assert_not_reached(); ++} +diff --git a/target/i386/csv.c b/target/i386/csv.c +index 2a596681b8..12282ba451 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -143,3 +143,24 @@ csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp) + + return ret; + } ++ ++int ++csv3_launch_encrypt_vmcb(void) ++{ ++ int ret, fw_error; ++ ++ if (!csv3_enabled()) { ++ error_report("%s: CSV3 is not enabled", __func__); ++ return -1; ++ } ++ ++ ret = csv3_ioctl(KVM_CSV3_LAUNCH_ENCRYPT_VMCB, NULL, &fw_error); ++ if (ret) { ++ error_report("%s: CSV3 LAUNCH_ENCRYPT_VMCB ret=%d fw_error=%d '%s'", ++ __func__, ret, fw_error, fw_error_to_str(fw_error)); ++ goto err; ++ } ++ ++err: ++ return ret; ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 27b66f7857..3caf216743 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -86,6 +86,7 @@ typedef struct Csv3GuestState Csv3GuestState; + + extern struct Csv3GuestState csv3_guest; + extern int csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops); ++extern int csv3_launch_encrypt_vmcb(void); + + int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); + +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 1c453b3148..6ff8891678 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -880,8 +880,12 @@ sev_launch_get_measure(Notifier *notifier, void *unused) + } + + if (sev_es_enabled()) { +- /* measure all the VM save areas before getting launch_measure */ +- ret = sev_launch_update_vmsa(sev); ++ if (csv3_enabled()) { ++ ret = csv3_launch_encrypt_vmcb(); ++ } else { ++ /* measure all the VM save areas before getting launch_measure */ ++ ret = sev_launch_update_vmsa(sev); ++ } + if (ret) { + exit(1); + } +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Add-support-to-migrate-the-incoming--new.patch b/target-i386-csv-Add-support-to-migrate-the-incoming--new.patch new file mode 100644 index 0000000000000000000000000000000000000000..7990698b08b76233d1f8ccc26f11295ba94d2ab2 --- /dev/null +++ b/target-i386-csv-Add-support-to-migrate-the-incoming--new.patch @@ -0,0 +1,110 @@ +From b31be8b06440deccdf00de2a7886d04fe87dc802 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Fri, 17 Jun 2022 10:00:46 +0800 +Subject: [PATCH] target/i386: csv: Add support to migrate the incoming context + for CSV3 guest + +The csv3_load_incoming_context() provides the method to read incoming +guest's context from socket. It loads them into guest private memory. +This is the last step during migration and RECEIVE FINISH command is +performed by then to complete the whole migration. + +Signed-off-by: Jiang Xin +Signed-off-by: hanliyang +--- + target/i386/csv.c | 45 ++++++++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 1 + + target/i386/trace-events | 1 + + 3 files changed, 47 insertions(+) + +diff --git a/target/i386/csv.c b/target/i386/csv.c +index cc90b57e5b..571beeb61f 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -47,6 +47,7 @@ struct ConfidentialGuestMemoryEncryptionOps csv3_memory_encryption_ops = { + .queue_incoming_page = NULL, + .load_queued_incoming_pages = NULL, + .save_outgoing_cpu_state = csv3_save_outgoing_context, ++ .load_incoming_cpu_state = csv3_load_incoming_context, + }; + + #define CSV3_OUTGOING_PAGE_NUM \ +@@ -644,6 +645,42 @@ err: + return ret; + } + ++static int ++csv3_receive_encrypt_context(Csv3GuestState *s, QEMUFile *f) ++{ ++ int ret = 1, fw_error = 0; ++ gchar *hdr = NULL, *trans = NULL; ++ struct kvm_csv3_receive_encrypt_context update = {}; ++ ++ /* 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 = (uintptr_t)hdr; ++ ++ /* get transport buffer */ ++ update.trans_len = qemu_get_be32(f); ++ ++ 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_csv3_receive_encrypt_context(trans, update.trans_len, hdr, update.hdr_len); ++ ++ ret = csv3_ioctl(KVM_CSV3_RECEIVE_ENCRYPT_CONTEXT, &update, &fw_error); ++ if (ret) { ++ error_report("Error RECEIVE_ENCRYPT_CONTEXT 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 csv3_save_outgoing_context(QEMUFile *f, uint64_t *bytes_sent) + { + Csv3GuestState *s = &csv3_guest; +@@ -651,3 +688,11 @@ int csv3_save_outgoing_context(QEMUFile *f, uint64_t *bytes_sent) + /* send csv3 context. */ + return csv3_send_encrypt_context(s, f, bytes_sent); + } ++ ++int csv3_load_incoming_context(QEMUFile *f) ++{ ++ Csv3GuestState *s = &csv3_guest; ++ ++ /* receive csv3 context. */ ++ return csv3_receive_encrypt_context(s, f); ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 9f83a271fd..8621f0b6fd 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -123,6 +123,7 @@ int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); + int csv3_shared_region_dma_map(uint64_t start, uint64_t end); + void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end); + int csv3_load_incoming_page(QEMUFile *f, uint8_t *ptr); ++int csv3_load_incoming_context(QEMUFile *f); + int csv3_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr); + int csv3_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent); + int csv3_save_outgoing_context(QEMUFile *f, uint64_t *bytes_sent); +diff --git a/target/i386/trace-events b/target/i386/trace-events +index 043412c569..ad3cfb9612 100644 +--- a/target/i386/trace-events ++++ b/target/i386/trace-events +@@ -25,3 +25,4 @@ kvm_csv3_launch_encrypt_data(uint64_t gpa, void *addr, uint64_t len) "gpa 0x%" P + kvm_csv3_send_encrypt_data(void *dst, int len) "trans %p len %d" + kvm_csv3_send_encrypt_context(void *dst, int len) "trans %p len %d" + kvm_csv3_receive_encrypt_data(void *dst, int len, void *hdr, int hdr_len) "trans %p len %d hdr %p hdr_len %d" ++kvm_csv3_receive_encrypt_context(void *dst, int len, void *hdr, int hdr_len) "trans %p len %d hdr %p hdr_len %d" +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Add-support-to-migrate-the-incoming-.patch b/target-i386-csv-Add-support-to-migrate-the-incoming-.patch new file mode 100644 index 0000000000000000000000000000000000000000..53491fbfd32d942487b0428130cb2bf48d18ae02 --- /dev/null +++ b/target-i386-csv-Add-support-to-migrate-the-incoming-.patch @@ -0,0 +1,205 @@ +From 3434042340ca031b6d355cc79dd00e166bd2e2fd Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Fri, 17 Jun 2022 09:45:45 +0800 +Subject: [PATCH] target/i386: csv: Add support to migrate the incoming page + for CSV3 guest + +The csv3_receive_encrypt_data() provides the method to read incoming +guest private pages from socket and load them into guest memory. +The routine is similar to CSV2's. Usually, it starts with a RECEIVE +START command to create the migration context. Then RECEIVE ENCRYPT +DATA command is performed to let the firmware load incoming pages +into guest memory. After migration is completed, a RECEIVE FINISH +command is performed to the firmware. + +Signed-off-by: Jiang Xin +Signed-off-by: hanliyang +--- + target/i386/csv.c | 87 ++++++++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 2 + + target/i386/sev.c | 8 ++++ + target/i386/sev.h | 1 + + target/i386/trace-events | 1 + + 5 files changed, 99 insertions(+) + +diff --git a/target/i386/csv.c b/target/i386/csv.c +index 22e709a95c..ac080b3766 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -38,11 +38,14 @@ bool csv_kvm_cpu_reset_inhibit; + struct ConfidentialGuestMemoryEncryptionOps csv3_memory_encryption_ops = { + .save_setup = sev_save_setup, + .save_outgoing_page = NULL, ++ .load_incoming_page = csv3_load_incoming_page, + .is_gfn_in_unshared_region = NULL, + .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 = csv3_queue_outgoing_page, + .save_queued_outgoing_pages = csv3_save_queued_outgoing_pages, ++ .queue_incoming_page = NULL, ++ .load_queued_incoming_pages = NULL, + }; + + #define CSV3_OUTGOING_PAGE_NUM \ +@@ -89,6 +92,7 @@ csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) + QTAILQ_INIT(&csv3_guest.dma_map_regions_list); + qemu_mutex_init(&csv3_guest.dma_map_regions_list_mutex); + csv3_guest.sev_send_start = ops->sev_send_start; ++ csv3_guest.sev_receive_start = ops->sev_receive_start; + } + return 0; + } +@@ -483,3 +487,86 @@ csv3_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent) + + return csv3_send_encrypt_data(s, f, NULL, 0, bytes_sent); + } ++ ++static int ++csv3_receive_start(QEMUFile *f) ++{ ++ if (csv3_guest.sev_receive_start) ++ return csv3_guest.sev_receive_start(f); ++ else ++ return -1; ++} ++ ++static int csv3_receive_encrypt_data(QEMUFile *f, uint8_t *ptr) ++{ ++ int ret = 1, fw_error = 0; ++ uint32_t i, guest_addr_entry_num; ++ gchar *hdr = NULL, *trans = NULL; ++ struct guest_addr_entry *guest_addr_data; ++ struct kvm_csv3_receive_encrypt_data update = {}; ++ void *hva = NULL; ++ MemoryRegion *mr = NULL; ++ ++ /* 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 = (uintptr_t)hdr; ++ ++ /* get guest addr data */ ++ update.guest_addr_len = qemu_get_be32(f); ++ ++ guest_addr_data = (struct guest_addr_entry *)g_new(gchar, update.guest_addr_len); ++ qemu_get_buffer(f, (uint8_t *)guest_addr_data, update.guest_addr_len); ++ update.guest_addr_data = (uintptr_t)guest_addr_data; ++ ++ /* get transport buffer */ ++ update.trans_len = qemu_get_be32(f); ++ ++ 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 share memory. */ ++ guest_addr_entry_num = update.guest_addr_len / sizeof(struct guest_addr_entry); ++ for (i = 0; i < guest_addr_entry_num; i++) { ++ if (guest_addr_data[i].share) { ++ hva = gpa2hva(&mr, ++ ((uint64_t)guest_addr_data[i].gfn << TARGET_PAGE_BITS), ++ TARGET_PAGE_SIZE, ++ NULL); ++ if (hva) ++ memcpy(hva, trans + i * TARGET_PAGE_SIZE, TARGET_PAGE_SIZE); ++ } ++ } ++ ++ trace_kvm_csv3_receive_encrypt_data(trans, update.trans_len, hdr, update.hdr_len); ++ ++ ret = csv3_ioctl(KVM_CSV3_RECEIVE_ENCRYPT_DATA, &update, &fw_error); ++ if (ret) { ++ error_report("Error RECEIVE_ENCRYPT_DATA ret=%d fw_error=%d '%s'", ++ ret, fw_error, fw_error_to_str(fw_error)); ++ goto err; ++ } ++ ++err: ++ g_free(trans); ++ g_free(guest_addr_data); ++ g_free(hdr); ++ return ret; ++} ++ ++int csv3_load_incoming_page(QEMUFile *f, uint8_t *ptr) ++{ ++ /* ++ * If this is first buffer and SEV is not in recieiving state then ++ * use RECEIVE_START command to create a encryption context. ++ */ ++ if (!csv3_check_state(SEV_STATE_RECEIVE_UPDATE) && ++ csv3_receive_start(f)) { ++ return 1; ++ } ++ ++ return csv3_receive_encrypt_data(f, ptr); ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 12c1b22659..afcd59180c 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -108,6 +108,7 @@ struct Csv3GuestState { + size_t guest_addr_len; + + int (*sev_send_start)(QEMUFile *f, uint64_t *bytes_sent); ++ int (*sev_receive_start)(QEMUFile *f); + }; + + typedef struct Csv3GuestState Csv3GuestState; +@@ -121,6 +122,7 @@ int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); + + int csv3_shared_region_dma_map(uint64_t start, uint64_t end); + void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end); ++int csv3_load_incoming_page(QEMUFile *f, uint8_t *ptr); + int csv3_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr); + int csv3_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent); + +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 5a96b0b452..5124bf3dee 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -2665,10 +2665,18 @@ static int _sev_send_start(QEMUFile *f, uint64_t *bytes_sent) + return sev_send_start(s, f, bytes_sent); + } + ++static int _sev_receive_start(QEMUFile *f) ++{ ++ SevGuestState *s = sev_guest; ++ ++ return sev_receive_start(s, f); ++} ++ + struct sev_ops sev_ops = { + .sev_ioctl = sev_ioctl, + .fw_error_to_str = fw_error_to_str, + .sev_send_start = _sev_send_start, ++ .sev_receive_start = _sev_receive_start, + }; + + static void +diff --git a/target/i386/sev.h b/target/i386/sev.h +index 8ccef22a95..647b426b16 100644 +--- a/target/i386/sev.h ++++ b/target/i386/sev.h +@@ -84,6 +84,7 @@ struct sev_ops { + int (*sev_ioctl)(int fd, int cmd, void *data, int *error); + const char *(*fw_error_to_str)(int code); + int (*sev_send_start)(QEMUFile *f, uint64_t *bytes_sent); ++ int (*sev_receive_start)(QEMUFile *f); + }; + + extern struct sev_ops sev_ops; +diff --git a/target/i386/trace-events b/target/i386/trace-events +index a4a58b12a1..b3cb9aaf71 100644 +--- a/target/i386/trace-events ++++ b/target/i386/trace-events +@@ -23,3 +23,4 @@ kvm_sev_receive_update_vmsa(uint32_t cpu_id, uint32_t cpu_index, void *src, int + # csv.c + kvm_csv3_launch_encrypt_data(uint64_t gpa, void *addr, uint64_t len) "gpa 0x%" PRIx64 "addr %p len 0x%" PRIx64 + kvm_csv3_send_encrypt_data(void *dst, int len) "trans %p len %d" ++kvm_csv3_receive_encrypt_data(void *dst, int len, void *hdr, int hdr_len) "trans %p len %d hdr %p hdr_len %d" +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Add-support-to-migrate-the-outgoing--new.patch b/target-i386-csv-Add-support-to-migrate-the-outgoing--new.patch new file mode 100644 index 0000000000000000000000000000000000000000..bef06efc36eb4d6d34518e5b738617b5f601a1ff --- /dev/null +++ b/target-i386-csv-Add-support-to-migrate-the-outgoing--new.patch @@ -0,0 +1,139 @@ +From 0ebf32463e858c5f9cbd98e3f2fe494d0fbea259 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Fri, 17 Jun 2022 09:52:31 +0800 +Subject: [PATCH] target/i386: csv: Add support to migrate the outgoing context + for CSV3 guest + +CSV3 needs to migrate guest cpu's context pages. Prior to migration +of the context, it should query transfer buffer length and header +data length by SEND ENCRYPT CONTEXT command. New migration flag +RAM_SAVE_ENCRYPTED_CSV3_CONTEXT is defined for CSV3. + +Signed-off-by: Jiang Xin +Signed-off-by: hanliyang +--- + target/i386/csv.c | 81 ++++++++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 1 + + target/i386/trace-events | 1 + + 3 files changed, 83 insertions(+) + +diff --git a/target/i386/csv.c b/target/i386/csv.c +index ac080b3766..cc90b57e5b 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -46,6 +46,7 @@ struct ConfidentialGuestMemoryEncryptionOps csv3_memory_encryption_ops = { + .save_queued_outgoing_pages = csv3_save_queued_outgoing_pages, + .queue_incoming_page = NULL, + .load_queued_incoming_pages = NULL, ++ .save_outgoing_cpu_state = csv3_save_outgoing_context, + }; + + #define CSV3_OUTGOING_PAGE_NUM \ +@@ -570,3 +571,83 @@ int csv3_load_incoming_page(QEMUFile *f, uint8_t *ptr) + + return csv3_receive_encrypt_data(f, ptr); + } ++ ++static int ++csv3_send_get_context_len(int *fw_err, int *context_len, int *hdr_len) ++{ ++ int ret = 0; ++ struct kvm_csv3_send_encrypt_context update = { 0 }; ++ ++ ret = csv3_ioctl(KVM_CSV3_SEND_ENCRYPT_CONTEXT, &update, fw_err); ++ if (*fw_err != SEV_RET_INVALID_LEN) { ++ error_report("%s: failed to get context length ret=%d fw_error=%d '%s'", ++ __func__, ret, *fw_err, fw_error_to_str(*fw_err)); ++ ret = -1; ++ goto err; ++ } ++ ++ if (update.trans_len <= INT_MAX && update.hdr_len <= INT_MAX) { ++ *context_len = update.trans_len; ++ *hdr_len = update.hdr_len; ++ } ++ ret = 0; ++err: ++ return ret; ++} ++ ++static int ++csv3_send_encrypt_context(Csv3GuestState *s, QEMUFile *f, uint64_t *bytes_sent) ++{ ++ int ret, fw_error = 0; ++ int context_len = 0; ++ int hdr_len = 0; ++ guchar *trans; ++ guchar *hdr; ++ struct kvm_csv3_send_encrypt_context update = { }; ++ ++ ret = csv3_send_get_context_len(&fw_error, &context_len, &hdr_len); ++ if (context_len < 1 || hdr_len < 1) { ++ error_report("%s: fail to get context length fw_error=%d '%s'", ++ __func__, fw_error, fw_error_to_str(fw_error)); ++ return 1; ++ } ++ ++ /* allocate transport buffer */ ++ trans = g_new(guchar, context_len); ++ hdr = g_new(guchar, hdr_len); ++ ++ update.hdr_uaddr = (uintptr_t)hdr; ++ update.hdr_len = hdr_len; ++ update.trans_uaddr = (uintptr_t)trans; ++ update.trans_len = context_len; ++ ++ trace_kvm_csv3_send_encrypt_context(trans, update.trans_len); ++ ++ ret = csv3_ioctl(KVM_CSV3_SEND_ENCRYPT_CONTEXT, &update, &fw_error); ++ if (ret) { ++ error_report("%s: SEND_ENCRYPT_CONTEXT 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); ++ g_free(hdr); ++ return ret; ++} ++ ++int csv3_save_outgoing_context(QEMUFile *f, uint64_t *bytes_sent) ++{ ++ Csv3GuestState *s = &csv3_guest; ++ ++ /* send csv3 context. */ ++ return csv3_send_encrypt_context(s, f, bytes_sent); ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index afcd59180c..9f83a271fd 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -125,5 +125,6 @@ void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end); + int csv3_load_incoming_page(QEMUFile *f, uint8_t *ptr); + int csv3_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr); + int csv3_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent); ++int csv3_save_outgoing_context(QEMUFile *f, uint64_t *bytes_sent); + + #endif +diff --git a/target/i386/trace-events b/target/i386/trace-events +index b3cb9aaf71..043412c569 100644 +--- a/target/i386/trace-events ++++ b/target/i386/trace-events +@@ -23,4 +23,5 @@ kvm_sev_receive_update_vmsa(uint32_t cpu_id, uint32_t cpu_index, void *src, int + # csv.c + kvm_csv3_launch_encrypt_data(uint64_t gpa, void *addr, uint64_t len) "gpa 0x%" PRIx64 "addr %p len 0x%" PRIx64 + kvm_csv3_send_encrypt_data(void *dst, int len) "trans %p len %d" ++kvm_csv3_send_encrypt_context(void *dst, int len) "trans %p len %d" + kvm_csv3_receive_encrypt_data(void *dst, int len, void *hdr, int hdr_len) "trans %p len %d hdr %p hdr_len %d" +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Add-support-to-migrate-the-outgoing-.patch b/target-i386-csv-Add-support-to-migrate-the-outgoing-.patch new file mode 100644 index 0000000000000000000000000000000000000000..886f065a8d588e03e8e97b830cc7a73bf508f0ca --- /dev/null +++ b/target-i386-csv-Add-support-to-migrate-the-outgoing-.patch @@ -0,0 +1,452 @@ +From 13bd2629b78f528b0b4684a643f59d30b7274aa8 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Fri, 17 Jun 2022 09:37:56 +0800 +Subject: [PATCH] target/i386: csv: Add support to migrate the outgoing page + for CSV3 guest + +The csv3_send_encrypt_data() provides the method to encrypt the +guest's private pages during migration. The routine is similar to +CSV2's. Usually, it starts with a SEND_START command to create the +migration context. Then SEND_ENCRYPT_DATA command is performed to +encrypt guest pages. After migration is completed, a SEND_FINISH +command is performed to the firmware. + +Signed-off-by: Jiang Xin +Signed-off-by: hanliyang +--- + migration/ram.c | 87 +++++++++++++++++++ + target/i386/csv.c | 182 +++++++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 22 +++++ + target/i386/sev.c | 14 ++- + target/i386/sev.h | 1 + + target/i386/trace-events | 1 + + 6 files changed, 306 insertions(+), 1 deletion(-) + +diff --git a/migration/ram.c b/migration/ram.c +index 1377b9eb37..1f9348fd06 100644 +--- a/migration/ram.c ++++ b/migration/ram.c +@@ -2480,6 +2480,90 @@ ram_save_encrypted_pages_in_batch(RAMState *rs, PageSearchStatus *pss) + } + #endif + ++/** ++ * ram_save_csv3_pages - send the given csv3 VM pages to the stream ++ */ ++static int ram_save_csv3_pages(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; ++ RAMBlock *block = pss->block; ++ ram_addr_t offset = 0; ++ hwaddr paddr = RAM_ADDR_INVALID; ++ MachineState *ms = MACHINE(qdev_get_machine()); ++ ConfidentialGuestSupportClass *cgs_class = ++ (ConfidentialGuestSupportClass *) object_get_class(OBJECT(ms->cgs)); ++ struct ConfidentialGuestMemoryEncryptionOps *ops = ++ cgs_class->memory_encryption_ops; ++ ++ if (!kvm_csv3_enabled()) ++ return 0; ++ ++ do { ++ page_dirty = migration_bitmap_clear_dirty(rs, block, pss->page); ++ ++ /* Check the pages is dirty and if it is send it */ ++ if (page_dirty) { ++ ret = kvm_physical_memory_addr_from_host(kvm_state, ++ block->host + (pss->page << TARGET_PAGE_BITS), &paddr); ++ /* Process ROM or MMIO */ ++ if (paddr == RAM_ADDR_INVALID || ++ memory_region_is_rom(block->mr)) { ++ tmppages = migration_ops->ram_save_target_page(rs, pss); ++ } else { ++ /* Caculate the offset and host virtual address of the page */ ++ offset = pss->page << TARGET_PAGE_BITS; ++ p = block->host + offset; ++ ++ 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(block, ++ ((ram_addr_t)pss->page) << TARGET_PAGE_BITS) && ++ host_len < CSV3_OUTGOING_PAGE_WINDOW_SIZE); ++ ++ /* Check if there are any queued pages */ ++ if (host_len != 0) { ++ /* Always set offset as 0 for csv3. */ ++ ram_transferred_add(save_page_header(pss, pss->pss_channel, ++ block, 0 | RAM_SAVE_FLAG_ENCRYPTED_DATA)); ++ ++ qemu_put_be32(pss->pss_channel, RAM_SAVE_ENCRYPTED_PAGE); ++ 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; ++} ++ + /** + * ram_save_host_page: save a whole host page + * +@@ -2515,6 +2599,9 @@ static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss) + return 0; + } + ++ if (kvm_csv3_enabled()) ++ return ram_save_csv3_pages(rs, pss); ++ + #ifdef CONFIG_HYGON_CSV_MIG_ACCEL + /* + * If command_batch function is enabled and memory encryption is enabled +diff --git a/target/i386/csv.c b/target/i386/csv.c +index e4706efa27..22e709a95c 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -16,8 +16,13 @@ + #include "qapi/error.h" + #include "sysemu/kvm.h" + #include "exec/address-spaces.h" ++#include "migration/blocker.h" ++#include "migration/qemu-file.h" ++#include "migration/misc.h" ++#include "monitor/monitor.h" + + #include ++#include + + #ifdef CONFIG_NUMA + #include +@@ -30,6 +35,19 @@ + + bool csv_kvm_cpu_reset_inhibit; + ++struct ConfidentialGuestMemoryEncryptionOps csv3_memory_encryption_ops = { ++ .save_setup = sev_save_setup, ++ .save_outgoing_page = NULL, ++ .is_gfn_in_unshared_region = NULL, ++ .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 = csv3_queue_outgoing_page, ++ .save_queued_outgoing_pages = csv3_save_queued_outgoing_pages, ++}; ++ ++#define CSV3_OUTGOING_PAGE_NUM \ ++ (CSV3_OUTGOING_PAGE_WINDOW_SIZE / TARGET_PAGE_SIZE) ++ + Csv3GuestState csv3_guest = { 0 }; + + int +@@ -70,6 +88,7 @@ csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) + csv3_guest.fw_error_to_str = ops->fw_error_to_str; + QTAILQ_INIT(&csv3_guest.dma_map_regions_list); + qemu_mutex_init(&csv3_guest.dma_map_regions_list_mutex); ++ csv3_guest.sev_send_start = ops->sev_send_start; + } + return 0; + } +@@ -301,3 +320,166 @@ end: + qemu_mutex_unlock(&s->dma_map_regions_list_mutex); + return; + } ++ ++static inline hwaddr csv3_hva_to_gfn(uint8_t *ptr) ++{ ++ ram_addr_t offset = RAM_ADDR_INVALID; ++ ++ kvm_physical_memory_addr_from_host(kvm_state, ptr, &offset); ++ ++ return offset >> TARGET_PAGE_BITS; ++} ++ ++static int ++csv3_send_start(QEMUFile *f, uint64_t *bytes_sent) ++{ ++ if (csv3_guest.sev_send_start) ++ return csv3_guest.sev_send_start(f, bytes_sent); ++ else ++ return -1; ++} ++ ++static int ++csv3_send_get_packet_len(int *fw_err) ++{ ++ int ret; ++ struct kvm_csv3_send_encrypt_data update = {0}; ++ ++ update.hdr_len = 0; ++ update.trans_len = 0; ++ ret = csv3_ioctl(KVM_CSV3_SEND_ENCRYPT_DATA, &update, fw_err); ++ if (*fw_err != SEV_RET_INVALID_LEN) { ++ error_report("%s: failed to get session length ret=%d fw_error=%d '%s'", ++ __func__, ret, *fw_err, fw_error_to_str(*fw_err)); ++ ret = 0; ++ goto err; ++ } ++ ++ if (update.hdr_len <= INT_MAX) ++ ret = update.hdr_len; ++ else ++ ret = 0; ++ ++err: ++ return ret; ++} ++ ++static int ++csv3_send_encrypt_data(Csv3GuestState *s, QEMUFile *f, ++ uint8_t *ptr, uint32_t size, uint64_t *bytes_sent) ++{ ++ int ret, fw_error = 0; ++ guchar *trans; ++ uint32_t guest_addr_entry_num; ++ uint32_t i; ++ struct kvm_csv3_send_encrypt_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 = csv3_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); ++ } ++ ++ if (!s->guest_addr_len || !s->guest_addr_data) { ++ error_report("%s: invalid host address or size", __func__); ++ return 1; ++ } else { ++ guest_addr_entry_num = s->guest_addr_len / sizeof(struct guest_addr_entry); ++ } ++ ++ /* allocate transport buffer */ ++ trans = g_new(guchar, guest_addr_entry_num * TARGET_PAGE_SIZE); ++ ++ update.hdr_uaddr = (uintptr_t)s->send_packet_hdr; ++ update.hdr_len = s->send_packet_hdr_len; ++ update.guest_addr_data = (uintptr_t)s->guest_addr_data; ++ update.guest_addr_len = s->guest_addr_len; ++ update.trans_uaddr = (uintptr_t)trans; ++ update.trans_len = guest_addr_entry_num * TARGET_PAGE_SIZE; ++ ++ trace_kvm_csv3_send_encrypt_data(trans, update.trans_len); ++ ++ ret = csv3_ioctl(KVM_CSV3_SEND_ENCRYPT_DATA, &update, &fw_error); ++ if (ret) { ++ error_report("%s: SEND_ENCRYPT_DATA ret=%d fw_error=%d '%s'", ++ __func__, ret, fw_error, fw_error_to_str(fw_error)); ++ goto err; ++ } ++ ++ for (i = 0; i < guest_addr_entry_num; i++) { ++ if (s->guest_addr_data[i].share) ++ memcpy(trans + i * TARGET_PAGE_SIZE, (guchar *)s->guest_hva_data[i].hva, ++ TARGET_PAGE_SIZE); ++ } ++ ++ 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.guest_addr_len); ++ qemu_put_buffer(f, (uint8_t *)update.guest_addr_data, update.guest_addr_len); ++ *bytes_sent += 4 + update.guest_addr_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: ++ s->guest_addr_len = 0; ++ g_free(trans); ++ return ret; ++} ++ ++int ++csv3_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr) ++{ ++ Csv3GuestState *s = &csv3_guest; ++ uint32_t i = 0; ++ ++ if (!s->guest_addr_data) { ++ s->guest_hva_data = g_new0(struct guest_hva_entry, CSV3_OUTGOING_PAGE_NUM); ++ s->guest_addr_data = g_new0(struct guest_addr_entry, CSV3_OUTGOING_PAGE_NUM); ++ s->guest_addr_len = 0; ++ } ++ ++ if (s->guest_addr_len >= sizeof(struct guest_addr_entry) * CSV3_OUTGOING_PAGE_NUM) { ++ error_report("Failed to queue outgoing page"); ++ return 1; ++ } ++ ++ i = s->guest_addr_len / sizeof(struct guest_addr_entry); ++ s->guest_hva_data[i].hva = (uintptr_t)ptr; ++ s->guest_addr_data[i].share = 0; ++ s->guest_addr_data[i].reserved = 0; ++ s->guest_addr_data[i].gfn = csv3_hva_to_gfn(ptr); ++ s->guest_addr_len += sizeof(struct guest_addr_entry); ++ ++ return 0; ++} ++ ++int ++csv3_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent) ++{ ++ Csv3GuestState *s = &csv3_guest; ++ ++ /* ++ * If this is a first buffer then create outgoing encryption context ++ * and write our PDH, policy and session data. ++ */ ++ if (!csv3_check_state(SEV_STATE_SEND_UPDATE) && ++ csv3_send_start(f, bytes_sent)) { ++ error_report("Failed to create outgoing context"); ++ return 1; ++ } ++ ++ return csv3_send_encrypt_data(s, f, NULL, 0, bytes_sent); ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 12733341b3..12c1b22659 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -81,6 +81,18 @@ struct dma_map_region { + QTAILQ_ENTRY(dma_map_region) list; + }; + ++#define CSV3_OUTGOING_PAGE_WINDOW_SIZE (512 * TARGET_PAGE_SIZE) ++ ++struct guest_addr_entry { ++ uint64_t share: 1; ++ uint64_t reserved: 11; ++ uint64_t gfn: 52; ++}; ++ ++struct guest_hva_entry { ++ uint64_t hva; ++}; ++ + struct Csv3GuestState { + uint32_t policy; + int sev_fd; +@@ -89,11 +101,19 @@ struct Csv3GuestState { + const char *(*fw_error_to_str)(int code); + QTAILQ_HEAD(, dma_map_region) dma_map_regions_list; + QemuMutex dma_map_regions_list_mutex; ++ gchar *send_packet_hdr; ++ size_t send_packet_hdr_len; ++ struct guest_hva_entry *guest_hva_data; ++ struct guest_addr_entry *guest_addr_data; ++ size_t guest_addr_len; ++ ++ int (*sev_send_start)(QEMUFile *f, uint64_t *bytes_sent); + }; + + typedef struct Csv3GuestState Csv3GuestState; + + extern struct Csv3GuestState csv3_guest; ++extern struct ConfidentialGuestMemoryEncryptionOps csv3_memory_encryption_ops; + extern int csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops); + extern int csv3_launch_encrypt_vmcb(void); + +@@ -101,5 +121,7 @@ int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); + + int csv3_shared_region_dma_map(uint64_t start, uint64_t end); + void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end); ++int csv3_queue_outgoing_page(uint8_t *ptr, uint32_t sz, uint64_t addr); ++int csv3_save_queued_outgoing_pages(QEMUFile *f, uint64_t *bytes_sent); + + #endif +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 0012a5efb0..5a96b0b452 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -1270,7 +1270,11 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) + 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; ++ if (csv3_enabled()) { ++ cgs_class->memory_encryption_ops = &csv3_memory_encryption_ops; ++ } else { ++ cgs_class->memory_encryption_ops = &sev_memory_encryption_ops; ++ } + QTAILQ_INIT(&sev->shared_regions_list); + + /* Determine whether support MSR_AMD64_SEV_ES_GHCB */ +@@ -2654,9 +2658,17 @@ bool sev_add_kernel_loader_hashes(SevKernelLoaderContext *ctx, Error **errp) + return ret; + } + ++static int _sev_send_start(QEMUFile *f, uint64_t *bytes_sent) ++{ ++ SevGuestState *s = sev_guest; ++ ++ return sev_send_start(s, f, bytes_sent); ++} ++ + struct sev_ops sev_ops = { + .sev_ioctl = sev_ioctl, + .fw_error_to_str = fw_error_to_str, ++ .sev_send_start = _sev_send_start, + }; + + static void +diff --git a/target/i386/sev.h b/target/i386/sev.h +index e91431e0f7..8ccef22a95 100644 +--- a/target/i386/sev.h ++++ b/target/i386/sev.h +@@ -83,6 +83,7 @@ extern bool sev_kvm_has_msr_ghcb; + struct sev_ops { + int (*sev_ioctl)(int fd, int cmd, void *data, int *error); + const char *(*fw_error_to_str)(int code); ++ int (*sev_send_start)(QEMUFile *f, uint64_t *bytes_sent); + }; + + extern struct sev_ops sev_ops; +diff --git a/target/i386/trace-events b/target/i386/trace-events +index 34c205ffda..a4a58b12a1 100644 +--- a/target/i386/trace-events ++++ b/target/i386/trace-events +@@ -22,3 +22,4 @@ kvm_sev_receive_update_vmsa(uint32_t cpu_id, uint32_t cpu_index, void *src, int + + # csv.c + kvm_csv3_launch_encrypt_data(uint64_t gpa, void *addr, uint64_t len) "gpa 0x%" PRIx64 "addr %p len 0x%" PRIx64 ++kvm_csv3_send_encrypt_data(void *dst, int len) "trans %p len %d" +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Do-not-register-unregister-guest-sec.patch b/target-i386-csv-Do-not-register-unregister-guest-sec.patch new file mode 100644 index 0000000000000000000000000000000000000000..419aa8bc7352cc29c77745824fa28171efddb6e2 --- /dev/null +++ b/target-i386-csv-Do-not-register-unregister-guest-sec.patch @@ -0,0 +1,35 @@ +From a3e8267b93d1e77dc547fff6fb9af6f8d48a674f Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 12:36:00 +0800 +Subject: [PATCH] target/i386: csv: Do not register/unregister guest secure + memory for CSV3 guest + +CSV3's guest memory is allocated by firmware in secure processor +from dedicated memory reserved upon system boot up, consequently +it is not necessary to add notifier to pin/unpin memory. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + target/i386/sev.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 6ff8891678..0012a5efb0 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -1262,7 +1262,10 @@ int sev_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) + } + } + +- ram_block_notifier_add(&sev_ram_notifier); ++ /* CSV3 guest do not need notifier to reg/unreg memory */ ++ if (!csv3_enabled()) { ++ ram_block_notifier_add(&sev_ram_notifier); ++ } + qemu_add_machine_init_done_notifier(&sev_machine_done_notify); + qemu_add_vm_change_state_handler(sev_vm_state_change, sev); + migration_add_notifier(&sev_migration_state, sev_migration_state_notifier); +-- +2.41.0.windows.1 + diff --git a/target-i386-csv-Load-initial-image-to-private-memory.patch b/target-i386-csv-Load-initial-image-to-private-memory.patch new file mode 100644 index 0000000000000000000000000000000000000000..011ce59be4132b566b400141c5496c6e7f9dad63 --- /dev/null +++ b/target-i386-csv-Load-initial-image-to-private-memory.patch @@ -0,0 +1,52 @@ +From ed3c233cc00d4c30718fc64b3afc48a51b4eb438 Mon Sep 17 00:00:00 2001 +From: jiangxin +Date: Wed, 25 Aug 2021 14:29:40 +0800 +Subject: [PATCH] target/i386: csv: Load initial image to private memory for + CSV3 guest + +The initial image of CSV3 guest should be loaded into private memory +before boot the guest. + +Add APIs to implement the image load. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + hw/i386/pc_sysfw.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c +index c8d9e71b88..2bbcbb8d35 100644 +--- a/hw/i386/pc_sysfw.c ++++ b/hw/i386/pc_sysfw.c +@@ -37,6 +37,7 @@ + #include "hw/block/flash.h" + #include "sysemu/kvm.h" + #include "sev.h" ++#include "csv.h" + + #define FLASH_SECTOR_SIZE 4096 + +@@ -263,7 +264,18 @@ void x86_firmware_configure(void *ptr, int size) + error_report("failed to locate and/or save reset vector"); + exit(1); + } ++ if (csv3_enabled()) { ++ ram_addr_t offset = 0; ++ MemoryRegion *mr; + +- sev_encrypt_flash(ptr, size, &error_fatal); ++ mr = memory_region_from_host(ptr, &offset); ++ if (!mr) { ++ error_report("failed to get memory region of flash"); ++ exit(1); ++ } ++ csv3_load_data(mr->addr + offset, ptr, size, &error_fatal); ++ } else { ++ sev_encrypt_flash(ptr, size, &error_fatal); ++ } + } + } +-- +2.41.0.windows.1 + diff --git a/target-m68k-Map-FPU-exceptions-to-FPSR-register.patch b/target-m68k-Map-FPU-exceptions-to-FPSR-register.patch new file mode 100644 index 0000000000000000000000000000000000000000..de9b79c30fcd435b6456cae0ae289b19462e6af9 --- /dev/null +++ b/target-m68k-Map-FPU-exceptions-to-FPSR-register.patch @@ -0,0 +1,218 @@ +From a8a621a06d54b987502d277f33021547d00fd133 Mon Sep 17 00:00:00 2001 +From: Keith Packard +Date: Wed, 2 Aug 2023 20:52:31 -0700 +Subject: [PATCH] target/m68k: Map FPU exceptions to FPSR register + +Add helpers for reading/writing the 68881 FPSR register so that +changes in floating point exception state can be seen by the +application. + +Call these helpers in pre_load/post_load hooks to synchronize +exception state. + +Signed-off-by: Keith Packard +Reviewed-by: Richard Henderson +Message-Id: <20230803035231.429697-1-keithp@keithp.com> +Signed-off-by: Richard Henderson +(cherry picked from commit 5888357942da1fd5a50efb6e4a6af8b1a27a5af8) +Signed-off-by: zhujun2 +--- + target/m68k/cpu.c | 12 +++++-- + target/m68k/cpu.h | 3 +- + target/m68k/fpu_helper.c | 72 ++++++++++++++++++++++++++++++++++++++++ + target/m68k/helper.c | 4 +-- + target/m68k/helper.h | 2 ++ + target/m68k/translate.c | 4 +-- + 6 files changed, 90 insertions(+), 7 deletions(-) + +diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c +index 11c7e0a790..d95deaafcd 100644 +--- a/target/m68k/cpu.c ++++ b/target/m68k/cpu.c +@@ -396,12 +396,19 @@ static const VMStateDescription vmstate_freg = { + } + }; + +-static int fpu_post_load(void *opaque, int version) ++static int fpu_pre_save(void *opaque) + { + M68kCPU *s = opaque; + +- cpu_m68k_restore_fp_status(&s->env); ++ s->env.fpsr = cpu_m68k_get_fpsr(&s->env); ++ return 0; ++} ++ ++static int fpu_post_load(void *opaque, int version) ++{ ++ M68kCPU *s = opaque; + ++ cpu_m68k_set_fpsr(&s->env, s->env.fpsr); + return 0; + } + +@@ -410,6 +417,7 @@ const VMStateDescription vmmstate_fpu = { + .version_id = 1, + .minimum_version_id = 1, + .needed = fpu_needed, ++ .pre_save = fpu_pre_save, + .post_load = fpu_post_load, + .fields = (VMStateField[]) { + VMSTATE_UINT32(env.fpcr, M68kCPU), +diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h +index 6cfc696d2b..4d78da9d5f 100644 +--- a/target/m68k/cpu.h ++++ b/target/m68k/cpu.h +@@ -199,7 +199,8 @@ void cpu_m68k_set_ccr(CPUM68KState *env, uint32_t); + void cpu_m68k_set_sr(CPUM68KState *env, uint32_t); + void cpu_m68k_restore_fp_status(CPUM68KState *env); + void cpu_m68k_set_fpcr(CPUM68KState *env, uint32_t val); +- ++uint32_t cpu_m68k_get_fpsr(CPUM68KState *env); ++void cpu_m68k_set_fpsr(CPUM68KState *env, uint32_t val); + + /* + * Instead of computing the condition codes after each m68k instruction, +diff --git a/target/m68k/fpu_helper.c b/target/m68k/fpu_helper.c +index ab120b5f59..8314791f50 100644 +--- a/target/m68k/fpu_helper.c ++++ b/target/m68k/fpu_helper.c +@@ -164,6 +164,78 @@ void HELPER(set_fpcr)(CPUM68KState *env, uint32_t val) + cpu_m68k_set_fpcr(env, val); + } + ++/* Convert host exception flags to cpu_m68k form. */ ++static int cpu_m68k_exceptbits_from_host(int host_bits) ++{ ++ int target_bits = 0; ++ ++ if (host_bits & float_flag_invalid) { ++ target_bits |= 0x80; ++ } ++ if (host_bits & float_flag_overflow) { ++ target_bits |= 0x40; ++ } ++ if (host_bits & (float_flag_underflow | float_flag_output_denormal)) { ++ target_bits |= 0x20; ++ } ++ if (host_bits & float_flag_divbyzero) { ++ target_bits |= 0x10; ++ } ++ if (host_bits & float_flag_inexact) { ++ target_bits |= 0x08; ++ } ++ return target_bits; ++} ++ ++/* Convert cpu_m68k exception flags to target form. */ ++static int cpu_m68k_exceptbits_to_host(int target_bits) ++{ ++ int host_bits = 0; ++ ++ if (target_bits & 0x80) { ++ host_bits |= float_flag_invalid; ++ } ++ if (target_bits & 0x40) { ++ host_bits |= float_flag_overflow; ++ } ++ if (target_bits & 0x20) { ++ host_bits |= float_flag_underflow; ++ } ++ if (target_bits & 0x10) { ++ host_bits |= float_flag_divbyzero; ++ } ++ if (target_bits & 0x08) { ++ host_bits |= float_flag_inexact; ++ } ++ return host_bits; ++} ++ ++uint32_t cpu_m68k_get_fpsr(CPUM68KState *env) ++{ ++ int host_flags = get_float_exception_flags(&env->fp_status); ++ int target_flags = cpu_m68k_exceptbits_from_host(host_flags); ++ int except = (env->fpsr & ~(0xf8)) | target_flags; ++ return except; ++} ++ ++uint32_t HELPER(get_fpsr)(CPUM68KState *env) ++{ ++ return cpu_m68k_get_fpsr(env); ++} ++ ++void cpu_m68k_set_fpsr(CPUM68KState *env, uint32_t val) ++{ ++ env->fpsr = val; ++ ++ int host_flags = cpu_m68k_exceptbits_to_host((int) env->fpsr); ++ set_float_exception_flags(host_flags, &env->fp_status); ++} ++ ++void HELPER(set_fpsr)(CPUM68KState *env, uint32_t val) ++{ ++ cpu_m68k_set_fpsr(env, val); ++} ++ + #define PREC_BEGIN(prec) \ + do { \ + FloatX80RoundPrec old = \ +diff --git a/target/m68k/helper.c b/target/m68k/helper.c +index 0a1544cd68..beab4b96bc 100644 +--- a/target/m68k/helper.c ++++ b/target/m68k/helper.c +@@ -118,7 +118,7 @@ static int m68k_fpu_gdb_get_reg(CPUM68KState *env, GByteArray *mem_buf, int n) + case 8: /* fpcontrol */ + return gdb_get_reg32(mem_buf, env->fpcr); + case 9: /* fpstatus */ +- return gdb_get_reg32(mem_buf, env->fpsr); ++ return gdb_get_reg32(mem_buf, cpu_m68k_get_fpsr(env)); + case 10: /* fpiar, not implemented */ + return gdb_get_reg32(mem_buf, 0); + } +@@ -137,7 +137,7 @@ static int m68k_fpu_gdb_set_reg(CPUM68KState *env, uint8_t *mem_buf, int n) + cpu_m68k_set_fpcr(env, ldl_p(mem_buf)); + return 4; + case 9: /* fpstatus */ +- env->fpsr = ldl_p(mem_buf); ++ cpu_m68k_set_fpsr(env, ldl_p(mem_buf)); + return 4; + case 10: /* fpiar, not implemented */ + return 4; +diff --git a/target/m68k/helper.h b/target/m68k/helper.h +index 2bbe0dc032..95aa5e53bb 100644 +--- a/target/m68k/helper.h ++++ b/target/m68k/helper.h +@@ -54,6 +54,8 @@ DEF_HELPER_4(fsdiv, void, env, fp, fp, fp) + DEF_HELPER_4(fddiv, void, env, fp, fp, fp) + DEF_HELPER_4(fsgldiv, void, env, fp, fp, fp) + DEF_HELPER_FLAGS_3(fcmp, TCG_CALL_NO_RWG, void, env, fp, fp) ++DEF_HELPER_2(set_fpsr, void, env, i32) ++DEF_HELPER_1(get_fpsr, i32, env) + DEF_HELPER_FLAGS_2(set_fpcr, TCG_CALL_NO_RWG, void, env, i32) + DEF_HELPER_FLAGS_2(ftst, TCG_CALL_NO_RWG, void, env, fp) + DEF_HELPER_3(fconst, void, env, fp, i32) +diff --git a/target/m68k/translate.c b/target/m68k/translate.c +index 4a0b0b2703..f8eeb70379 100644 +--- a/target/m68k/translate.c ++++ b/target/m68k/translate.c +@@ -4686,7 +4686,7 @@ static void gen_load_fcr(DisasContext *s, TCGv res, int reg) + tcg_gen_movi_i32(res, 0); + break; + case M68K_FPSR: +- tcg_gen_ld_i32(res, tcg_env, offsetof(CPUM68KState, fpsr)); ++ gen_helper_get_fpsr(res, tcg_env); + break; + case M68K_FPCR: + tcg_gen_ld_i32(res, tcg_env, offsetof(CPUM68KState, fpcr)); +@@ -4700,7 +4700,7 @@ static void gen_store_fcr(DisasContext *s, TCGv val, int reg) + case M68K_FPIAR: + break; + case M68K_FPSR: +- tcg_gen_st_i32(val, tcg_env, offsetof(CPUM68KState, fpsr)); ++ gen_helper_set_fpsr(tcg_env, val); + break; + case M68K_FPCR: + gen_helper_set_fpcr(tcg_env, val); +-- +2.41.0.windows.1 + diff --git a/target-riscv-Fix-the-element-agnostic-function-probl.patch b/target-riscv-Fix-the-element-agnostic-function-probl.patch new file mode 100644 index 0000000000000000000000000000000000000000..6951aa9cc634518b278225555d866d1945b082a9 --- /dev/null +++ b/target-riscv-Fix-the-element-agnostic-function-probl.patch @@ -0,0 +1,60 @@ +From 194c3cadc1879ff4c3d2fc6c5f962ad751c83d9c Mon Sep 17 00:00:00 2001 +From: Huang Tao +Date: Mon, 25 Mar 2024 10:16:54 +0800 +Subject: [PATCH] target/riscv: Fix the element agnostic function problem + +In RVV and vcrypto instructions, the masked and tail elements are set to 1s +using vext_set_elems_1s function if the vma/vta bit is set. It is the element +agnostic policy. + +However, this function can't deal the big endian situation. This patch fixes +the problem by adding handling of such case. + +Signed-off-by: Huang Tao +Suggested-by: Richard Henderson +Reviewed-by: LIU Zhiwei +Cc: qemu-stable +Message-ID: <20240325021654.6594-1-eric.huang@linux.alibaba.com> +Signed-off-by: Alistair Francis +(cherry picked from commit 75115d880c6d396f8a2d56aab8c12236d85a90e0) +Signed-off-by: zhujun2 +--- + target/riscv/vector_internals.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c +index 9cf5c17cde..be6eb040d2 100644 +--- a/target/riscv/vector_internals.c ++++ b/target/riscv/vector_internals.c +@@ -29,6 +29,28 @@ void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt, + if (tot - cnt == 0) { + return ; + } ++ ++ if (HOST_BIG_ENDIAN) { ++ /* ++ * Deal the situation when the elements are insdie ++ * only one uint64 block including setting the ++ * masked-off element. ++ */ ++ if (((tot - 1) ^ cnt) < 8) { ++ memset(base + H1(tot - 1), -1, tot - cnt); ++ return; ++ } ++ /* ++ * Otherwise, at least cross two uint64_t blocks. ++ * Set first unaligned block. ++ */ ++ if (cnt % 8 != 0) { ++ uint32_t j = ROUND_UP(cnt, 8); ++ memset(base + H1(j - 1), -1, j - cnt); ++ cnt = j; ++ } ++ /* Set other 64bit aligend blocks */ ++ } + memset(base + cnt, -1, tot - cnt); + } + +-- +2.41.0.windows.1 + diff --git a/tcg-Allow-top-bit-of-SIMD_DATA_BITS-to-be-set-in-sim.patch b/tcg-Allow-top-bit-of-SIMD_DATA_BITS-to-be-set-in-sim.patch new file mode 100644 index 0000000000000000000000000000000000000000..28535595883614649dbdae076b6eddc171f83b21 --- /dev/null +++ b/tcg-Allow-top-bit-of-SIMD_DATA_BITS-to-be-set-in-sim.patch @@ -0,0 +1,69 @@ +From d0b24cfdeb8bd64fa55154d79574352be33ecc51 Mon Sep 17 00:00:00 2001 +From: Peter Maydell +Date: Fri, 15 Nov 2024 17:25:15 +0000 +Subject: [PATCH] tcg: Allow top bit of SIMD_DATA_BITS to be set in simd_desc() + +In simd_desc() we create a SIMD descriptor from various pieces +including an arbitrary data value from the caller. We try to +sanitize these to make sure everything will fit: the 'data' value +needs to fit in the SIMD_DATA_BITS (== 22) sized field. However we +do that sanitizing with: + tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS)); + +This works for the case where the data is supposed to be considered +as a signed integer (which can then be returned via simd_data()). +However, some callers want to treat the data value as unsigned. + +Specifically, for the Arm SVE operations, make_svemte_desc() +assembles a data value as a collection of fields, and it needs to use +all 22 bits. Currently if MTE is enabled then its MTEDESC SIZEM1 +field may have the most significant bit set, and then it will trip +this assertion. + +Loosen the assertion so that we only check that the data value will +fit into the field in some way, either as a signed or as an unsigned +value. This means we will fail to detect some kinds of bug in the +callers, but we won't spuriously assert for intentional use of the +data field as unsigned. + +Cc: qemu-stable@nongnu.org +Fixes: db432672dc50e ("tcg: Add generic vector expanders") +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2601 +Signed-off-by: Peter Maydell +Message-ID: <20241115172515.1229393-1-peter.maydell@linaro.org> +Reviewed-by: Richard Henderson +Signed-off-by: Richard Henderson +Signed-off-by: Zhongrui Tang +--- + tcg/tcg-op-gvec.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c +index bb88943f79..733b44f105 100644 +--- a/tcg/tcg-op-gvec.c ++++ b/tcg/tcg-op-gvec.c +@@ -88,7 +88,20 @@ uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data) + uint32_t desc = 0; + + check_size_align(oprsz, maxsz, 0); +- tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS)); ++ ++ /* ++ * We want to check that 'data' will fit into SIMD_DATA_BITS. ++ * However, some callers want to treat the data as a signed ++ * value (which they can later get back with simd_data()) ++ * and some want to treat it as an unsigned value. ++ * So here we assert only that the data will fit into the ++ * field in at least one way. This means that some invalid ++ * values from the caller will not be detected, e.g. if the ++ * caller wants to handle the value as a signed integer but ++ * incorrectly passes us 1 << (SIMD_DATA_BITS - 1). ++ */ ++ tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS) || ++ data == extract32(data, 0, SIMD_DATA_BITS)); + + oprsz = (oprsz / 8) - 1; + maxsz = (maxsz / 8) - 1; +-- +2.41.0.windows.1 + diff --git a/tcg-loongarch64-Fix-tcg_out_movi-vs-some-pcrel-point.patch b/tcg-loongarch64-Fix-tcg_out_movi-vs-some-pcrel-point.patch new file mode 100644 index 0000000000000000000000000000000000000000..67809a17bf0ddd171efb68d881e343c3a64dfcf2 --- /dev/null +++ b/tcg-loongarch64-Fix-tcg_out_movi-vs-some-pcrel-point.patch @@ -0,0 +1,77 @@ +From 6477ff9d89317a6124f3a46215b1567306b6ebe4 Mon Sep 17 00:00:00 2001 +From: Richard Henderson +Date: Wed, 19 Jun 2024 05:41:13 +0000 +Subject: [PATCH] tcg/loongarch64: Fix tcg_out_movi vs some pcrel pointers + +Simplify the logic for two-part, 32-bit pc-relative addresses. +Rather than assume all such fit in int32_t, do some arithmetic +and assert a result, do some arithmetic first and then check +to see if the pieces are in range. + +Cc: qemu-stable@nongnu.org +Fixes: dacc51720db ("tcg/loongarch64: Implement tcg_out_mov and tcg_out_movi") +Reviewed-by: Song Gao +Reported-by: Song Gao +Signed-off-by: Richard Henderson +(cherry picked from commit 521d7fb3ebdf88112ed13556a93e3037742b9eb8) +Signed-off-by: zhujun2 +--- + tcg/loongarch64/tcg-target.c.inc | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc +index bab0a173a3..ad2690b90d 100644 +--- a/tcg/loongarch64/tcg-target.c.inc ++++ b/tcg/loongarch64/tcg-target.c.inc +@@ -365,8 +365,7 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, + * back to the slow path. + */ + +- intptr_t pc_offset; +- tcg_target_long val_lo, val_hi, pc_hi, offset_hi; ++ intptr_t src_rx, pc_offset; + tcg_target_long hi12, hi32, hi52; + + /* Value fits in signed i32. */ +@@ -376,24 +375,23 @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, + } + + /* PC-relative cases. */ +- pc_offset = tcg_pcrel_diff(s, (void *)val); +- if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) { +- /* Single pcaddu2i. */ +- tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2); +- return; ++ src_rx = (intptr_t)tcg_splitwx_to_rx(s->code_ptr); ++ if ((val & 3) == 0) { ++ pc_offset = val - src_rx; ++ if (pc_offset == sextreg(pc_offset, 0, 22)) { ++ /* Single pcaddu2i. */ ++ tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2); ++ return; ++ } + } + +- if (pc_offset == (int32_t)pc_offset) { +- /* Offset within 32 bits; load with pcalau12i + ori. */ +- val_lo = sextreg(val, 0, 12); +- val_hi = val >> 12; +- pc_hi = (val - pc_offset) >> 12; +- offset_hi = val_hi - pc_hi; +- +- tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20)); +- tcg_out_opc_pcalau12i(s, rd, offset_hi); ++ pc_offset = (val >> 12) - (src_rx >> 12); ++ if (pc_offset == sextreg(pc_offset, 0, 20)) { ++ /* Load with pcalau12i + ori. */ ++ tcg_target_long val_lo = val & 0xfff; ++ tcg_out_opc_pcalau12i(s, rd, pc_offset); + if (val_lo != 0) { +- tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff); ++ tcg_out_opc_ori(s, rd, rd, val_lo); + } + return; + } +-- +2.41.0.windows.1 + diff --git a/ui-vnc-don-t-return-an-empty-SASL-mechlist-to-the-cl.patch b/ui-vnc-don-t-return-an-empty-SASL-mechlist-to-the-cl.patch new file mode 100644 index 0000000000000000000000000000000000000000..10049b8fbec458c6b85787d15b1d77a0f48980b3 --- /dev/null +++ b/ui-vnc-don-t-return-an-empty-SASL-mechlist-to-the-cl.patch @@ -0,0 +1,47 @@ +From 838c585cf6c899a0b48683a0b46ed01cc24d835c Mon Sep 17 00:00:00 2001 +From: Susanooo +Date: Fri, 25 Oct 2024 10:08:39 +0800 +Subject: [PATCH] ui/vnc: don't return an empty SASL mechlist to the client +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The SASL initialization phase may determine that there are no valid +mechanisms available to use. This may be because the host OS admin +forgot to install some packages, or it might be because the requested +SSF level is incompatible with available mechanisms, or other unknown +reasons. + +If we return an empty mechlist to the client, they're going to get a +failure from the SASL library on their end and drop the connection. +Thus there is no point even sending this back to the client, we can +just drop the connection immediately. + +Reviewed-by: Marc-André Lureau +Signed-off-by: Daniel P. Berrangé +Signed-off-by: zhangchujun +--- + ui/vnc-auth-sasl.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c +index 47fdae5b21..e321c9decc 100644 +--- a/ui/vnc-auth-sasl.c ++++ b/ui/vnc-auth-sasl.c +@@ -674,6 +674,13 @@ void start_auth_sasl(VncState *vs) + } + trace_vnc_auth_sasl_mech_list(vs, mechlist); + ++ if (g_str_equal(mechlist, "")) { ++ trace_vnc_auth_fail(vs, vs->auth, "no available SASL mechanisms", ""); ++ sasl_dispose(&vs->sasl.conn); ++ vs->sasl.conn = NULL; ++ goto authabort; ++ } ++ + vs->sasl.mechlist = g_strdup(mechlist); + mechlistlen = strlen(mechlist); + vnc_write_u32(vs, mechlistlen); +-- +2.41.0.windows.1 + diff --git a/vdpa-dev-Fix-initialisation-order-to-restore-VDUSE-c.patch b/vdpa-dev-Fix-initialisation-order-to-restore-VDUSE-c.patch new file mode 100644 index 0000000000000000000000000000000000000000..109974b7c783df1ff2ff627c988be4215db17b7c --- /dev/null +++ b/vdpa-dev-Fix-initialisation-order-to-restore-VDUSE-c.patch @@ -0,0 +1,180 @@ +From 9ab31c6abf095d8f7c986676cf6a70132a3441b7 Mon Sep 17 00:00:00 2001 +From: Adttil <2429917001@qq.com> +Date: Tue, 10 Dec 2024 00:33:28 +0800 +Subject: [PATCH] vdpa-dev: Fix initialisation order to restore VDUSE + compatibility +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +VDUSE requires that virtqueues are first enabled before the DRIVER_OK +status flag is set; with the current API of the kernel module, it is +impossible to enable the opposite order in our block export code because +userspace is not notified when a virtqueue is enabled. + +This requirement also mathces the normal initialisation order as done by +the generic vhost code in QEMU. However, commit 6c48254 accidentally +changed the order for vdpa-dev and broke access to VDUSE devices with +this. + +This changes vdpa-dev to use the normal order again and use the standard +vhost callback .vhost_set_vring_enable for this. VDUSE devices can be +used with vdpa-dev again after this fix. + +vhost_net intentionally avoided enabling the vrings for vdpa and does +this manually later while it does enable them for other vhost backends. +Reflect this in the vhost_net code and return early for vdpa, so that +the behaviour doesn't change for this device. + +Cc: qemu-stable@nongnu.org +Fixes: 6c48254 ('vdpa: move vhost_vdpa_set_vring_ready to the caller') +Signed-off-by: Kevin Wolf +Message-ID: <20240315155949.86066-1-kwolf@redhat.com> +Reviewed-by: Eugenio Pérez +Reviewed-by: Stefano Garzarella +Signed-off-by: Kevin Wolf +--- + hw/net/vhost_net.c | 10 ++++++++++ + hw/virtio/trace-events | 2 +- + hw/virtio/vdpa-dev.c | 5 +---- + hw/virtio/vhost-vdpa.c | 29 ++++++++++++++++++++++++++--- + hw/virtio/vhost.c | 8 +++++++- + 5 files changed, 45 insertions(+), 9 deletions(-) + +diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c +index e48c373b14..a02d65d208 100644 +--- a/hw/net/vhost_net.c ++++ b/hw/net/vhost_net.c +@@ -599,6 +599,16 @@ int vhost_set_vring_enable(NetClientState *nc, int enable) + VHostNetState *net = get_vhost_net(nc); + const VhostOps *vhost_ops = net->dev.vhost_ops; + ++ /* ++ * vhost-vdpa network devices need to enable dataplane virtqueues after ++ * DRIVER_OK, so they can recover device state before starting dataplane. ++ * Because of that, we don't enable virtqueues here and leave it to ++ * net/vhost-vdpa.c. ++ */ ++ if (nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { ++ return 0; ++ } ++ + nc->vring_enable = enable; + + if (vhost_ops && vhost_ops->vhost_set_vring_enable) { +diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events +index 637cac4edf..f136815072 100644 +--- a/hw/virtio/trace-events ++++ b/hw/virtio/trace-events +@@ -48,7 +48,7 @@ vhost_vdpa_set_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRI + vhost_vdpa_get_device_id(void *dev, uint32_t device_id) "dev: %p device_id %"PRIu32 + vhost_vdpa_reset_device(void *dev) "dev: %p" + vhost_vdpa_get_vq_index(void *dev, int idx, int vq_idx) "dev: %p idx: %d vq idx: %d" +-vhost_vdpa_set_vring_ready(void *dev, unsigned i, int r) "dev: %p, idx: %u, r: %d" ++vhost_vdpa_set_vring_enable_one(void *dev, unsigned i, int enable, int r) "dev: %p, idx: %u, enable: %u, r: %d" + vhost_vdpa_dump_config(void *dev, const char *line) "dev: %p %s" + vhost_vdpa_set_config(void *dev, uint32_t offset, uint32_t size, uint32_t flags) "dev: %p offset: %"PRIu32" size: %"PRIu32" flags: 0x%"PRIx32 + vhost_vdpa_get_config(void *dev, void *config, uint32_t config_len) "dev: %p config: %p config_len: %"PRIu32 +diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c +index 91e71847b0..7b2b19dfb8 100644 +--- a/hw/virtio/vdpa-dev.c ++++ b/hw/virtio/vdpa-dev.c +@@ -259,14 +259,11 @@ static int vhost_vdpa_device_start(VirtIODevice *vdev, Error **errp) + + s->dev.acked_features = vdev->guest_features; + +- ret = vhost_dev_start(&s->dev, vdev, false); ++ ret = vhost_dev_start(&s->dev, vdev, true); + if (ret < 0) { + error_setg_errno(errp, -ret, "Error starting vhost"); + goto err_guest_notifiers; + } +- for (i = 0; i < s->dev.nvqs; ++i) { +- vhost_vdpa_set_vring_ready(&s->vdpa, i); +- } + s->started = true; + + /* +diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c +index d49826845f..7e172eee49 100644 +--- a/hw/virtio/vhost-vdpa.c ++++ b/hw/virtio/vhost-vdpa.c +@@ -883,12 +883,13 @@ static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, int idx) + return idx; + } + +-int vhost_vdpa_set_vring_ready(struct vhost_vdpa *v, unsigned idx) ++static int vhost_vdpa_set_vring_enable_one(struct vhost_vdpa *v, unsigned idx, ++ int enable) + { + struct vhost_dev *dev = v->dev; + struct vhost_vring_state state = { + .index = idx, +- .num = 1, ++ .num = enable, + }; + hwaddr addr = virtio_queue_get_desc_addr(dev->vdev, idx); + if (addr == 0) { +@@ -897,10 +898,31 @@ int vhost_vdpa_set_vring_ready(struct vhost_vdpa *v, unsigned idx) + + int r = vhost_vdpa_call(dev, VHOST_VDPA_SET_VRING_ENABLE, &state); + +- trace_vhost_vdpa_set_vring_ready(dev, idx, r); ++ trace_vhost_vdpa_set_vring_enable_one(dev, idx, enable, r); + return r; + } + ++static int vhost_vdpa_set_vring_enable(struct vhost_dev *dev, int enable) ++{ ++ struct vhost_vdpa *v = dev->opaque; ++ unsigned int i; ++ int ret; ++ ++ for (i = 0; i < dev->nvqs; ++i) { ++ ret = vhost_vdpa_set_vring_enable_one(v, i, enable); ++ if (ret < 0) { ++ return ret; ++ } ++ } ++ ++ return 0; ++} ++ ++int vhost_vdpa_set_vring_ready(struct vhost_vdpa *v, unsigned idx) ++{ ++ return vhost_vdpa_set_vring_enable_one(v, idx, 1); ++} ++ + static int vhost_vdpa_set_config_call(struct vhost_dev *dev, + int fd) + { +@@ -1584,6 +1606,7 @@ const VhostOps vdpa_ops = { + .vhost_set_features = vhost_vdpa_set_features, + .vhost_reset_device = vhost_vdpa_reset_device, + .vhost_get_vq_index = vhost_vdpa_get_vq_index, ++ .vhost_set_vring_enable = vhost_vdpa_set_vring_enable, + .vhost_get_config = vhost_vdpa_get_config, + .vhost_set_config = vhost_vdpa_set_config, + .vhost_requires_shm_log = NULL, +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index d073a6d5a5..d29075aa04 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -2063,7 +2063,13 @@ static int vhost_dev_set_vring_enable(struct vhost_dev *hdev, int enable) + return hdev->vhost_ops->vhost_set_vring_enable(hdev, enable); + } + +-/* Host notifiers must be enabled at this point. */ ++/* ++ * Host notifiers must be enabled at this point. ++ * ++ * If @vrings is true, this function will enable all vrings before starting the ++ * device. If it is false, the vring initialization is left to be done by the ++ * caller. ++ */ + int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings) + { + int i, r; +-- +2.41.0.windows.1 + diff --git a/vfio-Only-map-shared-region-for-CSV3-virtual-machine.patch b/vfio-Only-map-shared-region-for-CSV3-virtual-machine.patch new file mode 100644 index 0000000000000000000000000000000000000000..3c0d37715fd29001bbf093f41fb764147e640630 --- /dev/null +++ b/vfio-Only-map-shared-region-for-CSV3-virtual-machine.patch @@ -0,0 +1,397 @@ +From 5631d7e167d87c4e2f9283cfac39f2f4107203cc Mon Sep 17 00:00:00 2001 +From: liuyafei +Date: Mon, 22 May 2023 20:37:40 +0800 +Subject: [PATCH] vfio: Only map shared region for CSV3 virtual machine + +qemu vfio listener map/unmap all of the virtual machine's memory. +It does not work for CSV3 virtual machine, as only shared memory +should be accessed by device. + +Signed-off-by: liuyafei +Signed-off-by: hanliyang +--- + hw/vfio/container.c | 46 +++++++++++- + include/exec/memory.h | 11 +++ + system/memory.c | 18 +++++ + target/i386/csv-sysemu-stub.c | 10 +++ + target/i386/csv.c | 134 ++++++++++++++++++++++++++++++++++ + target/i386/csv.h | 12 +++ + target/i386/kvm/kvm.c | 2 + + 7 files changed, 230 insertions(+), 3 deletions(-) + +diff --git a/hw/vfio/container.c b/hw/vfio/container.c +index 422235a221..77e61cfedd 100644 +--- a/hw/vfio/container.c ++++ b/hw/vfio/container.c +@@ -30,6 +30,7 @@ + #include "qemu/error-report.h" + #include "qemu/range.h" + #include "sysemu/reset.h" ++#include "sysemu/kvm.h" + #include "trace.h" + #include "qapi/error.h" + #include "migration/migration.h" +@@ -534,6 +535,32 @@ static void vfio_free_container(VFIOContainer *container) + g_free(container); + } + ++static SharedRegionListener *g_shl; ++ ++static void shared_memory_listener_register(MemoryListener *listener, ++ AddressSpace *as) ++{ ++ SharedRegionListener *shl; ++ ++ shl = g_new0(SharedRegionListener, 1); ++ ++ shl->listener = listener; ++ shl->as = as; ++ ++ shared_region_register_listener(shl); ++ g_shl = shl; ++} ++ ++static void shared_memory_listener_unregister(void) ++{ ++ SharedRegionListener *shl = g_shl; ++ ++ shared_region_unregister_listener(shl); ++ ++ g_free(shl); ++ g_shl = NULL; ++} ++ + static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, + Error **errp) + { +@@ -681,7 +708,12 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, + + container->listener = vfio_memory_listener; + +- memory_listener_register(&container->listener, container->space->as); ++ if (kvm_csv3_enabled()) { ++ shared_memory_listener_register(&container->listener, ++ container->space->as); ++ } else { ++ memory_listener_register(&container->listener, container->space->as); ++ } + + if (container->error) { + ret = -1; +@@ -697,7 +729,11 @@ listener_release_exit: + QLIST_REMOVE(group, container_next); + QLIST_REMOVE(container, next); + vfio_kvm_device_del_group(group); +- memory_listener_unregister(&container->listener); ++ if (kvm_csv3_enabled()) { ++ shared_memory_listener_unregister(); ++ } else { ++ memory_listener_unregister(&container->listener); ++ } + if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU || + container->iommu_type == VFIO_SPAPR_TCE_IOMMU) { + vfio_spapr_container_deinit(container); +@@ -731,7 +767,11 @@ static void vfio_disconnect_container(VFIOGroup *group) + * group. + */ + if (QLIST_EMPTY(&container->group_list)) { +- memory_listener_unregister(&container->listener); ++ if (kvm_csv3_enabled()) { ++ shared_memory_listener_unregister(); ++ } else { ++ memory_listener_unregister(&container->listener); ++ } + if (container->iommu_type == VFIO_SPAPR_TCE_v2_IOMMU || + container->iommu_type == VFIO_SPAPR_TCE_IOMMU) { + vfio_spapr_container_deinit(container); +diff --git a/include/exec/memory.h b/include/exec/memory.h +index 73d274d8f3..542c9da918 100644 +--- a/include/exec/memory.h ++++ b/include/exec/memory.h +@@ -775,6 +775,17 @@ bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, + ram_addr_t *ram_addr, bool *read_only, + bool *mr_has_discard_manager); + ++typedef struct SharedRegionListener SharedRegionListener; ++struct SharedRegionListener { ++ MemoryListener *listener; ++ AddressSpace *as; ++ QTAILQ_ENTRY(SharedRegionListener) next; ++}; ++ ++void shared_region_register_listener(SharedRegionListener *shl); ++void shared_region_unregister_listener(SharedRegionListener *shl); ++void *shared_region_listeners_get(void); ++ + typedef struct CoalescedMemoryRange CoalescedMemoryRange; + typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd; + +diff --git a/system/memory.c b/system/memory.c +index 1ae03074f3..9db07fd832 100644 +--- a/system/memory.c ++++ b/system/memory.c +@@ -48,6 +48,9 @@ static QTAILQ_HEAD(, MemoryListener) memory_listeners + static QTAILQ_HEAD(, AddressSpace) address_spaces + = QTAILQ_HEAD_INITIALIZER(address_spaces); + ++static QTAILQ_HEAD(, SharedRegionListener) shared_region_listeners ++ = QTAILQ_HEAD_INITIALIZER(shared_region_listeners); ++ + static GHashTable *flat_views; + + typedef struct AddrRange AddrRange; +@@ -2226,6 +2229,21 @@ bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr, + return true; + } + ++void shared_region_register_listener(SharedRegionListener *shl) ++{ ++ QTAILQ_INSERT_TAIL(&shared_region_listeners, shl, next); ++} ++ ++void shared_region_unregister_listener(SharedRegionListener *shl) ++{ ++ QTAILQ_REMOVE(&shared_region_listeners, shl, next); ++} ++ ++void *shared_region_listeners_get(void) ++{ ++ return &shared_region_listeners; ++} ++ + void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client) + { + uint8_t mask = 1 << client; +diff --git a/target/i386/csv-sysemu-stub.c b/target/i386/csv-sysemu-stub.c +index 23d885f0f3..db22c299a6 100644 +--- a/target/i386/csv-sysemu-stub.c ++++ b/target/i386/csv-sysemu-stub.c +@@ -29,3 +29,13 @@ int csv3_launch_encrypt_vmcb(void) + { + g_assert_not_reached(); + } ++ ++int csv3_shared_region_dma_map(uint64_t start, uint64_t end) ++{ ++ return 0; ++} ++ ++void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end) ++{ ++ ++} +diff --git a/target/i386/csv.c b/target/i386/csv.c +index 65d87de003..e4706efa27 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -15,6 +15,7 @@ + #include "qemu/error-report.h" + #include "qapi/error.h" + #include "sysemu/kvm.h" ++#include "exec/address-spaces.h" + + #include + +@@ -67,6 +68,8 @@ csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) + csv3_guest.state = state; + csv3_guest.sev_ioctl = ops->sev_ioctl; + csv3_guest.fw_error_to_str = ops->fw_error_to_str; ++ QTAILQ_INIT(&csv3_guest.dma_map_regions_list); ++ qemu_mutex_init(&csv3_guest.dma_map_regions_list_mutex); + } + return 0; + } +@@ -167,3 +170,134 @@ csv3_launch_encrypt_vmcb(void) + err: + return ret; + } ++ ++int csv3_shared_region_dma_map(uint64_t start, uint64_t end) ++{ ++ MemoryRegionSection section; ++ AddressSpace *as; ++ QTAILQ_HEAD(, SharedRegionListener) *shared_region_listeners; ++ SharedRegionListener *shl; ++ MemoryListener *listener; ++ uint64_t size; ++ Csv3GuestState *s = &csv3_guest; ++ struct dma_map_region *region, *pos; ++ int ret = 0; ++ ++ if (!csv3_enabled()) ++ return 0; ++ ++ if (end <= start) ++ return 0; ++ ++ shared_region_listeners = shared_region_listeners_get(); ++ if (QTAILQ_EMPTY(shared_region_listeners)) ++ return 0; ++ ++ size = end - start; ++ ++ qemu_mutex_lock(&s->dma_map_regions_list_mutex); ++ QTAILQ_FOREACH(pos, &s->dma_map_regions_list, list) { ++ if (start >= (pos->start + pos->size)) { ++ continue; ++ } else if ((start + size) <= pos->start) { ++ break; ++ } else { ++ goto end; ++ } ++ } ++ QTAILQ_FOREACH(shl, shared_region_listeners, next) { ++ listener = shl->listener; ++ as = shl->as; ++ section = memory_region_find(as->root, start, size); ++ if (!section.mr) { ++ goto end; ++ } ++ ++ if (!memory_region_is_ram(section.mr)) { ++ memory_region_unref(section.mr); ++ goto end; ++ } ++ ++ if (listener->region_add) { ++ listener->region_add(listener, §ion); ++ } ++ memory_region_unref(section.mr); ++ } ++ ++ region = g_malloc0(sizeof(*region)); ++ if (!region) { ++ ret = -1; ++ goto end; ++ } ++ region->start = start; ++ region->size = size; ++ ++ if (pos) { ++ QTAILQ_INSERT_BEFORE(pos, region, list); ++ } else { ++ QTAILQ_INSERT_TAIL(&s->dma_map_regions_list, region, list); ++ } ++ ++end: ++ qemu_mutex_unlock(&s->dma_map_regions_list_mutex); ++ return ret; ++} ++ ++void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end) ++{ ++ MemoryRegionSection section; ++ AddressSpace *as; ++ QTAILQ_HEAD(, SharedRegionListener) *shared_region_listeners; ++ SharedRegionListener *shl; ++ MemoryListener *listener; ++ uint64_t size; ++ Csv3GuestState *s = &csv3_guest; ++ struct dma_map_region *pos, *next_pos; ++ ++ if (!csv3_enabled()) ++ return; ++ ++ if (end <= start) ++ return; ++ ++ shared_region_listeners = shared_region_listeners_get(); ++ if (QTAILQ_EMPTY(shared_region_listeners)) ++ return; ++ ++ size = end - start; ++ ++ qemu_mutex_lock(&s->dma_map_regions_list_mutex); ++ QTAILQ_FOREACH_SAFE(pos, &s->dma_map_regions_list, list, next_pos) { ++ uint64_t l, r; ++ uint64_t curr_end = pos->start + pos->size; ++ ++ l = MAX(start, pos->start); ++ r = MIN(start + size, pos->start + pos->size); ++ if (l < r) { ++ if ((start <= pos->start) && (start + size >= pos->start + pos->size)) { ++ QTAILQ_FOREACH(shl, shared_region_listeners, next) { ++ listener = shl->listener; ++ as = shl->as; ++ section = memory_region_find(as->root, pos->start, pos->size); ++ if (!section.mr) { ++ goto end; ++ } ++ if (listener->region_del) { ++ listener->region_del(listener, §ion); ++ } ++ memory_region_unref(section.mr); ++ } ++ ++ QTAILQ_REMOVE(&s->dma_map_regions_list, pos, list); ++ g_free(pos); ++ } ++ break; ++ } ++ if ((start + size) <= curr_end) { ++ break; ++ } ++ } ++end: ++ qemu_mutex_unlock(&s->dma_map_regions_list_mutex); ++ return; ++} +diff --git a/target/i386/csv.h b/target/i386/csv.h +index 3caf216743..12733341b3 100644 +--- a/target/i386/csv.h ++++ b/target/i386/csv.h +@@ -15,6 +15,8 @@ + #define I386_CSV_H + + #include "qapi/qapi-commands-misc-target.h" ++#include "qemu/thread.h" ++#include "qemu/queue.h" + #include "sev.h" + + #define GUEST_POLICY_CSV3_BIT (1 << 6) +@@ -74,12 +76,19 @@ int csv_save_outgoing_cpu_state(QEMUFile *f, uint64_t *bytes_sent); + int csv_load_incoming_cpu_state(QEMUFile *f); + + /* CSV3 */ ++struct dma_map_region { ++ uint64_t start, size; ++ QTAILQ_ENTRY(dma_map_region) list; ++}; ++ + struct Csv3GuestState { + uint32_t policy; + int sev_fd; + void *state; + int (*sev_ioctl)(int fd, int cmd, void *data, int *error); + const char *(*fw_error_to_str)(int code); ++ QTAILQ_HEAD(, dma_map_region) dma_map_regions_list; ++ QemuMutex dma_map_regions_list_mutex; + }; + + typedef struct Csv3GuestState Csv3GuestState; +@@ -90,4 +99,7 @@ extern int csv3_launch_encrypt_vmcb(void); + + int csv3_load_data(uint64_t gpa, uint8_t *ptr, uint64_t len, Error **errp); + ++int csv3_shared_region_dma_map(uint64_t start, uint64_t end); ++void csv3_shared_region_dma_unmap(uint64_t start, uint64_t end); ++ + #endif +diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c +index 2866a6d0ec..925f4f8040 100644 +--- a/target/i386/kvm/kvm.c ++++ b/target/i386/kvm/kvm.c +@@ -5026,8 +5026,10 @@ static int kvm_handle_exit_hypercall(X86CPU *cpu, struct kvm_run *run) + + if (enc) { + sev_remove_shared_regions_list(gfn_start, gfn_end); ++ csv3_shared_region_dma_unmap(gpa, gfn_end << TARGET_PAGE_BITS); + } else { + sev_add_shared_regions_list(gfn_start, gfn_end); ++ csv3_shared_region_dma_map(gpa, gfn_end << TARGET_PAGE_BITS); + } + } + return 0; +-- +2.41.0.windows.1 + diff --git a/vga-Force-full-update-for-CSV3-guest.patch b/vga-Force-full-update-for-CSV3-guest.patch new file mode 100644 index 0000000000000000000000000000000000000000..3c7e89e03d3144c57cc84fe7e4b876e84f13fd37 --- /dev/null +++ b/vga-Force-full-update-for-CSV3-guest.patch @@ -0,0 +1,129 @@ +From b791d13a0630e6640b3c39dc90671a2150734a24 Mon Sep 17 00:00:00 2001 +From: Xin Jiang +Date: Thu, 13 Jul 2023 09:35:10 +0800 +Subject: [PATCH] vga: Force full update for CSV3 guest + +As CSV3's NPT(nested page table) is managed by firmware, VMM is hard +to track the dirty pages of vga buffer. Although VMM could perform +a command to firmware to update read/write attribute of vga buffer +in NPT, it costs more time due to communication between VMM and +firmware. So the simplest method is to fully update vga buffer +always. + +Signed-off-by: Xin Jiang +Signed-off-by: hanliyang +--- + accel/kvm/kvm-all.c | 1 + + accel/stubs/kvm-stub.c | 2 ++ + hw/display/vga.c | 7 +++++++ + include/sysemu/kvm.h | 8 ++++++++ + target/i386/csv.c | 3 +++ + 5 files changed, 21 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 8077630825..8028caddf9 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -103,6 +103,7 @@ bool kvm_allowed; + bool kvm_readonly_mem_allowed; + bool kvm_vm_attributes_allowed; + bool kvm_msi_use_devid; ++bool kvm_csv3_allowed; + bool kvm_has_guest_debug; + static int kvm_sstep_flags; + static bool kvm_immediate_exit; +diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c +index ad39a434c4..b071afee45 100644 +--- a/accel/stubs/kvm-stub.c ++++ b/accel/stubs/kvm-stub.c +@@ -27,6 +27,8 @@ bool kvm_msi_use_devid; + + bool virtcca_cvm_allowed; + ++bool kvm_csv3_allowed; ++ + void kvm_flush_coalesced_mmio_buffer(void) + { + } +diff --git a/hw/display/vga.c b/hw/display/vga.c +index cb6b6ee2ca..3f1358676b 100644 +--- a/hw/display/vga.c ++++ b/hw/display/vga.c +@@ -39,6 +39,8 @@ + #include "migration/vmstate.h" + #include "trace.h" + ++#include "sysemu/kvm.h" ++ + //#define DEBUG_VGA_MEM + //#define DEBUG_VGA_REG + +@@ -1790,6 +1792,11 @@ static void vga_update_display(void *opaque) + s->cursor_blink_time = qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL); + full_update = 1; + } ++ ++ /* Force to full update in CSV guest. */ ++ if (kvm_csv3_enabled()) ++ full_update = 1; ++ + switch(graphic_mode) { + case GMODE_TEXT: + vga_draw_text(s, full_update); +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 31af5f0e24..fd8634cc8f 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -44,6 +44,7 @@ extern bool kvm_gsi_routing_allowed; + extern bool kvm_gsi_direct_mapping; + extern bool kvm_readonly_mem_allowed; + extern bool kvm_msi_use_devid; ++extern bool kvm_csv3_allowed; + + #define kvm_enabled() (kvm_allowed) + #define virtcca_cvm_enabled() (virtcca_cvm_allowed) +@@ -147,6 +148,12 @@ extern bool kvm_msi_use_devid; + */ + #define kvm_msi_devid_required() (kvm_msi_use_devid) + ++/** ++ * kvm_csv3_enabled: ++ * Returns: true if CSV3 feature is used for the VM. ++ */ ++#define kvm_csv3_enabled() (kvm_csv3_allowed) ++ + #else + + #define kvm_enabled() (0) +@@ -163,6 +170,7 @@ extern bool kvm_msi_use_devid; + #define kvm_gsi_direct_mapping() (false) + #define kvm_readonly_mem_enabled() (false) + #define kvm_msi_devid_required() (false) ++#define kvm_csv3_enabled() (false) + + #endif /* CONFIG_KVM_IS_POSSIBLE */ + +diff --git a/target/i386/csv.c b/target/i386/csv.c +index 12282ba451..65d87de003 100644 +--- a/target/i386/csv.c ++++ b/target/i386/csv.c +@@ -14,6 +14,7 @@ + #include "qemu/osdep.h" + #include "qemu/error-report.h" + #include "qapi/error.h" ++#include "sysemu/kvm.h" + + #include + +@@ -60,6 +61,8 @@ csv3_init(uint32_t policy, int fd, void *state, struct sev_ops *ops) + return -1; + } + ++ kvm_csv3_allowed = true; ++ + csv3_guest.sev_fd = fd; + csv3_guest.state = state; + csv3_guest.sev_ioctl = ops->sev_ioctl; +-- +2.41.0.windows.1 +