!1055 [sync] PR-1053: QEMU update to version 8.2.0-26:

From: @openeuler-sync-bot 
Reviewed-by: @imxcc 
Signed-off-by: @imxcc
This commit is contained in:
openeuler-ci-bot 2024-12-12 11:47:26 +00:00 committed by Gitee
commit 4f20e01d35
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
45 changed files with 5370 additions and 1 deletions

View File

@ -0,0 +1,64 @@
From 93e7987cb5a7b33c2d2e0a02b7f310955ca11851 Mon Sep 17 00:00:00 2001
From: Christian Schoenebeck <qemu_oss@crudebyte.com>
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=<optimized out>) 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=<optimized out>,
max_count=<optimized out>) 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 <suda.kyoto@gmail.com>
Tested-by: Akihiro Suda <suda.kyoto@gmail.com>
Signed-off-by: Christian Schoenebeck <qemu_oss@crudebyte.com>
Reviewed-by: Greg Kurz <groug@kaod.org>
Message-Id: <E1t8GnN-002RS8-E2@kylie.crudebyte.com>
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,52 @@
From 378d79fa6b9410af702776ffa93865219f273380 Mon Sep 17 00:00:00 2001
From: Anton Johansson <anjo@rev.ng>
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 <anjo@rev.ng>
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
Message-Id: <20240612133031.15298-1-anjo@rev.ng>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
(cherry picked from commit 3b279f73fa37bec8d3ba04a15f5153d6491cffaf)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,39 @@
From 9a12c439cb9d1e59175be4b96adf0732dca39db3 Mon Sep 17 00:00:00 2001
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
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é <philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20241003234211.53644-3-philmd@linaro.org>
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,211 @@
From ab7c657e05f896600c310c74e7584fc345ff235c Mon Sep 17 00:00:00 2001
From: Zenghui Yu <zenghui.yu@linux.dev>
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 <zenghui.yu@linux.dev>
Reviewed-by: Alexander Graf <agraf@csgraf.de>
Message-id: 20240503153453.54389-1-zenghui.yu@linux.dev
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 19ed42e8adc87a3c739f61608b66a046bb9237e2)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,50 @@
From 322f39889ff60a6fda87d7d95a6f233efb558e8a Mon Sep 17 00:00:00 2001
From: Marco Palumbi <Marco.Palumbi@tii.ae>
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 <Marco.Palumbi@tii.ae>
Message-id: 20240730073123.72992-1-marco@palumbi.it
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 5a558be93ad628e5bed6e0ee062870f49251725c)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,324 @@
From d29bc8738131dcaaa1a1ae2870ea29b59a137f30 Mon Sep 17 00:00:00 2001
From: xiongmengbiao <xiongmengbiao@hygon.cn>
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 <xiongmengbiao@hygon.cn>
---
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

View File

@ -0,0 +1,50 @@
From 1b0d08faf1daaed39809ed1a3516eaa0f7d61534 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
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 <peter.maydell@linaro.org>
Message-Id: <20240731170019.3590563-1-peter.maydell@linaro.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
(cherry picked from commit 9a45b0761628cc59267b3283a85d15294464ac31)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,61 @@
From 20541823659dc78a6a7be427f8fc03ccc58c88d1 Mon Sep 17 00:00:00 2001
From: Andrey Shumilin <shum.sdl@nppct.ru>
Date: Thu, 23 May 2024 16:06:20 +0100
Subject: [PATCH] hw/intc/arm_gic: Fix handling of NS view of GICC_APR<n>
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<n> 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<n>, GICC_NSAPR<n> registers")
Signed-off-by: Andrey Shumilin <shum.sdl@nppct.ru>
[PMM: Rewrote commit message]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Reviewed-by: Alex Bennée<alex.bennee@linaro.org>
(cherry picked from commit daafa78b297291fea36fb4daeed526705fa7c035)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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<n> is the top half of GIC_NSAPR<n> */
- *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<n> is the top half of GIC_NSAPR<n> */
- 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

View File

@ -0,0 +1,212 @@
From ddaa38853d386e5b9f9fa1c3813048872c8ad687 Mon Sep 17 00:00:00 2001
From: niuyongwen <niuyongwen@hygon.cn>
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 <niuyongwen@hygon.cn>
---
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 <sys/ioctl.h>
@@ -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

View File

@ -0,0 +1,123 @@
From 884c4d6bc101454f0e0f3c779bc1155024b056c3 Mon Sep 17 00:00:00 2001
From: xiongmengbiao <xiongmengbiao@hygon.cn>
Date: Wed, 29 May 2024 15:18:55 +0800
Subject: [PATCH] hw/misc: support tkm use mem2 memory
Signed-off-by: xiongmengbiao <xiongmengbiao@hygon.cn>
---
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 <sys/ioctl.h>
#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

View File

@ -0,0 +1,102 @@
From c4423b70160eb7ae91dac9f2cf61513758ee017d Mon Sep 17 00:00:00 2001
From: Klaus Jensen <k.jensen@samsung.com>
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 <jwkozaczuk@gmail.com>
Reviewed-by: Keith Busch <kbusch@kernel.org>
Signed-off-by: Klaus Jensen <k.jensen@samsung.com>
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,44 @@
From e025c40fac7d6cc5b4752c392a9c66a074dcaa0b Mon Sep 17 00:00:00 2001
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
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 <clg@redhat.com>
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Message-ID: <20241103133412.73536-6-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,44 @@
From b85c8374d8b78a6ec1c250bb7562423e6f5d89a0 Mon Sep 17 00:00:00 2001
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
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 <balaton@eik.bme.hu>
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Message-ID: <20241103133412.73536-4-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,44 @@
From 239e256d5510b9aaa3e099359dcda54970e2f08a Mon Sep 17 00:00:00 2001
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
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 <balaton@eik.bme.hu>
Signed-off-by: Bernhard Beschow <shentey@gmail.com>
Message-ID: <20241103133412.73536-5-shentey@gmail.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,111 @@
From a2383a2a0537750794223f21156241b1b1e78d2e Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
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 <kraxel@redhat.com>
Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Message-ID: <20240318155336.156197-2-kraxel@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jason Zeng <jason.zeng@intel.com>
---
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

View File

@ -0,0 +1,79 @@
From 454079664e1492eeb9b90d1d05598e84dc436f11 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,65 @@
From 6c76354fdfbebca55e080fea5ae6bfc8a3db2d91 Mon Sep 17 00:00:00 2001
From: Fabiano Rosas <farosas@suse.de>
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é <berrange@redhat.com>
Reviewed-by: Prasad Pandit <pjp@fedoraproject.org>
Reviewed-by: Peter Xu <peterx@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Fabiano Rosas <farosas@suse.de>
(cherry picked from commit 6d3279655ac49b806265f08415165f471d33e032)
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,35 @@
From 254c67a88ab54fdfe1eb55d7efaf4386a9597cd0 Mon Sep 17 00:00:00 2001
From: tangzhongrui <tangzhongrui@cmss.chinamobile.com>
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 <frolov@swemel.ru>
Link: https://lore.kernel.org/r/20241113140509.325732-2-frolov@swemel.ru
Signed-off-by: Peter Xu <peterx@redhat.com>
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,224 @@
From 91e07a78026caafa181134beeb8c5b79157718ad Mon Sep 17 00:00:00 2001
From: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
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 <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Thomas Huth <huth@tuxfamily.org>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
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 <thuth@redhat.com>
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,37 @@
From 4fc36060bec2ac7de500068211b1282c38e3e073 Mon Sep 17 00:00:00 2001
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
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é <philmd@linaro.org>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20241003234211.53644-2-philmd@linaro.org>
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,48 @@
From 34fc72b12cc4887cb2b551b171f6a76c860b6997 Mon Sep 17 00:00:00 2001
From: Yuquan Wang <wangyuquan1236@phytium.com.cn>
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é <philmd@linaro.org>
(cherry picked from commit aa88f99c87c0e5d195d6d96190374650553ea61f)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -3,7 +3,7 @@
Name: qemu Name: qemu
Version: 8.2.0 Version: 8.2.0
Release: 25 Release: 26
Epoch: 11 Epoch: 11
Summary: QEMU is a generic and open source machine emulator and virtualizer Summary: QEMU is a generic and open source machine emulator and virtualizer
License: GPLv2 and BSD and MIT and CC-BY-SA-4.0 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 Patch0425: Add-virtCCA-Coda-annotation.patch
Patch0426: cvm-Add-support-for-TEE-based-national-encryption-ac.patch Patch0426: cvm-Add-support-for-TEE-based-national-encryption-ac.patch
Patch0427: hw-arm-virt-Keep-Guest-L1-cache-type-consistent-with.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: flex
BuildRequires: gcc BuildRequires: gcc
@ -1038,6 +1082,52 @@ getent passwd qemu >/dev/null || \
%endif %endif
%changelog %changelog
* Thu Dec 12 2024 Jiabo Feng <fengjiabo1@huawei.com> - 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<n>
- 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 <fengjiabo1@huawei.com> - 11:8.2.0-25 * Sat Nov 30 2024 Jiabo Feng <fengjiabo1@huawei.com> - 11:8.2.0-25
- hw/arm/virt:Keep Guest L1 cache type consistent with KVM - hw/arm/virt:Keep Guest L1 cache type consistent with KVM
- cvm : Add support for TEE-based national encryption acceleration. - cvm : Add support for TEE-based national encryption acceleration.

View File

@ -0,0 +1,121 @@
From 4dccc6603af2cd3deefb6ac94c3e7aec4b60485d Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
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 <stefanha@redhat.com>
CC: Daniel P. Berrangé <berrange@redhat.com>
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 <eblake@redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Message-ID: <20240518025246.791593-5-eblake@redhat.com>
(cherry picked from commit 199e84de1c903ba5aa1f7256310bbc4a20dd930b)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,156 @@
From c7fe47e4aab35c1817c4c53f0025a741a9e2ad57 Mon Sep 17 00:00:00 2001
From: Markus Armbruster <armbru@redhat.com>
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 <armbru@redhat.com>
Message-ID: <20240628112756.794237-1-armbru@redhat.com>
Reviewed-by: John Snow <jsnow@redhat.com>
(cherry picked from commit e389929d19a543ea5b34d02553b355f9f1c03162)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,106 @@
From 148e01eba8041bad93081a19a240034bb8138988 Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
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 <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20240625183536.1672454-4-richard.henderson@linaro.org
[PMM: fixed hardcoded tab in test case]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 7619129f0d4a14d918227c5c47ad7433662e9ccc)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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 <assert.h>
+
+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

View File

@ -0,0 +1,106 @@
From b6bfee023b15f25c1db077df7bfd2e9212cda762 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
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 <kraxel@redhat.com>
Message-ID: <20240318155336.156197-3-kraxel@redhat.com>
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
[jz: compatible property for 9.0 machines not included]
Signed-off-by: Jason Zeng <jason.zeng@intel.com>
---
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

View File

@ -0,0 +1,41 @@
From 120d0b9e5c92de91c69fb9fbea038b51c820013d Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,85 @@
From 54648e0e5a45acf2e472430ee83bb8dfa057fb30 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,201 @@
From 4ce59de673b1b190cde76c458ac9e92a6413172d Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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 <linux/kvm.h>
+
+#ifdef CONFIG_NUMA
+#include <numaif.h>
+#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

View File

@ -0,0 +1,166 @@
From 53cba8da8fb18cc9a463ec1f57990e8558cd4008 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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 <linux/kvm.h>
@@ -20,6 +21,7 @@
#include <numaif.h>
#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

View File

@ -0,0 +1,108 @@
From 368bf2c044fcdd21f10545de103af7cd2a5986f9 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,110 @@
From b31be8b06440deccdf00de2a7886d04fe87dc802 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,205 @@
From 3434042340ca031b6d355cc79dd00e166bd2e2fd Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,139 @@
From 0ebf32463e858c5f9cbd98e3f2fe494d0fbea259 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,452 @@
From 13bd2629b78f528b0b4684a643f59d30b7274aa8 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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 <linux/kvm.h>
+#include <linux/psp-sev.h>
#ifdef CONFIG_NUMA
#include <numaif.h>
@@ -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

View File

@ -0,0 +1,35 @@
From a3e8267b93d1e77dc547fff6fb9af6f8d48a674f Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,52 @@
From ed3c233cc00d4c30718fc64b3afc48a51b4eb438 Mon Sep 17 00:00:00 2001
From: jiangxin <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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

View File

@ -0,0 +1,218 @@
From a8a621a06d54b987502d277f33021547d00fd133 Mon Sep 17 00:00:00 2001
From: Keith Packard <keithp@keithp.com>
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 <keithp@keithp.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20230803035231.429697-1-keithp@keithp.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
(cherry picked from commit 5888357942da1fd5a50efb6e4a6af8b1a27a5af8)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,60 @@
From 194c3cadc1879ff4c3d2fc6c5f962ad751c83d9c Mon Sep 17 00:00:00 2001
From: Huang Tao <eric.huang@linux.alibaba.com>
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 <eric.huang@linux.alibaba.com>
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Cc: qemu-stable <qemu-stable@nongnu.org>
Message-ID: <20240325021654.6594-1-eric.huang@linux.alibaba.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
(cherry picked from commit 75115d880c6d396f8a2d56aab8c12236d85a90e0)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,69 @@
From d0b24cfdeb8bd64fa55154d79574352be33ecc51 Mon Sep 17 00:00:00 2001
From: Peter Maydell <peter.maydell@linaro.org>
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 <peter.maydell@linaro.org>
Message-ID: <20241115172515.1229393-1-peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,77 @@
From 6477ff9d89317a6124f3a46215b1567306b6ebe4 Mon Sep 17 00:00:00 2001
From: Richard Henderson <richard.henderson@linaro.org>
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 <gaosong@loongson.cn>
Reported-by: Song Gao <gaosong@loongson.cn>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
(cherry picked from commit 521d7fb3ebdf88112ed13556a93e3037742b9eb8)
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
---
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

View File

@ -0,0 +1,47 @@
From 838c585cf6c899a0b48683a0b46ed01cc24d835c Mon Sep 17 00:00:00 2001
From: Susanooo <zhangchujun_yewu@cmss.chinamobile.com>
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 <marcandre.lureau@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
---
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

View File

@ -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 <kwolf@redhat.com>
Message-ID: <20240315155949.86066-1-kwolf@redhat.com>
Reviewed-by: Eugenio Pérez <eperezma@redhat.com>
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
---
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

View File

@ -0,0 +1,397 @@
From 5631d7e167d87c4e2f9283cfac39f2f4107203cc Mon Sep 17 00:00:00 2001
From: liuyafei <liuyafei@hygon.cn>
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 <liuyafei@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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 <linux/kvm.h>
@@ -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, &section);
+ }
+ 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, &section);
+ }
+ 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

View File

@ -0,0 +1,129 @@
From b791d13a0630e6640b3c39dc90671a2150734a24 Mon Sep 17 00:00:00 2001
From: Xin Jiang <jiangxin@hygon.cn>
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 <jiangxin@hygon.cn>
Signed-off-by: hanliyang <hanliyang@hygon.cn>
---
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 <linux/kvm.h>
@@ -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