Compare commits
10 Commits
30a60a1815
...
3742d1b82c
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3742d1b82c | ||
|
|
04ca9e6c8f | ||
|
|
adb290ce5c | ||
|
|
f45f35e885 | ||
|
|
a02d180542 | ||
|
|
017a1d715c | ||
|
|
702a9cc4e2 | ||
|
|
b6e04df301 | ||
|
|
88e7dc4565 | ||
|
|
9e1fee891e |
64
9pfs-fix-crash-on-Treaddir-request.patch
Normal file
64
9pfs-fix-crash-on-Treaddir-request.patch
Normal 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
|
||||
|
||||
39
Add-virtCCA-Coda-annotation.patch
Normal file
39
Add-virtCCA-Coda-annotation.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 0cf5a4c56d34542bcc2f646446bf54828a51a014 Mon Sep 17 00:00:00 2001
|
||||
From: yangxiangkai <yangxiangkai@huawei.com>
|
||||
Date: Tue, 12 Nov 2024 09:03:51 +0800
|
||||
Subject: [PATCH] Add virtCCA Coda annotation Adjust the position of the
|
||||
security device Signed-off-by: yangxiangkai <yangxiangkai@huawei.com>
|
||||
|
||||
---
|
||||
hw/arm/virt.c | 1 +
|
||||
linux-headers/linux/vfio.h | 2 +-
|
||||
2 files changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index e73a795d3d..a744393f6e 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -162,6 +162,7 @@ static const MemMapEntry base_memmap[] = {
|
||||
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
|
||||
[VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
|
||||
[VIRT_CPUHP_ACPI] = { 0x090c0000, ACPI_CPU_HOTPLUG_REG_LEN},
|
||||
+ /* In the virtCCA scenario, this space is used for MSI interrupt mapping */
|
||||
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
|
||||
[VIRT_CPUFREQ] = { 0x0b000000, 0x00010000 },
|
||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||
diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h
|
||||
index c27a43d74b..5b1e2871af 100644
|
||||
--- a/linux-headers/linux/vfio.h
|
||||
+++ b/linux-headers/linux/vfio.h
|
||||
@@ -225,7 +225,7 @@ struct vfio_device_info {
|
||||
#define VFIO_DEVICE_FLAGS_FSL_MC (1 << 6) /* vfio-fsl-mc device */
|
||||
#define VFIO_DEVICE_FLAGS_CAPS (1 << 7) /* Info supports caps */
|
||||
#define VFIO_DEVICE_FLAGS_CDX (1 << 8) /* vfio-cdx device */
|
||||
-#define VFIO_DEVICE_FLAGS_SECURE (1 << 9) /* secure pci device */
|
||||
+#define VFIO_DEVICE_FLAGS_SECURE (1 << 15) /* secure pci device */
|
||||
__u32 num_regions; /* Max region index + 1 */
|
||||
__u32 num_irqs; /* Max IRQ index + 1 */
|
||||
__u32 cap_offset; /* Offset within info struct of first cap */
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
287
Consider-discard-option-when-writing-zeros.patch
Normal file
287
Consider-discard-option-when-writing-zeros.patch
Normal file
@ -0,0 +1,287 @@
|
||||
From 60b9463e35fe801e49db14539ccb8c9a6057e5c3 Mon Sep 17 00:00:00 2001
|
||||
From: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
Date: Sat, 12 Oct 2024 14:12:17 +0800
|
||||
Subject: [PATCH] Consider discard option when writing zeros
|
||||
|
||||
When opening an image with discard=off, we punch hole in the image when
|
||||
writing zeroes, making the image sparse. This breaks users that want to
|
||||
ensure that writes cannot fail with ENOSPACE by using fully allocated
|
||||
images[1].
|
||||
|
||||
bdrv_co_pwrite_zeroes() correctly disables BDRV_REQ_MAY_UNMAP if we
|
||||
opened the child without discard=unmap or discard=on. But we don't go
|
||||
through this function when accessing the top node. Move the check down
|
||||
to bdrv_co_do_pwrite_zeroes() which seems to be used in all code paths.
|
||||
|
||||
This change implements the documented behavior, punching holes only when
|
||||
opening the image with discard=on or discard=unmap. This may not be the
|
||||
best default but can improve it later.
|
||||
|
||||
The test depends on a file system supporting discard, deallocating the
|
||||
entire file when punching hole with the length of the entire file.
|
||||
Tested with xfs, ext4, and tmpfs.
|
||||
|
||||
[1] https://lists.nongnu.org/archive/html/qemu-discuss/2024-06/msg00003.html
|
||||
|
||||
Signed-off-by: Nir Soffer <nsoffer@redhat.com>
|
||||
Message-id: 20240628202058.1964986-3-nsoffer@redhat.com
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
Signed-off-by: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
---
|
||||
block/io.c | 9 +-
|
||||
tests/qemu-iotests/tests/write-zeroes-unmap | 127 ++++++++++++++++++
|
||||
.../qemu-iotests/tests/write-zeroes-unmap.out | 81 +++++++++++
|
||||
3 files changed, 213 insertions(+), 4 deletions(-)
|
||||
create mode 100644 tests/qemu-iotests/tests/write-zeroes-unmap
|
||||
create mode 100644 tests/qemu-iotests/tests/write-zeroes-unmap.out
|
||||
|
||||
diff --git a/block/io.c b/block/io.c
|
||||
index 7e62fabbf5..a280a5a4c9 100644
|
||||
--- a/block/io.c
|
||||
+++ b/block/io.c
|
||||
@@ -1885,6 +1885,11 @@ bdrv_co_do_pwrite_zeroes(BlockDriverState *bs, int64_t offset, int64_t bytes,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ /* If opened with discard=off we should never unmap. */
|
||||
+ if (!(bs->open_flags & BDRV_O_UNMAP)) {
|
||||
+ flags &= ~BDRV_REQ_MAY_UNMAP;
|
||||
+ }
|
||||
+
|
||||
/* Invalidate the cached block-status data range if this write overlaps */
|
||||
bdrv_bsc_invalidate_range(bs, offset, bytes);
|
||||
|
||||
@@ -2338,10 +2343,6 @@ int coroutine_fn bdrv_co_pwrite_zeroes(BdrvChild *child, int64_t offset,
|
||||
trace_bdrv_co_pwrite_zeroes(child->bs, offset, bytes, flags);
|
||||
assert_bdrv_graph_readable();
|
||||
|
||||
- if (!(child->bs->open_flags & BDRV_O_UNMAP)) {
|
||||
- flags &= ~BDRV_REQ_MAY_UNMAP;
|
||||
- }
|
||||
-
|
||||
return bdrv_co_pwritev(child, offset, bytes, NULL,
|
||||
BDRV_REQ_ZERO_WRITE | flags);
|
||||
}
|
||||
diff --git a/tests/qemu-iotests/tests/write-zeroes-unmap b/tests/qemu-iotests/tests/write-zeroes-unmap
|
||||
new file mode 100644
|
||||
index 0000000000..7cfeeaf839
|
||||
--- /dev/null
|
||||
+++ b/tests/qemu-iotests/tests/write-zeroes-unmap
|
||||
@@ -0,0 +1,127 @@
|
||||
+#!/usr/bin/env bash
|
||||
+# group: quick
|
||||
+#
|
||||
+# Test write zeros unmap.
|
||||
+#
|
||||
+# Copyright (C) Red Hat, Inc.
|
||||
+#
|
||||
+# This program is free software; you can redistribute it and/or modify
|
||||
+# it under the terms of the GNU General Public License as published by
|
||||
+# the Free Software Foundation; either version 2 of the License, or
|
||||
+# (at your option) any later version.
|
||||
+#
|
||||
+# This program is distributed in the hope that it will be useful,
|
||||
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+# GNU General Public License for more details.
|
||||
+#
|
||||
+# You should have received a copy of the GNU General Public License
|
||||
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
+#
|
||||
+
|
||||
+seq="$(basename $0)"
|
||||
+echo "QA output created by $seq"
|
||||
+
|
||||
+trap _cleanup_test_img exit
|
||||
+
|
||||
+# get standard environment, filters and checks
|
||||
+cd ..
|
||||
+. ./common.rc
|
||||
+. ./common.filter
|
||||
+
|
||||
+_supported_fmt raw
|
||||
+_supported_proto file
|
||||
+_supported_os Linux
|
||||
+
|
||||
+create_test_image() {
|
||||
+ _make_test_img -f $IMGFMT 1m
|
||||
+}
|
||||
+
|
||||
+filter_command() {
|
||||
+ _filter_testdir | _filter_qemu_io | _filter_qemu | _filter_hmp
|
||||
+}
|
||||
+
|
||||
+print_disk_usage() {
|
||||
+ du -sh $TEST_IMG | _filter_testdir
|
||||
+}
|
||||
+
|
||||
+echo
|
||||
+echo "=== defaults - write zeros ==="
|
||||
+echo
|
||||
+
|
||||
+create_test_image
|
||||
+echo -e 'qemu-io none0 "write -z 0 1m"\nquit' \
|
||||
+ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT \
|
||||
+ | filter_command
|
||||
+print_disk_usage
|
||||
+
|
||||
+echo
|
||||
+echo "=== defaults - write zeros unmap ==="
|
||||
+echo
|
||||
+
|
||||
+create_test_image
|
||||
+echo -e 'qemu-io none0 "write -zu 0 1m"\nquit' \
|
||||
+ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT \
|
||||
+ | filter_command
|
||||
+print_disk_usage
|
||||
+
|
||||
+
|
||||
+echo
|
||||
+echo "=== defaults - write actual zeros ==="
|
||||
+echo
|
||||
+
|
||||
+create_test_image
|
||||
+echo -e 'qemu-io none0 "write -P 0 0 1m"\nquit' \
|
||||
+ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT \
|
||||
+ | filter_command
|
||||
+print_disk_usage
|
||||
+
|
||||
+echo
|
||||
+echo "=== discard=off - write zeroes unmap ==="
|
||||
+echo
|
||||
+
|
||||
+create_test_image
|
||||
+echo -e 'qemu-io none0 "write -zu 0 1m"\nquit' \
|
||||
+ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,discard=off \
|
||||
+ | filter_command
|
||||
+print_disk_usage
|
||||
+
|
||||
+echo
|
||||
+echo "=== detect-zeroes=on - write actual zeros ==="
|
||||
+echo
|
||||
+
|
||||
+create_test_image
|
||||
+echo -e 'qemu-io none0 "write -P 0 0 1m"\nquit' \
|
||||
+ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,detect-zeroes=on \
|
||||
+ | filter_command
|
||||
+print_disk_usage
|
||||
+
|
||||
+echo
|
||||
+echo "=== detect-zeroes=on,discard=on - write actual zeros ==="
|
||||
+echo
|
||||
+
|
||||
+create_test_image
|
||||
+echo -e 'qemu-io none0 "write -P 0 0 1m"\nquit' \
|
||||
+ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,detect-zeroes=on,discard=on \
|
||||
+ | filter_command
|
||||
+print_disk_usage
|
||||
+
|
||||
+echo
|
||||
+echo "=== discard=on - write zeroes ==="
|
||||
+echo
|
||||
+
|
||||
+create_test_image
|
||||
+echo -e 'qemu-io none0 "write -z 0 1m"\nquit' \
|
||||
+ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,discard=on \
|
||||
+ | filter_command
|
||||
+print_disk_usage
|
||||
+
|
||||
+echo
|
||||
+echo "=== discard=on - write zeroes unmap ==="
|
||||
+echo
|
||||
+
|
||||
+create_test_image
|
||||
+echo -e 'qemu-io none0 "write -zu 0 1m"\nquit' \
|
||||
+ | $QEMU -monitor stdio -drive if=none,file=$TEST_IMG,format=$IMGFMT,discard=on \
|
||||
+ | filter_command
|
||||
+print_disk_usage
|
||||
diff --git a/tests/qemu-iotests/tests/write-zeroes-unmap.out b/tests/qemu-iotests/tests/write-zeroes-unmap.out
|
||||
new file mode 100644
|
||||
index 0000000000..c931994897
|
||||
--- /dev/null
|
||||
+++ b/tests/qemu-iotests/tests/write-zeroes-unmap.out
|
||||
@@ -0,0 +1,81 @@
|
||||
+QA output created by write-zeroes-unmap
|
||||
+
|
||||
+=== defaults - write zeros ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+QEMU X.Y.Z monitor - type 'help' for more information
|
||||
+(qemu) qemu-io none0 "write -z 0 1m"
|
||||
+wrote 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+(qemu) quit
|
||||
+1.0M TEST_DIR/t.raw
|
||||
+
|
||||
+=== defaults - write zeros unmap ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+QEMU X.Y.Z monitor - type 'help' for more information
|
||||
+(qemu) qemu-io none0 "write -zu 0 1m"
|
||||
+wrote 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+(qemu) quit
|
||||
+1.0M TEST_DIR/t.raw
|
||||
+
|
||||
+=== defaults - write actual zeros ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+QEMU X.Y.Z monitor - type 'help' for more information
|
||||
+(qemu) qemu-io none0 "write -P 0 0 1m"
|
||||
+wrote 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+(qemu) quit
|
||||
+1.0M TEST_DIR/t.raw
|
||||
+
|
||||
+=== discard=off - write zeroes unmap ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+QEMU X.Y.Z monitor - type 'help' for more information
|
||||
+(qemu) qemu-io none0 "write -zu 0 1m"
|
||||
+wrote 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+(qemu) quit
|
||||
+1.0M TEST_DIR/t.raw
|
||||
+
|
||||
+=== detect-zeroes=on - write actual zeros ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+QEMU X.Y.Z monitor - type 'help' for more information
|
||||
+(qemu) qemu-io none0 "write -P 0 0 1m"
|
||||
+wrote 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+(qemu) quit
|
||||
+1.0M TEST_DIR/t.raw
|
||||
+
|
||||
+=== detect-zeroes=on,discard=on - write actual zeros ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+QEMU X.Y.Z monitor - type 'help' for more information
|
||||
+(qemu) qemu-io none0 "write -P 0 0 1m"
|
||||
+wrote 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+(qemu) quit
|
||||
+1.0M TEST_DIR/t.raw
|
||||
+
|
||||
+=== discard=on - write zeroes ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+QEMU X.Y.Z monitor - type 'help' for more information
|
||||
+(qemu) qemu-io none0 "write -z 0 1m"
|
||||
+wrote 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+(qemu) quit
|
||||
+1.0M TEST_DIR/t.raw
|
||||
+
|
||||
+=== discard=on - write zeroes unmap ===
|
||||
+
|
||||
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576
|
||||
+QEMU X.Y.Z monitor - type 'help' for more information
|
||||
+(qemu) qemu-io none0 "write -zu 0 1m"
|
||||
+wrote 1048576/1048576 bytes at offset 0
|
||||
+1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
|
||||
+(qemu) quit
|
||||
+0 TEST_DIR/t.raw
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
35
Fix-calculation-of-minimum-in-colo_compare_tcp.patch
Normal file
35
Fix-calculation-of-minimum-in-colo_compare_tcp.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From f6ad72a5b215bc5b2d8df86cd537bf1c0f468108 Mon Sep 17 00:00:00 2001
|
||||
From: zhangchujun <zhangchujun@cmss.chinamobile.com>
|
||||
Date: Wed, 30 Oct 2024 13:33:58 +0800
|
||||
Subject: [PATCH] Fix calculation of minimum in colo_compare_tcp
|
||||
|
||||
GitHub's CodeQL reports a critical error which is fixed by using the MIN macro:
|
||||
|
||||
Unsigned difference expression compared to zero
|
||||
|
||||
Signed-off-by: Stefan Weil <sw@weilnetz.de>
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Reviewed-by: Zhang Chen <chen.zhang@intel.com>
|
||||
Signed-off-by: Jason Wang <jasowang@redhat.com>
|
||||
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
net/colo-compare.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
diff --git a/net/colo-compare.c b/net/colo-compare.c
|
||||
index 7f9e6f89ce..d4e51cb306 100644
|
||||
--- a/net/colo-compare.c
|
||||
+++ b/net/colo-compare.c
|
||||
@@ -413,8 +413,7 @@ static void colo_compare_tcp(CompareState *s, Connection *conn)
|
||||
* can ensure that the packet's payload is acknowledged by
|
||||
* primary and secondary.
|
||||
*/
|
||||
- uint32_t min_ack = conn->pack - conn->sack > 0 ?
|
||||
- conn->sack : conn->pack;
|
||||
+ uint32_t min_ack = MIN(conn->pack, conn->sack);
|
||||
|
||||
pri:
|
||||
if (g_queue_is_empty(&conn->primary_list)) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
48
Revert-vdpa-add-vhost_vdpa-suspended-parameter.patch
Normal file
48
Revert-vdpa-add-vhost_vdpa-suspended-parameter.patch
Normal file
@ -0,0 +1,48 @@
|
||||
From e1f733fcbc4eb39333ad9527865c1590d74092ed Mon Sep 17 00:00:00 2001
|
||||
From: fangyi <eric.fangyi@huawei.com>
|
||||
Date: Tue, 29 Oct 2024 19:53:27 +0800
|
||||
Subject: [PATCH 4/6] Revert "vdpa: add vhost_vdpa->suspended parameter"
|
||||
|
||||
Use a new scheme instead for kernel vdpa, So revert it.
|
||||
|
||||
This reverts commit b6662cb7e5376659c7abb56efe27dcf3898d4fe6.
|
||||
---
|
||||
hw/virtio/vhost-vdpa.c | 8 --------
|
||||
include/hw/virtio/vhost-vdpa.h | 2 --
|
||||
2 files changed, 10 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
|
||||
index 130afb06dc..bb3320946d 100644
|
||||
--- a/hw/virtio/vhost-vdpa.c
|
||||
+++ b/hw/virtio/vhost-vdpa.c
|
||||
@@ -1406,14 +1406,6 @@ static int vhost_vdpa_get_vring_base(struct vhost_dev *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
- if (!v->suspended) {
|
||||
- /*
|
||||
- * Cannot trust in value returned by device, let vhost recover used
|
||||
- * idx from guest.
|
||||
- */
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
ret = vhost_vdpa_call(dev, VHOST_GET_VRING_BASE, ring);
|
||||
trace_vhost_vdpa_get_vring_base(dev, ring->index, ring->num);
|
||||
return ret;
|
||||
diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h
|
||||
index 5407d54fd7..ee255bc1bd 100644
|
||||
--- a/include/hw/virtio/vhost-vdpa.h
|
||||
+++ b/include/hw/virtio/vhost-vdpa.h
|
||||
@@ -42,8 +42,6 @@ typedef struct vhost_vdpa {
|
||||
bool shadow_vqs_enabled;
|
||||
/* Vdpa must send shadow addresses as IOTLB key for data queues, not GPA */
|
||||
bool shadow_data;
|
||||
- /* Device suspended successfully */
|
||||
- bool suspended;
|
||||
/* IOVA mapping used by the Shadow Virtqueue */
|
||||
VhostIOVATree *iova_tree;
|
||||
GPtrArray *shadow_vqs;
|
||||
--
|
||||
2.43.0
|
||||
|
||||
84
Revert-vdpa-add-vhost_vdpa_suspend.patch
Normal file
84
Revert-vdpa-add-vhost_vdpa_suspend.patch
Normal file
@ -0,0 +1,84 @@
|
||||
From 05ee3017d156005e3d8d8fb19514d593858abd44 Mon Sep 17 00:00:00 2001
|
||||
From: fangyi <eric.fangyi@huawei.com>
|
||||
Date: Tue, 29 Oct 2024 19:51:41 +0800
|
||||
Subject: [PATCH 3/6] Revert "vdpa: add vhost_vdpa_suspend"
|
||||
|
||||
Use a new scheme instead for kernel vdpa, So revert it.
|
||||
|
||||
This reverts commit 0bb302a9960a186fc488068d268dc373e6b70876.
|
||||
---
|
||||
hw/virtio/trace-events | 1 -
|
||||
hw/virtio/vhost-vdpa.c | 26 --------------------------
|
||||
2 files changed, 27 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events
|
||||
index 637cac4edf..de02bdc1d0 100644
|
||||
--- a/hw/virtio/trace-events
|
||||
+++ b/hw/virtio/trace-events
|
||||
@@ -52,7 +52,6 @@ vhost_vdpa_set_vring_ready(void *dev, unsigned i, int r) "dev: %p, idx: %u, r: %
|
||||
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
|
||||
-vhost_vdpa_suspend(void *dev) "dev: %p"
|
||||
vhost_vdpa_dev_start(void *dev, bool started) "dev: %p started: %d"
|
||||
vhost_vdpa_set_log_base(void *dev, uint64_t base, unsigned long long size, int refcnt, int fd, void *log) "dev: %p base: 0x%"PRIx64" size: %llu refcnt: %d fd: %d log: %p"
|
||||
vhost_vdpa_set_vring_addr(void *dev, unsigned int index, unsigned int flags, uint64_t desc_user_addr, uint64_t used_user_addr, uint64_t avail_user_addr, uint64_t log_guest_addr) "dev: %p index: %u flags: 0x%x desc_user_addr: 0x%"PRIx64" used_user_addr: 0x%"PRIx64" avail_user_addr: 0x%"PRIx64" log_guest_addr: 0x%"PRIx64
|
||||
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
|
||||
index d49826845f..130afb06dc 100644
|
||||
--- a/hw/virtio/vhost-vdpa.c
|
||||
+++ b/hw/virtio/vhost-vdpa.c
|
||||
@@ -865,13 +865,11 @@ static int vhost_vdpa_get_device_id(struct vhost_dev *dev,
|
||||
|
||||
static int vhost_vdpa_reset_device(struct vhost_dev *dev)
|
||||
{
|
||||
- struct vhost_vdpa *v = dev->opaque;
|
||||
int ret;
|
||||
uint8_t status = 0;
|
||||
|
||||
ret = vhost_vdpa_call(dev, VHOST_VDPA_SET_STATUS, &status);
|
||||
trace_vhost_vdpa_reset_device(dev);
|
||||
- v->suspended = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1274,29 +1272,6 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev)
|
||||
}
|
||||
}
|
||||
|
||||
-static void vhost_vdpa_suspend(struct vhost_dev *dev)
|
||||
-{
|
||||
- struct vhost_vdpa *v = dev->opaque;
|
||||
- int r;
|
||||
-
|
||||
- if (!vhost_vdpa_first_dev(dev)) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (dev->backend_cap & BIT_ULL(VHOST_BACKEND_F_SUSPEND)) {
|
||||
- trace_vhost_vdpa_suspend(dev);
|
||||
- r = ioctl(v->device_fd, VHOST_VDPA_SUSPEND);
|
||||
- if (unlikely(r)) {
|
||||
- error_report("Cannot suspend: %s(%d)", g_strerror(errno), errno);
|
||||
- } else {
|
||||
- v->suspended = true;
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- vhost_vdpa_reset_device(dev);
|
||||
-}
|
||||
-
|
||||
static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
|
||||
{
|
||||
struct vhost_vdpa *v = dev->opaque;
|
||||
@@ -1310,7 +1285,6 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
- vhost_vdpa_suspend(dev);
|
||||
vhost_vdpa_svqs_stop(dev);
|
||||
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
|
||||
}
|
||||
--
|
||||
2.43.0
|
||||
|
||||
42
Revert-vdpa-block-migration-if-SVQ-does-not-admit-a-.patch
Normal file
42
Revert-vdpa-block-migration-if-SVQ-does-not-admit-a-.patch
Normal file
@ -0,0 +1,42 @@
|
||||
From 4a79b3c07dca4f1e21e4dbb1e59bf437b2a814fa Mon Sep 17 00:00:00 2001
|
||||
From: fangyi <eric.fangyi@huawei.com>
|
||||
Date: Tue, 29 Oct 2024 19:58:14 +0800
|
||||
Subject: [PATCH 5/6] Revert "vdpa: block migration if SVQ does not admit a
|
||||
feature"
|
||||
|
||||
Use a new scheme instead for kernel vdpa, So revert it.
|
||||
|
||||
This reverts commit 57ac831865e370012496fb581a38d261cb72c5d0.
|
||||
---
|
||||
hw/virtio/vhost-vdpa.c | 15 ---------------
|
||||
1 file changed, 15 deletions(-)
|
||||
|
||||
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
|
||||
index bb3320946d..69cf3b76e9 100644
|
||||
--- a/hw/virtio/vhost-vdpa.c
|
||||
+++ b/hw/virtio/vhost-vdpa.c
|
||||
@@ -596,21 +596,6 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque, Error **errp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
- /*
|
||||
- * If dev->shadow_vqs_enabled at initialization that means the device has
|
||||
- * been started with x-svq=on, so don't block migration
|
||||
- */
|
||||
- if (dev->migration_blocker == NULL && !v->shadow_vqs_enabled) {
|
||||
- /* We don't have dev->features yet */
|
||||
- uint64_t features;
|
||||
- ret = vhost_vdpa_get_dev_features(dev, &features);
|
||||
- if (unlikely(ret)) {
|
||||
- error_setg_errno(errp, -ret, "Could not get device features");
|
||||
- return ret;
|
||||
- }
|
||||
- vhost_svq_valid_features(features, &dev->migration_blocker);
|
||||
- }
|
||||
-
|
||||
/*
|
||||
* Similar to VFIO, we end up pinning all guest memory and have to
|
||||
* disable discarding of RAM.
|
||||
--
|
||||
2.43.0
|
||||
|
||||
@ -0,0 +1,236 @@
|
||||
From 2464d0d6115e1794468ff455e3acdb98e0d71a31 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 16 Jul 2024 12:14:56 +0100
|
||||
Subject: [PATCH 62/78] accel/kvm: Extract common KVM vCPU {creation,parking}
|
||||
code
|
||||
|
||||
KVM vCPU creation is done once during the vCPU realization when Qemu vCPU thread
|
||||
is spawned. This is common to all the architectures as of now.
|
||||
|
||||
Hot-unplug of vCPU results in destruction of the vCPU object in QOM but the
|
||||
corresponding KVM vCPU object in the Host KVM is not destroyed as KVM doesn't
|
||||
support vCPU removal. Therefore, its representative KVM vCPU object/context in
|
||||
Qemu is parked.
|
||||
|
||||
Refactor architecture common logic so that some APIs could be reused by vCPU
|
||||
Hotplug code of some architectures likes ARM, Loongson etc. Update new/old APIs
|
||||
with trace events. New APIs qemu_{create,park,unpark}_vcpu() can be externally
|
||||
called. No functional change is intended here.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Reviewed-by: Gavin Shan <gshan@redhat.com>
|
||||
Tested-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Tested-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Tested-by: Miguel Luis <miguel.luis@oracle.com>
|
||||
Reviewed-by: Shaoqin Huang <shahuang@redhat.com>
|
||||
Reviewed-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
Reviewed-by: Nicholas Piggin <npiggin@gmail.com>
|
||||
Tested-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Reviewed-by: Harsh Prateek Bora <harshpb@linux.ibm.com>
|
||||
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Message-Id: <20240716111502.202344-2-salil.mehta@huawei.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 71 +++++++++++++++++++++---------------------
|
||||
accel/kvm/trace-events | 11 +++++++
|
||||
include/sysemu/kvm.h | 27 ++++++++++++++--
|
||||
3 files changed, 71 insertions(+), 38 deletions(-)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 8077630825..8dea8f98bb 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -141,7 +141,6 @@ static QemuMutex kml_slots_lock;
|
||||
#define kvm_slots_unlock() qemu_mutex_unlock(&kml_slots_lock)
|
||||
|
||||
static void kvm_slot_init_dirty_bitmap(KVMSlot *mem);
|
||||
-static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id);
|
||||
|
||||
static inline void kvm_resample_fd_remove(int gsi)
|
||||
{
|
||||
@@ -334,39 +333,57 @@ void kvm_park_vcpu(CPUState *cpu)
|
||||
{
|
||||
struct KVMParkedVcpu *vcpu;
|
||||
|
||||
+ trace_kvm_park_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
|
||||
+
|
||||
vcpu = g_malloc0(sizeof(*vcpu));
|
||||
vcpu->vcpu_id = kvm_arch_vcpu_id(cpu);
|
||||
vcpu->kvm_fd = cpu->kvm_fd;
|
||||
QLIST_INSERT_HEAD(&kvm_state->kvm_parked_vcpus, vcpu, node);
|
||||
}
|
||||
|
||||
+int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id)
|
||||
+{
|
||||
+ struct KVMParkedVcpu *cpu;
|
||||
+ int kvm_fd = -ENOENT;
|
||||
+
|
||||
+ QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) {
|
||||
+ if (cpu->vcpu_id == vcpu_id) {
|
||||
+ QLIST_REMOVE(cpu, node);
|
||||
+ kvm_fd = cpu->kvm_fd;
|
||||
+ g_free(cpu);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ trace_kvm_unpark_vcpu(vcpu_id, kvm_fd > 0 ? "unparked" : "!found parked");
|
||||
+
|
||||
+ return kvm_fd;
|
||||
+}
|
||||
+
|
||||
int kvm_create_vcpu(CPUState *cpu)
|
||||
{
|
||||
- unsigned long vcpu_id = cpu->cpu_index;
|
||||
+ unsigned long vcpu_id = kvm_arch_vcpu_id(cpu);
|
||||
KVMState *s = kvm_state;
|
||||
- int ret;
|
||||
-
|
||||
- DPRINTF("kvm_create_vcpu\n");
|
||||
+ int kvm_fd;
|
||||
|
||||
/* check if the KVM vCPU already exist but is parked */
|
||||
- ret = kvm_get_vcpu(s, kvm_arch_vcpu_id(cpu));
|
||||
- if (ret > 0) {
|
||||
- goto found;
|
||||
- }
|
||||
-
|
||||
- /* create a new KVM vcpu */
|
||||
- ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, (void *)vcpu_id);
|
||||
- if (ret < 0) {
|
||||
- return ret;
|
||||
+ kvm_fd = kvm_unpark_vcpu(s, vcpu_id);
|
||||
+ if (kvm_fd < 0) {
|
||||
+ /* vCPU not parked: create a new KVM vCPU */
|
||||
+ kvm_fd = kvm_vm_ioctl(s, KVM_CREATE_VCPU, vcpu_id);
|
||||
+ if (kvm_fd < 0) {
|
||||
+ error_report("KVM_CREATE_VCPU IOCTL failed for vCPU %lu", vcpu_id);
|
||||
+ return kvm_fd;
|
||||
+ }
|
||||
}
|
||||
|
||||
-found:
|
||||
- cpu->vcpu_dirty = true;
|
||||
- cpu->kvm_fd = ret;
|
||||
+ cpu->kvm_fd = kvm_fd;
|
||||
cpu->kvm_state = s;
|
||||
+ cpu->vcpu_dirty = true;
|
||||
cpu->dirty_pages = 0;
|
||||
cpu->throttle_us_per_full = 0;
|
||||
|
||||
+ trace_kvm_create_vcpu(cpu->cpu_index, vcpu_id, kvm_fd);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -376,7 +393,7 @@ static int do_kvm_destroy_vcpu(CPUState *cpu)
|
||||
long mmap_size;
|
||||
int ret = 0;
|
||||
|
||||
- DPRINTF("kvm_destroy_vcpu\n");
|
||||
+ trace_kvm_destroy_vcpu(cpu->cpu_index, kvm_arch_vcpu_id(cpu));
|
||||
|
||||
ret = kvm_arch_destroy_vcpu(cpu);
|
||||
if (ret < 0) {
|
||||
@@ -415,24 +432,6 @@ void kvm_destroy_vcpu(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
-static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id)
|
||||
-{
|
||||
- struct KVMParkedVcpu *cpu;
|
||||
-
|
||||
- QLIST_FOREACH(cpu, &s->kvm_parked_vcpus, node) {
|
||||
- if (cpu->vcpu_id == vcpu_id) {
|
||||
- int kvm_fd;
|
||||
-
|
||||
- QLIST_REMOVE(cpu, node);
|
||||
- kvm_fd = cpu->kvm_fd;
|
||||
- g_free(cpu);
|
||||
- return kvm_fd;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return -1;
|
||||
-}
|
||||
-
|
||||
int kvm_init_vcpu(CPUState *cpu, Error **errp)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
diff --git a/accel/kvm/trace-events b/accel/kvm/trace-events
|
||||
index 399aaeb0ec..9c880fdcf4 100644
|
||||
--- a/accel/kvm/trace-events
|
||||
+++ b/accel/kvm/trace-events
|
||||
@@ -9,6 +9,10 @@ kvm_device_ioctl(int fd, int type, void *arg) "dev fd %d, type 0x%x, arg %p"
|
||||
kvm_failed_reg_get(uint64_t id, const char *msg) "Warning: Unable to retrieve ONEREG %" PRIu64 " from KVM: %s"
|
||||
kvm_failed_reg_set(uint64_t id, const char *msg) "Warning: Unable to set ONEREG %" PRIu64 " to KVM: %s"
|
||||
kvm_init_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
|
||||
+kvm_create_vcpu(int cpu_index, unsigned long arch_cpu_id, int kvm_fd) "index: %d, id: %lu, kvm fd: %d"
|
||||
+kvm_destroy_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
|
||||
+kvm_park_vcpu(int cpu_index, unsigned long arch_cpu_id) "index: %d id: %lu"
|
||||
+kvm_unpark_vcpu(unsigned long arch_cpu_id, const char *msg) "id: %lu %s"
|
||||
kvm_irqchip_commit_routes(void) ""
|
||||
kvm_irqchip_add_msi_route(char *name, int vector, int virq) "dev %s vector %d virq %d"
|
||||
kvm_irqchip_update_msi_route(int virq) "Updating MSI route virq=%d"
|
||||
@@ -26,3 +30,10 @@ kvm_dirty_ring_reap(uint64_t count, int64_t t) "reaped %"PRIu64" pages (took %"P
|
||||
kvm_dirty_ring_reaper_kick(const char *reason) "%s"
|
||||
kvm_dirty_ring_flush(int finished) "%d"
|
||||
|
||||
+kvm_failed_get_vcpu_mmap_size(void) ""
|
||||
+kvm_cpu_exec(void) ""
|
||||
+kvm_interrupt_exit_request(void) ""
|
||||
+kvm_io_window_exit(void) ""
|
||||
+kvm_run_exit_system_event(int cpu_index, uint32_t event_type) "cpu_index %d, system_even_type %"PRIu32
|
||||
+kvm_convert_memory(uint64_t start, uint64_t size, const char *msg) "start 0x%" PRIx64 " size 0x%" PRIx64 " %s"
|
||||
+kvm_memory_fault(uint64_t start, uint64_t size, uint64_t flags) "start 0x%" PRIx64 " size 0x%" PRIx64 " flags 0x%" PRIx64
|
||||
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
|
||||
index 31af5f0e24..7ffb5e4992 100644
|
||||
--- a/include/sysemu/kvm.h
|
||||
+++ b/include/sysemu/kvm.h
|
||||
@@ -319,6 +319,31 @@ int kvm_create_device(KVMState *s, uint64_t type, bool test);
|
||||
*/
|
||||
bool kvm_device_supported(int vmfd, uint64_t type);
|
||||
|
||||
+/**
|
||||
+ * kvm_create_vcpu - Gets a parked KVM vCPU or creates a KVM vCPU
|
||||
+ * @cpu: QOM CPUState object for which KVM vCPU has to be fetched/created.
|
||||
+ *
|
||||
+ * @returns: 0 when success, errno (<0) when failed.
|
||||
+ */
|
||||
+int kvm_create_vcpu(CPUState *cpu);
|
||||
+
|
||||
+/**
|
||||
+ * kvm_park_vcpu - Park QEMU KVM vCPU context
|
||||
+ * @cpu: QOM CPUState object for which QEMU KVM vCPU context has to be parked.
|
||||
+ *
|
||||
+ * @returns: none
|
||||
+ */
|
||||
+void kvm_park_vcpu(CPUState *cpu);
|
||||
+
|
||||
+/**
|
||||
+ * kvm_unpark_vcpu - unpark QEMU KVM vCPU context
|
||||
+ * @s: KVM State
|
||||
+ * @vcpu_id: Architecture vCPU ID of the parked vCPU
|
||||
+ *
|
||||
+ * @returns: KVM fd
|
||||
+ */
|
||||
+int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id);
|
||||
+
|
||||
/* Arch specific hooks */
|
||||
|
||||
extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
|
||||
@@ -440,8 +465,6 @@ void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len);
|
||||
|
||||
int kvm_physical_memory_addr_from_host(KVMState *s, void *ram_addr,
|
||||
hwaddr *phys_addr);
|
||||
-int kvm_create_vcpu(CPUState *cpu);
|
||||
-void kvm_park_vcpu(CPUState *cpu);
|
||||
|
||||
#endif /* NEED_CPU_H */
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
46
accel-kvm-kvm-all-Fixes-the-missing-break-in-vCPU-un.patch
Normal file
46
accel-kvm-kvm-all-Fixes-the-missing-break-in-vCPU-un.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 9bbc73e18d36d75c5dd842e478ed1f1b47ed4222 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Thu, 1 Aug 2024 10:15:03 +0100
|
||||
Subject: [PATCH 68/78] accel/kvm/kvm-all: Fixes the missing break in vCPU
|
||||
unpark logic
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Loop should exit prematurely on successfully finding out the parked vCPU (struct
|
||||
KVMParkedVcpu) in the 'struct KVMState' maintained 'kvm_parked_vcpus' list of
|
||||
parked vCPUs.
|
||||
|
||||
Fixes: Coverity CID 1558552
|
||||
Fixes: 08c3286822 ("accel/kvm: Extract common KVM vCPU {creation,parking} code")
|
||||
Reported-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Gavin Shan <gshan@redhat.com>
|
||||
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Message-id: 20240725145132.99355-1-salil.mehta@huawei.com
|
||||
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Message-ID: <CAFEAcA-3_d1c7XSXWkFubD-LsW5c5i95e6xxV09r2C9yGtzcdA@mail.gmail.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
accel/kvm/kvm-all.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
|
||||
index 8dea8f98bb..79d5671841 100644
|
||||
--- a/accel/kvm/kvm-all.c
|
||||
+++ b/accel/kvm/kvm-all.c
|
||||
@@ -351,6 +351,7 @@ int kvm_unpark_vcpu(KVMState *s, unsigned long vcpu_id)
|
||||
QLIST_REMOVE(cpu, node);
|
||||
kvm_fd = cpu->kvm_fd;
|
||||
g_free(cpu);
|
||||
+ break;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
52
accel-tcg-Fix-typo-causing-tb-page_addr-1-to-not-be-.patch
Normal file
52
accel-tcg-Fix-typo-causing-tb-page_addr-1-to-not-be-.patch
Normal 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
|
||||
|
||||
59
acpi-ged-Add-macro-for-acpi-sleep-control-register.patch
Normal file
59
acpi-ged-Add-macro-for-acpi-sleep-control-register.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 07fa80eacaa17d3cc3865050244b79d39cc61944 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
Date: Wed, 23 Oct 2024 14:34:56 +0800
|
||||
Subject: [PATCH] acpi: ged: Add macro for acpi sleep control register
|
||||
|
||||
cheery-pick from edafc90ba481c586d0a649f34dcb8cd1f29c4259
|
||||
|
||||
Macro definition is added for acpi sleep control register, ged emulation
|
||||
driver can use the macro , also it can be used in FDT table if ged is
|
||||
exposed with FDT table.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Message-Id: <20240918014206.2165821-2-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/acpi/generic_event_device.c | 6 +++---
|
||||
include/hw/acpi/generic_event_device.h | 7 +++++--
|
||||
2 files changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
||||
index 4731a614a3..2ce7031f1a 100644
|
||||
--- a/hw/acpi/generic_event_device.c
|
||||
+++ b/hw/acpi/generic_event_device.c
|
||||
@@ -203,9 +203,9 @@ static void ged_regs_write(void *opaque, hwaddr addr, uint64_t data,
|
||||
|
||||
switch (addr) {
|
||||
case ACPI_GED_REG_SLEEP_CTL:
|
||||
- slp_typ = (data >> 2) & 0x07;
|
||||
- slp_en = (data >> 5) & 0x01;
|
||||
- if (slp_en && slp_typ == 5) {
|
||||
+ slp_typ = (data >> ACPI_GED_SLP_TYP_POS) & ACPI_GED_SLP_TYP_MASK;
|
||||
+ slp_en = !!(data & ACPI_GED_SLP_EN);
|
||||
+ if (slp_en && slp_typ == ACPI_GED_SLP_TYP_S5) {
|
||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
||||
}
|
||||
return;
|
||||
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
|
||||
index 90fc41cbb8..8ed9534c57 100644
|
||||
--- a/include/hw/acpi/generic_event_device.h
|
||||
+++ b/include/hw/acpi/generic_event_device.h
|
||||
@@ -81,8 +81,11 @@ OBJECT_DECLARE_SIMPLE_TYPE(AcpiGedState, ACPI_GED)
|
||||
/* ACPI_GED_REG_RESET value for reset*/
|
||||
#define ACPI_GED_RESET_VALUE 0x42
|
||||
|
||||
-/* ACPI_GED_REG_SLEEP_CTL.SLP_TYP value for S5 (aka poweroff) */
|
||||
-#define ACPI_GED_SLP_TYP_S5 0x05
|
||||
+/* [ACPI 5.0 Chapter 4.8.3.7] Sleep Control and Status Register */
|
||||
+#define ACPI_GED_SLP_TYP_POS 0x2 /* SLP_TYPx Bit Offset */
|
||||
+#define ACPI_GED_SLP_TYP_MASK 0x07 /* SLP_TYPx 3-bit mask */
|
||||
+#define ACPI_GED_SLP_TYP_S5 0x05 /* System _S5 State (Soft Off) */
|
||||
+#define ACPI_GED_SLP_EN 0x20 /* SLP_EN write-only bit */
|
||||
|
||||
#define GED_DEVICE "GED"
|
||||
#define AML_GED_EVT_REG "EREG"
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
899
audio-pw-Report-more-accurate-error-when-connecting--new.patch
Normal file
899
audio-pw-Report-more-accurate-error-when-connecting--new.patch
Normal file
@ -0,0 +1,899 @@
|
||||
From 6adb429abb287b3143ed447b334aa89c1a1c0d71 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?=
|
||||
<zhangchujun@cmss.chinamobile.com>
|
||||
Date: Fri, 18 Oct 2024 10:29:16 +0800
|
||||
Subject: [PATCH] audio/pw: Report more accurate error when connecting to
|
||||
PipeWire fails
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
According to its man page [1], pw_context_connect() sets errno on
|
||||
failure:
|
||||
|
||||
Returns a Core on success or NULL with errno set on error.
|
||||
|
||||
It may be handy to see errno when figuring out why PipeWire
|
||||
failed to connect. That leaves us with just one possible path to
|
||||
reach 'fail_error' label which is then moved to that path and
|
||||
also its error message is adjusted slightly.
|
||||
|
||||
1: https://docs.pipewire.org/group__pw__core.html#ga5994e3a54e4ec718094ca02a1234815b
|
||||
|
||||
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
||||
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
Message-ID: <3a78811ad5b0e87816b7616ab21d2eeef00b9c52.1726647033.git.mprivozn@redhat.com>
|
||||
Signed-off-by: Zhang Chujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
audio/pwaudio.c.orig | 858 -------------------------------------------
|
||||
1 file changed, 858 deletions(-)
|
||||
delete mode 100644 audio/pwaudio.c.orig
|
||||
|
||||
diff --git a/audio/pwaudio.c.orig b/audio/pwaudio.c.orig
|
||||
deleted file mode 100644
|
||||
index 3ce5f6507b..0000000000
|
||||
--- a/audio/pwaudio.c.orig
|
||||
+++ /dev/null
|
||||
@@ -1,858 +0,0 @@
|
||||
-/*
|
||||
- * QEMU PipeWire audio driver
|
||||
- *
|
||||
- * Copyright (c) 2023 Red Hat Inc.
|
||||
- *
|
||||
- * Author: Dorinda Bassey <dbassey@redhat.com>
|
||||
- *
|
||||
- * SPDX-License-Identifier: GPL-2.0-or-later
|
||||
- */
|
||||
-
|
||||
-#include "qemu/osdep.h"
|
||||
-#include "qemu/module.h"
|
||||
-#include "audio.h"
|
||||
-#include <errno.h>
|
||||
-#include "qemu/error-report.h"
|
||||
-#include "qapi/error.h"
|
||||
-#include <spa/param/audio/format-utils.h>
|
||||
-#include <spa/utils/ringbuffer.h>
|
||||
-#include <spa/utils/result.h>
|
||||
-#include <spa/param/props.h>
|
||||
-
|
||||
-#include <pipewire/pipewire.h>
|
||||
-#include "trace.h"
|
||||
-
|
||||
-#define AUDIO_CAP "pipewire"
|
||||
-#define RINGBUFFER_SIZE (1u << 22)
|
||||
-#define RINGBUFFER_MASK (RINGBUFFER_SIZE - 1)
|
||||
-
|
||||
-#include "audio_int.h"
|
||||
-
|
||||
-typedef struct pwvolume {
|
||||
- uint32_t channels;
|
||||
- float values[SPA_AUDIO_MAX_CHANNELS];
|
||||
-} pwvolume;
|
||||
-
|
||||
-typedef struct pwaudio {
|
||||
- Audiodev *dev;
|
||||
- struct pw_thread_loop *thread_loop;
|
||||
- struct pw_context *context;
|
||||
-
|
||||
- struct pw_core *core;
|
||||
- struct spa_hook core_listener;
|
||||
- int last_seq, pending_seq, error;
|
||||
-} pwaudio;
|
||||
-
|
||||
-typedef struct PWVoice {
|
||||
- pwaudio *g;
|
||||
- struct pw_stream *stream;
|
||||
- struct spa_hook stream_listener;
|
||||
- struct spa_audio_info_raw info;
|
||||
- uint32_t highwater_mark;
|
||||
- uint32_t frame_size, req;
|
||||
- struct spa_ringbuffer ring;
|
||||
- uint8_t buffer[RINGBUFFER_SIZE];
|
||||
-
|
||||
- pwvolume volume;
|
||||
- bool muted;
|
||||
-} PWVoice;
|
||||
-
|
||||
-typedef struct PWVoiceOut {
|
||||
- HWVoiceOut hw;
|
||||
- PWVoice v;
|
||||
-} PWVoiceOut;
|
||||
-
|
||||
-typedef struct PWVoiceIn {
|
||||
- HWVoiceIn hw;
|
||||
- PWVoice v;
|
||||
-} PWVoiceIn;
|
||||
-
|
||||
-#define PW_VOICE_IN(v) ((PWVoiceIn *)v)
|
||||
-#define PW_VOICE_OUT(v) ((PWVoiceOut *)v)
|
||||
-
|
||||
-static void
|
||||
-stream_destroy(void *data)
|
||||
-{
|
||||
- PWVoice *v = (PWVoice *) data;
|
||||
- spa_hook_remove(&v->stream_listener);
|
||||
- v->stream = NULL;
|
||||
-}
|
||||
-
|
||||
-/* output data processing function to read stuffs from the buffer */
|
||||
-static void
|
||||
-playback_on_process(void *data)
|
||||
-{
|
||||
- PWVoice *v = data;
|
||||
- void *p;
|
||||
- struct pw_buffer *b;
|
||||
- struct spa_buffer *buf;
|
||||
- uint32_t req, index, n_bytes;
|
||||
- int32_t avail;
|
||||
-
|
||||
- assert(v->stream);
|
||||
-
|
||||
- /* obtain a buffer to read from */
|
||||
- b = pw_stream_dequeue_buffer(v->stream);
|
||||
- if (b == NULL) {
|
||||
- error_report("out of buffers: %s", strerror(errno));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- buf = b->buffer;
|
||||
- p = buf->datas[0].data;
|
||||
- if (p == NULL) {
|
||||
- return;
|
||||
- }
|
||||
- /* calculate the total no of bytes to read data from buffer */
|
||||
- req = b->requested * v->frame_size;
|
||||
- if (req == 0) {
|
||||
- req = v->req;
|
||||
- }
|
||||
- n_bytes = SPA_MIN(req, buf->datas[0].maxsize);
|
||||
-
|
||||
- /* get no of available bytes to read data from buffer */
|
||||
- avail = spa_ringbuffer_get_read_index(&v->ring, &index);
|
||||
-
|
||||
- if (avail <= 0) {
|
||||
- PWVoiceOut *vo = container_of(data, PWVoiceOut, v);
|
||||
- audio_pcm_info_clear_buf(&vo->hw.info, p, n_bytes / v->frame_size);
|
||||
- } else {
|
||||
- if ((uint32_t) avail < n_bytes) {
|
||||
- /*
|
||||
- * PipeWire immediately calls this callback again if we provide
|
||||
- * less than n_bytes. Then audio_pcm_info_clear_buf() fills the
|
||||
- * rest of the buffer with silence.
|
||||
- */
|
||||
- n_bytes = avail;
|
||||
- }
|
||||
-
|
||||
- spa_ringbuffer_read_data(&v->ring,
|
||||
- v->buffer, RINGBUFFER_SIZE,
|
||||
- index & RINGBUFFER_MASK, p, n_bytes);
|
||||
-
|
||||
- index += n_bytes;
|
||||
- spa_ringbuffer_read_update(&v->ring, index);
|
||||
-
|
||||
- }
|
||||
- buf->datas[0].chunk->offset = 0;
|
||||
- buf->datas[0].chunk->stride = v->frame_size;
|
||||
- buf->datas[0].chunk->size = n_bytes;
|
||||
-
|
||||
- /* queue the buffer for playback */
|
||||
- pw_stream_queue_buffer(v->stream, b);
|
||||
-}
|
||||
-
|
||||
-/* output data processing function to generate stuffs in the buffer */
|
||||
-static void
|
||||
-capture_on_process(void *data)
|
||||
-{
|
||||
- PWVoice *v = (PWVoice *) data;
|
||||
- void *p;
|
||||
- struct pw_buffer *b;
|
||||
- struct spa_buffer *buf;
|
||||
- int32_t filled;
|
||||
- uint32_t index, offs, n_bytes;
|
||||
-
|
||||
- assert(v->stream);
|
||||
-
|
||||
- /* obtain a buffer */
|
||||
- b = pw_stream_dequeue_buffer(v->stream);
|
||||
- if (b == NULL) {
|
||||
- error_report("out of buffers: %s", strerror(errno));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- /* Write data into buffer */
|
||||
- buf = b->buffer;
|
||||
- p = buf->datas[0].data;
|
||||
- if (p == NULL) {
|
||||
- return;
|
||||
- }
|
||||
- offs = SPA_MIN(buf->datas[0].chunk->offset, buf->datas[0].maxsize);
|
||||
- n_bytes = SPA_MIN(buf->datas[0].chunk->size, buf->datas[0].maxsize - offs);
|
||||
-
|
||||
- filled = spa_ringbuffer_get_write_index(&v->ring, &index);
|
||||
-
|
||||
-
|
||||
- if (filled < 0) {
|
||||
- error_report("%p: underrun write:%u filled:%d", p, index, filled);
|
||||
- } else {
|
||||
- if ((uint32_t) filled + n_bytes > RINGBUFFER_SIZE) {
|
||||
- error_report("%p: overrun write:%u filled:%d + size:%u > max:%u",
|
||||
- p, index, filled, n_bytes, RINGBUFFER_SIZE);
|
||||
- }
|
||||
- }
|
||||
- spa_ringbuffer_write_data(&v->ring,
|
||||
- v->buffer, RINGBUFFER_SIZE,
|
||||
- index & RINGBUFFER_MASK,
|
||||
- SPA_PTROFF(p, offs, void), n_bytes);
|
||||
- index += n_bytes;
|
||||
- spa_ringbuffer_write_update(&v->ring, index);
|
||||
-
|
||||
- /* queue the buffer for playback */
|
||||
- pw_stream_queue_buffer(v->stream, b);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-on_stream_state_changed(void *data, enum pw_stream_state old,
|
||||
- enum pw_stream_state state, const char *error)
|
||||
-{
|
||||
- PWVoice *v = (PWVoice *) data;
|
||||
-
|
||||
- trace_pw_state_changed(pw_stream_get_node_id(v->stream),
|
||||
- pw_stream_state_as_string(state));
|
||||
-}
|
||||
-
|
||||
-static const struct pw_stream_events capture_stream_events = {
|
||||
- PW_VERSION_STREAM_EVENTS,
|
||||
- .destroy = stream_destroy,
|
||||
- .state_changed = on_stream_state_changed,
|
||||
- .process = capture_on_process
|
||||
-};
|
||||
-
|
||||
-static const struct pw_stream_events playback_stream_events = {
|
||||
- PW_VERSION_STREAM_EVENTS,
|
||||
- .destroy = stream_destroy,
|
||||
- .state_changed = on_stream_state_changed,
|
||||
- .process = playback_on_process
|
||||
-};
|
||||
-
|
||||
-static size_t
|
||||
-qpw_read(HWVoiceIn *hw, void *data, size_t len)
|
||||
-{
|
||||
- PWVoiceIn *pw = (PWVoiceIn *) hw;
|
||||
- PWVoice *v = &pw->v;
|
||||
- pwaudio *c = v->g;
|
||||
- const char *error = NULL;
|
||||
- size_t l;
|
||||
- int32_t avail;
|
||||
- uint32_t index;
|
||||
-
|
||||
- pw_thread_loop_lock(c->thread_loop);
|
||||
- if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
|
||||
- /* wait for stream to become ready */
|
||||
- l = 0;
|
||||
- goto done_unlock;
|
||||
- }
|
||||
- /* get no of available bytes to read data from buffer */
|
||||
- avail = spa_ringbuffer_get_read_index(&v->ring, &index);
|
||||
-
|
||||
- trace_pw_read(avail, index, len);
|
||||
-
|
||||
- if (avail < (int32_t) len) {
|
||||
- len = avail;
|
||||
- }
|
||||
-
|
||||
- spa_ringbuffer_read_data(&v->ring,
|
||||
- v->buffer, RINGBUFFER_SIZE,
|
||||
- index & RINGBUFFER_MASK, data, len);
|
||||
- index += len;
|
||||
- spa_ringbuffer_read_update(&v->ring, index);
|
||||
- l = len;
|
||||
-
|
||||
-done_unlock:
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
- return l;
|
||||
-}
|
||||
-
|
||||
-static size_t qpw_buffer_get_free(HWVoiceOut *hw)
|
||||
-{
|
||||
- PWVoiceOut *pw = (PWVoiceOut *)hw;
|
||||
- PWVoice *v = &pw->v;
|
||||
- pwaudio *c = v->g;
|
||||
- const char *error = NULL;
|
||||
- int32_t filled, avail;
|
||||
- uint32_t index;
|
||||
-
|
||||
- pw_thread_loop_lock(c->thread_loop);
|
||||
- if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
|
||||
- /* wait for stream to become ready */
|
||||
- avail = 0;
|
||||
- goto done_unlock;
|
||||
- }
|
||||
-
|
||||
- filled = spa_ringbuffer_get_write_index(&v->ring, &index);
|
||||
- avail = v->highwater_mark - filled;
|
||||
-
|
||||
-done_unlock:
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
- return avail;
|
||||
-}
|
||||
-
|
||||
-static size_t
|
||||
-qpw_write(HWVoiceOut *hw, void *data, size_t len)
|
||||
-{
|
||||
- PWVoiceOut *pw = (PWVoiceOut *) hw;
|
||||
- PWVoice *v = &pw->v;
|
||||
- pwaudio *c = v->g;
|
||||
- const char *error = NULL;
|
||||
- int32_t filled, avail;
|
||||
- uint32_t index;
|
||||
-
|
||||
- pw_thread_loop_lock(c->thread_loop);
|
||||
- if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
|
||||
- /* wait for stream to become ready */
|
||||
- len = 0;
|
||||
- goto done_unlock;
|
||||
- }
|
||||
- filled = spa_ringbuffer_get_write_index(&v->ring, &index);
|
||||
- avail = v->highwater_mark - filled;
|
||||
-
|
||||
- trace_pw_write(filled, avail, index, len);
|
||||
-
|
||||
- if (len > avail) {
|
||||
- len = avail;
|
||||
- }
|
||||
-
|
||||
- if (filled < 0) {
|
||||
- error_report("%p: underrun write:%u filled:%d", pw, index, filled);
|
||||
- } else {
|
||||
- if ((uint32_t) filled + len > RINGBUFFER_SIZE) {
|
||||
- error_report("%p: overrun write:%u filled:%d + size:%zu > max:%u",
|
||||
- pw, index, filled, len, RINGBUFFER_SIZE);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- spa_ringbuffer_write_data(&v->ring,
|
||||
- v->buffer, RINGBUFFER_SIZE,
|
||||
- index & RINGBUFFER_MASK, data, len);
|
||||
- index += len;
|
||||
- spa_ringbuffer_write_update(&v->ring, index);
|
||||
-
|
||||
-done_unlock:
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
- return len;
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-audfmt_to_pw(AudioFormat fmt, int endianness)
|
||||
-{
|
||||
- int format;
|
||||
-
|
||||
- switch (fmt) {
|
||||
- case AUDIO_FORMAT_S8:
|
||||
- format = SPA_AUDIO_FORMAT_S8;
|
||||
- break;
|
||||
- case AUDIO_FORMAT_U8:
|
||||
- format = SPA_AUDIO_FORMAT_U8;
|
||||
- break;
|
||||
- case AUDIO_FORMAT_S16:
|
||||
- format = endianness ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE;
|
||||
- break;
|
||||
- case AUDIO_FORMAT_U16:
|
||||
- format = endianness ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE;
|
||||
- break;
|
||||
- case AUDIO_FORMAT_S32:
|
||||
- format = endianness ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE;
|
||||
- break;
|
||||
- case AUDIO_FORMAT_U32:
|
||||
- format = endianness ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE;
|
||||
- break;
|
||||
- case AUDIO_FORMAT_F32:
|
||||
- format = endianness ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE;
|
||||
- break;
|
||||
- default:
|
||||
- dolog("Internal logic error: Bad audio format %d\n", fmt);
|
||||
- format = SPA_AUDIO_FORMAT_U8;
|
||||
- break;
|
||||
- }
|
||||
- return format;
|
||||
-}
|
||||
-
|
||||
-static AudioFormat
|
||||
-pw_to_audfmt(enum spa_audio_format fmt, int *endianness,
|
||||
- uint32_t *sample_size)
|
||||
-{
|
||||
- switch (fmt) {
|
||||
- case SPA_AUDIO_FORMAT_S8:
|
||||
- *sample_size = 1;
|
||||
- return AUDIO_FORMAT_S8;
|
||||
- case SPA_AUDIO_FORMAT_U8:
|
||||
- *sample_size = 1;
|
||||
- return AUDIO_FORMAT_U8;
|
||||
- case SPA_AUDIO_FORMAT_S16_BE:
|
||||
- *sample_size = 2;
|
||||
- *endianness = 1;
|
||||
- return AUDIO_FORMAT_S16;
|
||||
- case SPA_AUDIO_FORMAT_S16_LE:
|
||||
- *sample_size = 2;
|
||||
- *endianness = 0;
|
||||
- return AUDIO_FORMAT_S16;
|
||||
- case SPA_AUDIO_FORMAT_U16_BE:
|
||||
- *sample_size = 2;
|
||||
- *endianness = 1;
|
||||
- return AUDIO_FORMAT_U16;
|
||||
- case SPA_AUDIO_FORMAT_U16_LE:
|
||||
- *sample_size = 2;
|
||||
- *endianness = 0;
|
||||
- return AUDIO_FORMAT_U16;
|
||||
- case SPA_AUDIO_FORMAT_S32_BE:
|
||||
- *sample_size = 4;
|
||||
- *endianness = 1;
|
||||
- return AUDIO_FORMAT_S32;
|
||||
- case SPA_AUDIO_FORMAT_S32_LE:
|
||||
- *sample_size = 4;
|
||||
- *endianness = 0;
|
||||
- return AUDIO_FORMAT_S32;
|
||||
- case SPA_AUDIO_FORMAT_U32_BE:
|
||||
- *sample_size = 4;
|
||||
- *endianness = 1;
|
||||
- return AUDIO_FORMAT_U32;
|
||||
- case SPA_AUDIO_FORMAT_U32_LE:
|
||||
- *sample_size = 4;
|
||||
- *endianness = 0;
|
||||
- return AUDIO_FORMAT_U32;
|
||||
- case SPA_AUDIO_FORMAT_F32_BE:
|
||||
- *sample_size = 4;
|
||||
- *endianness = 1;
|
||||
- return AUDIO_FORMAT_F32;
|
||||
- case SPA_AUDIO_FORMAT_F32_LE:
|
||||
- *sample_size = 4;
|
||||
- *endianness = 0;
|
||||
- return AUDIO_FORMAT_F32;
|
||||
- default:
|
||||
- *sample_size = 1;
|
||||
- dolog("Internal logic error: Bad spa_audio_format %d\n", fmt);
|
||||
- return AUDIO_FORMAT_U8;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
- const char *name, enum spa_direction dir)
|
||||
-{
|
||||
- int res;
|
||||
- uint32_t n_params;
|
||||
- const struct spa_pod *params[2];
|
||||
- uint8_t buffer[1024];
|
||||
- struct spa_pod_builder b;
|
||||
- uint64_t buf_samples;
|
||||
- struct pw_properties *props;
|
||||
-
|
||||
- props = pw_properties_new(NULL, NULL);
|
||||
- if (!props) {
|
||||
- error_report("Failed to create PW properties: %s", g_strerror(errno));
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* 75% of the timer period for faster updates */
|
||||
- buf_samples = (uint64_t)v->g->dev->timer_period * v->info.rate
|
||||
- * 3 / 4 / 1000000;
|
||||
- pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%" PRIu64 "/%u",
|
||||
- buf_samples, v->info.rate);
|
||||
-
|
||||
- trace_pw_period(buf_samples, v->info.rate);
|
||||
- if (name) {
|
||||
- pw_properties_set(props, PW_KEY_TARGET_OBJECT, name);
|
||||
- }
|
||||
- v->stream = pw_stream_new(c->core, stream_name, props);
|
||||
- if (v->stream == NULL) {
|
||||
- error_report("Failed to create PW stream: %s", g_strerror(errno));
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- if (dir == SPA_DIRECTION_INPUT) {
|
||||
- pw_stream_add_listener(v->stream,
|
||||
- &v->stream_listener, &capture_stream_events, v);
|
||||
- } else {
|
||||
- pw_stream_add_listener(v->stream,
|
||||
- &v->stream_listener, &playback_stream_events, v);
|
||||
- }
|
||||
-
|
||||
- n_params = 0;
|
||||
- spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||
- params[n_params++] = spa_format_audio_raw_build(&b,
|
||||
- SPA_PARAM_EnumFormat,
|
||||
- &v->info);
|
||||
-
|
||||
- /* connect the stream to a sink or source */
|
||||
- res = pw_stream_connect(v->stream,
|
||||
- dir ==
|
||||
- SPA_DIRECTION_INPUT ? PW_DIRECTION_INPUT :
|
||||
- PW_DIRECTION_OUTPUT, PW_ID_ANY,
|
||||
- PW_STREAM_FLAG_AUTOCONNECT |
|
||||
- PW_STREAM_FLAG_INACTIVE |
|
||||
- PW_STREAM_FLAG_MAP_BUFFERS |
|
||||
- PW_STREAM_FLAG_RT_PROCESS, params, n_params);
|
||||
- if (res < 0) {
|
||||
- error_report("Failed to connect PW stream: %s", g_strerror(errno));
|
||||
- pw_stream_destroy(v->stream);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS])
|
||||
-{
|
||||
- memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, },
|
||||
- sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS);
|
||||
- /*
|
||||
- * TODO: This currently expects the only frontend supporting more than 2
|
||||
- * channels is the usb-audio. We will need some means to set channel
|
||||
- * order when a new frontend gains multi-channel support.
|
||||
- */
|
||||
- switch (channels) {
|
||||
- case 8:
|
||||
- position[6] = SPA_AUDIO_CHANNEL_SL;
|
||||
- position[7] = SPA_AUDIO_CHANNEL_SR;
|
||||
- /* fallthrough */
|
||||
- case 6:
|
||||
- position[2] = SPA_AUDIO_CHANNEL_FC;
|
||||
- position[3] = SPA_AUDIO_CHANNEL_LFE;
|
||||
- position[4] = SPA_AUDIO_CHANNEL_RL;
|
||||
- position[5] = SPA_AUDIO_CHANNEL_RR;
|
||||
- /* fallthrough */
|
||||
- case 2:
|
||||
- position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
- position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
- break;
|
||||
- case 1:
|
||||
- position[0] = SPA_AUDIO_CHANNEL_MONO;
|
||||
- break;
|
||||
- default:
|
||||
- dolog("Internal error: unsupported channel count %d\n", channels);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
|
||||
-{
|
||||
- PWVoiceOut *pw = (PWVoiceOut *) hw;
|
||||
- PWVoice *v = &pw->v;
|
||||
- struct audsettings obt_as = *as;
|
||||
- pwaudio *c = v->g = drv_opaque;
|
||||
- AudiodevPipewireOptions *popts = &c->dev->u.pipewire;
|
||||
- AudiodevPipewirePerDirectionOptions *ppdo = popts->out;
|
||||
- int r;
|
||||
-
|
||||
- pw_thread_loop_lock(c->thread_loop);
|
||||
-
|
||||
- v->info.format = audfmt_to_pw(as->fmt, as->endianness);
|
||||
- v->info.channels = as->nchannels;
|
||||
- qpw_set_position(as->nchannels, v->info.position);
|
||||
- v->info.rate = as->freq;
|
||||
-
|
||||
- obt_as.fmt =
|
||||
- pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size);
|
||||
- v->frame_size *= as->nchannels;
|
||||
-
|
||||
- v->req = (uint64_t)c->dev->timer_period * v->info.rate
|
||||
- * 1 / 2 / 1000000 * v->frame_size;
|
||||
-
|
||||
- /* call the function that creates a new stream for playback */
|
||||
- r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id,
|
||||
- ppdo->name, SPA_DIRECTION_OUTPUT);
|
||||
- if (r < 0) {
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* report the audio format we support */
|
||||
- audio_pcm_init_info(&hw->info, &obt_as);
|
||||
-
|
||||
- /* report the buffer size to qemu */
|
||||
- hw->samples = audio_buffer_frames(
|
||||
- qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
|
||||
- v->highwater_mark = MIN(RINGBUFFER_SIZE,
|
||||
- (ppdo->has_latency ? ppdo->latency : 46440)
|
||||
- * (uint64_t)v->info.rate / 1000000 * v->frame_size);
|
||||
-
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int
|
||||
-qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
-{
|
||||
- PWVoiceIn *pw = (PWVoiceIn *) hw;
|
||||
- PWVoice *v = &pw->v;
|
||||
- struct audsettings obt_as = *as;
|
||||
- pwaudio *c = v->g = drv_opaque;
|
||||
- AudiodevPipewireOptions *popts = &c->dev->u.pipewire;
|
||||
- AudiodevPipewirePerDirectionOptions *ppdo = popts->in;
|
||||
- int r;
|
||||
-
|
||||
- pw_thread_loop_lock(c->thread_loop);
|
||||
-
|
||||
- v->info.format = audfmt_to_pw(as->fmt, as->endianness);
|
||||
- v->info.channels = as->nchannels;
|
||||
- qpw_set_position(as->nchannels, v->info.position);
|
||||
- v->info.rate = as->freq;
|
||||
-
|
||||
- obt_as.fmt =
|
||||
- pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size);
|
||||
- v->frame_size *= as->nchannels;
|
||||
-
|
||||
- /* call the function that creates a new stream for recording */
|
||||
- r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id,
|
||||
- ppdo->name, SPA_DIRECTION_INPUT);
|
||||
- if (r < 0) {
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
- /* report the audio format we support */
|
||||
- audio_pcm_init_info(&hw->info, &obt_as);
|
||||
-
|
||||
- /* report the buffer size to qemu */
|
||||
- hw->samples = audio_buffer_frames(
|
||||
- qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
|
||||
-
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_voice_fini(PWVoice *v)
|
||||
-{
|
||||
- pwaudio *c = v->g;
|
||||
-
|
||||
- if (!v->stream) {
|
||||
- return;
|
||||
- }
|
||||
- pw_thread_loop_lock(c->thread_loop);
|
||||
- pw_stream_destroy(v->stream);
|
||||
- v->stream = NULL;
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_fini_out(HWVoiceOut *hw)
|
||||
-{
|
||||
- qpw_voice_fini(&PW_VOICE_OUT(hw)->v);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_fini_in(HWVoiceIn *hw)
|
||||
-{
|
||||
- qpw_voice_fini(&PW_VOICE_IN(hw)->v);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_voice_set_enabled(PWVoice *v, bool enable)
|
||||
-{
|
||||
- pwaudio *c = v->g;
|
||||
- pw_thread_loop_lock(c->thread_loop);
|
||||
- pw_stream_set_active(v->stream, enable);
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_enable_out(HWVoiceOut *hw, bool enable)
|
||||
-{
|
||||
- qpw_voice_set_enabled(&PW_VOICE_OUT(hw)->v, enable);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_enable_in(HWVoiceIn *hw, bool enable)
|
||||
-{
|
||||
- qpw_voice_set_enabled(&PW_VOICE_IN(hw)->v, enable);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_voice_set_volume(PWVoice *v, Volume *vol)
|
||||
-{
|
||||
- pwaudio *c = v->g;
|
||||
- int i, ret;
|
||||
-
|
||||
- pw_thread_loop_lock(c->thread_loop);
|
||||
- v->volume.channels = vol->channels;
|
||||
-
|
||||
- for (i = 0; i < vol->channels; ++i) {
|
||||
- v->volume.values[i] = (float)vol->vol[i] / 255;
|
||||
- }
|
||||
-
|
||||
- ret = pw_stream_set_control(v->stream,
|
||||
- SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0);
|
||||
- trace_pw_vol(ret == 0 ? "success" : "failed");
|
||||
-
|
||||
- v->muted = vol->mute;
|
||||
- float val = v->muted ? 1.f : 0.f;
|
||||
- ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0);
|
||||
- pw_thread_loop_unlock(c->thread_loop);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_volume_out(HWVoiceOut *hw, Volume *vol)
|
||||
-{
|
||||
- qpw_voice_set_volume(&PW_VOICE_OUT(hw)->v, vol);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_volume_in(HWVoiceIn *hw, Volume *vol)
|
||||
-{
|
||||
- qpw_voice_set_volume(&PW_VOICE_IN(hw)->v, vol);
|
||||
-}
|
||||
-
|
||||
-static int wait_resync(pwaudio *pw)
|
||||
-{
|
||||
- int res;
|
||||
- pw->pending_seq = pw_core_sync(pw->core, PW_ID_CORE, pw->pending_seq);
|
||||
-
|
||||
- while (true) {
|
||||
- pw_thread_loop_wait(pw->thread_loop);
|
||||
-
|
||||
- res = pw->error;
|
||||
- if (res < 0) {
|
||||
- pw->error = 0;
|
||||
- return res;
|
||||
- }
|
||||
- if (pw->pending_seq == pw->last_seq) {
|
||||
- break;
|
||||
- }
|
||||
- }
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
|
||||
-{
|
||||
- pwaudio *pw = data;
|
||||
-
|
||||
- error_report("error id:%u seq:%d res:%d (%s): %s",
|
||||
- id, seq, res, spa_strerror(res), message);
|
||||
-
|
||||
- /* stop and exit the thread loop */
|
||||
- pw_thread_loop_signal(pw->thread_loop, FALSE);
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-on_core_done(void *data, uint32_t id, int seq)
|
||||
-{
|
||||
- pwaudio *pw = data;
|
||||
- assert(id == PW_ID_CORE);
|
||||
- pw->last_seq = seq;
|
||||
- if (pw->pending_seq == seq) {
|
||||
- /* stop and exit the thread loop */
|
||||
- pw_thread_loop_signal(pw->thread_loop, FALSE);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static const struct pw_core_events core_events = {
|
||||
- PW_VERSION_CORE_EVENTS,
|
||||
- .done = on_core_done,
|
||||
- .error = on_core_error,
|
||||
-};
|
||||
-
|
||||
-static void *
|
||||
-qpw_audio_init(Audiodev *dev, Error **errp)
|
||||
-{
|
||||
- g_autofree pwaudio *pw = g_new0(pwaudio, 1);
|
||||
-
|
||||
- assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE);
|
||||
- trace_pw_audio_init();
|
||||
-
|
||||
- pw_init(NULL, NULL);
|
||||
-
|
||||
- pw->dev = dev;
|
||||
- pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL);
|
||||
- if (pw->thread_loop == NULL) {
|
||||
- error_setg_errno(errp, errno, "Could not create PipeWire loop");
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- pw->context =
|
||||
- pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0);
|
||||
- if (pw->context == NULL) {
|
||||
- error_setg_errno(errp, errno, "Could not create PipeWire context");
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- if (pw_thread_loop_start(pw->thread_loop) < 0) {
|
||||
- error_setg_errno(errp, errno, "Could not start PipeWire loop");
|
||||
- goto fail;
|
||||
- }
|
||||
-
|
||||
- pw_thread_loop_lock(pw->thread_loop);
|
||||
-
|
||||
- pw->core = pw_context_connect(pw->context, NULL, 0);
|
||||
- if (pw->core == NULL) {
|
||||
- pw_thread_loop_unlock(pw->thread_loop);
|
||||
- goto fail_error;
|
||||
- }
|
||||
-
|
||||
- if (pw_core_add_listener(pw->core, &pw->core_listener,
|
||||
- &core_events, pw) < 0) {
|
||||
- pw_thread_loop_unlock(pw->thread_loop);
|
||||
- goto fail_error;
|
||||
- }
|
||||
- if (wait_resync(pw) < 0) {
|
||||
- pw_thread_loop_unlock(pw->thread_loop);
|
||||
- }
|
||||
-
|
||||
- pw_thread_loop_unlock(pw->thread_loop);
|
||||
-
|
||||
- return g_steal_pointer(&pw);
|
||||
-
|
||||
-fail_error:
|
||||
- error_setg(errp, "Failed to initialize PW context");
|
||||
-fail:
|
||||
- if (pw->thread_loop) {
|
||||
- pw_thread_loop_stop(pw->thread_loop);
|
||||
- }
|
||||
- g_clear_pointer(&pw->context, pw_context_destroy);
|
||||
- g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy);
|
||||
- return NULL;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-qpw_audio_fini(void *opaque)
|
||||
-{
|
||||
- pwaudio *pw = opaque;
|
||||
-
|
||||
- if (pw->thread_loop) {
|
||||
- pw_thread_loop_stop(pw->thread_loop);
|
||||
- }
|
||||
-
|
||||
- if (pw->core) {
|
||||
- spa_hook_remove(&pw->core_listener);
|
||||
- spa_zero(pw->core_listener);
|
||||
- pw_core_disconnect(pw->core);
|
||||
- }
|
||||
-
|
||||
- if (pw->context) {
|
||||
- pw_context_destroy(pw->context);
|
||||
- }
|
||||
- pw_thread_loop_destroy(pw->thread_loop);
|
||||
-
|
||||
- g_free(pw);
|
||||
-}
|
||||
-
|
||||
-static struct audio_pcm_ops qpw_pcm_ops = {
|
||||
- .init_out = qpw_init_out,
|
||||
- .fini_out = qpw_fini_out,
|
||||
- .write = qpw_write,
|
||||
- .buffer_get_free = qpw_buffer_get_free,
|
||||
- .run_buffer_out = audio_generic_run_buffer_out,
|
||||
- .enable_out = qpw_enable_out,
|
||||
- .volume_out = qpw_volume_out,
|
||||
- .volume_in = qpw_volume_in,
|
||||
-
|
||||
- .init_in = qpw_init_in,
|
||||
- .fini_in = qpw_fini_in,
|
||||
- .read = qpw_read,
|
||||
- .run_buffer_in = audio_generic_run_buffer_in,
|
||||
- .enable_in = qpw_enable_in
|
||||
-};
|
||||
-
|
||||
-static struct audio_driver pw_audio_driver = {
|
||||
- .name = "pipewire",
|
||||
- .descr = "http://www.pipewire.org/",
|
||||
- .init = qpw_audio_init,
|
||||
- .fini = qpw_audio_fini,
|
||||
- .pcm_ops = &qpw_pcm_ops,
|
||||
- .max_voices_out = INT_MAX,
|
||||
- .max_voices_in = INT_MAX,
|
||||
- .voice_size_out = sizeof(PWVoiceOut),
|
||||
- .voice_size_in = sizeof(PWVoiceIn),
|
||||
-};
|
||||
-
|
||||
-static void
|
||||
-register_audio_pw(void)
|
||||
-{
|
||||
- audio_driver_register(&pw_audio_driver);
|
||||
-}
|
||||
-
|
||||
-type_init(register_audio_pw);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
931
audio-pw-Report-more-accurate-error-when-connecting-.patch
Normal file
931
audio-pw-Report-more-accurate-error-when-connecting-.patch
Normal file
@ -0,0 +1,931 @@
|
||||
From fab03a72da74e938a2a476f1824ac0acd4a1fee2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?=
|
||||
<zhangchujun@cmss.chinamobile.com>
|
||||
Date: Fri, 18 Oct 2024 10:17:10 +0800
|
||||
Subject: [PATCH] audio/pw: Report more accurate error when connecting to
|
||||
PipeWire fails
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
According to its man page [1], pw_context_connect() sets errno on
|
||||
failure:
|
||||
|
||||
Returns a Core on success or NULL with errno set on error.
|
||||
|
||||
It may be handy to see errno when figuring out why PipeWire
|
||||
failed to connect. That leaves us with just one possible path to
|
||||
reach 'fail_error' label which is then moved to that path and
|
||||
also its error message is adjusted slightly.
|
||||
|
||||
1: https://docs.pipewire.org/group__pw__core.html#ga5994e3a54e4ec718094ca02a1234815b
|
||||
|
||||
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
|
||||
Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>
|
||||
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
Message-ID: <3a78811ad5b0e87816b7616ab21d2eeef00b9c52.1726647033.git.mprivozn@redhat.com>
|
||||
Signed-off-by: Zhang Chujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
audio/pwaudio.c | 8 +-
|
||||
audio/pwaudio.c.orig | 858 +++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 862 insertions(+), 4 deletions(-)
|
||||
create mode 100644 audio/pwaudio.c.orig
|
||||
|
||||
diff --git a/audio/pwaudio.c b/audio/pwaudio.c
|
||||
index 3ce5f6507b..5d1c7126d3 100644
|
||||
--- a/audio/pwaudio.c
|
||||
+++ b/audio/pwaudio.c
|
||||
@@ -770,13 +770,15 @@ qpw_audio_init(Audiodev *dev, Error **errp)
|
||||
pw->core = pw_context_connect(pw->context, NULL, 0);
|
||||
if (pw->core == NULL) {
|
||||
pw_thread_loop_unlock(pw->thread_loop);
|
||||
- goto fail_error;
|
||||
+ error_setg_errno(errp, errno, "Failed to connect to PipeWire instance");
|
||||
+ goto fail;
|
||||
}
|
||||
|
||||
if (pw_core_add_listener(pw->core, &pw->core_listener,
|
||||
&core_events, pw) < 0) {
|
||||
pw_thread_loop_unlock(pw->thread_loop);
|
||||
- goto fail_error;
|
||||
+ error_setg(errp, "Failed to add PipeWire listener");
|
||||
+ goto fail;
|
||||
}
|
||||
if (wait_resync(pw) < 0) {
|
||||
pw_thread_loop_unlock(pw->thread_loop);
|
||||
@@ -786,8 +788,6 @@ qpw_audio_init(Audiodev *dev, Error **errp)
|
||||
|
||||
return g_steal_pointer(&pw);
|
||||
|
||||
-fail_error:
|
||||
- error_setg(errp, "Failed to initialize PW context");
|
||||
fail:
|
||||
if (pw->thread_loop) {
|
||||
pw_thread_loop_stop(pw->thread_loop);
|
||||
diff --git a/audio/pwaudio.c.orig b/audio/pwaudio.c.orig
|
||||
new file mode 100644
|
||||
index 0000000000..3ce5f6507b
|
||||
--- /dev/null
|
||||
+++ b/audio/pwaudio.c.orig
|
||||
@@ -0,0 +1,858 @@
|
||||
+/*
|
||||
+ * QEMU PipeWire audio driver
|
||||
+ *
|
||||
+ * Copyright (c) 2023 Red Hat Inc.
|
||||
+ *
|
||||
+ * Author: Dorinda Bassey <dbassey@redhat.com>
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+ */
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "qemu/module.h"
|
||||
+#include "audio.h"
|
||||
+#include <errno.h>
|
||||
+#include "qemu/error-report.h"
|
||||
+#include "qapi/error.h"
|
||||
+#include <spa/param/audio/format-utils.h>
|
||||
+#include <spa/utils/ringbuffer.h>
|
||||
+#include <spa/utils/result.h>
|
||||
+#include <spa/param/props.h>
|
||||
+
|
||||
+#include <pipewire/pipewire.h>
|
||||
+#include "trace.h"
|
||||
+
|
||||
+#define AUDIO_CAP "pipewire"
|
||||
+#define RINGBUFFER_SIZE (1u << 22)
|
||||
+#define RINGBUFFER_MASK (RINGBUFFER_SIZE - 1)
|
||||
+
|
||||
+#include "audio_int.h"
|
||||
+
|
||||
+typedef struct pwvolume {
|
||||
+ uint32_t channels;
|
||||
+ float values[SPA_AUDIO_MAX_CHANNELS];
|
||||
+} pwvolume;
|
||||
+
|
||||
+typedef struct pwaudio {
|
||||
+ Audiodev *dev;
|
||||
+ struct pw_thread_loop *thread_loop;
|
||||
+ struct pw_context *context;
|
||||
+
|
||||
+ struct pw_core *core;
|
||||
+ struct spa_hook core_listener;
|
||||
+ int last_seq, pending_seq, error;
|
||||
+} pwaudio;
|
||||
+
|
||||
+typedef struct PWVoice {
|
||||
+ pwaudio *g;
|
||||
+ struct pw_stream *stream;
|
||||
+ struct spa_hook stream_listener;
|
||||
+ struct spa_audio_info_raw info;
|
||||
+ uint32_t highwater_mark;
|
||||
+ uint32_t frame_size, req;
|
||||
+ struct spa_ringbuffer ring;
|
||||
+ uint8_t buffer[RINGBUFFER_SIZE];
|
||||
+
|
||||
+ pwvolume volume;
|
||||
+ bool muted;
|
||||
+} PWVoice;
|
||||
+
|
||||
+typedef struct PWVoiceOut {
|
||||
+ HWVoiceOut hw;
|
||||
+ PWVoice v;
|
||||
+} PWVoiceOut;
|
||||
+
|
||||
+typedef struct PWVoiceIn {
|
||||
+ HWVoiceIn hw;
|
||||
+ PWVoice v;
|
||||
+} PWVoiceIn;
|
||||
+
|
||||
+#define PW_VOICE_IN(v) ((PWVoiceIn *)v)
|
||||
+#define PW_VOICE_OUT(v) ((PWVoiceOut *)v)
|
||||
+
|
||||
+static void
|
||||
+stream_destroy(void *data)
|
||||
+{
|
||||
+ PWVoice *v = (PWVoice *) data;
|
||||
+ spa_hook_remove(&v->stream_listener);
|
||||
+ v->stream = NULL;
|
||||
+}
|
||||
+
|
||||
+/* output data processing function to read stuffs from the buffer */
|
||||
+static void
|
||||
+playback_on_process(void *data)
|
||||
+{
|
||||
+ PWVoice *v = data;
|
||||
+ void *p;
|
||||
+ struct pw_buffer *b;
|
||||
+ struct spa_buffer *buf;
|
||||
+ uint32_t req, index, n_bytes;
|
||||
+ int32_t avail;
|
||||
+
|
||||
+ assert(v->stream);
|
||||
+
|
||||
+ /* obtain a buffer to read from */
|
||||
+ b = pw_stream_dequeue_buffer(v->stream);
|
||||
+ if (b == NULL) {
|
||||
+ error_report("out of buffers: %s", strerror(errno));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ buf = b->buffer;
|
||||
+ p = buf->datas[0].data;
|
||||
+ if (p == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+ /* calculate the total no of bytes to read data from buffer */
|
||||
+ req = b->requested * v->frame_size;
|
||||
+ if (req == 0) {
|
||||
+ req = v->req;
|
||||
+ }
|
||||
+ n_bytes = SPA_MIN(req, buf->datas[0].maxsize);
|
||||
+
|
||||
+ /* get no of available bytes to read data from buffer */
|
||||
+ avail = spa_ringbuffer_get_read_index(&v->ring, &index);
|
||||
+
|
||||
+ if (avail <= 0) {
|
||||
+ PWVoiceOut *vo = container_of(data, PWVoiceOut, v);
|
||||
+ audio_pcm_info_clear_buf(&vo->hw.info, p, n_bytes / v->frame_size);
|
||||
+ } else {
|
||||
+ if ((uint32_t) avail < n_bytes) {
|
||||
+ /*
|
||||
+ * PipeWire immediately calls this callback again if we provide
|
||||
+ * less than n_bytes. Then audio_pcm_info_clear_buf() fills the
|
||||
+ * rest of the buffer with silence.
|
||||
+ */
|
||||
+ n_bytes = avail;
|
||||
+ }
|
||||
+
|
||||
+ spa_ringbuffer_read_data(&v->ring,
|
||||
+ v->buffer, RINGBUFFER_SIZE,
|
||||
+ index & RINGBUFFER_MASK, p, n_bytes);
|
||||
+
|
||||
+ index += n_bytes;
|
||||
+ spa_ringbuffer_read_update(&v->ring, index);
|
||||
+
|
||||
+ }
|
||||
+ buf->datas[0].chunk->offset = 0;
|
||||
+ buf->datas[0].chunk->stride = v->frame_size;
|
||||
+ buf->datas[0].chunk->size = n_bytes;
|
||||
+
|
||||
+ /* queue the buffer for playback */
|
||||
+ pw_stream_queue_buffer(v->stream, b);
|
||||
+}
|
||||
+
|
||||
+/* output data processing function to generate stuffs in the buffer */
|
||||
+static void
|
||||
+capture_on_process(void *data)
|
||||
+{
|
||||
+ PWVoice *v = (PWVoice *) data;
|
||||
+ void *p;
|
||||
+ struct pw_buffer *b;
|
||||
+ struct spa_buffer *buf;
|
||||
+ int32_t filled;
|
||||
+ uint32_t index, offs, n_bytes;
|
||||
+
|
||||
+ assert(v->stream);
|
||||
+
|
||||
+ /* obtain a buffer */
|
||||
+ b = pw_stream_dequeue_buffer(v->stream);
|
||||
+ if (b == NULL) {
|
||||
+ error_report("out of buffers: %s", strerror(errno));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Write data into buffer */
|
||||
+ buf = b->buffer;
|
||||
+ p = buf->datas[0].data;
|
||||
+ if (p == NULL) {
|
||||
+ return;
|
||||
+ }
|
||||
+ offs = SPA_MIN(buf->datas[0].chunk->offset, buf->datas[0].maxsize);
|
||||
+ n_bytes = SPA_MIN(buf->datas[0].chunk->size, buf->datas[0].maxsize - offs);
|
||||
+
|
||||
+ filled = spa_ringbuffer_get_write_index(&v->ring, &index);
|
||||
+
|
||||
+
|
||||
+ if (filled < 0) {
|
||||
+ error_report("%p: underrun write:%u filled:%d", p, index, filled);
|
||||
+ } else {
|
||||
+ if ((uint32_t) filled + n_bytes > RINGBUFFER_SIZE) {
|
||||
+ error_report("%p: overrun write:%u filled:%d + size:%u > max:%u",
|
||||
+ p, index, filled, n_bytes, RINGBUFFER_SIZE);
|
||||
+ }
|
||||
+ }
|
||||
+ spa_ringbuffer_write_data(&v->ring,
|
||||
+ v->buffer, RINGBUFFER_SIZE,
|
||||
+ index & RINGBUFFER_MASK,
|
||||
+ SPA_PTROFF(p, offs, void), n_bytes);
|
||||
+ index += n_bytes;
|
||||
+ spa_ringbuffer_write_update(&v->ring, index);
|
||||
+
|
||||
+ /* queue the buffer for playback */
|
||||
+ pw_stream_queue_buffer(v->stream, b);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+on_stream_state_changed(void *data, enum pw_stream_state old,
|
||||
+ enum pw_stream_state state, const char *error)
|
||||
+{
|
||||
+ PWVoice *v = (PWVoice *) data;
|
||||
+
|
||||
+ trace_pw_state_changed(pw_stream_get_node_id(v->stream),
|
||||
+ pw_stream_state_as_string(state));
|
||||
+}
|
||||
+
|
||||
+static const struct pw_stream_events capture_stream_events = {
|
||||
+ PW_VERSION_STREAM_EVENTS,
|
||||
+ .destroy = stream_destroy,
|
||||
+ .state_changed = on_stream_state_changed,
|
||||
+ .process = capture_on_process
|
||||
+};
|
||||
+
|
||||
+static const struct pw_stream_events playback_stream_events = {
|
||||
+ PW_VERSION_STREAM_EVENTS,
|
||||
+ .destroy = stream_destroy,
|
||||
+ .state_changed = on_stream_state_changed,
|
||||
+ .process = playback_on_process
|
||||
+};
|
||||
+
|
||||
+static size_t
|
||||
+qpw_read(HWVoiceIn *hw, void *data, size_t len)
|
||||
+{
|
||||
+ PWVoiceIn *pw = (PWVoiceIn *) hw;
|
||||
+ PWVoice *v = &pw->v;
|
||||
+ pwaudio *c = v->g;
|
||||
+ const char *error = NULL;
|
||||
+ size_t l;
|
||||
+ int32_t avail;
|
||||
+ uint32_t index;
|
||||
+
|
||||
+ pw_thread_loop_lock(c->thread_loop);
|
||||
+ if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
|
||||
+ /* wait for stream to become ready */
|
||||
+ l = 0;
|
||||
+ goto done_unlock;
|
||||
+ }
|
||||
+ /* get no of available bytes to read data from buffer */
|
||||
+ avail = spa_ringbuffer_get_read_index(&v->ring, &index);
|
||||
+
|
||||
+ trace_pw_read(avail, index, len);
|
||||
+
|
||||
+ if (avail < (int32_t) len) {
|
||||
+ len = avail;
|
||||
+ }
|
||||
+
|
||||
+ spa_ringbuffer_read_data(&v->ring,
|
||||
+ v->buffer, RINGBUFFER_SIZE,
|
||||
+ index & RINGBUFFER_MASK, data, len);
|
||||
+ index += len;
|
||||
+ spa_ringbuffer_read_update(&v->ring, index);
|
||||
+ l = len;
|
||||
+
|
||||
+done_unlock:
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+ return l;
|
||||
+}
|
||||
+
|
||||
+static size_t qpw_buffer_get_free(HWVoiceOut *hw)
|
||||
+{
|
||||
+ PWVoiceOut *pw = (PWVoiceOut *)hw;
|
||||
+ PWVoice *v = &pw->v;
|
||||
+ pwaudio *c = v->g;
|
||||
+ const char *error = NULL;
|
||||
+ int32_t filled, avail;
|
||||
+ uint32_t index;
|
||||
+
|
||||
+ pw_thread_loop_lock(c->thread_loop);
|
||||
+ if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
|
||||
+ /* wait for stream to become ready */
|
||||
+ avail = 0;
|
||||
+ goto done_unlock;
|
||||
+ }
|
||||
+
|
||||
+ filled = spa_ringbuffer_get_write_index(&v->ring, &index);
|
||||
+ avail = v->highwater_mark - filled;
|
||||
+
|
||||
+done_unlock:
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+ return avail;
|
||||
+}
|
||||
+
|
||||
+static size_t
|
||||
+qpw_write(HWVoiceOut *hw, void *data, size_t len)
|
||||
+{
|
||||
+ PWVoiceOut *pw = (PWVoiceOut *) hw;
|
||||
+ PWVoice *v = &pw->v;
|
||||
+ pwaudio *c = v->g;
|
||||
+ const char *error = NULL;
|
||||
+ int32_t filled, avail;
|
||||
+ uint32_t index;
|
||||
+
|
||||
+ pw_thread_loop_lock(c->thread_loop);
|
||||
+ if (pw_stream_get_state(v->stream, &error) != PW_STREAM_STATE_STREAMING) {
|
||||
+ /* wait for stream to become ready */
|
||||
+ len = 0;
|
||||
+ goto done_unlock;
|
||||
+ }
|
||||
+ filled = spa_ringbuffer_get_write_index(&v->ring, &index);
|
||||
+ avail = v->highwater_mark - filled;
|
||||
+
|
||||
+ trace_pw_write(filled, avail, index, len);
|
||||
+
|
||||
+ if (len > avail) {
|
||||
+ len = avail;
|
||||
+ }
|
||||
+
|
||||
+ if (filled < 0) {
|
||||
+ error_report("%p: underrun write:%u filled:%d", pw, index, filled);
|
||||
+ } else {
|
||||
+ if ((uint32_t) filled + len > RINGBUFFER_SIZE) {
|
||||
+ error_report("%p: overrun write:%u filled:%d + size:%zu > max:%u",
|
||||
+ pw, index, filled, len, RINGBUFFER_SIZE);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ spa_ringbuffer_write_data(&v->ring,
|
||||
+ v->buffer, RINGBUFFER_SIZE,
|
||||
+ index & RINGBUFFER_MASK, data, len);
|
||||
+ index += len;
|
||||
+ spa_ringbuffer_write_update(&v->ring, index);
|
||||
+
|
||||
+done_unlock:
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+ return len;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+audfmt_to_pw(AudioFormat fmt, int endianness)
|
||||
+{
|
||||
+ int format;
|
||||
+
|
||||
+ switch (fmt) {
|
||||
+ case AUDIO_FORMAT_S8:
|
||||
+ format = SPA_AUDIO_FORMAT_S8;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_U8:
|
||||
+ format = SPA_AUDIO_FORMAT_U8;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_S16:
|
||||
+ format = endianness ? SPA_AUDIO_FORMAT_S16_BE : SPA_AUDIO_FORMAT_S16_LE;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_U16:
|
||||
+ format = endianness ? SPA_AUDIO_FORMAT_U16_BE : SPA_AUDIO_FORMAT_U16_LE;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_S32:
|
||||
+ format = endianness ? SPA_AUDIO_FORMAT_S32_BE : SPA_AUDIO_FORMAT_S32_LE;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_U32:
|
||||
+ format = endianness ? SPA_AUDIO_FORMAT_U32_BE : SPA_AUDIO_FORMAT_U32_LE;
|
||||
+ break;
|
||||
+ case AUDIO_FORMAT_F32:
|
||||
+ format = endianness ? SPA_AUDIO_FORMAT_F32_BE : SPA_AUDIO_FORMAT_F32_LE;
|
||||
+ break;
|
||||
+ default:
|
||||
+ dolog("Internal logic error: Bad audio format %d\n", fmt);
|
||||
+ format = SPA_AUDIO_FORMAT_U8;
|
||||
+ break;
|
||||
+ }
|
||||
+ return format;
|
||||
+}
|
||||
+
|
||||
+static AudioFormat
|
||||
+pw_to_audfmt(enum spa_audio_format fmt, int *endianness,
|
||||
+ uint32_t *sample_size)
|
||||
+{
|
||||
+ switch (fmt) {
|
||||
+ case SPA_AUDIO_FORMAT_S8:
|
||||
+ *sample_size = 1;
|
||||
+ return AUDIO_FORMAT_S8;
|
||||
+ case SPA_AUDIO_FORMAT_U8:
|
||||
+ *sample_size = 1;
|
||||
+ return AUDIO_FORMAT_U8;
|
||||
+ case SPA_AUDIO_FORMAT_S16_BE:
|
||||
+ *sample_size = 2;
|
||||
+ *endianness = 1;
|
||||
+ return AUDIO_FORMAT_S16;
|
||||
+ case SPA_AUDIO_FORMAT_S16_LE:
|
||||
+ *sample_size = 2;
|
||||
+ *endianness = 0;
|
||||
+ return AUDIO_FORMAT_S16;
|
||||
+ case SPA_AUDIO_FORMAT_U16_BE:
|
||||
+ *sample_size = 2;
|
||||
+ *endianness = 1;
|
||||
+ return AUDIO_FORMAT_U16;
|
||||
+ case SPA_AUDIO_FORMAT_U16_LE:
|
||||
+ *sample_size = 2;
|
||||
+ *endianness = 0;
|
||||
+ return AUDIO_FORMAT_U16;
|
||||
+ case SPA_AUDIO_FORMAT_S32_BE:
|
||||
+ *sample_size = 4;
|
||||
+ *endianness = 1;
|
||||
+ return AUDIO_FORMAT_S32;
|
||||
+ case SPA_AUDIO_FORMAT_S32_LE:
|
||||
+ *sample_size = 4;
|
||||
+ *endianness = 0;
|
||||
+ return AUDIO_FORMAT_S32;
|
||||
+ case SPA_AUDIO_FORMAT_U32_BE:
|
||||
+ *sample_size = 4;
|
||||
+ *endianness = 1;
|
||||
+ return AUDIO_FORMAT_U32;
|
||||
+ case SPA_AUDIO_FORMAT_U32_LE:
|
||||
+ *sample_size = 4;
|
||||
+ *endianness = 0;
|
||||
+ return AUDIO_FORMAT_U32;
|
||||
+ case SPA_AUDIO_FORMAT_F32_BE:
|
||||
+ *sample_size = 4;
|
||||
+ *endianness = 1;
|
||||
+ return AUDIO_FORMAT_F32;
|
||||
+ case SPA_AUDIO_FORMAT_F32_LE:
|
||||
+ *sample_size = 4;
|
||||
+ *endianness = 0;
|
||||
+ return AUDIO_FORMAT_F32;
|
||||
+ default:
|
||||
+ *sample_size = 1;
|
||||
+ dolog("Internal logic error: Bad spa_audio_format %d\n", fmt);
|
||||
+ return AUDIO_FORMAT_U8;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qpw_stream_new(pwaudio *c, PWVoice *v, const char *stream_name,
|
||||
+ const char *name, enum spa_direction dir)
|
||||
+{
|
||||
+ int res;
|
||||
+ uint32_t n_params;
|
||||
+ const struct spa_pod *params[2];
|
||||
+ uint8_t buffer[1024];
|
||||
+ struct spa_pod_builder b;
|
||||
+ uint64_t buf_samples;
|
||||
+ struct pw_properties *props;
|
||||
+
|
||||
+ props = pw_properties_new(NULL, NULL);
|
||||
+ if (!props) {
|
||||
+ error_report("Failed to create PW properties: %s", g_strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* 75% of the timer period for faster updates */
|
||||
+ buf_samples = (uint64_t)v->g->dev->timer_period * v->info.rate
|
||||
+ * 3 / 4 / 1000000;
|
||||
+ pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%" PRIu64 "/%u",
|
||||
+ buf_samples, v->info.rate);
|
||||
+
|
||||
+ trace_pw_period(buf_samples, v->info.rate);
|
||||
+ if (name) {
|
||||
+ pw_properties_set(props, PW_KEY_TARGET_OBJECT, name);
|
||||
+ }
|
||||
+ v->stream = pw_stream_new(c->core, stream_name, props);
|
||||
+ if (v->stream == NULL) {
|
||||
+ error_report("Failed to create PW stream: %s", g_strerror(errno));
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ if (dir == SPA_DIRECTION_INPUT) {
|
||||
+ pw_stream_add_listener(v->stream,
|
||||
+ &v->stream_listener, &capture_stream_events, v);
|
||||
+ } else {
|
||||
+ pw_stream_add_listener(v->stream,
|
||||
+ &v->stream_listener, &playback_stream_events, v);
|
||||
+ }
|
||||
+
|
||||
+ n_params = 0;
|
||||
+ spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||
+ params[n_params++] = spa_format_audio_raw_build(&b,
|
||||
+ SPA_PARAM_EnumFormat,
|
||||
+ &v->info);
|
||||
+
|
||||
+ /* connect the stream to a sink or source */
|
||||
+ res = pw_stream_connect(v->stream,
|
||||
+ dir ==
|
||||
+ SPA_DIRECTION_INPUT ? PW_DIRECTION_INPUT :
|
||||
+ PW_DIRECTION_OUTPUT, PW_ID_ANY,
|
||||
+ PW_STREAM_FLAG_AUTOCONNECT |
|
||||
+ PW_STREAM_FLAG_INACTIVE |
|
||||
+ PW_STREAM_FLAG_MAP_BUFFERS |
|
||||
+ PW_STREAM_FLAG_RT_PROCESS, params, n_params);
|
||||
+ if (res < 0) {
|
||||
+ error_report("Failed to connect PW stream: %s", g_strerror(errno));
|
||||
+ pw_stream_destroy(v->stream);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_set_position(uint32_t channels, uint32_t position[SPA_AUDIO_MAX_CHANNELS])
|
||||
+{
|
||||
+ memcpy(position, (uint32_t[SPA_AUDIO_MAX_CHANNELS]) { SPA_AUDIO_CHANNEL_UNKNOWN, },
|
||||
+ sizeof(uint32_t) * SPA_AUDIO_MAX_CHANNELS);
|
||||
+ /*
|
||||
+ * TODO: This currently expects the only frontend supporting more than 2
|
||||
+ * channels is the usb-audio. We will need some means to set channel
|
||||
+ * order when a new frontend gains multi-channel support.
|
||||
+ */
|
||||
+ switch (channels) {
|
||||
+ case 8:
|
||||
+ position[6] = SPA_AUDIO_CHANNEL_SL;
|
||||
+ position[7] = SPA_AUDIO_CHANNEL_SR;
|
||||
+ /* fallthrough */
|
||||
+ case 6:
|
||||
+ position[2] = SPA_AUDIO_CHANNEL_FC;
|
||||
+ position[3] = SPA_AUDIO_CHANNEL_LFE;
|
||||
+ position[4] = SPA_AUDIO_CHANNEL_RL;
|
||||
+ position[5] = SPA_AUDIO_CHANNEL_RR;
|
||||
+ /* fallthrough */
|
||||
+ case 2:
|
||||
+ position[0] = SPA_AUDIO_CHANNEL_FL;
|
||||
+ position[1] = SPA_AUDIO_CHANNEL_FR;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ position[0] = SPA_AUDIO_CHANNEL_MONO;
|
||||
+ break;
|
||||
+ default:
|
||||
+ dolog("Internal error: unsupported channel count %d\n", channels);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qpw_init_out(HWVoiceOut *hw, struct audsettings *as, void *drv_opaque)
|
||||
+{
|
||||
+ PWVoiceOut *pw = (PWVoiceOut *) hw;
|
||||
+ PWVoice *v = &pw->v;
|
||||
+ struct audsettings obt_as = *as;
|
||||
+ pwaudio *c = v->g = drv_opaque;
|
||||
+ AudiodevPipewireOptions *popts = &c->dev->u.pipewire;
|
||||
+ AudiodevPipewirePerDirectionOptions *ppdo = popts->out;
|
||||
+ int r;
|
||||
+
|
||||
+ pw_thread_loop_lock(c->thread_loop);
|
||||
+
|
||||
+ v->info.format = audfmt_to_pw(as->fmt, as->endianness);
|
||||
+ v->info.channels = as->nchannels;
|
||||
+ qpw_set_position(as->nchannels, v->info.position);
|
||||
+ v->info.rate = as->freq;
|
||||
+
|
||||
+ obt_as.fmt =
|
||||
+ pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size);
|
||||
+ v->frame_size *= as->nchannels;
|
||||
+
|
||||
+ v->req = (uint64_t)c->dev->timer_period * v->info.rate
|
||||
+ * 1 / 2 / 1000000 * v->frame_size;
|
||||
+
|
||||
+ /* call the function that creates a new stream for playback */
|
||||
+ r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id,
|
||||
+ ppdo->name, SPA_DIRECTION_OUTPUT);
|
||||
+ if (r < 0) {
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* report the audio format we support */
|
||||
+ audio_pcm_init_info(&hw->info, &obt_as);
|
||||
+
|
||||
+ /* report the buffer size to qemu */
|
||||
+ hw->samples = audio_buffer_frames(
|
||||
+ qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
|
||||
+ v->highwater_mark = MIN(RINGBUFFER_SIZE,
|
||||
+ (ppdo->has_latency ? ppdo->latency : 46440)
|
||||
+ * (uint64_t)v->info.rate / 1000000 * v->frame_size);
|
||||
+
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+qpw_init_in(HWVoiceIn *hw, struct audsettings *as, void *drv_opaque)
|
||||
+{
|
||||
+ PWVoiceIn *pw = (PWVoiceIn *) hw;
|
||||
+ PWVoice *v = &pw->v;
|
||||
+ struct audsettings obt_as = *as;
|
||||
+ pwaudio *c = v->g = drv_opaque;
|
||||
+ AudiodevPipewireOptions *popts = &c->dev->u.pipewire;
|
||||
+ AudiodevPipewirePerDirectionOptions *ppdo = popts->in;
|
||||
+ int r;
|
||||
+
|
||||
+ pw_thread_loop_lock(c->thread_loop);
|
||||
+
|
||||
+ v->info.format = audfmt_to_pw(as->fmt, as->endianness);
|
||||
+ v->info.channels = as->nchannels;
|
||||
+ qpw_set_position(as->nchannels, v->info.position);
|
||||
+ v->info.rate = as->freq;
|
||||
+
|
||||
+ obt_as.fmt =
|
||||
+ pw_to_audfmt(v->info.format, &obt_as.endianness, &v->frame_size);
|
||||
+ v->frame_size *= as->nchannels;
|
||||
+
|
||||
+ /* call the function that creates a new stream for recording */
|
||||
+ r = qpw_stream_new(c, v, ppdo->stream_name ? : c->dev->id,
|
||||
+ ppdo->name, SPA_DIRECTION_INPUT);
|
||||
+ if (r < 0) {
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ /* report the audio format we support */
|
||||
+ audio_pcm_init_info(&hw->info, &obt_as);
|
||||
+
|
||||
+ /* report the buffer size to qemu */
|
||||
+ hw->samples = audio_buffer_frames(
|
||||
+ qapi_AudiodevPipewirePerDirectionOptions_base(ppdo), &obt_as, 46440);
|
||||
+
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_voice_fini(PWVoice *v)
|
||||
+{
|
||||
+ pwaudio *c = v->g;
|
||||
+
|
||||
+ if (!v->stream) {
|
||||
+ return;
|
||||
+ }
|
||||
+ pw_thread_loop_lock(c->thread_loop);
|
||||
+ pw_stream_destroy(v->stream);
|
||||
+ v->stream = NULL;
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_fini_out(HWVoiceOut *hw)
|
||||
+{
|
||||
+ qpw_voice_fini(&PW_VOICE_OUT(hw)->v);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_fini_in(HWVoiceIn *hw)
|
||||
+{
|
||||
+ qpw_voice_fini(&PW_VOICE_IN(hw)->v);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_voice_set_enabled(PWVoice *v, bool enable)
|
||||
+{
|
||||
+ pwaudio *c = v->g;
|
||||
+ pw_thread_loop_lock(c->thread_loop);
|
||||
+ pw_stream_set_active(v->stream, enable);
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_enable_out(HWVoiceOut *hw, bool enable)
|
||||
+{
|
||||
+ qpw_voice_set_enabled(&PW_VOICE_OUT(hw)->v, enable);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_enable_in(HWVoiceIn *hw, bool enable)
|
||||
+{
|
||||
+ qpw_voice_set_enabled(&PW_VOICE_IN(hw)->v, enable);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_voice_set_volume(PWVoice *v, Volume *vol)
|
||||
+{
|
||||
+ pwaudio *c = v->g;
|
||||
+ int i, ret;
|
||||
+
|
||||
+ pw_thread_loop_lock(c->thread_loop);
|
||||
+ v->volume.channels = vol->channels;
|
||||
+
|
||||
+ for (i = 0; i < vol->channels; ++i) {
|
||||
+ v->volume.values[i] = (float)vol->vol[i] / 255;
|
||||
+ }
|
||||
+
|
||||
+ ret = pw_stream_set_control(v->stream,
|
||||
+ SPA_PROP_channelVolumes, v->volume.channels, v->volume.values, 0);
|
||||
+ trace_pw_vol(ret == 0 ? "success" : "failed");
|
||||
+
|
||||
+ v->muted = vol->mute;
|
||||
+ float val = v->muted ? 1.f : 0.f;
|
||||
+ ret = pw_stream_set_control(v->stream, SPA_PROP_mute, 1, &val, 0);
|
||||
+ pw_thread_loop_unlock(c->thread_loop);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_volume_out(HWVoiceOut *hw, Volume *vol)
|
||||
+{
|
||||
+ qpw_voice_set_volume(&PW_VOICE_OUT(hw)->v, vol);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_volume_in(HWVoiceIn *hw, Volume *vol)
|
||||
+{
|
||||
+ qpw_voice_set_volume(&PW_VOICE_IN(hw)->v, vol);
|
||||
+}
|
||||
+
|
||||
+static int wait_resync(pwaudio *pw)
|
||||
+{
|
||||
+ int res;
|
||||
+ pw->pending_seq = pw_core_sync(pw->core, PW_ID_CORE, pw->pending_seq);
|
||||
+
|
||||
+ while (true) {
|
||||
+ pw_thread_loop_wait(pw->thread_loop);
|
||||
+
|
||||
+ res = pw->error;
|
||||
+ if (res < 0) {
|
||||
+ pw->error = 0;
|
||||
+ return res;
|
||||
+ }
|
||||
+ if (pw->pending_seq == pw->last_seq) {
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+on_core_error(void *data, uint32_t id, int seq, int res, const char *message)
|
||||
+{
|
||||
+ pwaudio *pw = data;
|
||||
+
|
||||
+ error_report("error id:%u seq:%d res:%d (%s): %s",
|
||||
+ id, seq, res, spa_strerror(res), message);
|
||||
+
|
||||
+ /* stop and exit the thread loop */
|
||||
+ pw_thread_loop_signal(pw->thread_loop, FALSE);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+on_core_done(void *data, uint32_t id, int seq)
|
||||
+{
|
||||
+ pwaudio *pw = data;
|
||||
+ assert(id == PW_ID_CORE);
|
||||
+ pw->last_seq = seq;
|
||||
+ if (pw->pending_seq == seq) {
|
||||
+ /* stop and exit the thread loop */
|
||||
+ pw_thread_loop_signal(pw->thread_loop, FALSE);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static const struct pw_core_events core_events = {
|
||||
+ PW_VERSION_CORE_EVENTS,
|
||||
+ .done = on_core_done,
|
||||
+ .error = on_core_error,
|
||||
+};
|
||||
+
|
||||
+static void *
|
||||
+qpw_audio_init(Audiodev *dev, Error **errp)
|
||||
+{
|
||||
+ g_autofree pwaudio *pw = g_new0(pwaudio, 1);
|
||||
+
|
||||
+ assert(dev->driver == AUDIODEV_DRIVER_PIPEWIRE);
|
||||
+ trace_pw_audio_init();
|
||||
+
|
||||
+ pw_init(NULL, NULL);
|
||||
+
|
||||
+ pw->dev = dev;
|
||||
+ pw->thread_loop = pw_thread_loop_new("PipeWire thread loop", NULL);
|
||||
+ if (pw->thread_loop == NULL) {
|
||||
+ error_setg_errno(errp, errno, "Could not create PipeWire loop");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ pw->context =
|
||||
+ pw_context_new(pw_thread_loop_get_loop(pw->thread_loop), NULL, 0);
|
||||
+ if (pw->context == NULL) {
|
||||
+ error_setg_errno(errp, errno, "Could not create PipeWire context");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ if (pw_thread_loop_start(pw->thread_loop) < 0) {
|
||||
+ error_setg_errno(errp, errno, "Could not start PipeWire loop");
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ pw_thread_loop_lock(pw->thread_loop);
|
||||
+
|
||||
+ pw->core = pw_context_connect(pw->context, NULL, 0);
|
||||
+ if (pw->core == NULL) {
|
||||
+ pw_thread_loop_unlock(pw->thread_loop);
|
||||
+ goto fail_error;
|
||||
+ }
|
||||
+
|
||||
+ if (pw_core_add_listener(pw->core, &pw->core_listener,
|
||||
+ &core_events, pw) < 0) {
|
||||
+ pw_thread_loop_unlock(pw->thread_loop);
|
||||
+ goto fail_error;
|
||||
+ }
|
||||
+ if (wait_resync(pw) < 0) {
|
||||
+ pw_thread_loop_unlock(pw->thread_loop);
|
||||
+ }
|
||||
+
|
||||
+ pw_thread_loop_unlock(pw->thread_loop);
|
||||
+
|
||||
+ return g_steal_pointer(&pw);
|
||||
+
|
||||
+fail_error:
|
||||
+ error_setg(errp, "Failed to initialize PW context");
|
||||
+fail:
|
||||
+ if (pw->thread_loop) {
|
||||
+ pw_thread_loop_stop(pw->thread_loop);
|
||||
+ }
|
||||
+ g_clear_pointer(&pw->context, pw_context_destroy);
|
||||
+ g_clear_pointer(&pw->thread_loop, pw_thread_loop_destroy);
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+qpw_audio_fini(void *opaque)
|
||||
+{
|
||||
+ pwaudio *pw = opaque;
|
||||
+
|
||||
+ if (pw->thread_loop) {
|
||||
+ pw_thread_loop_stop(pw->thread_loop);
|
||||
+ }
|
||||
+
|
||||
+ if (pw->core) {
|
||||
+ spa_hook_remove(&pw->core_listener);
|
||||
+ spa_zero(pw->core_listener);
|
||||
+ pw_core_disconnect(pw->core);
|
||||
+ }
|
||||
+
|
||||
+ if (pw->context) {
|
||||
+ pw_context_destroy(pw->context);
|
||||
+ }
|
||||
+ pw_thread_loop_destroy(pw->thread_loop);
|
||||
+
|
||||
+ g_free(pw);
|
||||
+}
|
||||
+
|
||||
+static struct audio_pcm_ops qpw_pcm_ops = {
|
||||
+ .init_out = qpw_init_out,
|
||||
+ .fini_out = qpw_fini_out,
|
||||
+ .write = qpw_write,
|
||||
+ .buffer_get_free = qpw_buffer_get_free,
|
||||
+ .run_buffer_out = audio_generic_run_buffer_out,
|
||||
+ .enable_out = qpw_enable_out,
|
||||
+ .volume_out = qpw_volume_out,
|
||||
+ .volume_in = qpw_volume_in,
|
||||
+
|
||||
+ .init_in = qpw_init_in,
|
||||
+ .fini_in = qpw_fini_in,
|
||||
+ .read = qpw_read,
|
||||
+ .run_buffer_in = audio_generic_run_buffer_in,
|
||||
+ .enable_in = qpw_enable_in
|
||||
+};
|
||||
+
|
||||
+static struct audio_driver pw_audio_driver = {
|
||||
+ .name = "pipewire",
|
||||
+ .descr = "http://www.pipewire.org/",
|
||||
+ .init = qpw_audio_init,
|
||||
+ .fini = qpw_audio_fini,
|
||||
+ .pcm_ops = &qpw_pcm_ops,
|
||||
+ .max_voices_out = INT_MAX,
|
||||
+ .max_voices_in = INT_MAX,
|
||||
+ .voice_size_out = sizeof(PWVoiceOut),
|
||||
+ .voice_size_in = sizeof(PWVoiceIn),
|
||||
+};
|
||||
+
|
||||
+static void
|
||||
+register_audio_pw(void)
|
||||
+{
|
||||
+ audio_driver_register(&pw_audio_driver);
|
||||
+}
|
||||
+
|
||||
+type_init(register_audio_pw);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
61
block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch
Normal file
61
block-blkio-use-FUA-flag-on-write-zeroes-only-if-sup.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From 9daf2b936101d612a295217822791d323e908fc9 Mon Sep 17 00:00:00 2001
|
||||
From: Stefano Garzarella <sgarzare@redhat.com>
|
||||
Date: Thu, 8 Aug 2024 10:05:45 +0200
|
||||
Subject: [PATCH] block/blkio: use FUA flag on write zeroes only if supported
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
libblkio supports BLKIO_REQ_FUA with write zeros requests only since
|
||||
version 1.4.0, so let's inform the block layer that the blkio driver
|
||||
supports it only in this case. Otherwise we can have runtime errors
|
||||
as reported in https://issues.redhat.com/browse/RHEL-32878
|
||||
|
||||
Fixes: fd66dbd424 ("blkio: add libblkio block driver")
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Buglink: https://issues.redhat.com/browse/RHEL-32878
|
||||
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
|
||||
Reviewed-by: Eric Blake <eblake@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Message-id: 20240808080545.40744-1-sgarzare@redhat.com
|
||||
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
|
||||
(cherry picked from commit 547c4e50929ec6c091d9c16a7b280e829b12b463)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
block/blkio.c | 6 ++++--
|
||||
meson.build | 2 ++
|
||||
2 files changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/block/blkio.c b/block/blkio.c
|
||||
index b989617608..027c16ceb6 100644
|
||||
--- a/block/blkio.c
|
||||
+++ b/block/blkio.c
|
||||
@@ -899,8 +899,10 @@ static int blkio_file_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
}
|
||||
|
||||
bs->supported_write_flags = BDRV_REQ_FUA | BDRV_REQ_REGISTERED_BUF;
|
||||
- bs->supported_zero_flags = BDRV_REQ_FUA | BDRV_REQ_MAY_UNMAP |
|
||||
- BDRV_REQ_NO_FALLBACK;
|
||||
+ bs->supported_zero_flags = BDRV_REQ_MAY_UNMAP | BDRV_REQ_NO_FALLBACK;
|
||||
+#ifdef CONFIG_BLKIO_WRITE_ZEROS_FUA
|
||||
+ bs->supported_zero_flags |= BDRV_REQ_FUA;
|
||||
+#endif
|
||||
|
||||
qemu_mutex_init(&s->blkio_lock);
|
||||
qemu_co_mutex_init(&s->bounce_lock);
|
||||
diff --git a/meson.build b/meson.build
|
||||
index 4024f9a4bb..ce2fd07963 100644
|
||||
--- a/meson.build
|
||||
+++ b/meson.build
|
||||
@@ -2181,6 +2181,8 @@ config_host_data.set('CONFIG_BLKIO', blkio.found())
|
||||
if blkio.found()
|
||||
config_host_data.set('CONFIG_BLKIO_VHOST_VDPA_FD',
|
||||
blkio.version().version_compare('>=1.3.0'))
|
||||
+ config_host_data.set('CONFIG_BLKIO_WRITE_ZEROS_FUA',
|
||||
+ blkio.version().version_compare('>=1.4.0'))
|
||||
endif
|
||||
config_host_data.set('CONFIG_CURL', curl.found())
|
||||
config_host_data.set('CONFIG_CURSES', curses.found())
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
57
crypto-drop-gnutls-debug-logging-support.patch
Normal file
57
crypto-drop-gnutls-debug-logging-support.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From c64bd463b120056ff1e6c32e48fa24b6afd17f23 Mon Sep 17 00:00:00 2001
|
||||
From: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
Date: Sat, 12 Oct 2024 13:47:25 +0800
|
||||
Subject: [PATCH] crypto: drop gnutls debug logging support MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
GNUTLS already supports dynamically enabling its logging at runtime by
|
||||
setting the env var 'GNUTLS_DEBUG_LEVEL=10', so there is no need to
|
||||
re-invent this logic in QEMU in a way that requires a re-compile.
|
||||
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
---
|
||||
crypto/init.c | 15 ++++-----------
|
||||
1 file changed, 4 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/crypto/init.c b/crypto/init.c
|
||||
index fb7f1bff10..674d237fa9 100644
|
||||
--- a/crypto/init.c
|
||||
+++ b/crypto/init.c
|
||||
@@ -34,14 +34,11 @@
|
||||
|
||||
#include "crypto/random.h"
|
||||
|
||||
-/* #define DEBUG_GNUTLS */
|
||||
-#ifdef DEBUG_GNUTLS
|
||||
-static void qcrypto_gnutls_log(int level, const char *str)
|
||||
-{
|
||||
- fprintf(stderr, "%d: %s", level, str);
|
||||
-}
|
||||
-#endif
|
||||
|
||||
+/*
|
||||
+ * To debug GNUTLS see env vars listed in
|
||||
+ * https://gnutls.org/manual/html_node/Debugging-and-auditing.html
|
||||
+ */
|
||||
int qcrypto_init(Error **errp)
|
||||
{
|
||||
#ifdef CONFIG_GNUTLS
|
||||
@@ -53,10 +50,6 @@ int qcrypto_init(Error **errp)
|
||||
gnutls_strerror(ret));
|
||||
return -1;
|
||||
}
|
||||
-#ifdef DEBUG_GNUTLS
|
||||
- gnutls_global_set_log_level(10);
|
||||
- gnutls_global_set_log_function(qcrypto_gnutls_log);
|
||||
-#endif
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_GCRYPT
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
168
crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch
Normal file
168
crypto-factor-out-conversion-of-QAPI-to-gcrypt-const.patch
Normal file
@ -0,0 +1,168 @@
|
||||
From e1aaa51fc2de072871cce45dd165e2cb38515978 Mon Sep 17 00:00:00 2001
|
||||
From: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
Date: Sat, 12 Oct 2024 14:00:08 +0800
|
||||
Subject: [PATCH] crypto: factor out conversion of QAPI to gcrypt constants
|
||||
MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The conversion of cipher mode will shortly be required in more
|
||||
than one place.
|
||||
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
---
|
||||
crypto/cipher-gcrypt.c.inc | 116 +++++++++++++++++++------------------
|
||||
1 file changed, 60 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/crypto/cipher-gcrypt.c.inc b/crypto/cipher-gcrypt.c.inc
|
||||
index 1377cbaf14..6b82280f90 100644
|
||||
--- a/crypto/cipher-gcrypt.c.inc
|
||||
+++ b/crypto/cipher-gcrypt.c.inc
|
||||
@@ -20,6 +20,56 @@
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
+static int qcrypto_cipher_alg_to_gcry_alg(QCryptoCipherAlgorithm alg)
|
||||
+{
|
||||
+ switch (alg) {
|
||||
+ case QCRYPTO_CIPHER_ALG_DES:
|
||||
+ return GCRY_CIPHER_DES;
|
||||
+ case QCRYPTO_CIPHER_ALG_3DES:
|
||||
+ return GCRY_CIPHER_3DES;
|
||||
+ case QCRYPTO_CIPHER_ALG_AES_128:
|
||||
+ return GCRY_CIPHER_AES128;
|
||||
+ case QCRYPTO_CIPHER_ALG_AES_192:
|
||||
+ return GCRY_CIPHER_AES192;
|
||||
+ case QCRYPTO_CIPHER_ALG_AES_256:
|
||||
+ return GCRY_CIPHER_AES256;
|
||||
+ case QCRYPTO_CIPHER_ALG_CAST5_128:
|
||||
+ return GCRY_CIPHER_CAST5;
|
||||
+ case QCRYPTO_CIPHER_ALG_SERPENT_128:
|
||||
+ return GCRY_CIPHER_SERPENT128;
|
||||
+ case QCRYPTO_CIPHER_ALG_SERPENT_192:
|
||||
+ return GCRY_CIPHER_SERPENT192;
|
||||
+ case QCRYPTO_CIPHER_ALG_SERPENT_256:
|
||||
+ return GCRY_CIPHER_SERPENT256;
|
||||
+ case QCRYPTO_CIPHER_ALG_TWOFISH_128:
|
||||
+ return GCRY_CIPHER_TWOFISH128;
|
||||
+ case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
||||
+ return GCRY_CIPHER_TWOFISH;
|
||||
+#ifdef CONFIG_CRYPTO_SM4
|
||||
+ case QCRYPTO_CIPHER_ALG_SM4:
|
||||
+ return GCRY_CIPHER_SM4;
|
||||
+#endif
|
||||
+ default:
|
||||
+ return GCRY_CIPHER_NONE;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int qcrypto_cipher_mode_to_gcry_mode(QCryptoCipherMode mode)
|
||||
+{
|
||||
+ switch (mode) {
|
||||
+ case QCRYPTO_CIPHER_MODE_ECB:
|
||||
+ return GCRY_CIPHER_MODE_ECB;
|
||||
+ case QCRYPTO_CIPHER_MODE_XTS:
|
||||
+ return GCRY_CIPHER_MODE_XTS;
|
||||
+ case QCRYPTO_CIPHER_MODE_CBC:
|
||||
+ return GCRY_CIPHER_MODE_CBC;
|
||||
+ case QCRYPTO_CIPHER_MODE_CTR:
|
||||
+ return GCRY_CIPHER_MODE_CTR;
|
||||
+ default:
|
||||
+ return GCRY_CIPHER_MODE_NONE;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
|
||||
QCryptoCipherMode mode)
|
||||
{
|
||||
@@ -188,72 +238,26 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- switch (alg) {
|
||||
- case QCRYPTO_CIPHER_ALG_DES:
|
||||
- gcryalg = GCRY_CIPHER_DES;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_3DES:
|
||||
- gcryalg = GCRY_CIPHER_3DES;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_AES_128:
|
||||
- gcryalg = GCRY_CIPHER_AES128;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_AES_192:
|
||||
- gcryalg = GCRY_CIPHER_AES192;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_AES_256:
|
||||
- gcryalg = GCRY_CIPHER_AES256;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_CAST5_128:
|
||||
- gcryalg = GCRY_CIPHER_CAST5;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_SERPENT_128:
|
||||
- gcryalg = GCRY_CIPHER_SERPENT128;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_SERPENT_192:
|
||||
- gcryalg = GCRY_CIPHER_SERPENT192;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_SERPENT_256:
|
||||
- gcryalg = GCRY_CIPHER_SERPENT256;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_TWOFISH_128:
|
||||
- gcryalg = GCRY_CIPHER_TWOFISH128;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_ALG_TWOFISH_256:
|
||||
- gcryalg = GCRY_CIPHER_TWOFISH;
|
||||
- break;
|
||||
-#ifdef CONFIG_CRYPTO_SM4
|
||||
- case QCRYPTO_CIPHER_ALG_SM4:
|
||||
- gcryalg = GCRY_CIPHER_SM4;
|
||||
- break;
|
||||
-#endif
|
||||
- default:
|
||||
+ gcryalg = qcrypto_cipher_alg_to_gcry_alg(alg);
|
||||
+ if (gcryalg == GCRY_CIPHER_NONE) {
|
||||
error_setg(errp, "Unsupported cipher algorithm %s",
|
||||
QCryptoCipherAlgorithm_str(alg));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- drv = &qcrypto_gcrypt_driver;
|
||||
- switch (mode) {
|
||||
- case QCRYPTO_CIPHER_MODE_ECB:
|
||||
- gcrymode = GCRY_CIPHER_MODE_ECB;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_MODE_XTS:
|
||||
- gcrymode = GCRY_CIPHER_MODE_XTS;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_MODE_CBC:
|
||||
- gcrymode = GCRY_CIPHER_MODE_CBC;
|
||||
- break;
|
||||
- case QCRYPTO_CIPHER_MODE_CTR:
|
||||
- drv = &qcrypto_gcrypt_ctr_driver;
|
||||
- gcrymode = GCRY_CIPHER_MODE_CTR;
|
||||
- break;
|
||||
- default:
|
||||
+ gcrymode = qcrypto_cipher_mode_to_gcry_mode(mode);
|
||||
+ if (gcrymode == GCRY_CIPHER_MODE_NONE) {
|
||||
error_setg(errp, "Unsupported cipher mode %s",
|
||||
QCryptoCipherMode_str(mode));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+ if (mode == QCRYPTO_CIPHER_MODE_CTR) {
|
||||
+ drv = &qcrypto_gcrypt_ctr_driver;
|
||||
+ } else {
|
||||
+ drv = &qcrypto_gcrypt_driver;
|
||||
+ }
|
||||
+
|
||||
ctx = g_new0(QCryptoCipherGcrypt, 1);
|
||||
ctx->base.driver = drv;
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
78
crypto-use-consistent-error-reporting-pattern-for-un.patch
Normal file
78
crypto-use-consistent-error-reporting-pattern-for-un.patch
Normal file
@ -0,0 +1,78 @@
|
||||
From 7bd04536327357a97206d8048f5d9341780bbe5a Mon Sep 17 00:00:00 2001
|
||||
From: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
Date: Sat, 12 Oct 2024 11:26:16 +0800
|
||||
Subject: [PATCH] crypto: use consistent error reporting pattern for
|
||||
unsupported cipher modes MIME-Version: 1.0 Content-Type: text/plain;
|
||||
charset=UTF-8 Content-Transfer-Encoding: 8bit
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Not all paths in qcrypto_cipher_ctx_new() were correctly distinguishing
|
||||
between valid user input for cipher mode (which should report a user
|
||||
facing error), vs program logic errors (which should assert).
|
||||
|
||||
Reported-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Signed-off-by: dinglimin <dinglimin@cmss.chinamobile.com>
|
||||
---
|
||||
crypto/cipher-nettle.c.inc | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/crypto/cipher-nettle.c.inc b/crypto/cipher-nettle.c.inc
|
||||
index 766de036ba..2654b439c1 100644
|
||||
--- a/crypto/cipher-nettle.c.inc
|
||||
+++ b/crypto/cipher-nettle.c.inc
|
||||
@@ -525,8 +525,10 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
case QCRYPTO_CIPHER_MODE_CTR:
|
||||
drv = &qcrypto_nettle_des_driver_ctr;
|
||||
break;
|
||||
- default:
|
||||
+ case QCRYPTO_CIPHER_MODE_XTS:
|
||||
goto bad_cipher_mode;
|
||||
+ default:
|
||||
+ g_assert_not_reached();
|
||||
}
|
||||
|
||||
ctx = g_new0(QCryptoNettleDES, 1);
|
||||
@@ -551,8 +553,10 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
case QCRYPTO_CIPHER_MODE_CTR:
|
||||
drv = &qcrypto_nettle_des3_driver_ctr;
|
||||
break;
|
||||
- default:
|
||||
+ case QCRYPTO_CIPHER_MODE_XTS:
|
||||
goto bad_cipher_mode;
|
||||
+ default:
|
||||
+ g_assert_not_reached();
|
||||
}
|
||||
|
||||
ctx = g_new0(QCryptoNettleDES3, 1);
|
||||
@@ -663,8 +667,10 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
case QCRYPTO_CIPHER_MODE_CTR:
|
||||
drv = &qcrypto_nettle_cast128_driver_ctr;
|
||||
break;
|
||||
- default:
|
||||
+ case QCRYPTO_CIPHER_MODE_XTS:
|
||||
goto bad_cipher_mode;
|
||||
+ default:
|
||||
+ g_assert_not_reached();
|
||||
}
|
||||
|
||||
ctx = g_new0(QCryptoNettleCAST128, 1);
|
||||
@@ -741,8 +747,12 @@ static QCryptoCipher *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
|
||||
case QCRYPTO_CIPHER_MODE_ECB:
|
||||
drv = &qcrypto_nettle_sm4_driver_ecb;
|
||||
break;
|
||||
- default:
|
||||
+ case QCRYPTO_CIPHER_MODE_CBC:
|
||||
+ case QCRYPTO_CIPHER_MODE_CTR:
|
||||
+ case QCRYPTO_CIPHER_MODE_XTS:
|
||||
goto bad_cipher_mode;
|
||||
+ default:
|
||||
+ g_assert_not_reached();
|
||||
}
|
||||
|
||||
ctx = g_new0(QCryptoNettleSm4, 1);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
294
cvm-Add-support-for-TEE-based-national-encryption-ac.patch
Normal file
294
cvm-Add-support-for-TEE-based-national-encryption-ac.patch
Normal file
@ -0,0 +1,294 @@
|
||||
From dffc0f55d93ececee55a8548d7dab227ee76b234 Mon Sep 17 00:00:00 2001
|
||||
From: liupingwei <liupingwei0317@outlook.com>
|
||||
Date: Thu, 24 Oct 2024 19:05:58 +0800
|
||||
Subject: [PATCH] cvm : Add support for TEE-based national encryption
|
||||
acceleration.
|
||||
|
||||
This commit enables the use of TEE for national encryption acceleration
|
||||
in cvm and speeds up OpenSSL encrption /decryption operations.
|
||||
|
||||
Signed-off-by: liupingwei <liupingwei0317@outlook.com>
|
||||
---
|
||||
hw/arm/virt.c | 61 ++++++++++++++++++++++++++++++-
|
||||
include/hw/arm/virt.h | 1 +
|
||||
linux-headers/asm-arm64/kvm.h | 10 ++++++
|
||||
qapi/qom.json | 1 +
|
||||
target/arm/kvm-tmm.c | 68 +++++++++++++++++++++++++++++++++--
|
||||
target/arm/kvm_arm.h | 4 +++
|
||||
6 files changed, 142 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index e73a795d3d..248788db03 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -1967,6 +1967,10 @@ static void virt_set_memmap(VirtMachineState *vms, int pa_bits)
|
||||
"kvm-type", &error_abort);
|
||||
|
||||
if (!strcmp(kvm_type, "cvm")) {
|
||||
+ /* support kae vf device tree nodes */
|
||||
+ vms->memmap[VIRT_PCIE_MMIO] = (MemMapEntry) { 0x10000000, 0x2edf0000 };
|
||||
+ vms->memmap[VIRT_KAE_DEVICE] = (MemMapEntry) { 0x3edf0000, 0x00200000 };
|
||||
+
|
||||
vms->memmap[VIRT_MEM].base = 3 * GiB;
|
||||
vms->memmap[VIRT_MEM].size = ms->ram_size;
|
||||
info_report("[qemu] fix VIRT_MEM range 0x%llx - 0x%llx\n", (unsigned long long)(vms->memmap[VIRT_MEM].base),
|
||||
@@ -2380,6 +2384,56 @@ out:
|
||||
return;
|
||||
}
|
||||
|
||||
+static void fdt_add_hisi_sec_nodes(const VirtMachineState *vms, int dev_id)
|
||||
+{
|
||||
+ const MachineState *ms = MACHINE(vms);
|
||||
+ hwaddr size = 0x10000;
|
||||
+
|
||||
+ /*
|
||||
+ * Calculate the base address for the sec device node.
|
||||
+ * Each device group contains one sec device and one hpre device,spaced by 2 * size.
|
||||
+ */
|
||||
+ hwaddr base = vms->memmap[VIRT_KAE_DEVICE].base + dev_id * 2 * size;
|
||||
+ char *nodename;
|
||||
+
|
||||
+ tmm_set_sec_addr(base, dev_id);
|
||||
+
|
||||
+ nodename = g_strdup_printf("/hisi-sec@%" PRIx64, base);
|
||||
+ qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "hisilicon,hip07-sec-vf");
|
||||
+ qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
|
||||
+ g_free(nodename);
|
||||
+}
|
||||
+
|
||||
+static void fdt_add_hisi_hpre_nodes(const VirtMachineState *vms, int dev_id)
|
||||
+{
|
||||
+ const MachineState *ms = MACHINE(vms);
|
||||
+ hwaddr size = 0x10000;
|
||||
+
|
||||
+ /*
|
||||
+ * Calculate the base address for the hpre device node.
|
||||
+ * Each hpre device follows the corresponding sec device by an additional offset of size.
|
||||
+ */
|
||||
+ hwaddr base = vms->memmap[VIRT_KAE_DEVICE].base + dev_id * 2 * size + size;
|
||||
+ char *nodename;
|
||||
+
|
||||
+ tmm_set_hpre_addr(base, dev_id);
|
||||
+
|
||||
+ nodename = g_strdup_printf("/hisi-hpre@%" PRIx64, base);
|
||||
+ qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "hisilicon,hip07-hpre-vf");
|
||||
+ qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
|
||||
+ g_free(nodename);
|
||||
+}
|
||||
+
|
||||
+static void fdt_add_all_hisi_nodes(const VirtMachineState *vms, int dev_id)
|
||||
+{
|
||||
+ for (int i = 0; i < dev_id; i++) {
|
||||
+ fdt_add_hisi_sec_nodes(vms, i);
|
||||
+ fdt_add_hisi_hpre_nodes(vms, i);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void machvirt_init(MachineState *machine)
|
||||
{
|
||||
VirtMachineState *vms = VIRT_MACHINE(machine);
|
||||
@@ -2530,14 +2584,19 @@ static void machvirt_init(MachineState *machine)
|
||||
}
|
||||
}
|
||||
|
||||
+ create_fdt(vms);
|
||||
+
|
||||
if (virtcca_cvm_enabled()) {
|
||||
+ int kae_num = tmm_get_kae_num();
|
||||
+ fdt_add_all_hisi_nodes(vms, kae_num);
|
||||
+
|
||||
int ret = kvm_arm_tmm_init(machine->cgs, &error_fatal);
|
||||
if (ret != 0) {
|
||||
error_report("fail to initialize TMM");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
- create_fdt(vms);
|
||||
+
|
||||
qemu_log("cpu init start\n");
|
||||
|
||||
cpu_class = object_class_by_name(machine->cpu_type);
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index 27f5333772..76a0d3fa5b 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -66,6 +66,7 @@ enum {
|
||||
VIRT_FW_CFG,
|
||||
VIRT_PCIE,
|
||||
VIRT_PCIE_MMIO,
|
||||
+ VIRT_KAE_DEVICE,
|
||||
VIRT_PCIE_PIO,
|
||||
VIRT_PCIE_ECAM,
|
||||
VIRT_PLATFORM_BUS,
|
||||
diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h
|
||||
index 2b040b5d60..552fdcb18f 100644
|
||||
--- a/linux-headers/asm-arm64/kvm.h
|
||||
+++ b/linux-headers/asm-arm64/kvm.h
|
||||
@@ -541,6 +541,9 @@ struct reg_mask_range {
|
||||
#define KVM_CAP_ARM_TMM_CFG_SVE 2
|
||||
#define KVM_CAP_ARM_TMM_CFG_DBG 3
|
||||
#define KVM_CAP_ARM_TMM_CFG_PMU 4
|
||||
+#define KVM_CAP_ARM_TMM_CFG_KAE 5
|
||||
+
|
||||
+#define KVM_ARM_TMM_MAX_KAE_VF_NUM 11
|
||||
|
||||
struct kvm_cap_arm_tmm_config_item {
|
||||
__u32 cfg;
|
||||
@@ -570,6 +573,13 @@ struct kvm_cap_arm_tmm_config_item {
|
||||
struct {
|
||||
__u32 num_pmu_cntrs;
|
||||
};
|
||||
+
|
||||
+ /* cfg == KVM_CAP_ARM_TMM_CFG_KAE */
|
||||
+ struct {
|
||||
+ __u32 kae_vf_num;
|
||||
+ __u64 sec_addr[KVM_ARM_TMM_MAX_KAE_VF_NUM];
|
||||
+ __u64 hpre_addr[KVM_ARM_TMM_MAX_KAE_VF_NUM];
|
||||
+ };
|
||||
/* Fix the size of the union */
|
||||
__u8 reserved[256];
|
||||
};
|
||||
diff --git a/qapi/qom.json b/qapi/qom.json
|
||||
index 213edd8db2..293d727a04 100644
|
||||
--- a/qapi/qom.json
|
||||
+++ b/qapi/qom.json
|
||||
@@ -921,6 +921,7 @@
|
||||
{ 'struct': 'TmmGuestProperties',
|
||||
'data': { '*sve-vector-length': 'uint32',
|
||||
'*num-pmu-counters': 'uint32',
|
||||
+ '*kae': 'uint32',
|
||||
'*measurement-algo': 'TmmGuestMeasurementAlgo' } }
|
||||
|
||||
##
|
||||
diff --git a/target/arm/kvm-tmm.c b/target/arm/kvm-tmm.c
|
||||
index efe2ca0006..ea6bcc0f40 100644
|
||||
--- a/target/arm/kvm-tmm.c
|
||||
+++ b/target/arm/kvm-tmm.c
|
||||
@@ -19,13 +19,20 @@
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "hw/loader.h"
|
||||
+#include "linux-headers/asm-arm64/kvm.h"
|
||||
|
||||
#define TYPE_TMM_GUEST "tmm-guest"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(TmmGuest, TMM_GUEST)
|
||||
|
||||
#define TMM_PAGE_SIZE qemu_real_host_page_size()
|
||||
-#define TMM_MAX_PMU_CTRS 0x20
|
||||
-#define TMM_MAX_CFG 5
|
||||
+#define TMM_MAX_PMU_CTRS 0x20
|
||||
+#define TMM_MAX_CFG 6
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint32_t kae_vf_num;
|
||||
+ hwaddr sec_addr[KVM_ARM_TMM_MAX_KAE_VF_NUM];
|
||||
+ hwaddr hpre_addr[KVM_ARM_TMM_MAX_KAE_VF_NUM];
|
||||
+} KaeDeviceInfo;
|
||||
|
||||
struct TmmGuest {
|
||||
ConfidentialGuestSupport parent_obj;
|
||||
@@ -33,6 +40,7 @@ struct TmmGuest {
|
||||
TmmGuestMeasurementAlgo measurement_algo;
|
||||
uint32_t sve_vl;
|
||||
uint32_t num_pmu_cntrs;
|
||||
+ KaeDeviceInfo kae_device_info;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -92,6 +100,17 @@ static int tmm_configure_one(TmmGuest *guest, uint32_t cfg, Error **errp)
|
||||
args.num_pmu_cntrs = guest->num_pmu_cntrs;
|
||||
cfg_str = "PMU";
|
||||
break;
|
||||
+ case KVM_CAP_ARM_TMM_CFG_KAE:
|
||||
+ if (!guest->kae_device_info.kae_vf_num) {
|
||||
+ return 0;
|
||||
+ }
|
||||
+ args.kae_vf_num= guest->kae_device_info.kae_vf_num;
|
||||
+ for (int i = 0; i < guest->kae_device_info.kae_vf_num; i++) {
|
||||
+ args.sec_addr[i] = guest->kae_device_info.sec_addr[i];
|
||||
+ args.hpre_addr[i] = guest->kae_device_info.hpre_addr[i];
|
||||
+ }
|
||||
+ cfg_str = "KAE";
|
||||
+ break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
@@ -289,6 +308,47 @@ static void tmm_set_measurement_algo(Object *obj, int algo, Error **errp G_GNUC_
|
||||
guest->measurement_algo = algo;
|
||||
}
|
||||
|
||||
+static void tmm_get_kae_vf_num(Object *obj, Visitor *v, const char *name,
|
||||
+ void *opaque, Error **errp)
|
||||
+{
|
||||
+ TmmGuest *guest = TMM_GUEST(obj);
|
||||
+
|
||||
+ visit_type_uint32(v, name, &guest->kae_device_info.kae_vf_num, errp);
|
||||
+}
|
||||
+
|
||||
+static void tmm_set_kae_vf_num(Object *obj, Visitor *v, const char *name,
|
||||
+ void *opaque, Error **errp)
|
||||
+{
|
||||
+ TmmGuest *guest = TMM_GUEST(obj);
|
||||
+ uint32_t value;
|
||||
+
|
||||
+ if (!visit_type_uint32(v, name, &value, errp)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (value > KVM_ARM_TMM_MAX_KAE_VF_NUM) {
|
||||
+ error_setg(errp, "invalid number of kae vfs");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ guest->kae_device_info.kae_vf_num = value;
|
||||
+}
|
||||
+
|
||||
+int tmm_get_kae_num(void)
|
||||
+{
|
||||
+ return tmm_guest->kae_device_info.kae_vf_num;
|
||||
+}
|
||||
+
|
||||
+void tmm_set_sec_addr(hwaddr base, int num)
|
||||
+{
|
||||
+ tmm_guest->kae_device_info.sec_addr[num] = base;
|
||||
+}
|
||||
+
|
||||
+void tmm_set_hpre_addr(hwaddr base, int num)
|
||||
+{
|
||||
+ tmm_guest->kae_device_info.hpre_addr[num] = base;
|
||||
+}
|
||||
+
|
||||
static void tmm_guest_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
object_class_property_add_enum(oc, "measurement-algo",
|
||||
@@ -314,6 +374,10 @@ static void tmm_guest_class_init(ObjectClass *oc, void *data)
|
||||
NULL, NULL);
|
||||
object_class_property_set_description(oc, "num-pmu-counters",
|
||||
"Number of PMU counters");
|
||||
+ object_class_property_add(oc, "kae", "uint32", tmm_get_kae_vf_num,
|
||||
+ tmm_set_kae_vf_num, NULL, NULL);
|
||||
+ object_class_property_set_description(oc, "kae",
|
||||
+ "Number of KAE virtual functions. 0 disables KAE (the default)");
|
||||
}
|
||||
|
||||
static void tmm_guest_instance_init(Object *obj)
|
||||
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
|
||||
index d6c7139f4a..31457a57f7 100644
|
||||
--- a/target/arm/kvm_arm.h
|
||||
+++ b/target/arm/kvm_arm.h
|
||||
@@ -390,6 +390,10 @@ int kvm_arm_set_irq(int cpu, int irqtype, int irq, int level);
|
||||
|
||||
void tmm_add_ram_region(hwaddr base1, hwaddr len1, hwaddr base2, hwaddr len2, bool populate);
|
||||
|
||||
+int tmm_get_kae_num(void);
|
||||
+void tmm_set_sec_addr(hwaddr base, int num);
|
||||
+void tmm_set_hpre_addr(hwaddr base, int num);
|
||||
+
|
||||
int kvm_arm_tmm_init(ConfidentialGuestSupport *cgs, Error **errp);
|
||||
bool kvm_arm_tmm_enabled(void);
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
61
dma-Fix-function-names-in-documentation.patch
Normal file
61
dma-Fix-function-names-in-documentation.patch
Normal file
@ -0,0 +1,61 @@
|
||||
From d490ccc1254c7d4dbe8ab40dd78e189108155ae0 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?=
|
||||
<zhangchujun@cmss.chinamobile.com>
|
||||
Date: Fri, 18 Oct 2024 10:10:17 +0800
|
||||
Subject: [PATCH] dma: Fix function names in documentation Ensure the function
|
||||
names match.
|
||||
|
||||
Signed-off-by: Akihiko Odaki <akihiko.odaki@daynix.com>
|
||||
Message-id: 20241012-dma-v2-1-6afddf5f3c8d@daynix.com
|
||||
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Signed-off-by: Zhang Chujun <zhangchujun@cmss.chinamoile.com>
|
||||
---
|
||||
include/sysemu/dma.h | 11 +++++------
|
||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/include/sysemu/dma.h b/include/sysemu/dma.h
|
||||
index a1ac5bc1b5..5a49a30628 100644
|
||||
--- a/include/sysemu/dma.h
|
||||
+++ b/include/sysemu/dma.h
|
||||
@@ -152,7 +152,7 @@ static inline MemTxResult dma_memory_read(AddressSpace *as, dma_addr_t addr,
|
||||
}
|
||||
|
||||
/**
|
||||
- * address_space_write: Write to address space from DMA controller.
|
||||
+ * dma_memory_write: Write to address space from DMA controller.
|
||||
*
|
||||
* Return a MemTxResult indicating whether the operation succeeded
|
||||
* or failed (eg unassigned memory, device rejected the transaction,
|
||||
@@ -189,7 +189,7 @@ MemTxResult dma_memory_set(AddressSpace *as, dma_addr_t addr,
|
||||
uint8_t c, dma_addr_t len, MemTxAttrs attrs);
|
||||
|
||||
/**
|
||||
- * address_space_map: Map a physical memory region into a host virtual address.
|
||||
+ * dma_memory_map: Map a physical memory region into a host virtual address.
|
||||
*
|
||||
* May map a subset of the requested range, given by and returned in @plen.
|
||||
* May return %NULL and set *@plen to zero(0), if resources needed to perform
|
||||
@@ -216,16 +216,15 @@ static inline void *dma_memory_map(AddressSpace *as,
|
||||
}
|
||||
|
||||
/**
|
||||
- * address_space_unmap: Unmaps a memory region previously mapped
|
||||
- * by dma_memory_map()
|
||||
+ * dma_memory_unmap: Unmaps a memory region previously mapped by dma_memory_map()
|
||||
*
|
||||
* Will also mark the memory as dirty if @dir == %DMA_DIRECTION_FROM_DEVICE.
|
||||
* @access_len gives the amount of memory that was actually read or written
|
||||
* by the caller.
|
||||
*
|
||||
* @as: #AddressSpace used
|
||||
- * @buffer: host pointer as returned by address_space_map()
|
||||
- * @len: buffer length as returned by address_space_map()
|
||||
+ * @buffer: host pointer as returned by dma_memory_map()
|
||||
+ * @len: buffer length as returned by dma_memory_map()
|
||||
* @dir: indicates the transfer direction
|
||||
* @access_len: amount of data actually transferred
|
||||
*/
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
52
docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch
Normal file
52
docs-sphinx-depfile.py-Handle-env.doc2path-returning.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From e16c3aa63a203e376a40404314252a11e85a5bda Mon Sep 17 00:00:00 2001
|
||||
From: Peter Maydell <peter.maydell@linaro.org>
|
||||
Date: Mon, 29 Jul 2024 13:05:33 +0100
|
||||
Subject: [PATCH] docs/sphinx/depfile.py: Handle env.doc2path() returning a
|
||||
Path not a str
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In newer versions of Sphinx the env.doc2path() API is going to change
|
||||
to return a Path object rather than a str. This was originally visible
|
||||
in Sphinx 8.0.0rc1, but has been rolled back for the final 8.0.0
|
||||
release. However it will probably emit a deprecation warning and is
|
||||
likely to change for good in 9.0:
|
||||
https://github.com/sphinx-doc/sphinx/issues/12686
|
||||
|
||||
Our use in depfile.py assumes a str, and if it is passed a Path
|
||||
it will fall over:
|
||||
Handler <function write_depfile at 0x77a1775ff560> for event 'build-finished' threw an exception (exception: unsupported operand type(s) for +: 'PosixPath' and 'str')
|
||||
|
||||
Wrapping the env.doc2path() call in str() will coerce a Path object
|
||||
to the str we expect, and have no effect in older Sphinx versions
|
||||
that do return a str.
|
||||
|
||||
Cc: qemu-stable@nongnu.org
|
||||
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2458
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Message-ID: <20240729120533.2486427-1-peter.maydell@linaro.org>
|
||||
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
(cherry picked from commit 48e5b5f994bccf161dd88a67fdd819d4bfb400f1)
|
||||
Signed-off-by: zhujun2 <zhujun2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
docs/sphinx/depfile.py | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/sphinx/depfile.py b/docs/sphinx/depfile.py
|
||||
index afdcbcec6e..e74be6af98 100644
|
||||
--- a/docs/sphinx/depfile.py
|
||||
+++ b/docs/sphinx/depfile.py
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
def get_infiles(env):
|
||||
for x in env.found_docs:
|
||||
- yield env.doc2path(x)
|
||||
+ yield str(env.doc2path(x))
|
||||
yield from ((os.path.join(env.srcdir, dep)
|
||||
for dep in env.dependencies[x]))
|
||||
for mod in sys.modules.values():
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
31
docs-tools-qemu-img.rst-fix-typo-sumarizes.patch
Normal file
31
docs-tools-qemu-img.rst-fix-typo-sumarizes.patch
Normal file
@ -0,0 +1,31 @@
|
||||
From ac7182ca1b9ed7dbb524da734a9f426b2ca07503 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
Date: Mon, 21 Oct 2024 09:48:30 +0800
|
||||
Subject: [PATCH] docs/tools/qemu-img.rst: fix typo (sumarizes)
|
||||
|
||||
cheery-pick from 8a8be21dde814e7cef43acac8140a7ccd0c4f6fb
|
||||
|
||||
Signed-off-by: Samuel Tardieu <sam@rfc1149.net>
|
||||
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
docs/tools/qemu-img.rst | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst
|
||||
index 4459c065f1..3653adb963 100644
|
||||
--- a/docs/tools/qemu-img.rst
|
||||
+++ b/docs/tools/qemu-img.rst
|
||||
@@ -406,7 +406,7 @@ Command description:
|
||||
Compare exits with ``0`` in case the images are equal and with ``1``
|
||||
in case the images differ. Other exit codes mean an error occurred during
|
||||
execution and standard error output should contain an error message.
|
||||
- The following table sumarizes all exit codes of the compare subcommand:
|
||||
+ The following table summarizes all exit codes of the compare subcommand:
|
||||
|
||||
0
|
||||
Images are identical (or requested help was printed)
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
47
edu-fix-DMA-range-upper-bound-check.patch
Normal file
47
edu-fix-DMA-range-upper-bound-check.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From edf3b2b0a9b9aa992592951a979d1b4642026fe5 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
Date: Fri, 18 Oct 2024 09:12:50 +0800
|
||||
Subject: [PATCH] edu: fix DMA range upper bound check
|
||||
|
||||
cheery-pick from 2c5107e1b455d4a157124f021826ead4e04b4aea
|
||||
|
||||
The edu_check_range function checks that start <= end1 < end2, where
|
||||
end1 is the upper bound (exclusive) of the guest-supplied DMA range and
|
||||
end2 is the upper bound (exclusive) of the device's allowed DMA range.
|
||||
When the guest tries to transfer exactly DMA_SIZE (4096) bytes, end1
|
||||
will be equal to end2, so the check fails and QEMU aborts with this
|
||||
puzzling error message (newlines added for formatting):
|
||||
|
||||
qemu: hardware error: EDU: DMA range
|
||||
0x0000000000040000-0x0000000000040fff out of bounds
|
||||
(0x0000000000040000-0x0000000000040fff)!
|
||||
|
||||
By checking end1 <= end2 instead, guests will be allowed to transfer
|
||||
exactly 4096 bytes. It is not necessary to explicitly check for
|
||||
start <= end1 because the previous two checks (within(addr, start, end2)
|
||||
and end1 > addr) imply start < end1.
|
||||
|
||||
Fixes: b30934cb52a7 ("hw: misc, add educational driver", 2015-01-21)
|
||||
Signed-off-by: Max Erenberg <merenber@uwaterloo.ca>
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/misc/edu.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/misc/edu.c b/hw/misc/edu.c
|
||||
index a1f8bc77e7..e64a246d3f 100644
|
||||
--- a/hw/misc/edu.c
|
||||
+++ b/hw/misc/edu.c
|
||||
@@ -115,7 +115,7 @@ static void edu_check_range(uint64_t addr, uint64_t size1, uint64_t start,
|
||||
uint64_t end2 = start + size2;
|
||||
|
||||
if (within(addr, start, end2) &&
|
||||
- end1 > addr && within(end1, start, end2)) {
|
||||
+ end1 > addr && end1 <= end2) {
|
||||
return;
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
39
exec-memop-Remove-unused-memop_big_endian-helper.patch
Normal file
39
exec-memop-Remove-unused-memop_big_endian-helper.patch
Normal 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
|
||||
|
||||
27
fix-compile-error-on-loongarch.patch
Normal file
27
fix-compile-error-on-loongarch.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 0826efefea34a6fb6e17502f3a293572f109a261 Mon Sep 17 00:00:00 2001
|
||||
From: Xianglai Li <lixianglai@loongson.cn>
|
||||
Date: Thu, 5 Dec 2024 14:18:01 +0800
|
||||
Subject: [PATCH] fix compile error on loongarch
|
||||
|
||||
add cpu.h in loongarch_ipi.c
|
||||
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/intc/loongarch_ipi.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
|
||||
index e228669aa5..630bcb14ea 100644
|
||||
--- a/hw/intc/loongarch_ipi.c
|
||||
+++ b/hw/intc/loongarch_ipi.c
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/loongarch/virt.h"
|
||||
#include "migration/vmstate.h"
|
||||
+#include "target/loongarch/cpu.h"
|
||||
#include "target/loongarch/internals.h"
|
||||
#include "trace.h"
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
87
gdbstub-Add-helper-function-to-unregister-GDB-regist.patch
Normal file
87
gdbstub-Add-helper-function-to-unregister-GDB-regist.patch
Normal file
@ -0,0 +1,87 @@
|
||||
From 7754cf384417295dc74add4e774c506d751671a9 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 16 Jul 2024 12:15:02 +0100
|
||||
Subject: [PATCH 67/78] gdbstub: Add helper function to unregister GDB register
|
||||
space
|
||||
|
||||
Add common function to help unregister the GDB register space. This shall be
|
||||
done in context to the CPU unrealization.
|
||||
|
||||
Note: These are common functions exported to arch specific code. For example,
|
||||
for ARM this code is being referred in associated arch specific patch-set:
|
||||
|
||||
Link: https://lore.kernel.org/qemu-devel/20230926103654.34424-1-salil.mehta@huawei.com/
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Tested-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
Reviewed-by: Gavin Shan <gshan@redhat.com>
|
||||
Tested-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Tested-by: Miguel Luis <miguel.luis@oracle.com>
|
||||
Reviewed-by: Shaoqin Huang <shahuang@redhat.com>
|
||||
Reviewed-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
Tested-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Acked-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Message-Id: <20240716111502.202344-8-salil.mehta@huawei.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
gdbstub/gdbstub.c | 7 +++++++
|
||||
hw/core/cpu-common.c | 4 ++++
|
||||
include/exec/gdbstub.h | 5 +++++
|
||||
3 files changed, 16 insertions(+)
|
||||
|
||||
diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c
|
||||
index f16006d2a8..31c3dae525 100644
|
||||
--- a/gdbstub/gdbstub.c
|
||||
+++ b/gdbstub/gdbstub.c
|
||||
@@ -584,8 +584,15 @@ void gdb_register_coprocessor(CPUState *cpu,
|
||||
|
||||
void gdb_unregister_coprocessor_all(CPUState *cpu)
|
||||
{
|
||||
+ /*
|
||||
+ * Safe to nuke everything. GDBRegisterState::xml is static const char so
|
||||
+ * it won't be freed
|
||||
+ */
|
||||
g_array_free(cpu->gdb_regs, true);
|
||||
+
|
||||
cpu->gdb_regs = NULL;
|
||||
+ cpu->gdb_num_regs = 0;
|
||||
+ cpu->gdb_num_g_regs = 0;
|
||||
}
|
||||
|
||||
static void gdb_process_breakpoint_remove_all(GDBProcess *p)
|
||||
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
|
||||
index 82dae51a55..e36ca2c207 100644
|
||||
--- a/hw/core/cpu-common.c
|
||||
+++ b/hw/core/cpu-common.c
|
||||
@@ -262,6 +262,10 @@ static void cpu_common_finalize(Object *obj)
|
||||
{
|
||||
CPUState *cpu = CPU(obj);
|
||||
|
||||
+ /* If cleanup didn't happen in context to gdb_unregister_coprocessor_all */
|
||||
+ if (cpu->gdb_regs) {
|
||||
+ g_array_free(cpu->gdb_regs, TRUE);
|
||||
+ }
|
||||
qemu_lockcnt_destroy(&cpu->in_ioctl_lock);
|
||||
qemu_mutex_destroy(&cpu->work_mutex);
|
||||
}
|
||||
diff --git a/include/exec/gdbstub.h b/include/exec/gdbstub.h
|
||||
index d123b838c2..e2e8dff051 100644
|
||||
--- a/include/exec/gdbstub.h
|
||||
+++ b/include/exec/gdbstub.h
|
||||
@@ -39,6 +39,11 @@ typedef int (*gdb_set_reg_cb)(CPUArchState *env, uint8_t *buf, int reg);
|
||||
void gdb_register_coprocessor(CPUState *cpu,
|
||||
gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
|
||||
int num_regs, const char *xml, int g_pos);
|
||||
+
|
||||
+/**
|
||||
+ * gdb_unregister_coprocessor_all() - unregisters supplemental set of registers
|
||||
+ * @cpu - the CPU associated with registers
|
||||
+ */
|
||||
void gdb_unregister_coprocessor_all(CPUState *cpu);
|
||||
|
||||
/**
|
||||
--
|
||||
2.39.1
|
||||
|
||||
211
hvf-arm-Fix-encodings-for-ID_AA64PFR1_EL1-and-debug-.patch
Normal file
211
hvf-arm-Fix-encodings-for-ID_AA64PFR1_EL1-and-debug-.patch
Normal 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
|
||||
|
||||
@ -0,0 +1,49 @@
|
||||
From a8416845f721aa5ba03446b3ccf83b096b7a0d77 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 16 Jul 2024 12:14:57 +0100
|
||||
Subject: [PATCH 63/78] hw/acpi: Move CPU ctrl-dev MMIO region len macro to
|
||||
common header file
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
CPU ctrl-dev MMIO region length could be used in ACPI GED and various other
|
||||
architecture specific places. Move ACPI_CPU_HOTPLUG_REG_LEN macro to more
|
||||
appropriate common header file.
|
||||
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
|
||||
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Reviewed-by: Gavin Shan <gshan@redhat.com>
|
||||
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||
Reviewed-by: Shaoqin Huang <shahuang@redhat.com>
|
||||
Tested-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
Tested-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Tested-by: Miguel Luis <miguel.luis@oracle.com>
|
||||
Tested-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Message-Id: <20240716111502.202344-3-salil.mehta@huawei.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
include/hw/acpi/cpu.h | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
|
||||
index fced952152..fa5b5e5f01 100644
|
||||
--- a/include/hw/acpi/cpu.h
|
||||
+++ b/include/hw/acpi/cpu.h
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "hw/boards.h"
|
||||
#include "hw/hotplug.h"
|
||||
|
||||
+#define ACPI_CPU_HOTPLUG_REG_LEN 12
|
||||
+
|
||||
typedef struct AcpiCpuStatus {
|
||||
CPUState *cpu;
|
||||
uint64_t arch_id;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
@ -0,0 +1,128 @@
|
||||
From ac96f216155002d0c874ff88e301e83495093085 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 16 Jul 2024 12:14:58 +0100
|
||||
Subject: [PATCH 64/78] hw/acpi: Update ACPI GED framework to support vCPU
|
||||
Hotplug
|
||||
|
||||
ACPI GED (as described in the ACPI 6.4 spec) uses an interrupt listed in the
|
||||
_CRS object of GED to intimate OSPM about an event. Later then demultiplexes the
|
||||
notified event by evaluating ACPI _EVT method to know the type of event. Use
|
||||
ACPI GED to also notify the guest kernel about any CPU hot(un)plug events.
|
||||
|
||||
Note, GED interface is used by many hotplug events like memory hotplug, NVDIMM
|
||||
hotplug and non-hotplug events like system power down event. Each of these can
|
||||
be selected using a bit in the 32 bit GED IO interface. A bit has been reserved
|
||||
for the CPU hotplug event.
|
||||
|
||||
ACPI CPU hotplug related initialization should only happen if ACPI_CPU_HOTPLUG
|
||||
support has been enabled for particular architecture. Add cpu_hotplug_hw_init()
|
||||
stub to avoid compilation break.
|
||||
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Reviewed-by: Gavin Shan <gshan@redhat.com>
|
||||
Reviewed-by: David Hildenbrand <david@redhat.com>
|
||||
Reviewed-by: Shaoqin Huang <shahuang@redhat.com>
|
||||
Tested-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
Tested-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Tested-by: Miguel Luis <miguel.luis@oracle.com>
|
||||
Reviewed-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
Tested-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Reviewed-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Message-Id: <20240716111502.202344-4-salil.mehta@huawei.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Acked-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
docs/specs/acpi_hw_reduced_hotplug.rst | 3 ++-
|
||||
hw/acpi/generic_event_device.c | 37 ++++++++++++++++++++++++++
|
||||
include/hw/acpi/generic_event_device.h | 1 +
|
||||
3 files changed, 40 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/docs/specs/acpi_hw_reduced_hotplug.rst b/docs/specs/acpi_hw_reduced_hotplug.rst
|
||||
index 0bd3f9399f..3acd6fcd8b 100644
|
||||
--- a/docs/specs/acpi_hw_reduced_hotplug.rst
|
||||
+++ b/docs/specs/acpi_hw_reduced_hotplug.rst
|
||||
@@ -64,7 +64,8 @@ GED IO interface (4 byte access)
|
||||
0: Memory hotplug event
|
||||
1: System power down event
|
||||
2: NVDIMM hotplug event
|
||||
- 3-31: Reserved
|
||||
+ 3: CPU hotplug event
|
||||
+ 4-31: Reserved
|
||||
|
||||
**write_access:**
|
||||
|
||||
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
|
||||
index 2ce7031f1a..755653dc26 100644
|
||||
--- a/hw/acpi/generic_event_device.c
|
||||
+++ b/hw/acpi/generic_event_device.c
|
||||
@@ -397,6 +397,42 @@ static const VMStateDescription vmstate_acpi_ged = {
|
||||
}
|
||||
};
|
||||
|
||||
+static void acpi_ged_realize(DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
+ AcpiGedState *s = ACPI_GED(dev);
|
||||
+ uint32_t ged_events;
|
||||
+ int i;
|
||||
+
|
||||
+ ged_events = ctpop32(s->ged_event_bitmap);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) {
|
||||
+ uint32_t event = s->ged_event_bitmap & ged_supported_events[i];
|
||||
+
|
||||
+ if (!event) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
+ switch (event) {
|
||||
+ case ACPI_GED_CPU_HOTPLUG_EVT:
|
||||
+ /* initialize CPU Hotplug related regions */
|
||||
+ memory_region_init(&s->container_cpuhp, OBJECT(dev),
|
||||
+ "cpuhp container",
|
||||
+ ACPI_CPU_HOTPLUG_REG_LEN);
|
||||
+ sysbus_init_mmio(sbd, &s->container_cpuhp);
|
||||
+ cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev),
|
||||
+ &s->cpuhp_state, 0);
|
||||
+ break;
|
||||
+ }
|
||||
+ ged_events--;
|
||||
+ }
|
||||
+
|
||||
+ if (ged_events) {
|
||||
+ error_report("Unsupported events specified");
|
||||
+ abort();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void acpi_ged_initfn(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
@@ -447,6 +483,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data)
|
||||
dc->desc = "ACPI Generic Event Device";
|
||||
device_class_set_props(dc, acpi_ged_properties);
|
||||
dc->vmsd = &vmstate_acpi_ged;
|
||||
+ dc->realize = acpi_ged_realize;
|
||||
|
||||
hc->plug = acpi_ged_device_plug_cb;
|
||||
hc->unplug_request = acpi_ged_unplug_request_cb;
|
||||
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
|
||||
index 8ed9534c57..d1df3c12e5 100644
|
||||
--- a/include/hw/acpi/generic_event_device.h
|
||||
+++ b/include/hw/acpi/generic_event_device.h
|
||||
@@ -63,6 +63,7 @@
|
||||
#include "hw/acpi/cpu_hotplug.h"
|
||||
#include "hw/acpi/memory_hotplug.h"
|
||||
#include "hw/acpi/ghes.h"
|
||||
+#include "hw/acpi/cpu.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
|
||||
--
|
||||
2.39.1
|
||||
|
||||
@ -0,0 +1,54 @@
|
||||
From 16d44ddb63becd559cc2185549c4b18d26feab60 Mon Sep 17 00:00:00 2001
|
||||
From: Salil Mehta <salil.mehta@huawei.com>
|
||||
Date: Tue, 16 Jul 2024 12:15:00 +0100
|
||||
Subject: [PATCH 65/78] hw/acpi: Update CPUs AML with cpu-(ctrl)dev change
|
||||
|
||||
CPUs Control device(\\_SB.PCI0) register interface for the x86 arch is IO port
|
||||
based and existing CPUs AML code assumes _CRS objects would evaluate to a system
|
||||
resource which describes IO Port address. But on ARM arch CPUs control
|
||||
device(\\_SB.PRES) register interface is memory-mapped hence _CRS object should
|
||||
evaluate to system resource which describes memory-mapped base address. Update
|
||||
build CPUs AML function to accept both IO/MEMORY region spaces and accordingly
|
||||
update the _CRS object.
|
||||
|
||||
Co-developed-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Keqian Zhu <zhukeqian1@huawei.com>
|
||||
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
|
||||
Reviewed-by: Gavin Shan <gshan@redhat.com>
|
||||
Tested-by: Vishnu Pajjuri <vishnu@os.amperecomputing.com>
|
||||
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Tested-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Tested-by: Miguel Luis <miguel.luis@oracle.com>
|
||||
Reviewed-by: Shaoqin Huang <shahuang@redhat.com>
|
||||
Tested-by: Zhao Liu <zhao1.liu@intel.com>
|
||||
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
|
||||
Message-Id: <20240716111502.202344-6-salil.mehta@huawei.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/acpi/cpu.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
|
||||
index 292e1daca2..5e9093991e 100644
|
||||
--- a/hw/acpi/cpu.c
|
||||
+++ b/hw/acpi/cpu.c
|
||||
@@ -392,11 +392,13 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
aml_name_decl("_UID", aml_string("CPU Hotplug resources")));
|
||||
aml_append(cpu_ctrl_dev, aml_mutex(CPU_LOCK, 0));
|
||||
|
||||
+ assert((rs == AML_SYSTEM_IO) || (rs == AML_SYSTEM_MEMORY));
|
||||
+
|
||||
crs = aml_resource_template();
|
||||
if (rs == AML_SYSTEM_IO) {
|
||||
aml_append(crs, aml_io(AML_DECODE16, base_addr, base_addr, 1,
|
||||
ACPI_CPU_HOTPLUG_REG_LEN));
|
||||
- } else {
|
||||
+ } else if (rs == AML_SYSTEM_MEMORY) {
|
||||
aml_append(crs, aml_memory32_fixed(base_addr,
|
||||
ACPI_CPU_HOTPLUG_REG_LEN, AML_READ_WRITE));
|
||||
}
|
||||
--
|
||||
2.39.1
|
||||
|
||||
50
hw-arm-mps2-tz.c-fix-RX-TX-interrupts-order.patch
Normal file
50
hw-arm-mps2-tz.c-fix-RX-TX-interrupts-order.patch
Normal 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
|
||||
|
||||
671
hw-arm-virt-Keep-Guest-L1-cache-type-consistent-with.patch
Normal file
671
hw-arm-virt-Keep-Guest-L1-cache-type-consistent-with.patch
Normal file
@ -0,0 +1,671 @@
|
||||
From 6060f8cad07a3d2a49795fef19d585a9d205ecef Mon Sep 17 00:00:00 2001
|
||||
From: Jia Qingtong <jiaqingtong97@gmail.com>
|
||||
Date: Tue, 24 Sep 2024 18:24:33 +0800
|
||||
Subject: [PATCH] hw/arm/virt:Keep Guest L1 cache type consistent with KVM
|
||||
|
||||
Linux KVM normalize the cache configuration and expose a
|
||||
fabricated CLIDR_EL1 value to guest, where L1 cache type
|
||||
could be unified or seperate instruction cache and data
|
||||
cache. Let's keep guest L1 cache type consistent with
|
||||
KVM by checking the guest visable CLIDR_EL1, which can
|
||||
avoid abnormal issue in guest when it's probing cache
|
||||
info conbined CLIDR_EL1 with ACPI PPTT and DT.
|
||||
|
||||
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
|
||||
Signed-off-by: lishusen <lishusen2@huawei.com>
|
||||
---
|
||||
hw/acpi/aml-build.c | 165 ++---------------------------------
|
||||
hw/arm/virt-acpi-build.c | 167 ++++++++++++++++++++++++++++++++++++
|
||||
hw/arm/virt.c | 86 +++++++++++++++----
|
||||
include/hw/acpi/aml-build.h | 54 ++----------
|
||||
include/hw/arm/virt.h | 60 +++++++++++++
|
||||
5 files changed, 306 insertions(+), 226 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
|
||||
index bf9c59f544..0d4994bafe 100644
|
||||
--- a/hw/acpi/aml-build.c
|
||||
+++ b/hw/acpi/aml-build.c
|
||||
@@ -47,7 +47,7 @@ static void build_prepend_byte(GArray *array, uint8_t val)
|
||||
g_array_prepend_val(array, val);
|
||||
}
|
||||
|
||||
-static void build_append_byte(GArray *array, uint8_t val)
|
||||
+void build_append_byte(GArray *array, uint8_t val)
|
||||
{
|
||||
g_array_append_val(array, val);
|
||||
}
|
||||
@@ -1990,10 +1990,10 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
* ACPI spec, Revision 6.3
|
||||
* 5.2.29.1 Processor hierarchy node structure (Type 0)
|
||||
*/
|
||||
-static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
|
||||
- uint32_t parent, uint32_t id,
|
||||
- uint32_t *priv_rsrc,
|
||||
- uint32_t priv_num)
|
||||
+void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
|
||||
+ uint32_t parent, uint32_t id,
|
||||
+ uint32_t *priv_rsrc,
|
||||
+ uint32_t priv_num)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -2016,161 +2016,6 @@ static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
|
||||
}
|
||||
}
|
||||
|
||||
-/*
|
||||
- * ACPI spec, Revision 6.3
|
||||
- * 5.2.29.2 Cache Type Structure (Type 1)
|
||||
- */
|
||||
-static void build_cache_hierarchy_node(GArray *tbl, uint32_t next_level,
|
||||
- uint32_t cache_type)
|
||||
-{
|
||||
- build_append_byte(tbl, 1);
|
||||
- build_append_byte(tbl, 24);
|
||||
- build_append_int_noprefix(tbl, 0, 2);
|
||||
- build_append_int_noprefix(tbl, 127, 4);
|
||||
- build_append_int_noprefix(tbl, next_level, 4);
|
||||
-
|
||||
- switch (cache_type) {
|
||||
- case ARM_L1D_CACHE: /* L1 dcache info */
|
||||
- build_append_int_noprefix(tbl, ARM_L1DCACHE_SIZE, 4);
|
||||
- build_append_int_noprefix(tbl, ARM_L1DCACHE_SETS, 4);
|
||||
- build_append_byte(tbl, ARM_L1DCACHE_ASSOCIATIVITY);
|
||||
- build_append_byte(tbl, ARM_L1DCACHE_ATTRIBUTES);
|
||||
- build_append_int_noprefix(tbl, ARM_L1DCACHE_LINE_SIZE, 2);
|
||||
- break;
|
||||
- case ARM_L1I_CACHE: /* L1 icache info */
|
||||
- build_append_int_noprefix(tbl, ARM_L1ICACHE_SIZE, 4);
|
||||
- build_append_int_noprefix(tbl, ARM_L1ICACHE_SETS, 4);
|
||||
- build_append_byte(tbl, ARM_L1ICACHE_ASSOCIATIVITY);
|
||||
- build_append_byte(tbl, ARM_L1ICACHE_ATTRIBUTES);
|
||||
- build_append_int_noprefix(tbl, ARM_L1ICACHE_LINE_SIZE, 2);
|
||||
- break;
|
||||
- case ARM_L2_CACHE: /* L2 cache info */
|
||||
- build_append_int_noprefix(tbl, ARM_L2CACHE_SIZE, 4);
|
||||
- build_append_int_noprefix(tbl, ARM_L2CACHE_SETS, 4);
|
||||
- build_append_byte(tbl, ARM_L2CACHE_ASSOCIATIVITY);
|
||||
- build_append_byte(tbl, ARM_L2CACHE_ATTRIBUTES);
|
||||
- build_append_int_noprefix(tbl, ARM_L2CACHE_LINE_SIZE, 2);
|
||||
- break;
|
||||
- case ARM_L3_CACHE: /* L3 cache info */
|
||||
- build_append_int_noprefix(tbl, ARM_L3CACHE_SIZE, 4);
|
||||
- build_append_int_noprefix(tbl, ARM_L3CACHE_SETS, 4);
|
||||
- build_append_byte(tbl, ARM_L3CACHE_ASSOCIATIVITY);
|
||||
- build_append_byte(tbl, ARM_L3CACHE_ATTRIBUTES);
|
||||
- build_append_int_noprefix(tbl, ARM_L3CACHE_LINE_SIZE, 2);
|
||||
- break;
|
||||
- default:
|
||||
- build_append_int_noprefix(tbl, 0, 4);
|
||||
- build_append_int_noprefix(tbl, 0, 4);
|
||||
- build_append_byte(tbl, 0);
|
||||
- build_append_byte(tbl, 0);
|
||||
- build_append_int_noprefix(tbl, 0, 2);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * ACPI spec, Revision 6.3
|
||||
- * 5.2.29 Processor Properties Topology Table (PPTT)
|
||||
- */
|
||||
-void build_pptt_arm(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
- const char *oem_id, const char *oem_table_id)
|
||||
-{
|
||||
- MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
- GQueue *list = g_queue_new();
|
||||
- guint pptt_start = table_data->len;
|
||||
- guint parent_offset;
|
||||
- guint length, i;
|
||||
- int uid = 0;
|
||||
- int socket;
|
||||
- AcpiTable table = { .sig = "PPTT", .rev = 2,
|
||||
- .oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
-
|
||||
- acpi_table_begin(&table, table_data);
|
||||
-
|
||||
- for (socket = 0; socket < ms->smp.sockets; socket++) {
|
||||
- uint32_t l3_cache_offset = table_data->len - pptt_start;
|
||||
- build_cache_hierarchy_node(table_data, 0, ARM_L3_CACHE);
|
||||
-
|
||||
- g_queue_push_tail(list,
|
||||
- GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
- build_processor_hierarchy_node(
|
||||
- table_data,
|
||||
- /*
|
||||
- * Physical package - represents the boundary
|
||||
- * of a physical package
|
||||
- */
|
||||
- (1 << 0),
|
||||
- 0, socket, &l3_cache_offset, 1);
|
||||
- }
|
||||
-
|
||||
- if (mc->smp_props.clusters_supported) {
|
||||
- length = g_queue_get_length(list);
|
||||
- for (i = 0; i < length; i++) {
|
||||
- int cluster;
|
||||
-
|
||||
- parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
- for (cluster = 0; cluster < ms->smp.clusters; cluster++) {
|
||||
- g_queue_push_tail(list,
|
||||
- GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
- build_processor_hierarchy_node(
|
||||
- table_data,
|
||||
- (0 << 0), /* not a physical package */
|
||||
- parent_offset, cluster, NULL, 0);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- length = g_queue_get_length(list);
|
||||
- for (i = 0; i < length; i++) {
|
||||
- int core;
|
||||
-
|
||||
- parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
- for (core = 0; core < ms->smp.cores; core++) {
|
||||
- uint32_t priv_rsrc[3] = {};
|
||||
- priv_rsrc[0] = table_data->len - pptt_start; /* L2 cache offset */
|
||||
- build_cache_hierarchy_node(table_data, 0, ARM_L2_CACHE);
|
||||
-
|
||||
- priv_rsrc[1] = table_data->len - pptt_start; /* L1 dcache offset */
|
||||
- build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1D_CACHE);
|
||||
-
|
||||
- priv_rsrc[2] = table_data->len - pptt_start; /* L1 icache offset */
|
||||
- build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1I_CACHE);
|
||||
-
|
||||
- if (ms->smp.threads > 1) {
|
||||
- g_queue_push_tail(list,
|
||||
- GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
- build_processor_hierarchy_node(
|
||||
- table_data,
|
||||
- (0 << 0), /* not a physical package */
|
||||
- parent_offset, core, priv_rsrc, 3);
|
||||
- } else {
|
||||
- build_processor_hierarchy_node(
|
||||
- table_data,
|
||||
- (1 << 1) | /* ACPI Processor ID valid */
|
||||
- (1 << 3), /* Node is a Leaf */
|
||||
- parent_offset, uid++, priv_rsrc, 3);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- length = g_queue_get_length(list);
|
||||
- for (i = 0; i < length; i++) {
|
||||
- int thread;
|
||||
-
|
||||
- parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
- for (thread = 0; thread < ms->smp.threads; thread++) {
|
||||
- build_processor_hierarchy_node(
|
||||
- table_data,
|
||||
- (1 << 1) | /* ACPI Processor ID valid */
|
||||
- (1 << 2) | /* Processor is a Thread */
|
||||
- (1 << 3), /* Node is a Leaf */
|
||||
- parent_offset, uid++, NULL, 0);
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- g_queue_free(list);
|
||||
- acpi_table_end(linker, &table);
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* ACPI spec, Revision 6.3
|
||||
* 5.2.29 Processor Properties Topology Table (PPTT)
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index 179600d4fe..86984b7167 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -63,6 +63,173 @@
|
||||
|
||||
#define ACPI_BUILD_TABLE_SIZE 0x20000
|
||||
|
||||
+/*
|
||||
+ * ACPI spec, Revision 6.3
|
||||
+ * 5.2.29.2 Cache Type Structure (Type 1)
|
||||
+ */
|
||||
+static void build_cache_hierarchy_node(GArray *tbl, uint32_t next_level,
|
||||
+ uint32_t cache_type)
|
||||
+{
|
||||
+ build_append_byte(tbl, 1);
|
||||
+ build_append_byte(tbl, 24);
|
||||
+ build_append_int_noprefix(tbl, 0, 2);
|
||||
+ build_append_int_noprefix(tbl, 127, 4);
|
||||
+ build_append_int_noprefix(tbl, next_level, 4);
|
||||
+
|
||||
+ switch (cache_type) {
|
||||
+ case ARM_L1D_CACHE: /* L1 dcache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L1DCACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L1DCACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1DCACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ case ARM_L1I_CACHE: /* L1 icache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L1ICACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L1ICACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1ICACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ case ARM_L1_CACHE: /* L1 cache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L1CACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1CACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L1CACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L1CACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L1CACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ case ARM_L2_CACHE: /* L2 cache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L2CACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L2CACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L2CACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L2CACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L2CACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ case ARM_L3_CACHE: /* L3 cache info */
|
||||
+ build_append_int_noprefix(tbl, ARM_L3CACHE_SIZE, 4);
|
||||
+ build_append_int_noprefix(tbl, ARM_L3CACHE_SETS, 4);
|
||||
+ build_append_byte(tbl, ARM_L3CACHE_ASSOCIATIVITY);
|
||||
+ build_append_byte(tbl, ARM_L3CACHE_ATTRIBUTES);
|
||||
+ build_append_int_noprefix(tbl, ARM_L3CACHE_LINE_SIZE, 2);
|
||||
+ break;
|
||||
+ default:
|
||||
+ build_append_int_noprefix(tbl, 0, 4);
|
||||
+ build_append_int_noprefix(tbl, 0, 4);
|
||||
+ build_append_byte(tbl, 0);
|
||||
+ build_append_byte(tbl, 0);
|
||||
+ build_append_int_noprefix(tbl, 0, 2);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * ACPI spec, Revision 6.3
|
||||
+ * 5.2.29 Processor Properties Topology Table (PPTT)
|
||||
+ */
|
||||
+static void build_pptt_arm(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
+ const char *oem_id, const char *oem_table_id)
|
||||
+{
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(ms);
|
||||
+ GQueue *list = g_queue_new();
|
||||
+ guint pptt_start = table_data->len;
|
||||
+ guint parent_offset;
|
||||
+ guint length, i;
|
||||
+ int uid = 0;
|
||||
+ int socket;
|
||||
+ AcpiTable table = { .sig = "PPTT", .rev = 2,
|
||||
+ .oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
+ bool unified_l1 = cpu_l1_cache_unified(0);
|
||||
+
|
||||
+ acpi_table_begin(&table, table_data);
|
||||
+
|
||||
+ for (socket = 0; socket < ms->smp.sockets; socket++) {
|
||||
+ uint32_t l3_cache_offset = table_data->len - pptt_start;
|
||||
+ build_cache_hierarchy_node(table_data, 0, ARM_L3_CACHE);
|
||||
+
|
||||
+ g_queue_push_tail(list,
|
||||
+ GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ /*
|
||||
+ * Physical package - represents the boundary
|
||||
+ * of a physical package
|
||||
+ */
|
||||
+ (1 << 0),
|
||||
+ 0, socket, &l3_cache_offset, 1);
|
||||
+ }
|
||||
+
|
||||
+ if (mc->smp_props.clusters_supported) {
|
||||
+ length = g_queue_get_length(list);
|
||||
+ for (i = 0; i < length; i++) {
|
||||
+ int cluster;
|
||||
+
|
||||
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
+ for (cluster = 0; cluster < ms->smp.clusters; cluster++) {
|
||||
+ g_queue_push_tail(list,
|
||||
+ GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ (0 << 0), /* not a physical package */
|
||||
+ parent_offset, cluster, NULL, 0);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ length = g_queue_get_length(list);
|
||||
+ for (i = 0; i < length; i++) {
|
||||
+ int core;
|
||||
+
|
||||
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
+ for (core = 0; core < ms->smp.cores; core++) {
|
||||
+ uint32_t priv_rsrc[3] = {};
|
||||
+ priv_rsrc[0] = table_data->len - pptt_start; /* L2 cache offset */
|
||||
+ build_cache_hierarchy_node(table_data, 0, ARM_L2_CACHE);
|
||||
+
|
||||
+ if (unified_l1) {
|
||||
+ priv_rsrc[1] = table_data->len - pptt_start; /* L1 cache offset */
|
||||
+ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1_CACHE);
|
||||
+ } else {
|
||||
+ priv_rsrc[1] = table_data->len - pptt_start; /* L1 dcache offset */
|
||||
+ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1D_CACHE);
|
||||
+ priv_rsrc[2] = table_data->len - pptt_start; /* L1 icache offset */
|
||||
+ build_cache_hierarchy_node(table_data, priv_rsrc[0], ARM_L1I_CACHE);
|
||||
+ }
|
||||
+
|
||||
+ if (ms->smp.threads > 1) {
|
||||
+ g_queue_push_tail(list,
|
||||
+ GUINT_TO_POINTER(table_data->len - pptt_start));
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ (0 << 0), /* not a physical package */
|
||||
+ parent_offset, core, priv_rsrc, 3);
|
||||
+ } else {
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ (1 << 1) | /* ACPI Processor ID valid */
|
||||
+ (1 << 3), /* Node is a Leaf */
|
||||
+ parent_offset, uid++, priv_rsrc, 3);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ length = g_queue_get_length(list);
|
||||
+ for (i = 0; i < length; i++) {
|
||||
+ int thread;
|
||||
+
|
||||
+ parent_offset = GPOINTER_TO_UINT(g_queue_pop_head(list));
|
||||
+ for (thread = 0; thread < ms->smp.threads; thread++) {
|
||||
+ build_processor_hierarchy_node(
|
||||
+ table_data,
|
||||
+ (1 << 1) | /* ACPI Processor ID valid */
|
||||
+ (1 << 2) | /* Processor is a Thread */
|
||||
+ (1 << 3), /* Node is a Leaf */
|
||||
+ parent_offset, uid++, NULL, 0);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ g_queue_free(list);
|
||||
+ acpi_table_end(linker, &table);
|
||||
+}
|
||||
+
|
||||
static void acpi_dsdt_add_psd(Aml *dev, int cpus)
|
||||
{
|
||||
Aml *pkg;
|
||||
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
|
||||
index e31c289968..a9efcec85e 100644
|
||||
--- a/hw/arm/virt.c
|
||||
+++ b/hw/arm/virt.c
|
||||
@@ -401,6 +401,39 @@ static void fdt_add_timer_nodes(const VirtMachineState *vms)
|
||||
INTID_TO_PPI(ARCH_TIMER_NS_EL2_IRQ), irqflags);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * In CLIDR_EL1 exposed to guest by the hypervisor, L1 cache type
|
||||
+ * maybe unified or seperate ins and data. We need to read the
|
||||
+ * guest visable CLIDR_EL1 and check L1 cache type.
|
||||
+ */
|
||||
+bool cpu_l1_cache_unified(int cpu)
|
||||
+{
|
||||
+ bool unified = false;
|
||||
+ uint64_t clidr;
|
||||
+ ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu));
|
||||
+ CPUState *cs = CPU(armcpu);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (kvm_enabled()) {
|
||||
+ struct kvm_one_reg reg = {
|
||||
+ .id = ARM64_REG_CLIDR_EL1,
|
||||
+ .addr = (uintptr_t)&clidr
|
||||
+ };
|
||||
+
|
||||
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, ®);
|
||||
+ if (ret) {
|
||||
+ error_setg(&error_fatal, "Get vCPU clidr from KVM failed:%d", ret);
|
||||
+ return unified;
|
||||
+ }
|
||||
+
|
||||
+ if (CLIDR_CTYPE(clidr, 1) == CTYPE_UNIFIED) {
|
||||
+ unified = true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return unified;
|
||||
+}
|
||||
+
|
||||
static void fdt_add_l3cache_nodes(const VirtMachineState *vms)
|
||||
{
|
||||
int i;
|
||||
@@ -415,9 +448,10 @@ static void fdt_add_l3cache_nodes(const VirtMachineState *vms)
|
||||
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache");
|
||||
qemu_fdt_setprop_string(ms->fdt, nodename, "cache-unified", "true");
|
||||
qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-level", 3);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x2000000);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 128);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 2048);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", ARM_L3CACHE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size",
|
||||
+ ARM_L3CACHE_LINE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", ARM_L3CACHE_SETS);
|
||||
qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
|
||||
qemu_fdt_alloc_phandle(ms->fdt));
|
||||
g_free(nodename);
|
||||
@@ -436,10 +470,12 @@ static void fdt_add_l2cache_nodes(const VirtMachineState *vms)
|
||||
char *nodename = g_strdup_printf("/cpus/l2-cache%d", cpu);
|
||||
|
||||
qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "cache-unified", "true");
|
||||
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "cache");
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", 0x80000);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size", 64);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", 1024);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", ARM_L2CACHE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size",
|
||||
+ ARM_L2CACHE_LINE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", ARM_L2CACHE_SETS);
|
||||
qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache",
|
||||
next_path);
|
||||
qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle",
|
||||
@@ -453,18 +489,32 @@ static void fdt_add_l2cache_nodes(const VirtMachineState *vms)
|
||||
static void fdt_add_l1cache_prop(const VirtMachineState *vms,
|
||||
char *nodename, int cpu)
|
||||
{
|
||||
- const MachineState *ms = MACHINE(vms);
|
||||
- char *cachename = g_strdup_printf("/cpus/l2-cache%d", cpu);
|
||||
-
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-size", 0x10000);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-line-size", 64);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-sets", 256);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-size", 0x10000);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-line-size", 64);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-sets", 256);
|
||||
- qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache",
|
||||
- cachename);
|
||||
- g_free(cachename);
|
||||
+ const MachineState *ms = MACHINE(vms);
|
||||
+ char *next_path = g_strdup_printf("/cpus/l2-cache%d", cpu);
|
||||
+ bool unified_l1 = cpu_l1_cache_unified(0);
|
||||
+
|
||||
+ if (unified_l1) {
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-size", ARM_L1CACHE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-line-size",
|
||||
+ ARM_L1CACHE_LINE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "cache-sets", ARM_L1CACHE_SETS);
|
||||
+ } else {
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-size",
|
||||
+ ARM_L1DCACHE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-line-size",
|
||||
+ ARM_L1DCACHE_LINE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "d-cache-sets",
|
||||
+ ARM_L1DCACHE_SETS);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-size",
|
||||
+ ARM_L1ICACHE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-line-size",
|
||||
+ ARM_L1ICACHE_LINE_SIZE);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "i-cache-sets",
|
||||
+ ARM_L1ICACHE_SETS);
|
||||
+ }
|
||||
+ qemu_fdt_setprop_phandle(ms->fdt, nodename, "next-level-cache", next_path);
|
||||
+
|
||||
+ g_free(next_path);
|
||||
}
|
||||
|
||||
static void fdt_add_cpu_nodes(const VirtMachineState *vms)
|
||||
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
|
||||
index 7281c281f6..91f9cbf4f1 100644
|
||||
--- a/include/hw/acpi/aml-build.h
|
||||
+++ b/include/hw/acpi/aml-build.h
|
||||
@@ -221,51 +221,6 @@ struct AcpiBuildTables {
|
||||
BIOSLinker *linker;
|
||||
} AcpiBuildTables;
|
||||
|
||||
-/* Definitions of the hardcoded cache info*/
|
||||
-
|
||||
-typedef enum {
|
||||
- ARM_L1D_CACHE,
|
||||
- ARM_L1I_CACHE,
|
||||
- ARM_L2_CACHE,
|
||||
- ARM_L3_CACHE
|
||||
-} ArmCacheType;
|
||||
-
|
||||
-/* L1 data cache: */
|
||||
-#define ARM_L1DCACHE_SIZE 65536
|
||||
-#define ARM_L1DCACHE_SETS 256
|
||||
-#define ARM_L1DCACHE_ASSOCIATIVITY 4
|
||||
-#define ARM_L1DCACHE_ATTRIBUTES 2
|
||||
-#define ARM_L1DCACHE_LINE_SIZE 64
|
||||
-
|
||||
-/* L1 instruction cache: */
|
||||
-#define ARM_L1ICACHE_SIZE 65536
|
||||
-#define ARM_L1ICACHE_SETS 256
|
||||
-#define ARM_L1ICACHE_ASSOCIATIVITY 4
|
||||
-#define ARM_L1ICACHE_ATTRIBUTES 4
|
||||
-#define ARM_L1ICACHE_LINE_SIZE 64
|
||||
-
|
||||
-/* Level 2 unified cache: */
|
||||
-#define ARM_L2CACHE_SIZE 524288
|
||||
-#define ARM_L2CACHE_SETS 1024
|
||||
-#define ARM_L2CACHE_ASSOCIATIVITY 8
|
||||
-#define ARM_L2CACHE_ATTRIBUTES 10
|
||||
-#define ARM_L2CACHE_LINE_SIZE 64
|
||||
-
|
||||
-/* Level 3 unified cache: */
|
||||
-#define ARM_L3CACHE_SIZE 33554432
|
||||
-#define ARM_L3CACHE_SETS 2048
|
||||
-#define ARM_L3CACHE_ASSOCIATIVITY 15
|
||||
-#define ARM_L3CACHE_ATTRIBUTES 10
|
||||
-#define ARM_L3CACHE_LINE_SIZE 128
|
||||
-
|
||||
-struct offset_status {
|
||||
- uint32_t parent;
|
||||
- uint32_t l2_offset;
|
||||
- uint32_t l1d_offset;
|
||||
- uint32_t l1i_offset;
|
||||
-};
|
||||
-
|
||||
-
|
||||
typedef
|
||||
struct CrsRangeEntry {
|
||||
uint64_t base;
|
||||
@@ -460,6 +415,7 @@ Aml *aml_sizeof(Aml *arg);
|
||||
Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target);
|
||||
Aml *aml_object_type(Aml *object);
|
||||
|
||||
+void build_append_byte(GArray *array, uint8_t val);
|
||||
void build_append_int_noprefix(GArray *table, uint64_t value, int size);
|
||||
|
||||
typedef struct AcpiTable {
|
||||
@@ -537,10 +493,12 @@ void build_srat_memory(GArray *table_data, uint64_t base,
|
||||
void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
const char *oem_id, const char *oem_table_id);
|
||||
|
||||
-void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
- const char *oem_id, const char *oem_table_id);
|
||||
+void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
|
||||
+ uint32_t parent, uint32_t id,
|
||||
+ uint32_t *priv_rsrc,
|
||||
+ uint32_t priv_num);
|
||||
|
||||
-void build_pptt_arm(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
+void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
const char *oem_id, const char *oem_table_id);
|
||||
|
||||
void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
|
||||
index 76a0d3fa5b..4b7dc61c24 100644
|
||||
--- a/include/hw/arm/virt.h
|
||||
+++ b/include/hw/arm/virt.h
|
||||
@@ -47,6 +47,65 @@
|
||||
/* See Linux kernel arch/arm64/include/asm/pvclock-abi.h */
|
||||
#define PVTIME_SIZE_PER_CPU 64
|
||||
|
||||
+/* ARM CLIDR_EL1 related definitions */
|
||||
+/* Ctypen, bits[3(n - 1) + 2 : 3(n - 1)], for n = 1 to 7 */
|
||||
+#define CTYPE_NONE 0b000
|
||||
+#define CTYPE_INS 0b001
|
||||
+#define CTYPE_DATA 0b010
|
||||
+#define CTYPE_INS_DATA 0b011
|
||||
+#define CTYPE_UNIFIED 0b100
|
||||
+
|
||||
+#define ARM64_REG_CLIDR_EL1 ARM64_SYS_REG(3, 1, 0, 0, 1)
|
||||
+
|
||||
+#define CLIDR_CTYPE_SHIFT(level) (3 * (level - 1))
|
||||
+#define CLIDR_CTYPE_MASK(level) (7 << CLIDR_CTYPE_SHIFT(level))
|
||||
+#define CLIDR_CTYPE(clidr, level) \
|
||||
+ (((clidr) & CLIDR_CTYPE_MASK(level)) >> CLIDR_CTYPE_SHIFT(level))
|
||||
+
|
||||
+/* L1 data cache */
|
||||
+#define ARM_L1DCACHE_SIZE 65536
|
||||
+#define ARM_L1DCACHE_SETS 256
|
||||
+#define ARM_L1DCACHE_ASSOCIATIVITY 4
|
||||
+#define ARM_L1DCACHE_ATTRIBUTES 2
|
||||
+#define ARM_L1DCACHE_LINE_SIZE 64
|
||||
+
|
||||
+/* L1 instruction cache */
|
||||
+#define ARM_L1ICACHE_SIZE 65536
|
||||
+#define ARM_L1ICACHE_SETS 256
|
||||
+#define ARM_L1ICACHE_ASSOCIATIVITY 4
|
||||
+#define ARM_L1ICACHE_ATTRIBUTES 4
|
||||
+#define ARM_L1ICACHE_LINE_SIZE 64
|
||||
+
|
||||
+/* L1 unified cache */
|
||||
+#define ARM_L1CACHE_SIZE 131072
|
||||
+#define ARM_L1CACHE_SETS 256
|
||||
+#define ARM_L1CACHE_ASSOCIATIVITY 4
|
||||
+#define ARM_L1CACHE_ATTRIBUTES 10
|
||||
+#define ARM_L1CACHE_LINE_SIZE 128
|
||||
+
|
||||
+/* L2 unified cache */
|
||||
+#define ARM_L2CACHE_SIZE 524288
|
||||
+#define ARM_L2CACHE_SETS 1024
|
||||
+#define ARM_L2CACHE_ASSOCIATIVITY 8
|
||||
+#define ARM_L2CACHE_ATTRIBUTES 10
|
||||
+#define ARM_L2CACHE_LINE_SIZE 64
|
||||
+
|
||||
+/* L3 unified cache */
|
||||
+#define ARM_L3CACHE_SIZE 33554432
|
||||
+#define ARM_L3CACHE_SETS 2048
|
||||
+#define ARM_L3CACHE_ASSOCIATIVITY 15
|
||||
+#define ARM_L3CACHE_ATTRIBUTES 10
|
||||
+#define ARM_L3CACHE_LINE_SIZE 128
|
||||
+
|
||||
+/* Definitions of the hardcoded cache info */
|
||||
+typedef enum {
|
||||
+ ARM_L1D_CACHE,
|
||||
+ ARM_L1I_CACHE,
|
||||
+ ARM_L1_CACHE,
|
||||
+ ARM_L2_CACHE,
|
||||
+ ARM_L3_CACHE
|
||||
+} ArmCacheType;
|
||||
+
|
||||
enum {
|
||||
VIRT_FLASH,
|
||||
VIRT_MEM,
|
||||
@@ -194,6 +253,7 @@ OBJECT_DECLARE_TYPE(VirtMachineState, VirtMachineClass, VIRT_MACHINE)
|
||||
|
||||
void virt_acpi_setup(VirtMachineState *vms);
|
||||
bool virt_is_acpi_enabled(VirtMachineState *vms);
|
||||
+bool cpu_l1_cache_unified(int cpu);
|
||||
|
||||
/* Return number of redistributors that fit in the specified region */
|
||||
static uint32_t virt_redist_capacity(VirtMachineState *vms, int region)
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
237
hw-arm-virt-acpi-build.c-Migrate-SPCR-creation-to-co.patch
Normal file
237
hw-arm-virt-acpi-build.c-Migrate-SPCR-creation-to-co.patch
Normal file
@ -0,0 +1,237 @@
|
||||
From f6b4a18ba78b1daa2a69fccfb768ec2bdcafb1d4 Mon Sep 17 00:00:00 2001
|
||||
From: Sia Jee Heng <jeeheng.sia@starfivetech.com>
|
||||
Date: Sun, 28 Jan 2024 18:14:39 -0800
|
||||
Subject: [PATCH] hw/arm/virt-acpi-build.c: Migrate SPCR creation to common
|
||||
location
|
||||
|
||||
RISC-V should also generate the SPCR in a manner similar to ARM.
|
||||
Therefore, instead of replicating the code, relocate this function
|
||||
to the common AML build.
|
||||
|
||||
Signed-off-by: Sia Jee Heng <jeeheng.sia@starfivetech.com>
|
||||
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
|
||||
Message-ID: <20240129021440.17640-2-jeeheng.sia@starfivetech.com>
|
||||
[ Changes by AF:
|
||||
- Add missing Language SPCR entry
|
||||
]
|
||||
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/acpi/aml-build.c | 53 +++++++++++++++++++++++++++++
|
||||
hw/arm/virt-acpi-build.c | 68 +++++++++++++++----------------------
|
||||
include/hw/acpi/acpi-defs.h | 33 ++++++++++++++++++
|
||||
include/hw/acpi/aml-build.h | 4 +++
|
||||
4 files changed, 117 insertions(+), 41 deletions(-)
|
||||
|
||||
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
|
||||
index 0d4994baf..3fb996c03 100644
|
||||
--- a/hw/acpi/aml-build.c
|
||||
+++ b/hw/acpi/aml-build.c
|
||||
@@ -2016,6 +2016,59 @@ void build_processor_hierarchy_node(GArray *tbl, uint32_t flags,
|
||||
}
|
||||
}
|
||||
|
||||
+void build_spcr(GArray *table_data, BIOSLinker *linker,
|
||||
+ const AcpiSpcrData *f, const uint8_t rev,
|
||||
+ const char *oem_id, const char *oem_table_id)
|
||||
+{
|
||||
+ AcpiTable table = { .sig = "SPCR", .rev = rev, .oem_id = oem_id,
|
||||
+ .oem_table_id = oem_table_id };
|
||||
+
|
||||
+ acpi_table_begin(&table, table_data);
|
||||
+ /* Interface type */
|
||||
+ build_append_int_noprefix(table_data, f->interface_type, 1);
|
||||
+ /* Reserved */
|
||||
+ build_append_int_noprefix(table_data, 0, 3);
|
||||
+ /* Base Address */
|
||||
+ build_append_gas(table_data, f->base_addr.id, f->base_addr.width,
|
||||
+ f->base_addr.offset, f->base_addr.size,
|
||||
+ f->base_addr.addr);
|
||||
+ /* Interrupt type */
|
||||
+ build_append_int_noprefix(table_data, f->interrupt_type, 1);
|
||||
+ /* IRQ */
|
||||
+ build_append_int_noprefix(table_data, f->pc_interrupt, 1);
|
||||
+ /* Global System Interrupt */
|
||||
+ build_append_int_noprefix(table_data, f->interrupt, 4);
|
||||
+ /* Baud Rate */
|
||||
+ build_append_int_noprefix(table_data, f->baud_rate, 1);
|
||||
+ /* Parity */
|
||||
+ build_append_int_noprefix(table_data, f->parity, 1);
|
||||
+ /* Stop Bits */
|
||||
+ build_append_int_noprefix(table_data, f->stop_bits, 1);
|
||||
+ /* Flow Control */
|
||||
+ build_append_int_noprefix(table_data, f->flow_control, 1);
|
||||
+ /* Language */
|
||||
+ build_append_int_noprefix(table_data, f->language, 1);
|
||||
+ /* Terminal Type */
|
||||
+ build_append_int_noprefix(table_data, f->terminal_type, 1);
|
||||
+ /* PCI Device ID */
|
||||
+ build_append_int_noprefix(table_data, f->pci_device_id, 2);
|
||||
+ /* PCI Vendor ID */
|
||||
+ build_append_int_noprefix(table_data, f->pci_vendor_id, 2);
|
||||
+ /* PCI Bus Number */
|
||||
+ build_append_int_noprefix(table_data, f->pci_bus, 1);
|
||||
+ /* PCI Device Number */
|
||||
+ build_append_int_noprefix(table_data, f->pci_device, 1);
|
||||
+ /* PCI Function Number */
|
||||
+ build_append_int_noprefix(table_data, f->pci_function, 1);
|
||||
+ /* PCI Flags */
|
||||
+ build_append_int_noprefix(table_data, f->pci_flags, 4);
|
||||
+ /* PCI Segment */
|
||||
+ build_append_int_noprefix(table_data, f->pci_segment, 1);
|
||||
+ /* Reserved */
|
||||
+ build_append_int_noprefix(table_data, 0, 4);
|
||||
+
|
||||
+ acpi_table_end(linker, &table);
|
||||
+}
|
||||
/*
|
||||
* ACPI spec, Revision 6.3
|
||||
* 5.2.29 Processor Properties Topology Table (PPTT)
|
||||
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
|
||||
index 86984b716..076781423 100644
|
||||
--- a/hw/arm/virt-acpi-build.c
|
||||
+++ b/hw/arm/virt-acpi-build.c
|
||||
@@ -717,48 +717,34 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
* Rev: 1.07
|
||||
*/
|
||||
static void
|
||||
-build_spcr(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
+spcr_setup(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
{
|
||||
- AcpiTable table = { .sig = "SPCR", .rev = 2, .oem_id = vms->oem_id,
|
||||
- .oem_table_id = vms->oem_table_id };
|
||||
-
|
||||
- acpi_table_begin(&table, table_data);
|
||||
-
|
||||
- /* Interface Type */
|
||||
- build_append_int_noprefix(table_data, 3, 1); /* ARM PL011 UART */
|
||||
- build_append_int_noprefix(table_data, 0, 3); /* Reserved */
|
||||
- /* Base Address */
|
||||
- build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 32, 0, 3,
|
||||
- vms->memmap[VIRT_UART].base);
|
||||
- /* Interrupt Type */
|
||||
- build_append_int_noprefix(table_data,
|
||||
- (1 << 3) /* Bit[3] ARMH GIC interrupt */, 1);
|
||||
- build_append_int_noprefix(table_data, 0, 1); /* IRQ */
|
||||
- /* Global System Interrupt */
|
||||
- build_append_int_noprefix(table_data,
|
||||
- vms->irqmap[VIRT_UART] + ARM_SPI_BASE, 4);
|
||||
- build_append_int_noprefix(table_data, 3 /* 9600 */, 1); /* Baud Rate */
|
||||
- build_append_int_noprefix(table_data, 0 /* No Parity */, 1); /* Parity */
|
||||
- /* Stop Bits */
|
||||
- build_append_int_noprefix(table_data, 1 /* 1 Stop bit */, 1);
|
||||
- /* Flow Control */
|
||||
- build_append_int_noprefix(table_data,
|
||||
- (1 << 1) /* RTS/CTS hardware flow control */, 1);
|
||||
- /* Terminal Type */
|
||||
- build_append_int_noprefix(table_data, 0 /* VT100 */, 1);
|
||||
- build_append_int_noprefix(table_data, 0, 1); /* Language */
|
||||
- /* PCI Device ID */
|
||||
- build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2);
|
||||
- /* PCI Vendor ID */
|
||||
- build_append_int_noprefix(table_data, 0xffff /* not a PCI device*/, 2);
|
||||
- build_append_int_noprefix(table_data, 0, 1); /* PCI Bus Number */
|
||||
- build_append_int_noprefix(table_data, 0, 1); /* PCI Device Number */
|
||||
- build_append_int_noprefix(table_data, 0, 1); /* PCI Function Number */
|
||||
- build_append_int_noprefix(table_data, 0, 4); /* PCI Flags */
|
||||
- build_append_int_noprefix(table_data, 0, 1); /* PCI Segment */
|
||||
- build_append_int_noprefix(table_data, 0, 4); /* Reserved */
|
||||
+ AcpiSpcrData serial = {
|
||||
+ .interface_type = 3, /* ARM PL011 UART */
|
||||
+ .base_addr.id = AML_AS_SYSTEM_MEMORY,
|
||||
+ .base_addr.width = 32,
|
||||
+ .base_addr.offset = 0,
|
||||
+ .base_addr.size = 3,
|
||||
+ .base_addr.addr = vms->memmap[VIRT_UART].base,
|
||||
+ .interrupt_type = (1 << 3),/* Bit[3] ARMH GIC interrupt*/
|
||||
+ .pc_interrupt = 0, /* IRQ */
|
||||
+ .interrupt = (vms->irqmap[VIRT_UART] + ARM_SPI_BASE),
|
||||
+ .baud_rate = 3, /* 9600 */
|
||||
+ .parity = 0, /* No Parity */
|
||||
+ .stop_bits = 1, /* 1 Stop bit */
|
||||
+ .flow_control = 1 << 1, /* RTS/CTS hardware flow control */
|
||||
+ .terminal_type = 0, /* VT100 */
|
||||
+ .language = 0, /* Language */
|
||||
+ .pci_device_id = 0xffff, /* not a PCI device*/
|
||||
+ .pci_vendor_id = 0xffff, /* not a PCI device*/
|
||||
+ .pci_bus = 0,
|
||||
+ .pci_device = 0,
|
||||
+ .pci_function = 0,
|
||||
+ .pci_flags = 0,
|
||||
+ .pci_segment = 0,
|
||||
+ };
|
||||
|
||||
- acpi_table_end(linker, &table);
|
||||
+ build_spcr(table_data, linker, &serial, 2, vms->oem_id, vms->oem_table_id);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1316,7 +1302,7 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
||||
}
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
- build_spcr(tables_blob, tables->linker, vms);
|
||||
+ spcr_setup(tables_blob, tables->linker, vms);
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_dbg2(tables_blob, tables->linker, vms);
|
||||
diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h
|
||||
index b1f389fb4..7a8b708cd 100644
|
||||
--- a/include/hw/acpi/acpi-defs.h
|
||||
+++ b/include/hw/acpi/acpi-defs.h
|
||||
@@ -90,6 +90,39 @@ typedef struct AcpiFadtData {
|
||||
unsigned *xdsdt_tbl_offset;
|
||||
} AcpiFadtData;
|
||||
|
||||
+typedef struct AcpiGas {
|
||||
+ uint8_t id; /* Address space ID */
|
||||
+ uint8_t width; /* Register bit width */
|
||||
+ uint8_t offset; /* Register bit offset */
|
||||
+ uint8_t size; /* Access size */
|
||||
+ uint64_t addr; /* Address */
|
||||
+} AcpiGas;
|
||||
+
|
||||
+/* SPCR (Serial Port Console Redirection table) */
|
||||
+typedef struct AcpiSpcrData {
|
||||
+ uint8_t interface_type;
|
||||
+ uint8_t reserved[3];
|
||||
+ struct AcpiGas base_addr;
|
||||
+ uint8_t interrupt_type;
|
||||
+ uint8_t pc_interrupt;
|
||||
+ uint32_t interrupt; /* Global system interrupt */
|
||||
+ uint8_t baud_rate;
|
||||
+ uint8_t parity;
|
||||
+ uint8_t stop_bits;
|
||||
+ uint8_t flow_control;
|
||||
+ uint8_t terminal_type;
|
||||
+ uint8_t language;
|
||||
+ uint8_t reserved1;
|
||||
+ uint16_t pci_device_id; /* Must be 0xffff if not PCI device */
|
||||
+ uint16_t pci_vendor_id; /* Must be 0xffff if not PCI device */
|
||||
+ uint8_t pci_bus;
|
||||
+ uint8_t pci_device;
|
||||
+ uint8_t pci_function;
|
||||
+ uint32_t pci_flags;
|
||||
+ uint8_t pci_segment;
|
||||
+ uint32_t reserved2;
|
||||
+} AcpiSpcrData;
|
||||
+
|
||||
#define ACPI_FADT_ARM_PSCI_COMPLIANT (1 << 0)
|
||||
#define ACPI_FADT_ARM_PSCI_USE_HVC (1 << 1)
|
||||
|
||||
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
|
||||
index 91f9cbf4f..381ad4a8a 100644
|
||||
--- a/include/hw/acpi/aml-build.h
|
||||
+++ b/include/hw/acpi/aml-build.h
|
||||
@@ -506,4 +506,8 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
|
||||
void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
|
||||
const char *oem_id, const char *oem_table_id);
|
||||
+
|
||||
+void build_spcr(GArray *table_data, BIOSLinker *linker,
|
||||
+ const AcpiSpcrData *f, const uint8_t rev,
|
||||
+ const char *oem_id, const char *oem_table_id);
|
||||
#endif
|
||||
--
|
||||
2.43.0
|
||||
|
||||
36
hw-audio-hda-free-timer-on-exit.patch
Normal file
36
hw-audio-hda-free-timer-on-exit.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 28bf94c86d3914b8b517dae483d1d69b3afabacc Mon Sep 17 00:00:00 2001
|
||||
From: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
Date: Tue, 5 Nov 2024 07:03:48 -0500
|
||||
Subject: [PATCH] hw/audio/hda: free timer on exit
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cheery-pick from f27206ceedbe2efae37c8d143c5eb2db05251508
|
||||
|
||||
Fixes: 280c1e1cd ("audio/hda: create millisecond timers that handle IO")
|
||||
|
||||
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
|
||||
Reviewed-by: Akihiko Odaki <akihiko.odaki@daynix.com>
|
||||
Message-ID: <20241008125028.1177932-2-marcandre.lureau@redhat.com>
|
||||
Signed-off-by: qihao_yewu <qihao_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/audio/hda-codec.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/audio/hda-codec.c b/hw/audio/hda-codec.c
|
||||
index 0bc20d49f6..19f401cabe 100644
|
||||
--- a/hw/audio/hda-codec.c
|
||||
+++ b/hw/audio/hda-codec.c
|
||||
@@ -751,7 +751,7 @@ static void hda_audio_exit(HDACodecDevice *hda)
|
||||
continue;
|
||||
}
|
||||
if (a->use_timer) {
|
||||
- timer_del(st->buft);
|
||||
+ timer_free(st->buft);
|
||||
}
|
||||
if (st->output) {
|
||||
AUD_close_out(&a->card, st->voice.out);
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
37
hw-cxl-Ensure-there-is-enough-data-for-the-header-in.patch
Normal file
37
hw-cxl-Ensure-there-is-enough-data-for-the-header-in.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From 830009038a73e496598c26679b7e30d7e931a1cf Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Date: Fri, 1 Nov 2024 13:39:16 +0000
|
||||
Subject: [PATCH] hw/cxl: Ensure there is enough data for the header in
|
||||
cmd_ccls_set_lsa()
|
||||
|
||||
The properties of the requested set command cannot be established if
|
||||
len_in is less than the size of the header.
|
||||
|
||||
Reported-by: Esifiel <esifiel@gmail.com>
|
||||
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Message-Id: <20241101133917.27634-10-Jonathan.Cameron@huawei.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/cxl/cxl-mailbox-utils.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
|
||||
index 6eff56fb1b..9f2304389b 100644
|
||||
--- a/hw/cxl/cxl-mailbox-utils.c
|
||||
+++ b/hw/cxl/cxl-mailbox-utils.c
|
||||
@@ -897,8 +897,8 @@ static CXLRetCode cmd_ccls_set_lsa(const struct cxl_cmd *cmd,
|
||||
const size_t hdr_len = offsetof(struct set_lsa_pl, data);
|
||||
|
||||
*len_out = 0;
|
||||
- if (!len_in) {
|
||||
- return CXL_MBOX_SUCCESS;
|
||||
+ if (len_in < hdr_len) {
|
||||
+ return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
|
||||
}
|
||||
|
||||
if (set_lsa_payload->offset + len_in > cvc->get_lsa_size(ct3d) + hdr_len) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
37
hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch
Normal file
37
hw-cxl-Ensure-there-is-enough-data-to-read-the-input.patch
Normal file
@ -0,0 +1,37 @@
|
||||
From d96c34e132df55ca7be458095f23d81dfc14e0d5 Mon Sep 17 00:00:00 2001
|
||||
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Date: Fri, 1 Nov 2024 13:39:17 +0000
|
||||
Subject: [PATCH] hw/cxl: Ensure there is enough data to read the input header
|
||||
in cmd_get_physical_port_state()
|
||||
|
||||
If len_in is smaller than the header length then the accessing the
|
||||
number of ports will result in an out of bounds access.
|
||||
Add a check to avoid this.
|
||||
|
||||
Reported-by: Esifiel <esifiel@gmail.com>
|
||||
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
|
||||
Message-Id: <20241101133917.27634-11-Jonathan.Cameron@huawei.com>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/cxl/cxl-mailbox-utils.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c
|
||||
index 6eff56fb1b..11a26525a2 100644
|
||||
--- a/hw/cxl/cxl-mailbox-utils.c
|
||||
+++ b/hw/cxl/cxl-mailbox-utils.c
|
||||
@@ -505,6 +505,9 @@ static CXLRetCode cmd_get_physical_port_state(const struct cxl_cmd *cmd,
|
||||
in = (struct cxl_fmapi_get_phys_port_state_req_pl *)payload_in;
|
||||
out = (struct cxl_fmapi_get_phys_port_state_resp_pl *)payload_out;
|
||||
|
||||
+ if (len_in < sizeof(*in)) {
|
||||
+ return CXL_MBOX_INVALID_PAYLOAD_LENGTH;
|
||||
+ }
|
||||
/* Check if what was requested can fit */
|
||||
if (sizeof(*out) + sizeof(*out->ports) * in->num_ports > cci->payload_max) {
|
||||
return CXL_MBOX_INVALID_INPUT;
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
36
hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch
Normal file
36
hw-gpio-aspeed_gpio-Avoid-shift-into-sign-bit.patch
Normal file
@ -0,0 +1,36 @@
|
||||
From 10794f7a9bc3c88c8a26f094e5d3ef42e9fd290f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=E5=BC=A0=E6=A5=9A=E5=90=9B?=
|
||||
<zhangchujun@cmss.chinamobile.com>
|
||||
Date: Fri, 11 Oct 2024 14:04:54 +0800
|
||||
Subject: [PATCH] hw/gpio/aspeed_gpio: Avoid shift into sign bit
|
||||
|
||||
In aspeed_gpio_update() we calculate "mask = 1 << gpio", where gpio can be between 0 and 31.
|
||||
Coverity complains about this beacuse 1 << 31 won't fit in a signed integer.
|
||||
|
||||
For QEMU this isn't an error because we enable -fwrapv, but we can keep Coverity happy
|
||||
by doing the shift on unsigned numbers.
|
||||
|
||||
Resolves: Coverity CID 1547742
|
||||
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
|
||||
Reviewed-by: Cedric Le Goater <clg@redhat.com>
|
||||
Signed-off-by: zhangchujun <zhangchujun@cmss.chinamobile.com>
|
||||
---
|
||||
hw/gpio/aspeed_gpio.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/gpio/aspeed_gpio.c b/hw/gpio/aspeed_gpio.c
|
||||
index 1e267dd482..0fc3d4c05f 100644
|
||||
--- a/hw/gpio/aspeed_gpio.c
|
||||
+++ b/hw/gpio/aspeed_gpio.c
|
||||
@@ -281,7 +281,7 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
|
||||
diff &= mode_mask;
|
||||
if (diff) {
|
||||
for (gpio = 0; gpio < ASPEED_GPIOS_PER_SET; gpio++) {
|
||||
- uint32_t mask = 1 << gpio;
|
||||
+ uint32_t mask = 1U << gpio;
|
||||
|
||||
/* If the gpio needs to be updated... */
|
||||
if (!(diff & mask)) {
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
324
hw-i386-add-mem2-option-for-qemu.patch
Normal file
324
hw-i386-add-mem2-option-for-qemu.patch
Normal 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
|
||||
|
||||
50
hw-i386-amd_iommu-Don-t-leak-memory-in-amdvi_update_.patch
Normal file
50
hw-i386-amd_iommu-Don-t-leak-memory-in-amdvi_update_.patch
Normal 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
|
||||
|
||||
61
hw-intc-arm_gic-Fix-handling-of-NS-view-of-GICC_APR-.patch
Normal file
61
hw-intc-arm_gic-Fix-handling-of-NS-view-of-GICC_APR-.patch
Normal 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
|
||||
|
||||
51
hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch
Normal file
51
hw-intc-openpic-Improve-errors-for-out-of-bounds-pro.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From 15b6c032ed2f92aa3210fe30376119eb468af039 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
Date: Wed, 23 Oct 2024 14:19:00 +0800
|
||||
Subject: [PATCH] hw/intc/openpic: Improve errors for out of bounds property
|
||||
values
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cheery-pick from 627c1e012cb3f14745f9b7d991642894a4402d5c
|
||||
|
||||
The error message doesn't matter much, as the "openpic" device isn't
|
||||
user-creatable. But it's the last use of
|
||||
QERR_PROPERTY_VALUE_OUT_OF_RANGE, which has to go. Change the message
|
||||
just like the previous commit did for x86 CPUs.
|
||||
|
||||
Signed-off-by: Markus Armbruster <armbru@redhat.com>
|
||||
Message-ID: <20241010150144.986655-7-armbru@redhat.com>
|
||||
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/intc/openpic.c | 5 +----
|
||||
1 file changed, 1 insertion(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c
|
||||
index a6f91d4bcd..0f99b77a17 100644
|
||||
--- a/hw/intc/openpic.c
|
||||
+++ b/hw/intc/openpic.c
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "hw/pci/msi.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/bitops.h"
|
||||
-#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -1535,9 +1534,7 @@ static void openpic_realize(DeviceState *dev, Error **errp)
|
||||
};
|
||||
|
||||
if (opp->nb_cpus > MAX_CPU) {
|
||||
- error_setg(errp, QERR_PROPERTY_VALUE_OUT_OF_RANGE,
|
||||
- TYPE_OPENPIC, "nb_cpus", (uint64_t)opp->nb_cpus,
|
||||
- (uint64_t)0, (uint64_t)MAX_CPU);
|
||||
+ error_setg(errp, "property 'nb_cpus' can be at most %d", MAX_CPU);
|
||||
return;
|
||||
}
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
400
hw-loongarch-Add-KVM-IPI-device-support.patch
Normal file
400
hw-loongarch-Add-KVM-IPI-device-support.patch
Normal file
@ -0,0 +1,400 @@
|
||||
From 24e4e6742bdc8d804760e84f4e4bde5460e1e024 Mon Sep 17 00:00:00 2001
|
||||
From: gaosong <gaosong@loongson.cn>
|
||||
Date: Sun, 8 Sep 2024 09:29:00 +0800
|
||||
Subject: [PATCH 72/78] hw/loongarch: Add KVM IPI device support
|
||||
|
||||
Added ipi interrupt controller for kvm emulation.
|
||||
The main process is to send the command word for
|
||||
creating an ipi device to the kernel.
|
||||
When the VM is saved, the ioctl obtains the ipi
|
||||
interrupt controller data in the kernel and saves it.
|
||||
When the VM is recovered, the saved data is sent to the kernel.
|
||||
|
||||
Signed-off-by: gaosong <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/intc/Kconfig | 3 +
|
||||
hw/intc/loongarch_ipi_kvm.c | 207 ++++++++++++++++++++++++++++++++
|
||||
hw/intc/meson.build | 1 +
|
||||
hw/loongarch/Kconfig | 1 +
|
||||
hw/loongarch/virt.c | 35 ++++--
|
||||
include/hw/intc/loongarch_ipi.h | 23 ++++
|
||||
linux-headers/linux/kvm.h | 2 +
|
||||
target/loongarch/kvm/kvm.c | 4 +
|
||||
8 files changed, 263 insertions(+), 13 deletions(-)
|
||||
create mode 100644 hw/intc/loongarch_ipi_kvm.c
|
||||
|
||||
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
|
||||
index 97d550b06b..cbba74c22e 100644
|
||||
--- a/hw/intc/Kconfig
|
||||
+++ b/hw/intc/Kconfig
|
||||
@@ -93,6 +93,9 @@ config NIOS2_VIC
|
||||
config LOONGARCH_IPI
|
||||
bool
|
||||
|
||||
+config LOONGARCH_IPI_KVM
|
||||
+ bool
|
||||
+
|
||||
config LOONGARCH_PCH_PIC
|
||||
bool
|
||||
select UNIMP
|
||||
diff --git a/hw/intc/loongarch_ipi_kvm.c b/hw/intc/loongarch_ipi_kvm.c
|
||||
new file mode 100644
|
||||
index 0000000000..fd308eb0c0
|
||||
--- /dev/null
|
||||
+++ b/hw/intc/loongarch_ipi_kvm.c
|
||||
@@ -0,0 +1,207 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * LoongArch kvm ipi interrupt support
|
||||
+ *
|
||||
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
|
||||
+ */
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "hw/qdev-properties.h"
|
||||
+#include "qemu/typedefs.h"
|
||||
+#include "hw/intc/loongarch_ipi.h"
|
||||
+#include "hw/sysbus.h"
|
||||
+#include "linux/kvm.h"
|
||||
+#include "migration/vmstate.h"
|
||||
+#include "qapi/error.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
+
|
||||
+#define IPI_DEV_FD_UNDEF -1
|
||||
+
|
||||
+static void kvm_ipi_access_regs(int fd, uint64_t addr,
|
||||
+ uint32_t *val, int is_write)
|
||||
+{
|
||||
+ kvm_device_access(fd, KVM_DEV_LOONGARCH_IPI_GRP_REGS,
|
||||
+ addr, val, is_write, &error_abort);
|
||||
+}
|
||||
+
|
||||
+static int kvm_loongarch_ipi_pre_save(void *opaque)
|
||||
+{
|
||||
+ KVMLoongArchIPI *ipi = (KVMLoongArchIPI *)opaque;
|
||||
+ KVMLoongArchIPIClass *ipi_class = KVM_LOONGARCH_IPI_GET_CLASS(ipi);
|
||||
+ IPICore *cpu;
|
||||
+ uint64_t attr;
|
||||
+ int cpu_id = 0;
|
||||
+ int fd = ipi_class->dev_fd;
|
||||
+
|
||||
+ for (cpu_id = 0; cpu_id < ipi->num_cpu; cpu_id++) {
|
||||
+ cpu = &ipi->cpu[cpu_id];
|
||||
+ attr = (cpu_id << 16) | CORE_STATUS_OFF;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->status, false);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_EN_OFF;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->en, false);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_SET_OFF;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->set, false);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_CLEAR_OFF;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->clear, false);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_BUF_20;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->buf[0], false);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_BUF_28;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->buf[2], false);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_BUF_30;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->buf[4], false);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_BUF_38;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->buf[6], false);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int kvm_loongarch_ipi_post_load(void *opaque, int version_id)
|
||||
+{
|
||||
+ KVMLoongArchIPI *ipi = (KVMLoongArchIPI *)opaque;
|
||||
+ KVMLoongArchIPIClass *ipi_class = KVM_LOONGARCH_IPI_GET_CLASS(ipi);
|
||||
+ IPICore *cpu;
|
||||
+ uint64_t attr;
|
||||
+ int cpu_id = 0;
|
||||
+ int fd = ipi_class->dev_fd;
|
||||
+
|
||||
+ for (cpu_id = 0; cpu_id < ipi->num_cpu; cpu_id++) {
|
||||
+ cpu = &ipi->cpu[cpu_id];
|
||||
+ attr = (cpu_id << 16) | CORE_STATUS_OFF;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->status, true);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_EN_OFF;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->en, true);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_SET_OFF;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->set, true);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_CLEAR_OFF;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->clear, true);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_BUF_20;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->buf[0], true);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_BUF_28;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->buf[2], true);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_BUF_30;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->buf[4], true);
|
||||
+
|
||||
+ attr = (cpu_id << 16) | CORE_BUF_38;
|
||||
+ kvm_ipi_access_regs(fd, attr, &cpu->buf[6], true);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void kvm_loongarch_ipi_realize(DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ KVMLoongArchIPI *ipi = KVM_LOONGARCH_IPI(dev);
|
||||
+ KVMLoongArchIPIClass *ipi_class = KVM_LOONGARCH_IPI_GET_CLASS(dev);
|
||||
+ struct kvm_create_device cd = {0};
|
||||
+ Error *err = NULL;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (ipi->num_cpu == 0) {
|
||||
+ error_setg(errp, "num-cpu must be at least 1");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ipi_class->parent_realize(dev, &err);
|
||||
+ if (err) {
|
||||
+ error_propagate(errp, err);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ ipi->cpu = g_new0(IPICore, ipi->num_cpu);
|
||||
+ if (ipi->cpu == NULL) {
|
||||
+ error_setg(errp, "Memory allocation for ExtIOICore faile");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!ipi_class->is_created) {
|
||||
+ cd.type = KVM_DEV_TYPE_LA_IPI;
|
||||
+ ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
|
||||
+ if (ret < 0) {
|
||||
+ error_setg_errno(errp, errno, "Creating the KVM device failed");
|
||||
+ return;
|
||||
+ }
|
||||
+ ipi_class->is_created = true;
|
||||
+ ipi_class->dev_fd = cd.fd;
|
||||
+ fprintf(stdout, "Create LoongArch IPI irqchip in KVM done!\n");
|
||||
+ }
|
||||
+
|
||||
+ assert(ipi_class->dev_fd != IPI_DEV_FD_UNDEF);
|
||||
+}
|
||||
+
|
||||
+static Property kvm_loongarch_ipi_properties[] = {
|
||||
+ DEFINE_PROP_UINT32("num-cpu", KVMLoongArchIPI, num_cpu, 1),
|
||||
+ DEFINE_PROP_END_OF_LIST()
|
||||
+};
|
||||
+
|
||||
+static const VMStateDescription vmstate_kvm_ipi_core = {
|
||||
+ .name = "kvm-ipi-single",
|
||||
+ .version_id = 1,
|
||||
+ .minimum_version_id = 1,
|
||||
+ .fields = (VMStateField[]) {
|
||||
+ VMSTATE_UINT32(status, IPICore),
|
||||
+ VMSTATE_UINT32(en, IPICore),
|
||||
+ VMSTATE_UINT32(set, IPICore),
|
||||
+ VMSTATE_UINT32(clear, IPICore),
|
||||
+ VMSTATE_UINT32_ARRAY(buf, IPICore, 8),
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static const VMStateDescription vmstate_kvm_loongarch_ipi = {
|
||||
+ .name = TYPE_KVM_LOONGARCH_IPI,
|
||||
+ .version_id = 1,
|
||||
+ .minimum_version_id = 1,
|
||||
+ .pre_save = kvm_loongarch_ipi_pre_save,
|
||||
+ .post_load = kvm_loongarch_ipi_post_load,
|
||||
+ .fields = (VMStateField[]) {
|
||||
+ VMSTATE_STRUCT_VARRAY_POINTER_UINT32(cpu, KVMLoongArchIPI, num_cpu,
|
||||
+ vmstate_kvm_ipi_core, IPICore),
|
||||
+
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static void kvm_loongarch_ipi_class_init(ObjectClass *oc, void *data)
|
||||
+{
|
||||
+ DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
+ KVMLoongArchIPIClass *ipi_class = KVM_LOONGARCH_IPI_CLASS(oc);
|
||||
+
|
||||
+ ipi_class->parent_realize = dc->realize;
|
||||
+ dc->realize = kvm_loongarch_ipi_realize;
|
||||
+
|
||||
+ ipi_class->is_created = false;
|
||||
+ ipi_class->dev_fd = IPI_DEV_FD_UNDEF;
|
||||
+
|
||||
+ device_class_set_props(dc, kvm_loongarch_ipi_properties);
|
||||
+
|
||||
+ dc->vmsd = &vmstate_kvm_loongarch_ipi;
|
||||
+}
|
||||
+
|
||||
+static const TypeInfo kvm_loongarch_ipi_info = {
|
||||
+ .name = TYPE_KVM_LOONGARCH_IPI,
|
||||
+ .parent = TYPE_SYS_BUS_DEVICE,
|
||||
+ .instance_size = sizeof(KVMLoongArchIPI),
|
||||
+ .class_size = sizeof(KVMLoongArchIPIClass),
|
||||
+ .class_init = kvm_loongarch_ipi_class_init,
|
||||
+};
|
||||
+
|
||||
+static void kvm_loongarch_ipi_register_types(void)
|
||||
+{
|
||||
+ type_register_static(&kvm_loongarch_ipi_info);
|
||||
+}
|
||||
+
|
||||
+type_init(kvm_loongarch_ipi_register_types)
|
||||
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
|
||||
index ed355941d1..9deeeb51bb 100644
|
||||
--- a/hw/intc/meson.build
|
||||
+++ b/hw/intc/meson.build
|
||||
@@ -70,6 +70,7 @@ specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'],
|
||||
specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
|
||||
specific_ss.add(when: 'CONFIG_NIOS2_VIC', if_true: files('nios2_vic.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: files('loongarch_ipi.c'))
|
||||
+specific_ss.add(when: 'CONFIG_LOONGARCH_IPI_KVM', if_true: files('loongarch_ipi_kvm.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c'))
|
||||
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
|
||||
index b42a8573d4..1e761624c6 100644
|
||||
--- a/hw/loongarch/Kconfig
|
||||
+++ b/hw/loongarch/Kconfig
|
||||
@@ -14,6 +14,7 @@ config LOONGARCH_VIRT
|
||||
select LOONGARCH_PCH_PIC
|
||||
select LOONGARCH_PCH_MSI
|
||||
select LOONGARCH_EXTIOI
|
||||
+ select LOONGARCH_IPI_KVM if KVM
|
||||
select LS7A_RTC
|
||||
select SMBIOS
|
||||
select ACPI_CPU_HOTPLUG
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 6159fd9470..f065eb75f8 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -829,16 +829,28 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
||||
* +--------+ +---------+ +---------+
|
||||
*/
|
||||
|
||||
- /* Create IPI device */
|
||||
- ipi = qdev_new(TYPE_LOONGARCH_IPI);
|
||||
- qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.max_cpus);
|
||||
- sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
|
||||
-
|
||||
- /* IPI iocsr memory region */
|
||||
- memory_region_add_subregion(&lvms->system_iocsr, SMP_IPI_MAILBOX,
|
||||
- sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
|
||||
- memory_region_add_subregion(&lvms->system_iocsr, MAIL_SEND_ADDR,
|
||||
- sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
|
||||
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
+ ipi = qdev_new(TYPE_KVM_LOONGARCH_IPI);
|
||||
+ qdev_prop_set_int32(ipi, "num-cpu", ms->smp.max_cpus);
|
||||
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
|
||||
+ } else {
|
||||
+ ipi = qdev_new(TYPE_LOONGARCH_IPI);
|
||||
+ qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.max_cpus);
|
||||
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
|
||||
+
|
||||
+ /* IPI iocsr memory region */
|
||||
+ memory_region_add_subregion(&lvms->system_iocsr, SMP_IPI_MAILBOX,
|
||||
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 0));
|
||||
+ memory_region_add_subregion(&lvms->system_iocsr, MAIL_SEND_ADDR,
|
||||
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
|
||||
+ for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
|
||||
+ cpu_state = qemu_get_cpu(cpu);
|
||||
+ cpudev = DEVICE(cpu_state);
|
||||
+
|
||||
+ /* connect ipi irq to cpu irq */
|
||||
+ qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI));
|
||||
+ }
|
||||
+ }
|
||||
|
||||
/* Add cpu interrupt-controller */
|
||||
fdt_add_cpuic_node(lvms, &cpuintc_phandle);
|
||||
@@ -849,9 +861,6 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
||||
lacpu = LOONGARCH_CPU(cpu_state);
|
||||
env = &(lacpu->env);
|
||||
env->address_space_iocsr = &lvms->as_iocsr;
|
||||
-
|
||||
- /* connect ipi irq to cpu irq */
|
||||
- qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI));
|
||||
env->ipistate = ipi;
|
||||
}
|
||||
|
||||
diff --git a/include/hw/intc/loongarch_ipi.h b/include/hw/intc/loongarch_ipi.h
|
||||
index 1c1e834849..601b4f18a7 100644
|
||||
--- a/include/hw/intc/loongarch_ipi.h
|
||||
+++ b/include/hw/intc/loongarch_ipi.h
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#define TYPE_LOONGARCH_IPI "loongarch_ipi"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchIPI, LOONGARCH_IPI)
|
||||
+#define TYPE_KVM_LOONGARCH_IPI "loongarch-ipi-kvm"
|
||||
|
||||
typedef struct IPICore {
|
||||
uint32_t status;
|
||||
@@ -51,4 +52,26 @@ struct LoongArchIPI {
|
||||
IPICore *cpu;
|
||||
};
|
||||
|
||||
+struct KVMLoongArchIPI {
|
||||
+ SysBusDevice parent_obj;
|
||||
+ uint32_t num_cpu;
|
||||
+ IPICore *cpu;
|
||||
+};
|
||||
+typedef struct KVMLoongArchIPI KVMLoongArchIPI;
|
||||
+DECLARE_INSTANCE_CHECKER(KVMLoongArchIPI, KVM_LOONGARCH_IPI,
|
||||
+ TYPE_KVM_LOONGARCH_IPI)
|
||||
+
|
||||
+struct KVMLoongArchIPIClass {
|
||||
+ SysBusDeviceClass parent_class;
|
||||
+ DeviceRealize parent_realize;
|
||||
+
|
||||
+ bool is_created;
|
||||
+ int dev_fd;
|
||||
+
|
||||
+};
|
||||
+typedef struct KVMLoongArchIPIClass KVMLoongArchIPIClass;
|
||||
+DECLARE_CLASS_CHECKERS(KVMLoongArchIPIClass, KVM_LOONGARCH_IPI,
|
||||
+ TYPE_KVM_LOONGARCH_IPI)
|
||||
+
|
||||
+
|
||||
#endif
|
||||
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||||
index eb30402c2d..ea1f821a9f 100644
|
||||
--- a/linux-headers/linux/kvm.h
|
||||
+++ b/linux-headers/linux/kvm.h
|
||||
@@ -1470,6 +1470,8 @@ enum kvm_device_type {
|
||||
#define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME
|
||||
KVM_DEV_TYPE_RISCV_AIA,
|
||||
#define KVM_DEV_TYPE_RISCV_AIA KVM_DEV_TYPE_RISCV_AIA
|
||||
+ KVM_DEV_TYPE_LA_IPI,
|
||||
+#define KVM_DEV_TYPE_LA_IPI KVM_DEV_TYPE_LA_IPI
|
||||
KVM_DEV_TYPE_MAX,
|
||||
};
|
||||
|
||||
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
|
||||
index 550f14269e..ab1ea3d4fd 100644
|
||||
--- a/target/loongarch/kvm/kvm.c
|
||||
+++ b/target/loongarch/kvm/kvm.c
|
||||
@@ -1066,6 +1066,10 @@ int kvm_arch_get_default_type(MachineState *ms)
|
||||
int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
{
|
||||
cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
|
||||
+ if(!kvm_vm_check_attr(kvm_state, KVM_LOONGARCH_VM_HAVE_IRQCHIP, KVM_LOONGARCH_VM_HAVE_IRQCHIP)) {
|
||||
+ s->kernel_irqchip_allowed = false;
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
384
hw-loongarch-Add-KVM-extioi-device-support.patch
Normal file
384
hw-loongarch-Add-KVM-extioi-device-support.patch
Normal file
@ -0,0 +1,384 @@
|
||||
From 833cdea8037d9124cd2e0328739de1b85aaec2a2 Mon Sep 17 00:00:00 2001
|
||||
From: gaosong <gaosong@loongson.cn>
|
||||
Date: Sun, 8 Sep 2024 09:50:50 +0800
|
||||
Subject: [PATCH 73/78] hw/loongarch: Add KVM extioi device support
|
||||
|
||||
Added extioi interrupt controller for kvm emulation.
|
||||
The main process is to send the command word for
|
||||
creating an extioi device to the kernel.
|
||||
When the VM is saved, the ioctl obtains the related
|
||||
data of the extioi interrupt controller in the kernel
|
||||
and saves it. When the VM is recovered, the saved data
|
||||
is sent to the kernel.
|
||||
|
||||
Signed-off-by: gaosong <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/intc/Kconfig | 3 +
|
||||
hw/intc/loongarch_extioi_kvm.c | 150 +++++++++++++++++++++++++++++
|
||||
hw/intc/meson.build | 1 +
|
||||
hw/loongarch/Kconfig | 1 +
|
||||
hw/loongarch/virt.c | 50 +++++-----
|
||||
include/hw/intc/loongarch_extioi.h | 36 ++++++-
|
||||
include/hw/loongarch/virt.h | 15 +++
|
||||
linux-headers/linux/kvm.h | 2 +
|
||||
8 files changed, 232 insertions(+), 26 deletions(-)
|
||||
create mode 100644 hw/intc/loongarch_extioi_kvm.c
|
||||
|
||||
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
|
||||
index cbba74c22e..f1e8bd2fc9 100644
|
||||
--- a/hw/intc/Kconfig
|
||||
+++ b/hw/intc/Kconfig
|
||||
@@ -107,3 +107,6 @@ config LOONGARCH_PCH_MSI
|
||||
|
||||
config LOONGARCH_EXTIOI
|
||||
bool
|
||||
+
|
||||
+config LOONGARCH_EXTIOI_KVM
|
||||
+ bool
|
||||
diff --git a/hw/intc/loongarch_extioi_kvm.c b/hw/intc/loongarch_extioi_kvm.c
|
||||
new file mode 100644
|
||||
index 0000000000..f5bbc33255
|
||||
--- /dev/null
|
||||
+++ b/hw/intc/loongarch_extioi_kvm.c
|
||||
@@ -0,0 +1,150 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * LoongArch kvm extioi interrupt support
|
||||
+ *
|
||||
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
|
||||
+ */
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "hw/qdev-properties.h"
|
||||
+#include "qemu/typedefs.h"
|
||||
+#include "hw/intc/loongarch_extioi.h"
|
||||
+#include "hw/sysbus.h"
|
||||
+#include "linux/kvm.h"
|
||||
+#include "migration/vmstate.h"
|
||||
+#include "qapi/error.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
+
|
||||
+static void kvm_extioi_access_regs(int fd, uint64_t addr,
|
||||
+ void *val, int is_write)
|
||||
+{
|
||||
+ kvm_device_access(fd, KVM_DEV_LOONGARCH_EXTIOI_GRP_REGS,
|
||||
+ addr, val, is_write, &error_abort);
|
||||
+}
|
||||
+
|
||||
+static int kvm_loongarch_extioi_pre_save(void *opaque)
|
||||
+{
|
||||
+ KVMLoongArchExtIOI *s = (KVMLoongArchExtIOI *)opaque;
|
||||
+ KVMLoongArchExtIOIClass *class = KVM_LOONGARCH_EXTIOI_GET_CLASS(s);
|
||||
+ int fd = class->dev_fd;
|
||||
+
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_NODETYPE_START,
|
||||
+ (void *)s->nodetype, false);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_IPMAP_START, (void *)s->ipmap, false);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_ENABLE_START, (void *)s->enable, false);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_BOUNCE_START, (void *)s->bounce, false);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_ISR_START, (void *)s->isr, false);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_COREMAP_START,
|
||||
+ (void *)s->coremap, false);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_SW_COREMAP_FLAG,
|
||||
+ (void *)s->sw_coremap, false);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_COREISR_START,
|
||||
+ (void *)s->coreisr, false);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int kvm_loongarch_extioi_post_load(void *opaque, int version_id)
|
||||
+{
|
||||
+ KVMLoongArchExtIOI *s = (KVMLoongArchExtIOI *)opaque;
|
||||
+ KVMLoongArchExtIOIClass *class = KVM_LOONGARCH_EXTIOI_GET_CLASS(s);
|
||||
+ int fd = class->dev_fd;
|
||||
+
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_NODETYPE_START,
|
||||
+ (void *)s->nodetype, true);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_IPMAP_START, (void *)s->ipmap, true);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_ENABLE_START, (void *)s->enable, true);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_BOUNCE_START, (void *)s->bounce, true);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_ISR_START, (void *)s->isr, true);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_COREMAP_START, (void *)s->coremap, true);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_SW_COREMAP_FLAG,
|
||||
+ (void *)s->sw_coremap, true);
|
||||
+ kvm_extioi_access_regs(fd, EXTIOI_COREISR_START, (void *)s->coreisr, true);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void kvm_loongarch_extioi_realize(DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ KVMLoongArchExtIOIClass *extioi_class = KVM_LOONGARCH_EXTIOI_GET_CLASS(dev);
|
||||
+ struct kvm_create_device cd = {0};
|
||||
+ Error *err = NULL;
|
||||
+ int ret,i;
|
||||
+
|
||||
+ extioi_class->parent_realize(dev, &err);
|
||||
+ if (err) {
|
||||
+ error_propagate(errp, err);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!extioi_class->is_created) {
|
||||
+ cd.type = KVM_DEV_TYPE_LA_EXTIOI;
|
||||
+ ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
|
||||
+ if (ret < 0) {
|
||||
+ error_setg_errno(errp, errno,
|
||||
+ "Creating the KVM extioi device failed");
|
||||
+ return;
|
||||
+ }
|
||||
+ extioi_class->is_created = true;
|
||||
+ extioi_class->dev_fd = cd.fd;
|
||||
+ fprintf(stdout, "Create LoongArch extioi irqchip in KVM done!\n");
|
||||
+ }
|
||||
+
|
||||
+ kvm_async_interrupts_allowed = true;
|
||||
+ kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled();
|
||||
+ if (kvm_has_gsi_routing()) {
|
||||
+ for (i = 0; i < 64; ++i) {
|
||||
+ kvm_irqchip_add_irq_route(kvm_state, i, 0, i);
|
||||
+ }
|
||||
+ kvm_gsi_routing_allowed = true;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static const VMStateDescription vmstate_kvm_extioi_core = {
|
||||
+ .name = "kvm-extioi-single",
|
||||
+ .version_id = 1,
|
||||
+ .minimum_version_id = 1,
|
||||
+ .pre_save = kvm_loongarch_extioi_pre_save,
|
||||
+ .post_load = kvm_loongarch_extioi_post_load,
|
||||
+ .fields = (VMStateField[]) {
|
||||
+ VMSTATE_UINT32_ARRAY(nodetype, KVMLoongArchExtIOI,
|
||||
+ EXTIOI_IRQS_NODETYPE_COUNT / 2),
|
||||
+ VMSTATE_UINT32_ARRAY(bounce, KVMLoongArchExtIOI,
|
||||
+ EXTIOI_IRQS_GROUP_COUNT),
|
||||
+ VMSTATE_UINT32_ARRAY(isr, KVMLoongArchExtIOI, EXTIOI_IRQS / 32),
|
||||
+ VMSTATE_UINT32_2DARRAY(coreisr, KVMLoongArchExtIOI, EXTIOI_CPUS,
|
||||
+ EXTIOI_IRQS_GROUP_COUNT),
|
||||
+ VMSTATE_UINT32_ARRAY(enable, KVMLoongArchExtIOI, EXTIOI_IRQS / 32),
|
||||
+ VMSTATE_UINT32_ARRAY(ipmap, KVMLoongArchExtIOI,
|
||||
+ EXTIOI_IRQS_IPMAP_SIZE / 4),
|
||||
+ VMSTATE_UINT32_ARRAY(coremap, KVMLoongArchExtIOI, EXTIOI_IRQS / 4),
|
||||
+ VMSTATE_UINT8_ARRAY(sw_coremap, KVMLoongArchExtIOI, EXTIOI_IRQS),
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static void kvm_loongarch_extioi_class_init(ObjectClass *oc, void *data)
|
||||
+{
|
||||
+ DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
+ KVMLoongArchExtIOIClass *extioi_class = KVM_LOONGARCH_EXTIOI_CLASS(oc);
|
||||
+
|
||||
+ extioi_class->parent_realize = dc->realize;
|
||||
+ dc->realize = kvm_loongarch_extioi_realize;
|
||||
+ extioi_class->is_created = false;
|
||||
+ dc->vmsd = &vmstate_kvm_extioi_core;
|
||||
+}
|
||||
+
|
||||
+static const TypeInfo kvm_loongarch_extioi_info = {
|
||||
+ .name = TYPE_KVM_LOONGARCH_EXTIOI,
|
||||
+ .parent = TYPE_SYS_BUS_DEVICE,
|
||||
+ .instance_size = sizeof(KVMLoongArchExtIOI),
|
||||
+ .class_size = sizeof(KVMLoongArchExtIOIClass),
|
||||
+ .class_init = kvm_loongarch_extioi_class_init,
|
||||
+};
|
||||
+
|
||||
+static void kvm_loongarch_extioi_register_types(void)
|
||||
+{
|
||||
+ type_register_static(&kvm_loongarch_extioi_info);
|
||||
+}
|
||||
+
|
||||
+type_init(kvm_loongarch_extioi_register_types)
|
||||
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
|
||||
index 9deeeb51bb..a37d7da8aa 100644
|
||||
--- a/hw/intc/meson.build
|
||||
+++ b/hw/intc/meson.build
|
||||
@@ -74,3 +74,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_IPI_KVM', if_true: files('loongarch_ipi_
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c'))
|
||||
+specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI_KVM', if_true: files('loongarch_extioi_kvm.c'))
|
||||
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
|
||||
index 1e761624c6..1a47d44a64 100644
|
||||
--- a/hw/loongarch/Kconfig
|
||||
+++ b/hw/loongarch/Kconfig
|
||||
@@ -15,6 +15,7 @@ config LOONGARCH_VIRT
|
||||
select LOONGARCH_PCH_MSI
|
||||
select LOONGARCH_EXTIOI
|
||||
select LOONGARCH_IPI_KVM if KVM
|
||||
+ select LOONGARCH_EXTIOI_KVM if KVM
|
||||
select LS7A_RTC
|
||||
select SMBIOS
|
||||
select ACPI_CPU_HOTPLUG
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index f065eb75f8..71e2a3735c 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -867,31 +867,33 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
||||
lvms->ipi = ipi;
|
||||
|
||||
/* Create EXTIOI device */
|
||||
- extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
|
||||
- qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.max_cpus);
|
||||
- if (virt_is_veiointc_enabled(lvms)) {
|
||||
- qdev_prop_set_bit(extioi, "has-virtualization-extension", true);
|
||||
- }
|
||||
- sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
|
||||
-
|
||||
- memory_region_add_subregion(&lvms->system_iocsr, APIC_BASE,
|
||||
- sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 0));
|
||||
- if (virt_is_veiointc_enabled(lvms)) {
|
||||
- memory_region_add_subregion(&lvms->system_iocsr, EXTIOI_VIRT_BASE,
|
||||
- sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 1));
|
||||
- }
|
||||
- lvms->extioi = extioi;
|
||||
-
|
||||
- /*
|
||||
- * connect ext irq to the cpu irq
|
||||
- * cpu_pin[9:2] <= intc_pin[7:0]
|
||||
- */
|
||||
- for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
|
||||
- cpudev = DEVICE(qemu_get_cpu(cpu));
|
||||
- for (pin = 0; pin < LS3A_INTC_IP; pin++) {
|
||||
- qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
|
||||
- qdev_get_gpio_in(cpudev, pin + 2));
|
||||
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
+ extioi = qdev_new(TYPE_KVM_LOONGARCH_EXTIOI);
|
||||
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
|
||||
+ } else {
|
||||
+ extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
|
||||
+ qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.max_cpus);
|
||||
+ if (virt_is_veiointc_enabled(lvms)) {
|
||||
+ qdev_prop_set_bit(extioi, "has-virtualization-extension", true);
|
||||
}
|
||||
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), &error_fatal);
|
||||
+ memory_region_add_subregion(&lvms->system_iocsr, APIC_BASE,
|
||||
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 0));
|
||||
+ if (virt_is_veiointc_enabled(lvms)) {
|
||||
+ memory_region_add_subregion(&lvms->system_iocsr, EXTIOI_VIRT_BASE,
|
||||
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi), 1));
|
||||
+ }
|
||||
+ /*
|
||||
+ * connect ext irq to the cpu irq
|
||||
+ * cpu_pin[9:2] <= intc_pin[7:0]
|
||||
+ */
|
||||
+ for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
|
||||
+ cpudev = DEVICE(qemu_get_cpu(cpu));
|
||||
+ for (pin = 0; pin < LS3A_INTC_IP; pin++) {
|
||||
+ qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
|
||||
+ qdev_get_gpio_in(cpudev, pin + 2));
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
lvms->extioi = extioi;
|
||||
diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
|
||||
index 722ffee1bc..9966cd98d3 100644
|
||||
--- a/include/hw/intc/loongarch_extioi.h
|
||||
+++ b/include/hw/intc/loongarch_extioi.h
|
||||
@@ -15,7 +15,7 @@
|
||||
#define EXTIOI_IRQS (256)
|
||||
#define EXTIOI_IRQS_BITMAP_SIZE (256 / 8)
|
||||
/* irq from EXTIOI is routed to no more than 4 cpus */
|
||||
-#define EXTIOI_CPUS (4)
|
||||
+#define EXTIOI_CPUS (256)
|
||||
/* map to ipnum per 32 irqs */
|
||||
#define EXTIOI_IRQS_IPMAP_SIZE (256 / 32)
|
||||
#define EXTIOI_IRQS_COREMAP_SIZE 256
|
||||
@@ -59,13 +59,17 @@
|
||||
#define EXTIOI_VIRT_COREMAP_START (0x40)
|
||||
#define EXTIOI_VIRT_COREMAP_END (0x240)
|
||||
|
||||
+#define EXTIOI_SW_COREMAP_FLAG (1 << 0)
|
||||
+
|
||||
typedef struct ExtIOICore {
|
||||
uint32_t coreisr[EXTIOI_IRQS_GROUP_COUNT];
|
||||
DECLARE_BITMAP(sw_isr[LS3A_INTC_IP], EXTIOI_IRQS);
|
||||
qemu_irq parent_irq[LS3A_INTC_IP];
|
||||
} ExtIOICore;
|
||||
|
||||
-#define TYPE_LOONGARCH_EXTIOI "loongarch.extioi"
|
||||
+#define TYPE_LOONGARCH_EXTIOI "loongarch-extioi"
|
||||
+#define TYPE_KVM_LOONGARCH_EXTIOI "loongarch-kvm-extioi"
|
||||
+
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchExtIOI, LOONGARCH_EXTIOI)
|
||||
struct LoongArchExtIOI {
|
||||
SysBusDevice parent_obj;
|
||||
@@ -87,4 +91,32 @@ struct LoongArchExtIOI {
|
||||
MemoryRegion extioi_system_mem;
|
||||
MemoryRegion virt_extend;
|
||||
};
|
||||
+
|
||||
+struct KVMLoongArchExtIOI {
|
||||
+ SysBusDevice parent_obj;
|
||||
+ /* hardware state */
|
||||
+ uint32_t nodetype[EXTIOI_IRQS_NODETYPE_COUNT / 2];
|
||||
+ uint32_t bounce[EXTIOI_IRQS_GROUP_COUNT];
|
||||
+ uint32_t isr[EXTIOI_IRQS / 32];
|
||||
+ uint32_t coreisr[EXTIOI_CPUS][EXTIOI_IRQS_GROUP_COUNT];
|
||||
+ uint32_t enable[EXTIOI_IRQS / 32];
|
||||
+ uint32_t ipmap[EXTIOI_IRQS_IPMAP_SIZE / 4];
|
||||
+ uint32_t coremap[EXTIOI_IRQS / 4];
|
||||
+ uint8_t sw_coremap[EXTIOI_IRQS];
|
||||
+};
|
||||
+typedef struct KVMLoongArchExtIOI KVMLoongArchExtIOI;
|
||||
+DECLARE_INSTANCE_CHECKER(KVMLoongArchExtIOI, KVM_LOONGARCH_EXTIOI,
|
||||
+ TYPE_KVM_LOONGARCH_EXTIOI)
|
||||
+
|
||||
+struct KVMLoongArchExtIOIClass {
|
||||
+ SysBusDeviceClass parent_class;
|
||||
+ DeviceRealize parent_realize;
|
||||
+
|
||||
+ bool is_created;
|
||||
+ int dev_fd;
|
||||
+};
|
||||
+typedef struct KVMLoongArchExtIOIClass KVMLoongArchExtIOIClass;
|
||||
+DECLARE_CLASS_CHECKERS(KVMLoongArchExtIOIClass, KVM_LOONGARCH_EXTIOI,
|
||||
+ TYPE_KVM_LOONGARCH_EXTIOI)
|
||||
+
|
||||
#endif /* LOONGARCH_EXTIOI_H */
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 98c990327b..168b40c31b 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -38,6 +38,21 @@
|
||||
|
||||
#define FDT_BASE 0x100000
|
||||
|
||||
+/* KVM_IRQ_LINE irq field index values */
|
||||
+#define KVM_LOONGARCH_IRQ_TYPE_SHIFT 24
|
||||
+#define KVM_LOONGARCH_IRQ_TYPE_MASK 0xff
|
||||
+#define KVM_LOONGARCH_IRQ_VCPU_SHIFT 16
|
||||
+#define KVM_LOONGARCH_IRQ_VCPU_MASK 0xff
|
||||
+#define KVM_LOONGARCH_IRQ_NUM_SHIFT 0
|
||||
+#define KVM_LOONGARCH_IRQ_NUM_MASK 0xffff
|
||||
+
|
||||
+/* irq_type field */
|
||||
+#define KVM_LOONGARCH_IRQ_TYPE_CPU_IP 0
|
||||
+#define KVM_LOONGARCH_IRQ_TYPE_CPU_IO 1
|
||||
+#define KVM_LOONGARCH_IRQ_TYPE_HT 2
|
||||
+#define KVM_LOONGARCH_IRQ_TYPE_MSI 3
|
||||
+#define KVM_LOONGARCH_IRQ_TYPE_IOAPIC 4
|
||||
+
|
||||
struct LoongArchVirtMachineState {
|
||||
/*< private >*/
|
||||
MachineState parent_obj;
|
||||
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||||
index ea1f821a9f..0c0b82d1ef 100644
|
||||
--- a/linux-headers/linux/kvm.h
|
||||
+++ b/linux-headers/linux/kvm.h
|
||||
@@ -1472,6 +1472,8 @@ enum kvm_device_type {
|
||||
#define KVM_DEV_TYPE_RISCV_AIA KVM_DEV_TYPE_RISCV_AIA
|
||||
KVM_DEV_TYPE_LA_IPI,
|
||||
#define KVM_DEV_TYPE_LA_IPI KVM_DEV_TYPE_LA_IPI
|
||||
+ KVM_DEV_TYPE_LA_EXTIOI,
|
||||
+#define KVM_DEV_TYPE_LA_EXTIOI KVM_DEV_TYPE_LA_EXTIOI
|
||||
KVM_DEV_TYPE_MAX,
|
||||
};
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
136
hw-loongarch-Add-KVM-pch-msi-device-support.patch
Normal file
136
hw-loongarch-Add-KVM-pch-msi-device-support.patch
Normal file
@ -0,0 +1,136 @@
|
||||
From 24bd774f8146247c7ac6071492f6016140a97267 Mon Sep 17 00:00:00 2001
|
||||
From: gaosong <gaosong@loongson.cn>
|
||||
Date: Sun, 8 Sep 2024 22:18:50 +0800
|
||||
Subject: [PATCH 75/78] hw/loongarch: Add KVM pch msi device support
|
||||
|
||||
Added pch_msi interrupt controller handling
|
||||
during kernel emulation of irq chip.
|
||||
|
||||
Signed-off-by: gaosong <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/intc/loongarch_pch_msi.c | 39 ++++++++++++++++++++++-------
|
||||
hw/loongarch/virt.c | 22 +++++++++-------
|
||||
include/hw/intc/loongarch_pch_msi.h | 2 +-
|
||||
3 files changed, 44 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c
|
||||
index ecf3ed0267..901c2c21be 100644
|
||||
--- a/hw/intc/loongarch_pch_msi.c
|
||||
+++ b/hw/intc/loongarch_pch_msi.c
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "trace.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
+#include "hw/loongarch/virt.h"
|
||||
|
||||
static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
@@ -26,14 +28,24 @@ static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
|
||||
LoongArchPCHMSI *s = (LoongArchPCHMSI *)opaque;
|
||||
int irq_num;
|
||||
|
||||
- /*
|
||||
- * vector number is irq number from upper extioi intc
|
||||
- * need subtract irq base to get msi vector offset
|
||||
- */
|
||||
- irq_num = (val & 0xff) - s->irq_base;
|
||||
- trace_loongarch_msi_set_irq(irq_num);
|
||||
- assert(irq_num < s->irq_num);
|
||||
- qemu_set_irq(s->pch_msi_irq[irq_num], 1);
|
||||
+ MSIMessage msg = {
|
||||
+ .address = addr,
|
||||
+ .data = val,
|
||||
+ };
|
||||
+
|
||||
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
+ kvm_irqchip_send_msi(kvm_state, msg);
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * vector number is irq number from upper extioi intc
|
||||
+ * need subtract irq base to get msi vector offset
|
||||
+ */
|
||||
+ irq_num = (val & 0xff) - s->irq_base;
|
||||
+ trace_loongarch_msi_set_irq(irq_num);
|
||||
+ assert(irq_num < s->irq_num);
|
||||
+
|
||||
+ qemu_set_irq(s->pch_msi_irq[irq_num], 1);
|
||||
+ }
|
||||
}
|
||||
|
||||
static const MemoryRegionOps loongarch_pch_msi_ops = {
|
||||
@@ -46,7 +58,16 @@ static void pch_msi_irq_handler(void *opaque, int irq, int level)
|
||||
{
|
||||
LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
|
||||
|
||||
- qemu_set_irq(s->pch_msi_irq[irq], level);
|
||||
+ MSIMessage msg = {
|
||||
+ .address = 0,
|
||||
+ .data = irq,
|
||||
+ };
|
||||
+
|
||||
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
+ kvm_irqchip_send_msi(kvm_state, msg);
|
||||
+ } else {
|
||||
+ qemu_set_irq(s->pch_msi_irq[irq], level);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void loongarch_pch_msi_realize(DeviceState *dev, Error **errp)
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 270dcfd38f..5b0468f6cb 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -928,22 +928,26 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
||||
for (i = 0; i < num; i++) {
|
||||
qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i));
|
||||
}
|
||||
+ }
|
||||
|
||||
- pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
|
||||
- start = num;
|
||||
- num = EXTIOI_IRQS - start;
|
||||
- qdev_prop_set_uint32(pch_msi, "msi_irq_base", start);
|
||||
- qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
|
||||
- d = SYS_BUS_DEVICE(pch_msi);
|
||||
- sysbus_realize_and_unref(d, &error_fatal);
|
||||
- sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
|
||||
+ pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
|
||||
+ num = VIRT_PCH_PIC_IRQ_NUM;
|
||||
+ start = num;
|
||||
+ num = EXTIOI_IRQS - start;
|
||||
+ qdev_prop_set_uint32(pch_msi, "msi_irq_base", start);
|
||||
+ qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
|
||||
+ d = SYS_BUS_DEVICE(pch_msi);
|
||||
+ sysbus_realize_and_unref(d, &error_fatal);
|
||||
+
|
||||
+ if (!(kvm_enabled() && kvm_irqchip_in_kernel())) {
|
||||
+ /* Connect pch_msi irqs to extioi */
|
||||
for (i = 0; i < num; i++) {
|
||||
- /* Connect pch_msi irqs to extioi */
|
||||
qdev_connect_gpio_out(DEVICE(d), i,
|
||||
qdev_get_gpio_in(extioi, i + start));
|
||||
}
|
||||
}
|
||||
|
||||
+ sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
|
||||
virt_devices_init(pch_pic, lvms, &pch_pic_phandle, &pch_msi_phandle);
|
||||
}
|
||||
|
||||
diff --git a/include/hw/intc/loongarch_pch_msi.h b/include/hw/intc/loongarch_pch_msi.h
|
||||
index b8586fb3b6..fd4ea97a83 100644
|
||||
--- a/include/hw/intc/loongarch_pch_msi.h
|
||||
+++ b/include/hw/intc/loongarch_pch_msi.h
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
-#define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi"
|
||||
+#define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHMSI, LOONGARCH_PCH_MSI)
|
||||
|
||||
/* MSI irq start from 32 to 255 */
|
||||
--
|
||||
2.39.1
|
||||
|
||||
487
hw-loongarch-Add-KVM-pch-pic-device-support.patch
Normal file
487
hw-loongarch-Add-KVM-pch-pic-device-support.patch
Normal file
@ -0,0 +1,487 @@
|
||||
From 30f88e80a47d9bcde08c44c0d752c22c11f2224c Mon Sep 17 00:00:00 2001
|
||||
From: gaosong <gaosong@loongson.cn>
|
||||
Date: Sun, 8 Sep 2024 10:13:29 +0800
|
||||
Subject: [PATCH 74/78] hw/loongarch: Add KVM pch pic device support
|
||||
|
||||
Added pch_pic interrupt controller for kvm emulation.
|
||||
The main process is to send the command word for
|
||||
creating an pch_pic device to the kernel,
|
||||
Delivers the pch pic interrupt controller configuration
|
||||
register base address to the kernel.
|
||||
When the VM is saved, the ioctl obtains the pch_pic
|
||||
interrupt controller data in the kernel and saves it.
|
||||
When the VM is recovered, the saved data is sent to the kernel.
|
||||
|
||||
Signed-off-by: gaosong <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/intc/Kconfig | 3 +
|
||||
hw/intc/loongarch_pch_pic.c | 24 +++-
|
||||
hw/intc/loongarch_pch_pic_kvm.c | 189 ++++++++++++++++++++++++++++
|
||||
hw/intc/meson.build | 1 +
|
||||
hw/loongarch/Kconfig | 1 +
|
||||
hw/loongarch/virt.c | 70 ++++++-----
|
||||
include/hw/intc/loongarch_pch_pic.h | 51 +++++++-
|
||||
linux-headers/linux/kvm.h | 2 +
|
||||
8 files changed, 303 insertions(+), 38 deletions(-)
|
||||
create mode 100644 hw/intc/loongarch_pch_pic_kvm.c
|
||||
|
||||
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
|
||||
index f1e8bd2fc9..91c7aa668e 100644
|
||||
--- a/hw/intc/Kconfig
|
||||
+++ b/hw/intc/Kconfig
|
||||
@@ -100,6 +100,9 @@ config LOONGARCH_PCH_PIC
|
||||
bool
|
||||
select UNIMP
|
||||
|
||||
+config LOONGARCH_PCH_PIC_KVM
|
||||
+ bool
|
||||
+
|
||||
config LOONGARCH_PCH_MSI
|
||||
select MSI_NONBROKEN
|
||||
bool
|
||||
diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
|
||||
index 6aa4cadfa4..beb4ac188d 100644
|
||||
--- a/hw/intc/loongarch_pch_pic.c
|
||||
+++ b/hw/intc/loongarch_pch_pic.c
|
||||
@@ -16,19 +16,28 @@
|
||||
#include "migration/vmstate.h"
|
||||
#include "trace.h"
|
||||
#include "qapi/error.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
|
||||
static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int level)
|
||||
{
|
||||
uint64_t val;
|
||||
int irq;
|
||||
+ int kvm_irq;
|
||||
|
||||
if (level) {
|
||||
val = mask & s->intirr & ~s->int_mask;
|
||||
if (val) {
|
||||
irq = ctz64(val);
|
||||
s->intisr |= MAKE_64BIT_MASK(irq, 1);
|
||||
- qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
|
||||
- }
|
||||
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
+ kvm_irq = (
|
||||
+ KVM_LOONGARCH_IRQ_TYPE_IOAPIC << KVM_LOONGARCH_IRQ_TYPE_SHIFT)
|
||||
+ | (0 << KVM_LOONGARCH_IRQ_VCPU_SHIFT) | s->htmsi_vector[irq];
|
||||
+ kvm_set_irq(kvm_state, kvm_irq, !!level);
|
||||
+ } else {
|
||||
+ qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
|
||||
+ }
|
||||
+ }
|
||||
} else {
|
||||
/*
|
||||
* intirr means requested pending irq
|
||||
@@ -38,8 +47,15 @@ static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int level)
|
||||
if (val) {
|
||||
irq = ctz64(val);
|
||||
s->intisr &= ~MAKE_64BIT_MASK(irq, 1);
|
||||
- qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);
|
||||
- }
|
||||
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
+ kvm_irq = (
|
||||
+ KVM_LOONGARCH_IRQ_TYPE_IOAPIC << KVM_LOONGARCH_IRQ_TYPE_SHIFT)
|
||||
+ | (0 << KVM_LOONGARCH_IRQ_VCPU_SHIFT) | s->htmsi_vector[irq];
|
||||
+ kvm_set_irq(kvm_state, kvm_irq, !!level);
|
||||
+ } else {
|
||||
+ qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/hw/intc/loongarch_pch_pic_kvm.c b/hw/intc/loongarch_pch_pic_kvm.c
|
||||
new file mode 100644
|
||||
index 0000000000..8f66d9a01f
|
||||
--- /dev/null
|
||||
+++ b/hw/intc/loongarch_pch_pic_kvm.c
|
||||
@@ -0,0 +1,189 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * LoongArch kvm pch pic interrupt support
|
||||
+ *
|
||||
+ * Copyright (C) 2024 Loongson Technology Corporation Limited
|
||||
+ */
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "hw/qdev-properties.h"
|
||||
+#include "qemu/typedefs.h"
|
||||
+#include "hw/intc/loongarch_pch_pic.h"
|
||||
+#include "hw/sysbus.h"
|
||||
+#include "linux/kvm.h"
|
||||
+#include "migration/vmstate.h"
|
||||
+#include "qapi/error.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
+#include "hw/loongarch/virt.h"
|
||||
+#include "hw/pci-host/ls7a.h"
|
||||
+#include "qemu/error-report.h"
|
||||
+
|
||||
+static void kvm_pch_pic_access_regs(int fd, uint64_t addr,
|
||||
+ void *val, int is_write)
|
||||
+{
|
||||
+ kvm_device_access(fd, KVM_DEV_LOONGARCH_PCH_PIC_GRP_REGS,
|
||||
+ addr, val, is_write, &error_abort);
|
||||
+}
|
||||
+
|
||||
+static int kvm_loongarch_pch_pic_pre_save(void *opaque)
|
||||
+{
|
||||
+ KVMLoongArchPCHPIC *s = (KVMLoongArchPCHPIC *)opaque;
|
||||
+ KVMLoongArchPCHPICClass *class = KVM_LOONGARCH_PCH_PIC_GET_CLASS(s);
|
||||
+ int fd = class->dev_fd;
|
||||
+
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_MASK_START,
|
||||
+ (void *)&s->int_mask, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_HTMSI_EN_START,
|
||||
+ (void *)&s->htmsi_en, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_EDGE_START,
|
||||
+ (void *)&s->intedge, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_AUTO_CTRL0_START,
|
||||
+ (void *)&s->auto_crtl0, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_AUTO_CTRL1_START,
|
||||
+ (void *)&s->auto_crtl1, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_ROUTE_ENTRY_START,
|
||||
+ (void *)s->route_entry, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_HTMSI_VEC_START,
|
||||
+ (void *)s->htmsi_vector, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_INT_IRR_START,
|
||||
+ (void *)&s->intirr, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_INT_ISR_START,
|
||||
+ (void *)&s->intisr, false);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_POLARITY_START,
|
||||
+ (void *)&s->int_polarity, false);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int kvm_loongarch_pch_pic_post_load(void *opaque, int version_id)
|
||||
+{
|
||||
+ KVMLoongArchPCHPIC *s = (KVMLoongArchPCHPIC *)opaque;
|
||||
+ KVMLoongArchPCHPICClass *class = KVM_LOONGARCH_PCH_PIC_GET_CLASS(s);
|
||||
+ int fd = class->dev_fd;
|
||||
+
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_MASK_START,
|
||||
+ (void *)&s->int_mask, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_HTMSI_EN_START,
|
||||
+ (void *)&s->htmsi_en, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_EDGE_START,
|
||||
+ (void *)&s->intedge, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_AUTO_CTRL0_START,
|
||||
+ (void *)&s->auto_crtl0, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_AUTO_CTRL1_START,
|
||||
+ (void *)&s->auto_crtl1, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_ROUTE_ENTRY_START,
|
||||
+ (void *)s->route_entry, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_HTMSI_VEC_START,
|
||||
+ (void *)s->htmsi_vector, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_INT_IRR_START,
|
||||
+ (void *)&s->intirr, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_INT_ISR_START,
|
||||
+ (void *)&s->intisr, true);
|
||||
+ kvm_pch_pic_access_regs(fd, PCH_PIC_POLARITY_START,
|
||||
+ (void *)&s->int_polarity, true);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void kvm_pch_pic_handler(void *opaque, int irq, int level)
|
||||
+{
|
||||
+ int kvm_irq;
|
||||
+
|
||||
+ if (kvm_enabled()) {
|
||||
+ kvm_irq = \
|
||||
+ (KVM_LOONGARCH_IRQ_TYPE_IOAPIC << KVM_LOONGARCH_IRQ_TYPE_SHIFT)
|
||||
+ | (0 << KVM_LOONGARCH_IRQ_VCPU_SHIFT) | irq;
|
||||
+ kvm_set_irq(kvm_state, kvm_irq, !!level);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void kvm_loongarch_pch_pic_realize(DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ KVMLoongArchPCHPICClass *pch_pic_class =
|
||||
+ KVM_LOONGARCH_PCH_PIC_GET_CLASS(dev);
|
||||
+ struct kvm_create_device cd = {0};
|
||||
+ uint64_t pch_pic_base = VIRT_PCH_REG_BASE;
|
||||
+ Error *err = NULL;
|
||||
+ int ret;
|
||||
+
|
||||
+ pch_pic_class->parent_realize(dev, &err);
|
||||
+ if (err) {
|
||||
+ error_propagate(errp, err);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!pch_pic_class->is_created) {
|
||||
+ cd.type = KVM_DEV_TYPE_LA_PCH_PIC;
|
||||
+ ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
|
||||
+ if (ret < 0) {
|
||||
+ error_setg_errno(errp, errno,
|
||||
+ "Creating the KVM pch pic device failed");
|
||||
+ return;
|
||||
+ }
|
||||
+ pch_pic_class->is_created = true;
|
||||
+ pch_pic_class->dev_fd = cd.fd;
|
||||
+ fprintf(stdout, "Create LoongArch pch pic irqchip in KVM done!\n");
|
||||
+
|
||||
+ ret = kvm_device_access(cd.fd, KVM_DEV_LOONGARCH_PCH_PIC_GRP_CTRL,
|
||||
+ KVM_DEV_LOONGARCH_PCH_PIC_CTRL_INIT,
|
||||
+ &pch_pic_base, true, NULL);
|
||||
+ if (ret < 0) {
|
||||
+ error_report(
|
||||
+ "KVM EXTIOI: failed to set the base address of EXTIOI");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
+ qdev_init_gpio_in(dev, kvm_pch_pic_handler, VIRT_PCH_PIC_IRQ_NUM);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static const VMStateDescription vmstate_kvm_loongarch_pch_pic = {
|
||||
+ .name = TYPE_LOONGARCH_PCH_PIC,
|
||||
+ .version_id = 1,
|
||||
+ .minimum_version_id = 1,
|
||||
+ .pre_save = kvm_loongarch_pch_pic_pre_save,
|
||||
+ .post_load = kvm_loongarch_pch_pic_post_load,
|
||||
+ .fields = (const VMStateField[]) {
|
||||
+ VMSTATE_UINT64(int_mask, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT64(htmsi_en, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT64(intedge, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT64(intclr, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT64(auto_crtl0, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT64(auto_crtl1, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT8_ARRAY(route_entry, KVMLoongArchPCHPIC, 64),
|
||||
+ VMSTATE_UINT8_ARRAY(htmsi_vector, KVMLoongArchPCHPIC, 64),
|
||||
+ VMSTATE_UINT64(last_intirr, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT64(intirr, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT64(intisr, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_UINT64(int_polarity, KVMLoongArchPCHPIC),
|
||||
+ VMSTATE_END_OF_LIST()
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+
|
||||
+static void kvm_loongarch_pch_pic_class_init(ObjectClass *oc, void *data)
|
||||
+{
|
||||
+ DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
+ KVMLoongArchPCHPICClass *pch_pic_class = KVM_LOONGARCH_PCH_PIC_CLASS(oc);
|
||||
+
|
||||
+ pch_pic_class->parent_realize = dc->realize;
|
||||
+ dc->realize = kvm_loongarch_pch_pic_realize;
|
||||
+ pch_pic_class->is_created = false;
|
||||
+ dc->vmsd = &vmstate_kvm_loongarch_pch_pic;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static const TypeInfo kvm_loongarch_pch_pic_info = {
|
||||
+ .name = TYPE_KVM_LOONGARCH_PCH_PIC,
|
||||
+ .parent = TYPE_SYS_BUS_DEVICE,
|
||||
+ .instance_size = sizeof(KVMLoongArchPCHPIC),
|
||||
+ .class_size = sizeof(KVMLoongArchPCHPICClass),
|
||||
+ .class_init = kvm_loongarch_pch_pic_class_init,
|
||||
+};
|
||||
+
|
||||
+static void kvm_loongarch_pch_pic_register_types(void)
|
||||
+{
|
||||
+ type_register_static(&kvm_loongarch_pch_pic_info);
|
||||
+}
|
||||
+
|
||||
+type_init(kvm_loongarch_pch_pic_register_types)
|
||||
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
|
||||
index a37d7da8aa..49b4501315 100644
|
||||
--- a/hw/intc/meson.build
|
||||
+++ b/hw/intc/meson.build
|
||||
@@ -75,3 +75,4 @@ specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: files('loongarch_pch_
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c'))
|
||||
specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI_KVM', if_true: files('loongarch_extioi_kvm.c'))
|
||||
+specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC_KVM', if_true: files('loongarch_pch_pic_kvm.c'))
|
||||
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
|
||||
index 1a47d44a64..16c854c0d5 100644
|
||||
--- a/hw/loongarch/Kconfig
|
||||
+++ b/hw/loongarch/Kconfig
|
||||
@@ -15,6 +15,7 @@ config LOONGARCH_VIRT
|
||||
select LOONGARCH_PCH_MSI
|
||||
select LOONGARCH_EXTIOI
|
||||
select LOONGARCH_IPI_KVM if KVM
|
||||
+ select LOONGARCH_PCH_PIC_KVM if KVM
|
||||
select LOONGARCH_EXTIOI_KVM if KVM
|
||||
select LS7A_RTC
|
||||
select SMBIOS
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 71e2a3735c..270dcfd38f 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -901,45 +901,49 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
||||
/* Add Extend I/O Interrupt Controller node */
|
||||
fdt_add_eiointc_node(lvms, &cpuintc_phandle, &eiointc_phandle);
|
||||
|
||||
- pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
|
||||
- num = VIRT_PCH_PIC_IRQ_NUM;
|
||||
- qdev_prop_set_uint32(pch_pic, "pch_pic_irq_num", num);
|
||||
- d = SYS_BUS_DEVICE(pch_pic);
|
||||
- sysbus_realize_and_unref(d, &error_fatal);
|
||||
- memory_region_add_subregion(get_system_memory(), VIRT_IOAPIC_REG_BASE,
|
||||
- sysbus_mmio_get_region(d, 0));
|
||||
- memory_region_add_subregion(get_system_memory(),
|
||||
- VIRT_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET,
|
||||
- sysbus_mmio_get_region(d, 1));
|
||||
- memory_region_add_subregion(get_system_memory(),
|
||||
- VIRT_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO,
|
||||
- sysbus_mmio_get_region(d, 2));
|
||||
-
|
||||
- /* Connect pch_pic irqs to extioi */
|
||||
- for (i = 0; i < num; i++) {
|
||||
- qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i));
|
||||
- }
|
||||
-
|
||||
/* Add PCH PIC node */
|
||||
fdt_add_pch_pic_node(lvms, &eiointc_phandle, &pch_pic_phandle);
|
||||
|
||||
- pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
|
||||
- start = num;
|
||||
- num = EXTIOI_IRQS - start;
|
||||
- qdev_prop_set_uint32(pch_msi, "msi_irq_base", start);
|
||||
- qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
|
||||
- d = SYS_BUS_DEVICE(pch_msi);
|
||||
- sysbus_realize_and_unref(d, &error_fatal);
|
||||
- sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
|
||||
- for (i = 0; i < num; i++) {
|
||||
- /* Connect pch_msi irqs to extioi */
|
||||
- qdev_connect_gpio_out(DEVICE(d), i,
|
||||
- qdev_get_gpio_in(extioi, i + start));
|
||||
- }
|
||||
-
|
||||
/* Add PCH MSI node */
|
||||
fdt_add_pch_msi_node(lvms, &eiointc_phandle, &pch_msi_phandle);
|
||||
|
||||
+ if (kvm_enabled() && kvm_irqchip_in_kernel()) {
|
||||
+ pch_pic = qdev_new(TYPE_KVM_LOONGARCH_PCH_PIC);
|
||||
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(pch_pic), &error_fatal);
|
||||
+ } else {
|
||||
+ pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
|
||||
+ num = VIRT_PCH_PIC_IRQ_NUM;
|
||||
+ qdev_prop_set_uint32(pch_pic, "pch_pic_irq_num", num);
|
||||
+ d = SYS_BUS_DEVICE(pch_pic);
|
||||
+ sysbus_realize_and_unref(d, &error_fatal);
|
||||
+ memory_region_add_subregion(get_system_memory(), VIRT_IOAPIC_REG_BASE,
|
||||
+ sysbus_mmio_get_region(d, 0));
|
||||
+ memory_region_add_subregion(get_system_memory(),
|
||||
+ VIRT_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET,
|
||||
+ sysbus_mmio_get_region(d, 1));
|
||||
+ memory_region_add_subregion(get_system_memory(),
|
||||
+ VIRT_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO,
|
||||
+ sysbus_mmio_get_region(d, 2));
|
||||
+ /* Connect pch_pic irqs to extioi */
|
||||
+ for (i = 0; i < num; i++) {
|
||||
+ qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i));
|
||||
+ }
|
||||
+
|
||||
+ pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
|
||||
+ start = num;
|
||||
+ num = EXTIOI_IRQS - start;
|
||||
+ qdev_prop_set_uint32(pch_msi, "msi_irq_base", start);
|
||||
+ qdev_prop_set_uint32(pch_msi, "msi_irq_num", num);
|
||||
+ d = SYS_BUS_DEVICE(pch_msi);
|
||||
+ sysbus_realize_and_unref(d, &error_fatal);
|
||||
+ sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW);
|
||||
+ for (i = 0; i < num; i++) {
|
||||
+ /* Connect pch_msi irqs to extioi */
|
||||
+ qdev_connect_gpio_out(DEVICE(d), i,
|
||||
+ qdev_get_gpio_in(extioi, i + start));
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
virt_devices_init(pch_pic, lvms, &pch_pic_phandle, &pch_msi_phandle);
|
||||
}
|
||||
|
||||
diff --git a/include/hw/intc/loongarch_pch_pic.h b/include/hw/intc/loongarch_pch_pic.h
|
||||
index d5437e88f2..77f4cd74a1 100644
|
||||
--- a/include/hw/intc/loongarch_pch_pic.h
|
||||
+++ b/include/hw/intc/loongarch_pch_pic.h
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
-#define TYPE_LOONGARCH_PCH_PIC "loongarch_pch_pic"
|
||||
+#define TYPE_LOONGARCH_PCH_PIC "loongarch_pch_pic"
|
||||
+#define TYPE_KVM_LOONGARCH_PCH_PIC "loongarch_kvm_pch_pic"
|
||||
#define PCH_PIC_NAME(name) TYPE_LOONGARCH_PCH_PIC#name
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHPIC, LOONGARCH_PCH_PIC)
|
||||
|
||||
@@ -37,6 +38,19 @@ OBJECT_DECLARE_SIMPLE_TYPE(LoongArchPCHPIC, LOONGARCH_PCH_PIC)
|
||||
#define PCH_PIC_INT_POL_LO 0x3e0
|
||||
#define PCH_PIC_INT_POL_HI 0x3e4
|
||||
|
||||
+#define PCH_PIC_INT_ID_START PCH_PIC_INT_ID_LO
|
||||
+#define PCH_PIC_MASK_START PCH_PIC_INT_MASK_LO
|
||||
+#define PCH_PIC_HTMSI_EN_START PCH_PIC_HTMSI_EN_LO
|
||||
+#define PCH_PIC_EDGE_START PCH_PIC_INT_EDGE_LO
|
||||
+#define PCH_PIC_CLEAR_START PCH_PIC_INT_CLEAR_LO
|
||||
+#define PCH_PIC_AUTO_CTRL0_START PCH_PIC_AUTO_CTRL0_LO
|
||||
+#define PCH_PIC_AUTO_CTRL1_START PCH_PIC_AUTO_CTRL1_LO
|
||||
+#define PCH_PIC_ROUTE_ENTRY_START PCH_PIC_ROUTE_ENTRY_OFFSET
|
||||
+#define PCH_PIC_HTMSI_VEC_START PCH_PIC_HTMSI_VEC_OFFSET
|
||||
+#define PCH_PIC_INT_IRR_START 0x380
|
||||
+#define PCH_PIC_INT_ISR_START PCH_PIC_INT_STATUS_LO
|
||||
+#define PCH_PIC_POLARITY_START PCH_PIC_INT_POL_LO
|
||||
+
|
||||
#define STATUS_LO_START 0
|
||||
#define STATUS_HI_START 0x4
|
||||
#define POL_LO_START 0x40
|
||||
@@ -67,3 +81,38 @@ struct LoongArchPCHPIC {
|
||||
MemoryRegion iomem8;
|
||||
unsigned int irq_num;
|
||||
};
|
||||
+
|
||||
+struct KVMLoongArchPCHPIC {
|
||||
+ SysBusDevice parent_obj;
|
||||
+ uint64_t int_mask; /*0x020 interrupt mask register*/
|
||||
+ uint64_t htmsi_en; /*0x040 1=msi*/
|
||||
+ uint64_t intedge; /*0x060 edge=1 level =0*/
|
||||
+ uint64_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/
|
||||
+ uint64_t auto_crtl0; /*0x0c0*/
|
||||
+ uint64_t auto_crtl1; /*0x0e0*/
|
||||
+ uint64_t last_intirr; /* edge detection */
|
||||
+ uint64_t intirr; /* 0x380 interrupt request register */
|
||||
+ uint64_t intisr; /* 0x3a0 interrupt service register */
|
||||
+ /*
|
||||
+ * 0x3e0 interrupt level polarity selection
|
||||
+ * register 0 for high level trigger
|
||||
+ */
|
||||
+ uint64_t int_polarity;
|
||||
+
|
||||
+ uint8_t route_entry[64]; /*0x100 - 0x138*/
|
||||
+ uint8_t htmsi_vector[64]; /*0x200 - 0x238*/
|
||||
+};
|
||||
+typedef struct KVMLoongArchPCHPIC KVMLoongArchPCHPIC;
|
||||
+DECLARE_INSTANCE_CHECKER(KVMLoongArchPCHPIC, KVM_LOONGARCH_PCH_PIC,
|
||||
+ TYPE_KVM_LOONGARCH_PCH_PIC)
|
||||
+
|
||||
+struct KVMLoongArchPCHPICClass {
|
||||
+ SysBusDeviceClass parent_class;
|
||||
+ DeviceRealize parent_realize;
|
||||
+
|
||||
+ bool is_created;
|
||||
+ int dev_fd;
|
||||
+};
|
||||
+typedef struct KVMLoongArchPCHPICClass KVMLoongArchPCHPICClass;
|
||||
+DECLARE_CLASS_CHECKERS(KVMLoongArchPCHPICClass, KVM_LOONGARCH_PCH_PIC,
|
||||
+ TYPE_KVM_LOONGARCH_PCH_PIC)
|
||||
diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
|
||||
index 0c0b82d1ef..887f8268e7 100644
|
||||
--- a/linux-headers/linux/kvm.h
|
||||
+++ b/linux-headers/linux/kvm.h
|
||||
@@ -1470,6 +1470,8 @@ enum kvm_device_type {
|
||||
#define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME
|
||||
KVM_DEV_TYPE_RISCV_AIA,
|
||||
#define KVM_DEV_TYPE_RISCV_AIA KVM_DEV_TYPE_RISCV_AIA
|
||||
+ KVM_DEV_TYPE_LA_PCH_PIC = 0x100,
|
||||
+#define KVM_DEV_TYPE_LA_PCH_PIC KVM_DEV_TYPE_LA_PCH_PIC
|
||||
KVM_DEV_TYPE_LA_IPI,
|
||||
#define KVM_DEV_TYPE_LA_IPI KVM_DEV_TYPE_LA_IPI
|
||||
KVM_DEV_TYPE_LA_EXTIOI,
|
||||
--
|
||||
2.39.1
|
||||
|
||||
49
hw-loongarch-Add-VM-mode-in-IOCSR-feature-register-i.patch
Normal file
49
hw-loongarch-Add-VM-mode-in-IOCSR-feature-register-i.patch
Normal file
@ -0,0 +1,49 @@
|
||||
From 0437c11a20b3c66882770e468518d33ff71a932a Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Tue, 14 May 2024 10:51:09 +0800
|
||||
Subject: [PATCH 22/78] hw/loongarch: Add VM mode in IOCSR feature register in
|
||||
kvm mode
|
||||
|
||||
If VM runs in kvm mode, VM mode is added in IOCSR feature register.
|
||||
So guest can detect kvm hypervisor type and enable possible pv functions.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240514025109.3238398-1-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 8 ++++----
|
||||
1 file changed, 4 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index e82e3b6792..c3514f9293 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/char/serial.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "sysemu/runstate.h"
|
||||
@@ -914,12 +915,11 @@ static MemTxResult loongarch_qemu_read(void *opaque, hwaddr addr,
|
||||
ret = 0x11ULL;
|
||||
break;
|
||||
case FEATURE_REG:
|
||||
- ret = 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
|
||||
- 1ULL << IOCSRF_CSRIPI;
|
||||
+ ret = BIT(IOCSRF_MSI) | BIT(IOCSRF_EXTIOI) | BIT(IOCSRF_CSRIPI);
|
||||
if (kvm_enabled()) {
|
||||
- ret |= 1ULL << IOCSRF_VM;
|
||||
+ ret |= BIT(IOCSRF_VM);
|
||||
}
|
||||
- break;
|
||||
+ return ret;
|
||||
case VENDOR_REG:
|
||||
ret = 0x6e6f73676e6f6f4cULL; /* "Loongson" */
|
||||
break;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
82
hw-loongarch-Add-acpi-SPCR-table-support.patch
Normal file
82
hw-loongarch-Add-acpi-SPCR-table-support.patch
Normal file
@ -0,0 +1,82 @@
|
||||
From fe22e0efe4c1c99fc876a42446cb2c87f9457afb Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Sat, 7 Sep 2024 15:30:37 +0800
|
||||
Subject: [PATCH 37/78] hw/loongarch: Add acpi SPCR table support
|
||||
|
||||
Serial port console redirection table can be used for default serial
|
||||
port selection, like chosen stdout-path selection with FDT method.
|
||||
|
||||
With acpi SPCR table added, early debug console can be parsed from
|
||||
SPCR table with simple kernel parameter earlycon rather than
|
||||
earlycon=uart,mmio,0x1fe001e0
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240907073037.243353-1-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/acpi-build.c | 40 +++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 40 insertions(+)
|
||||
|
||||
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
|
||||
index 33a92223d8..bcdec2e1cb 100644
|
||||
--- a/hw/loongarch/acpi-build.c
|
||||
+++ b/hw/loongarch/acpi-build.c
|
||||
@@ -242,6 +242,44 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Serial Port Console Redirection Table (SPCR)
|
||||
+ * https://learn.microsoft.com/en-us/windows-hardware/drivers/serports/serial-port-console-redirection-table
|
||||
+ */
|
||||
+static void
|
||||
+spcr_setup(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
+{
|
||||
+ LoongArchVirtMachineState *lvms;
|
||||
+ AcpiSpcrData serial = {
|
||||
+ .interface_type = 0, /* 16550 compatible */
|
||||
+ .base_addr.id = AML_AS_SYSTEM_MEMORY,
|
||||
+ .base_addr.width = 32,
|
||||
+ .base_addr.offset = 0,
|
||||
+ .base_addr.size = 1,
|
||||
+ .base_addr.addr = VIRT_UART_BASE,
|
||||
+ .interrupt_type = 0, /* Interrupt not supported */
|
||||
+ .pc_interrupt = 0,
|
||||
+ .interrupt = VIRT_UART_IRQ,
|
||||
+ .baud_rate = 7, /* 115200 */
|
||||
+ .parity = 0,
|
||||
+ .stop_bits = 1,
|
||||
+ .flow_control = 0,
|
||||
+ .terminal_type = 3, /* ANSI */
|
||||
+ .language = 0, /* Language */
|
||||
+ .pci_device_id = 0xffff, /* not a PCI device*/
|
||||
+ .pci_vendor_id = 0xffff, /* not a PCI device*/
|
||||
+ .pci_bus = 0,
|
||||
+ .pci_device = 0,
|
||||
+ .pci_function = 0,
|
||||
+ .pci_flags = 0,
|
||||
+ .pci_segment = 0,
|
||||
+ };
|
||||
+
|
||||
+ lvms = LOONGARCH_VIRT_MACHINE(machine);
|
||||
+ build_spcr(table_data, linker, &serial, 2, lvms->oem_id,
|
||||
+ lvms->oem_table_id);
|
||||
+}
|
||||
+
|
||||
typedef
|
||||
struct AcpiBuildState {
|
||||
/* Copy of table in RAM (for patching). */
|
||||
@@ -484,6 +522,8 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_srat(tables_blob, tables->linker, machine);
|
||||
+ acpi_add_table(table_offsets, tables_blob);
|
||||
+ spcr_setup(tables_blob, tables->linker, machine);
|
||||
|
||||
if (machine->numa_state->num_nodes) {
|
||||
if (machine->numa_state->have_numa_distance) {
|
||||
--
|
||||
2.39.1
|
||||
|
||||
56
hw-loongarch-Add-cells-missing-from-rtc-node.patch
Normal file
56
hw-loongarch-Add-cells-missing-from-rtc-node.patch
Normal file
@ -0,0 +1,56 @@
|
||||
From 7266141c658cd00426922534a7de4dd5d89486b2 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:51 +0800
|
||||
Subject: [PATCH 16/78] hw/loongarch: Add cells missing from rtc node
|
||||
|
||||
rtc node need interrupts and interrupt-parent cells.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-18-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 12 +++++++++---
|
||||
1 file changed, 9 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index a6aea52ebb..0972ebd150 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -258,7 +258,8 @@ static void fdt_add_flash_node(LoongArchMachineState *lams)
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
-static void fdt_add_rtc_node(LoongArchMachineState *lams)
|
||||
+static void fdt_add_rtc_node(LoongArchMachineState *lams,
|
||||
+ uint32_t *pch_pic_phandle)
|
||||
{
|
||||
char *nodename;
|
||||
hwaddr base = VIRT_RTC_REG_BASE;
|
||||
@@ -267,8 +268,13 @@ static void fdt_add_rtc_node(LoongArchMachineState *lams)
|
||||
|
||||
nodename = g_strdup_printf("/rtc@%" PRIx64, base);
|
||||
qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
- qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "loongson,ls7a-rtc");
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
|
||||
+ "loongson,ls7a-rtc");
|
||||
qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base, 2, size);
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
||||
+ VIRT_RTC_IRQ - VIRT_GSI_BASE , 0x4);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
|
||||
+ *pch_pic_phandle);
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
@@ -677,7 +683,7 @@ static void loongarch_devices_init(DeviceState *pch_pic,
|
||||
sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE,
|
||||
qdev_get_gpio_in(pch_pic,
|
||||
VIRT_RTC_IRQ - VIRT_GSI_BASE));
|
||||
- fdt_add_rtc_node(lams);
|
||||
+ fdt_add_rtc_node(lams, pch_pic_phandle);
|
||||
|
||||
/* acpi ged */
|
||||
lams->acpi_ged = create_acpi_ged(pch_pic, lams);
|
||||
--
|
||||
2.39.1
|
||||
|
||||
52
hw-loongarch-Add-cells-missing-from-uart-node.patch
Normal file
52
hw-loongarch-Add-cells-missing-from-uart-node.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 33994eff45e75e91acf0a4753fec77ad0027e4dd Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:50 +0800
|
||||
Subject: [PATCH 15/78] hw/loongarch: Add cells missing from uart node
|
||||
|
||||
uart node need interrupts and interrupt-parent cells.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-17-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 9 +++++++--
|
||||
1 file changed, 7 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index ff9513034b..a6aea52ebb 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -272,7 +272,8 @@ static void fdt_add_rtc_node(LoongArchMachineState *lams)
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
-static void fdt_add_uart_node(LoongArchMachineState *lams)
|
||||
+static void fdt_add_uart_node(LoongArchMachineState *lams,
|
||||
+ uint32_t *pch_pic_phandle)
|
||||
{
|
||||
char *nodename;
|
||||
hwaddr base = VIRT_UART_BASE;
|
||||
@@ -285,6 +286,10 @@ static void fdt_add_uart_node(LoongArchMachineState *lams)
|
||||
qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0x0, base, 0x0, size);
|
||||
qemu_fdt_setprop_cell(ms->fdt, nodename, "clock-frequency", 100000000);
|
||||
qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
||||
+ VIRT_UART_IRQ - VIRT_GSI_BASE, 0x4);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
|
||||
+ *pch_pic_phandle);
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
@@ -657,7 +662,7 @@ static void loongarch_devices_init(DeviceState *pch_pic,
|
||||
qdev_get_gpio_in(pch_pic,
|
||||
VIRT_UART_IRQ - VIRT_GSI_BASE),
|
||||
115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
|
||||
- fdt_add_uart_node(lams);
|
||||
+ fdt_add_uart_node(lams, pch_pic_phandle);
|
||||
|
||||
/* Network init */
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
--
|
||||
2.39.1
|
||||
|
||||
117
hw-loongarch-Add-init_cmdline.patch
Normal file
117
hw-loongarch-Add-init_cmdline.patch
Normal file
@ -0,0 +1,117 @@
|
||||
From 206b799cb8c218c744f4dcdaf161d11f14c21e0f Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:38 +0800
|
||||
Subject: [PATCH 04/78] hw/loongarch: Add init_cmdline
|
||||
|
||||
Add init_cmline and set boot_info->a0, a1
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-5-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 30 ++++++++++++++++++++++++++++++
|
||||
include/hw/loongarch/virt.h | 2 ++
|
||||
target/loongarch/cpu.h | 2 ++
|
||||
3 files changed, 34 insertions(+)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index fb6effbaff..127085bcc4 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -63,6 +63,16 @@ static const unsigned int slave_boot_code[] = {
|
||||
0x4c000020, /* jirl $zero, $ra,0 */
|
||||
};
|
||||
|
||||
+static void init_cmdline(struct loongarch_boot_info *info, void *p, void *start)
|
||||
+{
|
||||
+ hwaddr cmdline_addr = p - start;
|
||||
+
|
||||
+ info->a0 = 1;
|
||||
+ info->a1 = cmdline_addr;
|
||||
+
|
||||
+ memcpy(p, info->kernel_cmdline, COMMAND_LINE_SIZE);
|
||||
+}
|
||||
+
|
||||
static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
|
||||
@@ -121,6 +131,10 @@ static void reset_load_elf(void *opaque)
|
||||
|
||||
cpu_reset(CPU(cpu));
|
||||
if (env->load_elf) {
|
||||
+ if (cpu == LOONGARCH_CPU(first_cpu)) {
|
||||
+ env->gpr[4] = env->boot_info->a0;
|
||||
+ env->gpr[5] = env->boot_info->a1;
|
||||
+ }
|
||||
cpu_set_pc(CPU(cpu), env->elf_address);
|
||||
}
|
||||
}
|
||||
@@ -158,8 +172,17 @@ static void loongarch_firmware_boot(LoongArchMachineState *lams,
|
||||
fw_cfg_add_kernel_info(info, lams->fw_cfg);
|
||||
}
|
||||
|
||||
+static void init_boot_rom(struct loongarch_boot_info *info, void *p)
|
||||
+{
|
||||
+ void *start = p;
|
||||
+
|
||||
+ init_cmdline(info, p, start);
|
||||
+ p += COMMAND_LINE_SIZE;
|
||||
+}
|
||||
+
|
||||
static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
{
|
||||
+ void *p, *bp;
|
||||
int64_t kernel_addr = 0;
|
||||
LoongArchCPU *lacpu;
|
||||
CPUState *cs;
|
||||
@@ -173,6 +196,12 @@ static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Load cmdline and system tables at [0 - 1 MiB] */
|
||||
+ p = g_malloc0(1 * MiB);
|
||||
+ bp = p;
|
||||
+ init_boot_rom(info, p);
|
||||
+ rom_add_blob_fixed_as("boot_info", bp, 1 * MiB, 0, &address_space_memory);
|
||||
+
|
||||
/* Load slave boot code at pflash0 . */
|
||||
void *boot_code = g_malloc0(VIRT_FLASH0_SIZE);
|
||||
memcpy(boot_code, &slave_boot_code, sizeof(slave_boot_code));
|
||||
@@ -190,6 +219,7 @@ static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
}
|
||||
|
||||
g_free(boot_code);
|
||||
+ g_free(bp);
|
||||
}
|
||||
|
||||
void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info)
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 02c8234b8d..ffff075f63 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -33,6 +33,8 @@
|
||||
#define VIRT_GED_MEM_ADDR (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN)
|
||||
#define VIRT_GED_REG_ADDR (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN)
|
||||
|
||||
+#define COMMAND_LINE_SIZE 512
|
||||
+
|
||||
struct LoongArchMachineState {
|
||||
/*< private >*/
|
||||
MachineState parent_obj;
|
||||
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
|
||||
index 0ed24051af..e3a15c593f 100644
|
||||
--- a/target/loongarch/cpu.h
|
||||
+++ b/target/loongarch/cpu.h
|
||||
@@ -364,6 +364,8 @@ typedef struct CPUArchState {
|
||||
uint32_t mp_state;
|
||||
/* Store ipistate to access from this struct */
|
||||
DeviceState *ipistate;
|
||||
+
|
||||
+ struct loongarch_boot_info *boot_info;
|
||||
#endif
|
||||
struct {
|
||||
uint64_t guest_addr;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
64
hw-loongarch-Add-load-initrd.patch
Normal file
64
hw-loongarch-Add-load-initrd.patch
Normal file
@ -0,0 +1,64 @@
|
||||
From 02c5f52da7f9458c0fc41e43f181f6e9b7101b57 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:36 +0800
|
||||
Subject: [PATCH 02/78] hw/loongarch: Add load initrd
|
||||
|
||||
we load initrd ramdisk after kernel_high address
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-3-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 28 +++++++++++++++++++++++++++-
|
||||
1 file changed, 27 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index 9feed17db3..a5135fe542 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -22,7 +22,8 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
|
||||
|
||||
static int64_t load_kernel_info(struct loongarch_boot_info *info)
|
||||
{
|
||||
- uint64_t kernel_entry, kernel_low, kernel_high;
|
||||
+ uint64_t kernel_entry, kernel_low, kernel_high, initrd_size;
|
||||
+ ram_addr_t initrd_offset;
|
||||
ssize_t kernel_size;
|
||||
|
||||
kernel_size = load_elf(info->kernel_filename, NULL,
|
||||
@@ -37,6 +38,31 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
|
||||
load_elf_strerror(kernel_size));
|
||||
exit(1);
|
||||
}
|
||||
+
|
||||
+ if (info->initrd_filename) {
|
||||
+ initrd_size = get_image_size(info->initrd_filename);
|
||||
+ if (initrd_size > 0) {
|
||||
+ initrd_offset = ROUND_UP(kernel_high + 4 * kernel_size, 64 * KiB);
|
||||
+
|
||||
+ if (initrd_offset + initrd_size > info->ram_size) {
|
||||
+ error_report("memory too small for initial ram disk '%s'",
|
||||
+ info->initrd_filename);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+
|
||||
+ initrd_size = load_image_targphys(info->initrd_filename, initrd_offset,
|
||||
+ info->ram_size - initrd_offset);
|
||||
+ }
|
||||
+
|
||||
+ if (initrd_size == (target_ulong)-1) {
|
||||
+ error_report("could not load initial ram disk '%s'",
|
||||
+ info->initrd_filename);
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ } else {
|
||||
+ initrd_size = 0;
|
||||
+ }
|
||||
+
|
||||
return kernel_entry;
|
||||
}
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
103
hw-loongarch-Add-slave-cpu-boot_code.patch
Normal file
103
hw-loongarch-Add-slave-cpu-boot_code.patch
Normal file
@ -0,0 +1,103 @@
|
||||
From 2e3e7bcf92284f41c08fce29f6c6d45849721e71 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:37 +0800
|
||||
Subject: [PATCH 03/78] hw/loongarch: Add slave cpu boot_code
|
||||
|
||||
Load the slave CPU boot code at pflash0 and set
|
||||
the slave CPU elf_address to VIRT_FLASH0_BASE.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-4-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 62 ++++++++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 61 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index a5135fe542..fb6effbaff 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -15,6 +15,54 @@
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
+static const unsigned int slave_boot_code[] = {
|
||||
+ /* Configure reset ebase. */
|
||||
+ 0x0400302c, /* csrwr $t0, LOONGARCH_CSR_EENTRY */
|
||||
+
|
||||
+ /* Disable interrupt. */
|
||||
+ 0x0380100c, /* ori $t0, $zero,0x4 */
|
||||
+ 0x04000180, /* csrxchg $zero, $t0, LOONGARCH_CSR_CRMD */
|
||||
+
|
||||
+ /* Clear mailbox. */
|
||||
+ 0x1400002d, /* lu12i.w $t1, 1(0x1) */
|
||||
+ 0x038081ad, /* ori $t1, $t1, CORE_BUF_20 */
|
||||
+ 0x06481da0, /* iocsrwr.d $zero, $t1 */
|
||||
+
|
||||
+ /* Enable IPI interrupt. */
|
||||
+ 0x1400002c, /* lu12i.w $t0, 1(0x1) */
|
||||
+ 0x0400118c, /* csrxchg $t0, $t0, LOONGARCH_CSR_ECFG */
|
||||
+ 0x02fffc0c, /* addi.d $t0, $r0,-1(0xfff) */
|
||||
+ 0x1400002d, /* lu12i.w $t1, 1(0x1) */
|
||||
+ 0x038011ad, /* ori $t1, $t1, CORE_EN_OFF */
|
||||
+ 0x064819ac, /* iocsrwr.w $t0, $t1 */
|
||||
+ 0x1400002d, /* lu12i.w $t1, 1(0x1) */
|
||||
+ 0x038081ad, /* ori $t1, $t1, CORE_BUF_20 */
|
||||
+
|
||||
+ /* Wait for wakeup <.L11>: */
|
||||
+ 0x06488000, /* idle 0x0 */
|
||||
+ 0x03400000, /* andi $zero, $zero, 0x0 */
|
||||
+ 0x064809ac, /* iocsrrd.w $t0, $t1 */
|
||||
+ 0x43fff59f, /* beqz $t0, -12(0x7ffff4) # 48 <.L11> */
|
||||
+
|
||||
+ /* Read and clear IPI interrupt. */
|
||||
+ 0x1400002d, /* lu12i.w $t1, 1(0x1) */
|
||||
+ 0x064809ac, /* iocsrrd.w $t0, $t1 */
|
||||
+ 0x1400002d, /* lu12i.w $t1, 1(0x1) */
|
||||
+ 0x038031ad, /* ori $t1, $t1, CORE_CLEAR_OFF */
|
||||
+ 0x064819ac, /* iocsrwr.w $t0, $t1 */
|
||||
+
|
||||
+ /* Disable IPI interrupt. */
|
||||
+ 0x1400002c, /* lu12i.w $t0, 1(0x1) */
|
||||
+ 0x04001180, /* csrxchg $zero, $t0, LOONGARCH_CSR_ECFG */
|
||||
+
|
||||
+ /* Read mail buf and jump to specified entry */
|
||||
+ 0x1400002d, /* lu12i.w $t1, 1(0x1) */
|
||||
+ 0x038081ad, /* ori $t1, $t1, CORE_BUF_20 */
|
||||
+ 0x06480dac, /* iocsrrd.d $t0, $t1 */
|
||||
+ 0x00150181, /* move $ra, $t0 */
|
||||
+ 0x4c000020, /* jirl $zero, $ra,0 */
|
||||
+};
|
||||
+
|
||||
static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
|
||||
{
|
||||
return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
|
||||
@@ -125,11 +173,23 @@ static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Load slave boot code at pflash0 . */
|
||||
+ void *boot_code = g_malloc0(VIRT_FLASH0_SIZE);
|
||||
+ memcpy(boot_code, &slave_boot_code, sizeof(slave_boot_code));
|
||||
+ rom_add_blob_fixed("boot_code", boot_code, VIRT_FLASH0_SIZE, VIRT_FLASH0_BASE);
|
||||
+
|
||||
CPU_FOREACH(cs) {
|
||||
lacpu = LOONGARCH_CPU(cs);
|
||||
lacpu->env.load_elf = true;
|
||||
- lacpu->env.elf_address = kernel_addr;
|
||||
+ if (cs == first_cpu) {
|
||||
+ lacpu->env.elf_address = kernel_addr;
|
||||
+ } else {
|
||||
+ lacpu->env.elf_address = VIRT_FLASH0_BASE;
|
||||
+ }
|
||||
+ lacpu->env.boot_info = info;
|
||||
}
|
||||
+
|
||||
+ g_free(boot_code);
|
||||
}
|
||||
|
||||
void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info)
|
||||
--
|
||||
2.39.1
|
||||
|
||||
46
hw-loongarch-Change-the-tpm-support-by-default.patch
Normal file
46
hw-loongarch-Change-the-tpm-support-by-default.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 67c68371e457a85e460221a8c56d8dc93186f79f Mon Sep 17 00:00:00 2001
|
||||
From: Xianglai Li <lixianglai@loongson.cn>
|
||||
Date: Mon, 24 Jun 2024 11:23:00 +0800
|
||||
Subject: [PATCH 31/78] hw/loongarch: Change the tpm support by default
|
||||
|
||||
Add devices that support tpm by default,
|
||||
Fixed incomplete tpm acpi table information.
|
||||
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240624032300.999157-1-lixianglai@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
---
|
||||
hw/loongarch/Kconfig | 1 +
|
||||
hw/loongarch/acpi-build.c | 3 +++
|
||||
2 files changed, 4 insertions(+)
|
||||
|
||||
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
|
||||
index 7864050563..b2a3adb7dc 100644
|
||||
--- a/hw/loongarch/Kconfig
|
||||
+++ b/hw/loongarch/Kconfig
|
||||
@@ -7,6 +7,7 @@ config LOONGARCH_VIRT
|
||||
imply VIRTIO_VGA
|
||||
imply PCI_DEVICES
|
||||
imply NVDIMM
|
||||
+ imply TPM_TIS_SYSBUS
|
||||
select SERIAL
|
||||
select VIRTIO_PCI
|
||||
select PLATFORM_BUS
|
||||
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
|
||||
index 2555c6763c..6593476409 100644
|
||||
--- a/hw/loongarch/acpi-build.c
|
||||
+++ b/hw/loongarch/acpi-build.c
|
||||
@@ -646,6 +646,9 @@ void loongarch_acpi_setup(LoongArchVirtMachineState *lvms)
|
||||
build_state, tables.rsdp,
|
||||
ACPI_BUILD_RSDP_FILE);
|
||||
|
||||
+ fw_cfg_add_file(lvms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
|
||||
+ acpi_data_len(tables.tcpalog));
|
||||
+
|
||||
qemu_register_reset(acpi_build_reset, build_state);
|
||||
acpi_build_reset(build_state);
|
||||
vmstate_register(NULL, 0, &vmstate_acpi_build, build_state);
|
||||
--
|
||||
2.39.1
|
||||
|
||||
39
hw-loongarch-Fix-length-for-lowram-in-ACPI-SRAT.patch
Normal file
39
hw-loongarch-Fix-length-for-lowram-in-ACPI-SRAT.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 087201cd62e71801855775c3aa6395c7e1c00cee Mon Sep 17 00:00:00 2001
|
||||
From: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
Date: Tue, 20 Aug 2024 19:42:33 +0100
|
||||
Subject: [PATCH 33/78] hw/loongarch: Fix length for lowram in ACPI SRAT
|
||||
|
||||
The size of lowram should be "gap" instead of the whole node.
|
||||
|
||||
This is failing kernel's sanity check:
|
||||
|
||||
[ 0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x00000000-0xffffffff]
|
||||
[ 0.000000] ACPI: SRAT: Node 0 PXM 0 [mem 0x80000000-0x16fffffff]
|
||||
[ 0.000000] ACPI: SRAT: Node 1 PXM 1 [mem 0x170000000-0x26fffffff]
|
||||
[ 0.000000] Warning: node 0 [mem 0x00000000-0xffffffff] overlaps with itself [mem 0x80000000-0x16fffffff]
|
||||
|
||||
Fixes: fc100011f38d ("hw/loongarch: Refine acpi srat table for numa memory")
|
||||
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/acpi-build.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
|
||||
index 6593476409..1a9d25fc51 100644
|
||||
--- a/hw/loongarch/acpi-build.c
|
||||
+++ b/hw/loongarch/acpi-build.c
|
||||
@@ -218,7 +218,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
* highram: [VIRT_HIGHMEM_BASE, +(len - gap))
|
||||
*/
|
||||
if (len >= gap) {
|
||||
- build_srat_memory(table_data, base, len, i, MEM_AFFINITY_ENABLED);
|
||||
+ build_srat_memory(table_data, base, gap, i, MEM_AFFINITY_ENABLED);
|
||||
len -= gap;
|
||||
base = VIRT_HIGHMEM_BASE;
|
||||
gap = machine->ram_size - VIRT_LOWMEM_SIZE;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
169
hw-loongarch-Init-efi_boot_memmap-table.patch
Normal file
169
hw-loongarch-Init-efi_boot_memmap-table.patch
Normal file
@ -0,0 +1,169 @@
|
||||
From 0245881108803abedf50e954d34ebcfff294d1c3 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:40 +0800
|
||||
Subject: [PATCH 06/78] hw/loongarch: Init efi_boot_memmap table
|
||||
|
||||
The efi_system_table adds a efi_boot_memmap configuration table.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-7-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 40 +++++++++++++++++++++++++++++++++++++
|
||||
hw/loongarch/virt.c | 11 ++--------
|
||||
include/hw/loongarch/boot.h | 27 +++++++++++++++++++++++++
|
||||
include/hw/loongarch/virt.h | 10 ++++++++++
|
||||
4 files changed, 79 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index 59889dbc90..527fc9c0be 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -63,8 +63,41 @@ static const unsigned int slave_boot_code[] = {
|
||||
0x4c000020, /* jirl $zero, $ra,0 */
|
||||
};
|
||||
|
||||
+static inline void *guidcpy(void *dst, const void *src)
|
||||
+{
|
||||
+ return memcpy(dst, src, sizeof(efi_guid_t));
|
||||
+}
|
||||
+
|
||||
+static void init_efi_boot_memmap(struct efi_system_table *systab,
|
||||
+ void *p, void *start)
|
||||
+{
|
||||
+ unsigned i;
|
||||
+ struct efi_boot_memmap *boot_memmap = p;
|
||||
+ efi_guid_t tbl_guid = LINUX_EFI_BOOT_MEMMAP_GUID;
|
||||
+
|
||||
+ /* efi_configuration_table 1 */
|
||||
+ guidcpy(&systab->tables[0].guid, &tbl_guid);
|
||||
+ systab->tables[0].table = (struct efi_configuration_table *)(p - start);
|
||||
+ systab->nr_tables = 1;
|
||||
+
|
||||
+ boot_memmap->desc_size = sizeof(efi_memory_desc_t);
|
||||
+ boot_memmap->desc_ver = 1;
|
||||
+ boot_memmap->map_size = 0;
|
||||
+
|
||||
+ efi_memory_desc_t *map = p + sizeof(struct efi_boot_memmap);
|
||||
+ for (i = 0; i < memmap_entries; i++) {
|
||||
+ map = (void *)boot_memmap + sizeof(*map);
|
||||
+ map[i].type = memmap_table[i].type;
|
||||
+ map[i].phys_addr = ROUND_UP(memmap_table[i].address, 64 * KiB);
|
||||
+ map[i].num_pages = ROUND_DOWN(memmap_table[i].address +
|
||||
+ memmap_table[i].length - map[i].phys_addr, 64 * KiB);
|
||||
+ p += sizeof(efi_memory_desc_t);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void init_systab(struct loongarch_boot_info *info, void *p, void *start)
|
||||
{
|
||||
+ void *bp_tables_start;
|
||||
struct efi_system_table *systab = p;
|
||||
|
||||
info->a2 = p - start;
|
||||
@@ -80,6 +113,13 @@ static void init_systab(struct loongarch_boot_info *info, void *p, void *start)
|
||||
p += ROUND_UP(sizeof(struct efi_system_table), 64 * KiB);
|
||||
|
||||
systab->tables = p;
|
||||
+ bp_tables_start = p;
|
||||
+
|
||||
+ init_efi_boot_memmap(systab, p, start);
|
||||
+ p += ROUND_UP(sizeof(struct efi_boot_memmap) +
|
||||
+ sizeof(efi_memory_desc_t) * memmap_entries, 64 * KiB);
|
||||
+
|
||||
+ systab->tables = (struct efi_configuration_table *)(bp_tables_start - start);
|
||||
}
|
||||
|
||||
static void init_cmdline(struct loongarch_boot_info *info, void *p, void *start)
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index a0aee28f41..028356acf5 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -405,15 +405,8 @@ static void virt_powerdown_req(Notifier *notifier, void *opaque)
|
||||
acpi_send_event(s->acpi_ged, ACPI_POWER_DOWN_STATUS);
|
||||
}
|
||||
|
||||
-struct memmap_entry {
|
||||
- uint64_t address;
|
||||
- uint64_t length;
|
||||
- uint32_t type;
|
||||
- uint32_t reserved;
|
||||
-};
|
||||
-
|
||||
-static struct memmap_entry *memmap_table;
|
||||
-static unsigned memmap_entries;
|
||||
+struct memmap_entry *memmap_table;
|
||||
+unsigned memmap_entries;
|
||||
|
||||
static void memmap_add_entry(uint64_t address, uint64_t length, uint32_t type)
|
||||
{
|
||||
diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
|
||||
index cf0e4d4f91..76622af2e2 100644
|
||||
--- a/include/hw/loongarch/boot.h
|
||||
+++ b/include/hw/loongarch/boot.h
|
||||
@@ -21,6 +21,15 @@ typedef struct {
|
||||
uint8_t b[16];
|
||||
} efi_guid_t QEMU_ALIGNED(8);
|
||||
|
||||
+#define EFI_GUID(a, b, c, d...) (efi_guid_t){ { \
|
||||
+ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
|
||||
+ (b) & 0xff, ((b) >> 8) & 0xff, \
|
||||
+ (c) & 0xff, ((c) >> 8) & 0xff, d } }
|
||||
+
|
||||
+#define LINUX_EFI_BOOT_MEMMAP_GUID \
|
||||
+ EFI_GUID(0x800f683f, 0xd08b, 0x423a, 0xa2, 0x93, \
|
||||
+ 0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4)
|
||||
+
|
||||
struct efi_config_table {
|
||||
efi_guid_t guid;
|
||||
uint64_t *ptr;
|
||||
@@ -56,6 +65,24 @@ struct efi_system_table {
|
||||
struct efi_configuration_table *tables;
|
||||
};
|
||||
|
||||
+typedef struct {
|
||||
+ uint32_t type;
|
||||
+ uint32_t pad;
|
||||
+ uint64_t phys_addr;
|
||||
+ uint64_t virt_addr;
|
||||
+ uint64_t num_pages;
|
||||
+ uint64_t attribute;
|
||||
+} efi_memory_desc_t;
|
||||
+
|
||||
+struct efi_boot_memmap {
|
||||
+ uint64_t map_size;
|
||||
+ uint64_t desc_size;
|
||||
+ uint32_t desc_ver;
|
||||
+ uint64_t map_key;
|
||||
+ uint64_t buff_size;
|
||||
+ efi_memory_desc_t map[32];
|
||||
+};
|
||||
+
|
||||
struct loongarch_boot_info {
|
||||
uint64_t ram_size;
|
||||
const char *kernel_filename;
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index ffff075f63..2f9eaf4b0e 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -35,6 +35,16 @@
|
||||
|
||||
#define COMMAND_LINE_SIZE 512
|
||||
|
||||
+extern struct memmap_entry *memmap_table;
|
||||
+extern unsigned memmap_entries;
|
||||
+
|
||||
+struct memmap_entry {
|
||||
+ uint64_t address;
|
||||
+ uint64_t length;
|
||||
+ uint32_t type;
|
||||
+ uint32_t reserved;
|
||||
+};
|
||||
+
|
||||
struct LoongArchMachineState {
|
||||
/*< private >*/
|
||||
MachineState parent_obj;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
105
hw-loongarch-Init-efi_fdt-table.patch
Normal file
105
hw-loongarch-Init-efi_fdt-table.patch
Normal file
@ -0,0 +1,105 @@
|
||||
From 605b2b372f972fffa2d198d8dee4cf37f335559d Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:42 +0800
|
||||
Subject: [PATCH 08/78] hw/loongarch: Init efi_fdt table
|
||||
|
||||
The efi_system_table adds a efi_fdt configuration table.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-9-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 11 +++++++++++
|
||||
hw/loongarch/virt.c | 6 ++----
|
||||
include/hw/loongarch/boot.h | 4 ++++
|
||||
include/hw/loongarch/virt.h | 2 ++
|
||||
4 files changed, 19 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index c8b3e742b4..7d1630b2e7 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -113,6 +113,16 @@ static void init_efi_initrd_table(struct efi_system_table *systab,
|
||||
initrd_table->size = initrd_size;
|
||||
}
|
||||
|
||||
+static void init_efi_fdt_table(struct efi_system_table *systab)
|
||||
+{
|
||||
+ efi_guid_t tbl_guid = DEVICE_TREE_GUID;
|
||||
+
|
||||
+ /* efi_configuration_table 3 */
|
||||
+ guidcpy(&systab->tables[2].guid, &tbl_guid);
|
||||
+ systab->tables[2].table = (void *)FDT_BASE;
|
||||
+ systab->nr_tables = 3;
|
||||
+}
|
||||
+
|
||||
static void init_systab(struct loongarch_boot_info *info, void *p, void *start)
|
||||
{
|
||||
void *bp_tables_start;
|
||||
@@ -138,6 +148,7 @@ static void init_systab(struct loongarch_boot_info *info, void *p, void *start)
|
||||
sizeof(efi_memory_desc_t) * memmap_entries, 64 * KiB);
|
||||
init_efi_initrd_table(systab, p, start);
|
||||
p += ROUND_UP(sizeof(struct efi_initrd), 64 * KiB);
|
||||
+ init_efi_fdt_table(systab);
|
||||
|
||||
systab->tables = (struct efi_configuration_table *)(bp_tables_start - start);
|
||||
}
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 028356acf5..99a3dc8696 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -820,7 +820,6 @@ static void loongarch_init(MachineState *machine)
|
||||
int nb_numa_nodes = machine->numa_state->num_nodes;
|
||||
NodeInfo *numa_info = machine->numa_state->nodes;
|
||||
int i;
|
||||
- hwaddr fdt_base;
|
||||
const CPUArchIdList *possible_cpus;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
CPUState *cpu;
|
||||
@@ -949,12 +948,11 @@ static void loongarch_init(MachineState *machine)
|
||||
* Put the FDT into the memory map as a ROM image: this will ensure
|
||||
* the FDT is copied again upon reset, even if addr points into RAM.
|
||||
*/
|
||||
- fdt_base = 1 * MiB;
|
||||
qemu_fdt_dumpdtb(machine->fdt, lams->fdt_size);
|
||||
- rom_add_blob_fixed_as("fdt", machine->fdt, lams->fdt_size, fdt_base,
|
||||
+ rom_add_blob_fixed_as("fdt", machine->fdt, lams->fdt_size, FDT_BASE,
|
||||
&address_space_memory);
|
||||
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
|
||||
- rom_ptr_for_as(&address_space_memory, fdt_base, lams->fdt_size));
|
||||
+ rom_ptr_for_as(&address_space_memory, FDT_BASE, lams->fdt_size));
|
||||
|
||||
lams->bootinfo.ram_size = ram_size;
|
||||
loongarch_load_kernel(machine, &lams->bootinfo);
|
||||
diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
|
||||
index 42d1ee3663..4ebcc89dcf 100644
|
||||
--- a/include/hw/loongarch/boot.h
|
||||
+++ b/include/hw/loongarch/boot.h
|
||||
@@ -34,6 +34,10 @@ typedef struct {
|
||||
EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, \
|
||||
0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
|
||||
|
||||
+#define DEVICE_TREE_GUID \
|
||||
+ EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, \
|
||||
+ 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0)
|
||||
+
|
||||
struct efi_config_table {
|
||||
efi_guid_t guid;
|
||||
uint64_t *ptr;
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 2f9eaf4b0e..673b57aa2b 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -35,6 +35,8 @@
|
||||
|
||||
#define COMMAND_LINE_SIZE 512
|
||||
|
||||
+#define FDT_BASE 0x100000
|
||||
+
|
||||
extern struct memmap_entry *memmap_table;
|
||||
extern unsigned memmap_entries;
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
101
hw-loongarch-Init-efi_initrd-table.patch
Normal file
101
hw-loongarch-Init-efi_initrd-table.patch
Normal file
@ -0,0 +1,101 @@
|
||||
From ad674827da4ab972a30d51818f7768de47336984 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:41 +0800
|
||||
Subject: [PATCH 07/78] hw/loongarch: Init efi_initrd table
|
||||
|
||||
The efi_system_table adds a efi_initrd configuration table.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-8-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 23 +++++++++++++++++++++--
|
||||
include/hw/loongarch/boot.h | 9 +++++++++
|
||||
2 files changed, 30 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index 527fc9c0be..c8b3e742b4 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -15,6 +15,9 @@
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
+ram_addr_t initrd_offset;
|
||||
+uint64_t initrd_size;
|
||||
+
|
||||
static const unsigned int slave_boot_code[] = {
|
||||
/* Configure reset ebase. */
|
||||
0x0400302c, /* csrwr $t0, LOONGARCH_CSR_EENTRY */
|
||||
@@ -95,6 +98,21 @@ static void init_efi_boot_memmap(struct efi_system_table *systab,
|
||||
}
|
||||
}
|
||||
|
||||
+static void init_efi_initrd_table(struct efi_system_table *systab,
|
||||
+ void *p, void *start)
|
||||
+{
|
||||
+ efi_guid_t tbl_guid = LINUX_EFI_INITRD_MEDIA_GUID;
|
||||
+ struct efi_initrd *initrd_table = p;
|
||||
+
|
||||
+ /* efi_configuration_table 2 */
|
||||
+ guidcpy(&systab->tables[1].guid, &tbl_guid);
|
||||
+ systab->tables[1].table = (struct efi_configuration_table *)(p - start);
|
||||
+ systab->nr_tables = 2;
|
||||
+
|
||||
+ initrd_table->base = initrd_offset;
|
||||
+ initrd_table->size = initrd_size;
|
||||
+}
|
||||
+
|
||||
static void init_systab(struct loongarch_boot_info *info, void *p, void *start)
|
||||
{
|
||||
void *bp_tables_start;
|
||||
@@ -118,6 +136,8 @@ static void init_systab(struct loongarch_boot_info *info, void *p, void *start)
|
||||
init_efi_boot_memmap(systab, p, start);
|
||||
p += ROUND_UP(sizeof(struct efi_boot_memmap) +
|
||||
sizeof(efi_memory_desc_t) * memmap_entries, 64 * KiB);
|
||||
+ init_efi_initrd_table(systab, p, start);
|
||||
+ p += ROUND_UP(sizeof(struct efi_initrd), 64 * KiB);
|
||||
|
||||
systab->tables = (struct efi_configuration_table *)(bp_tables_start - start);
|
||||
}
|
||||
@@ -139,8 +159,7 @@ static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
|
||||
|
||||
static int64_t load_kernel_info(struct loongarch_boot_info *info)
|
||||
{
|
||||
- uint64_t kernel_entry, kernel_low, kernel_high, initrd_size;
|
||||
- ram_addr_t initrd_offset;
|
||||
+ uint64_t kernel_entry, kernel_low, kernel_high;
|
||||
ssize_t kernel_size;
|
||||
|
||||
kernel_size = load_elf(info->kernel_filename, NULL,
|
||||
diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
|
||||
index 76622af2e2..42d1ee3663 100644
|
||||
--- a/include/hw/loongarch/boot.h
|
||||
+++ b/include/hw/loongarch/boot.h
|
||||
@@ -30,6 +30,10 @@ typedef struct {
|
||||
EFI_GUID(0x800f683f, 0xd08b, 0x423a, 0xa2, 0x93, \
|
||||
0x96, 0x5c, 0x3c, 0x6f, 0xe2, 0xb4)
|
||||
|
||||
+#define LINUX_EFI_INITRD_MEDIA_GUID \
|
||||
+ EFI_GUID(0x5568e427, 0x68fc, 0x4f3d, 0xac, 0x74, \
|
||||
+ 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68)
|
||||
+
|
||||
struct efi_config_table {
|
||||
efi_guid_t guid;
|
||||
uint64_t *ptr;
|
||||
@@ -83,6 +87,11 @@ struct efi_boot_memmap {
|
||||
efi_memory_desc_t map[32];
|
||||
};
|
||||
|
||||
+struct efi_initrd {
|
||||
+ uint64_t base;
|
||||
+ uint64_t size;
|
||||
+};
|
||||
+
|
||||
struct loongarch_boot_info {
|
||||
uint64_t ram_size;
|
||||
const char *kernel_filename;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
125
hw-loongarch-Init-efi_system_table.patch
Normal file
125
hw-loongarch-Init-efi_system_table.patch
Normal file
@ -0,0 +1,125 @@
|
||||
From 65ae44689bfa6a1b697fea6ec0e72027fdddee95 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:39 +0800
|
||||
Subject: [PATCH 05/78] hw/loongarch: Init efi_system_table
|
||||
|
||||
Add init_systab and set boot_info->a2
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-6-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 22 +++++++++++++++++
|
||||
include/hw/loongarch/boot.h | 48 +++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 70 insertions(+)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index 127085bcc4..59889dbc90 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -63,6 +63,25 @@ static const unsigned int slave_boot_code[] = {
|
||||
0x4c000020, /* jirl $zero, $ra,0 */
|
||||
};
|
||||
|
||||
+static void init_systab(struct loongarch_boot_info *info, void *p, void *start)
|
||||
+{
|
||||
+ struct efi_system_table *systab = p;
|
||||
+
|
||||
+ info->a2 = p - start;
|
||||
+
|
||||
+ systab->hdr.signature = EFI_SYSTEM_TABLE_SIGNATURE;
|
||||
+ systab->hdr.revision = EFI_SPECIFICATION_VERSION;
|
||||
+ systab->hdr.revision = sizeof(struct efi_system_table),
|
||||
+ systab->fw_revision = FW_VERSION << 16 | FW_PATCHLEVEL << 8;
|
||||
+ systab->runtime = 0;
|
||||
+ systab->boottime = 0;
|
||||
+ systab->nr_tables = 0;
|
||||
+
|
||||
+ p += ROUND_UP(sizeof(struct efi_system_table), 64 * KiB);
|
||||
+
|
||||
+ systab->tables = p;
|
||||
+}
|
||||
+
|
||||
static void init_cmdline(struct loongarch_boot_info *info, void *p, void *start)
|
||||
{
|
||||
hwaddr cmdline_addr = p - start;
|
||||
@@ -134,6 +153,7 @@ static void reset_load_elf(void *opaque)
|
||||
if (cpu == LOONGARCH_CPU(first_cpu)) {
|
||||
env->gpr[4] = env->boot_info->a0;
|
||||
env->gpr[5] = env->boot_info->a1;
|
||||
+ env->gpr[6] = env->boot_info->a2;
|
||||
}
|
||||
cpu_set_pc(CPU(cpu), env->elf_address);
|
||||
}
|
||||
@@ -178,6 +198,8 @@ static void init_boot_rom(struct loongarch_boot_info *info, void *p)
|
||||
|
||||
init_cmdline(info, p, start);
|
||||
p += COMMAND_LINE_SIZE;
|
||||
+
|
||||
+ init_systab(info, p, start);
|
||||
}
|
||||
|
||||
static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
|
||||
index 3275c1e295..cf0e4d4f91 100644
|
||||
--- a/include/hw/loongarch/boot.h
|
||||
+++ b/include/hw/loongarch/boot.h
|
||||
@@ -8,6 +8,54 @@
|
||||
#ifndef HW_LOONGARCH_BOOT_H
|
||||
#define HW_LOONGARCH_BOOT_H
|
||||
|
||||
+/* UEFI 2.10 */
|
||||
+#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249
|
||||
+#define EFI_2_100_SYSTEM_TABLE_REVISION ((2<<16) | (100))
|
||||
+#define EFI_SPECIFICATION_VERSION EFI_SYSTEM_TABLE_REVISION
|
||||
+#define EFI_SYSTEM_TABLE_REVISION EFI_2_100_SYSTEM_TABLE_REVISION
|
||||
+
|
||||
+#define FW_VERSION 0x1
|
||||
+#define FW_PATCHLEVEL 0x0
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint8_t b[16];
|
||||
+} efi_guid_t QEMU_ALIGNED(8);
|
||||
+
|
||||
+struct efi_config_table {
|
||||
+ efi_guid_t guid;
|
||||
+ uint64_t *ptr;
|
||||
+ const char name[16];
|
||||
+};
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint64_t signature;
|
||||
+ uint32_t revision;
|
||||
+ uint32_t headersize;
|
||||
+ uint32_t crc32;
|
||||
+ uint32_t reserved;
|
||||
+} efi_table_hdr_t;
|
||||
+
|
||||
+struct efi_configuration_table {
|
||||
+ efi_guid_t guid;
|
||||
+ void *table;
|
||||
+};
|
||||
+
|
||||
+struct efi_system_table {
|
||||
+ efi_table_hdr_t hdr;
|
||||
+ uint64_t fw_vendor; /* physical addr of CHAR16 vendor string */
|
||||
+ uint32_t fw_revision;
|
||||
+ uint64_t con_in_handle;
|
||||
+ uint64_t *con_in;
|
||||
+ uint64_t con_out_handle;
|
||||
+ uint64_t *con_out;
|
||||
+ uint64_t stderr_handle;
|
||||
+ uint64_t stderr_placeholder;
|
||||
+ uint64_t *runtime;
|
||||
+ uint64_t *boottime;
|
||||
+ uint64_t nr_tables;
|
||||
+ struct efi_configuration_table *tables;
|
||||
+};
|
||||
+
|
||||
struct loongarch_boot_info {
|
||||
uint64_t ram_size;
|
||||
const char *kernel_filename;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
390
hw-loongarch-Move-boot-functions-to-boot.c.patch
Normal file
390
hw-loongarch-Move-boot-functions-to-boot.c.patch
Normal file
@ -0,0 +1,390 @@
|
||||
From 2414b74bec88f4db58040a683191d3c3828f81ab Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:35 +0800
|
||||
Subject: [PATCH 01/78] hw/loongarch: Move boot functions to boot.c
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Move some boot functions to boot.c and struct
|
||||
loongarch_boot_info into struct LoongArchMachineState.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Message-Id: <20240426091551.2397867-2-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 128 ++++++++++++++++++++++++++++++++++++
|
||||
hw/loongarch/meson.build | 1 +
|
||||
hw/loongarch/virt.c | 121 +++-------------------------------
|
||||
include/hw/loongarch/boot.h | 21 ++++++
|
||||
include/hw/loongarch/virt.h | 2 +
|
||||
5 files changed, 160 insertions(+), 113 deletions(-)
|
||||
create mode 100644 hw/loongarch/boot.c
|
||||
create mode 100644 include/hw/loongarch/boot.h
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
new file mode 100644
|
||||
index 0000000000..9feed17db3
|
||||
--- /dev/null
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -0,0 +1,128 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * LoongArch boot helper functions.
|
||||
+ *
|
||||
+ * Copyright (c) 2023 Loongson Technology Corporation Limited
|
||||
+ */
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "qemu/units.h"
|
||||
+#include "target/loongarch/cpu.h"
|
||||
+#include "hw/loongarch/virt.h"
|
||||
+#include "hw/loader.h"
|
||||
+#include "elf.h"
|
||||
+#include "qemu/error-report.h"
|
||||
+#include "sysemu/reset.h"
|
||||
+#include "sysemu/qtest.h"
|
||||
+
|
||||
+static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
|
||||
+{
|
||||
+ return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
|
||||
+}
|
||||
+
|
||||
+static int64_t load_kernel_info(struct loongarch_boot_info *info)
|
||||
+{
|
||||
+ uint64_t kernel_entry, kernel_low, kernel_high;
|
||||
+ ssize_t kernel_size;
|
||||
+
|
||||
+ kernel_size = load_elf(info->kernel_filename, NULL,
|
||||
+ cpu_loongarch_virt_to_phys, NULL,
|
||||
+ &kernel_entry, &kernel_low,
|
||||
+ &kernel_high, NULL, 0,
|
||||
+ EM_LOONGARCH, 1, 0);
|
||||
+
|
||||
+ if (kernel_size < 0) {
|
||||
+ error_report("could not load kernel '%s': %s",
|
||||
+ info->kernel_filename,
|
||||
+ load_elf_strerror(kernel_size));
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ return kernel_entry;
|
||||
+}
|
||||
+
|
||||
+static void reset_load_elf(void *opaque)
|
||||
+{
|
||||
+ LoongArchCPU *cpu = opaque;
|
||||
+ CPULoongArchState *env = &cpu->env;
|
||||
+
|
||||
+ cpu_reset(CPU(cpu));
|
||||
+ if (env->load_elf) {
|
||||
+ cpu_set_pc(CPU(cpu), env->elf_address);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void fw_cfg_add_kernel_info(struct loongarch_boot_info *info,
|
||||
+ FWCfgState *fw_cfg)
|
||||
+{
|
||||
+ /*
|
||||
+ * Expose the kernel, the command line, and the initrd in fw_cfg.
|
||||
+ * We don't process them here at all, it's all left to the
|
||||
+ * firmware.
|
||||
+ */
|
||||
+ load_image_to_fw_cfg(fw_cfg,
|
||||
+ FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
|
||||
+ info->kernel_filename,
|
||||
+ false);
|
||||
+
|
||||
+ if (info->initrd_filename) {
|
||||
+ load_image_to_fw_cfg(fw_cfg,
|
||||
+ FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
|
||||
+ info->initrd_filename, false);
|
||||
+ }
|
||||
+
|
||||
+ if (info->kernel_cmdline) {
|
||||
+ fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
|
||||
+ strlen(info->kernel_cmdline) + 1);
|
||||
+ fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
|
||||
+ info->kernel_cmdline);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void loongarch_firmware_boot(LoongArchMachineState *lams,
|
||||
+ struct loongarch_boot_info *info)
|
||||
+{
|
||||
+ fw_cfg_add_kernel_info(info, lams->fw_cfg);
|
||||
+}
|
||||
+
|
||||
+static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
+{
|
||||
+ int64_t kernel_addr = 0;
|
||||
+ LoongArchCPU *lacpu;
|
||||
+ CPUState *cs;
|
||||
+
|
||||
+ if (info->kernel_filename) {
|
||||
+ kernel_addr = load_kernel_info(info);
|
||||
+ } else {
|
||||
+ if(!qtest_enabled()) {
|
||||
+ error_report("Need kernel filename\n");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ CPU_FOREACH(cs) {
|
||||
+ lacpu = LOONGARCH_CPU(cs);
|
||||
+ lacpu->env.load_elf = true;
|
||||
+ lacpu->env.elf_address = kernel_addr;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info)
|
||||
+{
|
||||
+ LoongArchMachineState *lams = LOONGARCH_MACHINE(ms);
|
||||
+ int i;
|
||||
+
|
||||
+ /* register reset function */
|
||||
+ for (i = 0; i < ms->smp.cpus; i++) {
|
||||
+ qemu_register_reset(reset_load_elf, LOONGARCH_CPU(qemu_get_cpu(i)));
|
||||
+ }
|
||||
+
|
||||
+ info->kernel_filename = ms->kernel_filename;
|
||||
+ info->kernel_cmdline = ms->kernel_cmdline;
|
||||
+ info->initrd_filename = ms->initrd_filename;
|
||||
+
|
||||
+ if (lams->bios_loaded) {
|
||||
+ loongarch_firmware_boot(lams, info);
|
||||
+ } else {
|
||||
+ loongarch_direct_kernel_boot(info);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
|
||||
index c0421502ab..d306d82c2e 100644
|
||||
--- a/hw/loongarch/meson.build
|
||||
+++ b/hw/loongarch/meson.build
|
||||
@@ -1,6 +1,7 @@
|
||||
loongarch_ss = ss.source_set()
|
||||
loongarch_ss.add(files(
|
||||
'fw_cfg.c',
|
||||
+ 'boot.c',
|
||||
))
|
||||
loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: [files('virt.c'), fdt])
|
||||
loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c'))
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index eca3b94581..a0aee28f41 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -48,14 +48,6 @@
|
||||
#include "hw/block/flash.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
-
|
||||
-struct loaderparams {
|
||||
- uint64_t ram_size;
|
||||
- const char *kernel_filename;
|
||||
- const char *kernel_cmdline;
|
||||
- const char *initrd_filename;
|
||||
-};
|
||||
-
|
||||
static bool virt_is_veiointc_enabled(LoongArchMachineState *lams)
|
||||
{
|
||||
if (lams->veiointc == ON_OFF_AUTO_OFF) {
|
||||
@@ -439,31 +431,6 @@ static void memmap_add_entry(uint64_t address, uint64_t length, uint32_t type)
|
||||
memmap_entries++;
|
||||
}
|
||||
|
||||
-static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
|
||||
-{
|
||||
- return addr & MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS);
|
||||
-}
|
||||
-
|
||||
-static int64_t load_kernel_info(const struct loaderparams *loaderparams)
|
||||
-{
|
||||
- uint64_t kernel_entry, kernel_low, kernel_high;
|
||||
- ssize_t kernel_size;
|
||||
-
|
||||
- kernel_size = load_elf(loaderparams->kernel_filename, NULL,
|
||||
- cpu_loongarch_virt_to_phys, NULL,
|
||||
- &kernel_entry, &kernel_low,
|
||||
- &kernel_high, NULL, 0,
|
||||
- EM_LOONGARCH, 1, 0);
|
||||
-
|
||||
- if (kernel_size < 0) {
|
||||
- error_report("could not load kernel '%s': %s",
|
||||
- loaderparams->kernel_filename,
|
||||
- load_elf_strerror(kernel_size));
|
||||
- exit(1);
|
||||
- }
|
||||
- return kernel_entry;
|
||||
-}
|
||||
-
|
||||
static DeviceState *create_acpi_ged(DeviceState *pch_pic, LoongArchMachineState *lams)
|
||||
{
|
||||
DeviceState *dev;
|
||||
@@ -755,67 +722,6 @@ static void loongarch_firmware_init(LoongArchMachineState *lams)
|
||||
}
|
||||
}
|
||||
|
||||
-static void reset_load_elf(void *opaque)
|
||||
-{
|
||||
- LoongArchCPU *cpu = opaque;
|
||||
- CPULoongArchState *env = &cpu->env;
|
||||
-
|
||||
- cpu_reset(CPU(cpu));
|
||||
- if (env->load_elf) {
|
||||
- cpu_set_pc(CPU(cpu), env->elf_address);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void fw_cfg_add_kernel_info(const struct loaderparams *loaderparams,
|
||||
- FWCfgState *fw_cfg)
|
||||
-{
|
||||
- /*
|
||||
- * Expose the kernel, the command line, and the initrd in fw_cfg.
|
||||
- * We don't process them here at all, it's all left to the
|
||||
- * firmware.
|
||||
- */
|
||||
- load_image_to_fw_cfg(fw_cfg,
|
||||
- FW_CFG_KERNEL_SIZE, FW_CFG_KERNEL_DATA,
|
||||
- loaderparams->kernel_filename,
|
||||
- false);
|
||||
-
|
||||
- if (loaderparams->initrd_filename) {
|
||||
- load_image_to_fw_cfg(fw_cfg,
|
||||
- FW_CFG_INITRD_SIZE, FW_CFG_INITRD_DATA,
|
||||
- loaderparams->initrd_filename, false);
|
||||
- }
|
||||
-
|
||||
- if (loaderparams->kernel_cmdline) {
|
||||
- fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE,
|
||||
- strlen(loaderparams->kernel_cmdline) + 1);
|
||||
- fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA,
|
||||
- loaderparams->kernel_cmdline);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void loongarch_firmware_boot(LoongArchMachineState *lams,
|
||||
- const struct loaderparams *loaderparams)
|
||||
-{
|
||||
- fw_cfg_add_kernel_info(loaderparams, lams->fw_cfg);
|
||||
-}
|
||||
-
|
||||
-static void loongarch_direct_kernel_boot(LoongArchMachineState *lams,
|
||||
- const struct loaderparams *loaderparams)
|
||||
-{
|
||||
- MachineState *machine = MACHINE(lams);
|
||||
- int64_t kernel_addr = 0;
|
||||
- LoongArchCPU *lacpu;
|
||||
- int i;
|
||||
-
|
||||
- kernel_addr = load_kernel_info(loaderparams);
|
||||
- if (!machine->firmware) {
|
||||
- for (i = 0; i < machine->smp.cpus; i++) {
|
||||
- lacpu = LOONGARCH_CPU(qemu_get_cpu(i));
|
||||
- lacpu->env.load_elf = true;
|
||||
- lacpu->env.elf_address = kernel_addr;
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
|
||||
static MemTxResult loongarch_qemu_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned size, MemTxAttrs attrs)
|
||||
@@ -925,7 +831,6 @@ static void loongarch_init(MachineState *machine)
|
||||
const CPUArchIdList *possible_cpus;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
CPUState *cpu;
|
||||
- struct loaderparams loaderparams = { };
|
||||
|
||||
if (!cpu_model) {
|
||||
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||
@@ -1028,24 +933,8 @@ static void loongarch_init(MachineState *machine)
|
||||
sizeof(struct memmap_entry) * (memmap_entries));
|
||||
}
|
||||
fdt_add_fw_cfg_node(lams);
|
||||
- loaderparams.ram_size = ram_size;
|
||||
- loaderparams.kernel_filename = machine->kernel_filename;
|
||||
- loaderparams.kernel_cmdline = machine->kernel_cmdline;
|
||||
- loaderparams.initrd_filename = machine->initrd_filename;
|
||||
- /* load the kernel. */
|
||||
- if (loaderparams.kernel_filename) {
|
||||
- if (lams->bios_loaded) {
|
||||
- loongarch_firmware_boot(lams, &loaderparams);
|
||||
- } else {
|
||||
- loongarch_direct_kernel_boot(lams, &loaderparams);
|
||||
- }
|
||||
- }
|
||||
fdt_add_flash_node(lams);
|
||||
- /* register reset function */
|
||||
- for (i = 0; i < machine->smp.cpus; i++) {
|
||||
- lacpu = LOONGARCH_CPU(qemu_get_cpu(i));
|
||||
- qemu_register_reset(reset_load_elf, lacpu);
|
||||
- }
|
||||
+
|
||||
/* Initialize the IO interrupt subsystem */
|
||||
loongarch_irq_init(lams);
|
||||
fdt_add_irqchip_node(lams);
|
||||
@@ -1069,7 +958,13 @@ static void loongarch_init(MachineState *machine)
|
||||
*/
|
||||
fdt_base = 1 * MiB;
|
||||
qemu_fdt_dumpdtb(machine->fdt, lams->fdt_size);
|
||||
- rom_add_blob_fixed("fdt", machine->fdt, lams->fdt_size, fdt_base);
|
||||
+ rom_add_blob_fixed_as("fdt", machine->fdt, lams->fdt_size, fdt_base,
|
||||
+ &address_space_memory);
|
||||
+ qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
|
||||
+ rom_ptr_for_as(&address_space_memory, fdt_base, lams->fdt_size));
|
||||
+
|
||||
+ lams->bootinfo.ram_size = ram_size;
|
||||
+ loongarch_load_kernel(machine, &lams->bootinfo);
|
||||
}
|
||||
|
||||
bool loongarch_is_acpi_enabled(LoongArchMachineState *lams)
|
||||
diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
|
||||
new file mode 100644
|
||||
index 0000000000..3275c1e295
|
||||
--- /dev/null
|
||||
+++ b/include/hw/loongarch/boot.h
|
||||
@@ -0,0 +1,21 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
+/*
|
||||
+ * Definitions for LoongArch boot.
|
||||
+ *
|
||||
+ * Copyright (C) 2023 Loongson Technology Corporation Limited
|
||||
+ */
|
||||
+
|
||||
+#ifndef HW_LOONGARCH_BOOT_H
|
||||
+#define HW_LOONGARCH_BOOT_H
|
||||
+
|
||||
+struct loongarch_boot_info {
|
||||
+ uint64_t ram_size;
|
||||
+ const char *kernel_filename;
|
||||
+ const char *kernel_cmdline;
|
||||
+ const char *initrd_filename;
|
||||
+ uint64_t a0, a1, a2;
|
||||
+};
|
||||
+
|
||||
+void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info);
|
||||
+
|
||||
+#endif /* HW_LOONGARCH_BOOT_H */
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 99447fd1d6..02c8234b8d 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "qemu/queue.h"
|
||||
#include "hw/intc/loongarch_ipi.h"
|
||||
#include "hw/block/flash.h"
|
||||
+#include "hw/loongarch/boot.h"
|
||||
|
||||
#define LOONGARCH_MAX_CPUS 256
|
||||
|
||||
@@ -58,6 +59,7 @@ struct LoongArchMachineState {
|
||||
MemoryRegion iocsr_mem;
|
||||
AddressSpace as_iocsr;
|
||||
int features;
|
||||
+ struct loongarch_boot_info bootinfo;
|
||||
};
|
||||
|
||||
#define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt")
|
||||
--
|
||||
2.39.1
|
||||
|
||||
108
hw-loongarch-Refine-acpi-srat-table-for-numa-memory.patch
Normal file
108
hw-loongarch-Refine-acpi-srat-table-for-numa-memory.patch
Normal file
@ -0,0 +1,108 @@
|
||||
From 1c9b7b7e76a63738721ac1092fdfff12ae87993a Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 15 May 2024 17:39:22 +0800
|
||||
Subject: [PATCH 23/78] hw/loongarch: Refine acpi srat table for numa memory
|
||||
|
||||
One LoongArch virt machine platform, there is limitation for memory
|
||||
map information. The minimum memory size is 256M and minimum memory
|
||||
size for numa node0 is 256M also. With qemu numa qtest, it is possible
|
||||
that memory size of numa node0 is 128M.
|
||||
|
||||
Limitations for minimum memory size for both total memory and numa
|
||||
node0 is removed for acpi srat table creation.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240515093927.3453674-2-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/acpi-build.c | 58 +++++++++++++++++++++++----------------
|
||||
1 file changed, 34 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
|
||||
index 2b4e09bf37..2555c6763c 100644
|
||||
--- a/hw/loongarch/acpi-build.c
|
||||
+++ b/hw/loongarch/acpi-build.c
|
||||
@@ -166,8 +166,9 @@ static void
|
||||
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
{
|
||||
int i, arch_id, node_id;
|
||||
- uint64_t mem_len, mem_base;
|
||||
- int nb_numa_nodes = machine->numa_state->num_nodes;
|
||||
+ hwaddr len, base, gap;
|
||||
+ NodeInfo *numa_info;
|
||||
+ int nodes, nb_numa_nodes = machine->numa_state->num_nodes;
|
||||
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(lvms);
|
||||
const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
|
||||
@@ -196,35 +197,44 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
|
||||
}
|
||||
|
||||
- /* Node0 */
|
||||
- build_srat_memory(table_data, VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE,
|
||||
- 0, MEM_AFFINITY_ENABLED);
|
||||
- mem_base = VIRT_HIGHMEM_BASE;
|
||||
- if (!nb_numa_nodes) {
|
||||
- mem_len = machine->ram_size - VIRT_LOWMEM_SIZE;
|
||||
- } else {
|
||||
- mem_len = machine->numa_state->nodes[0].node_mem - VIRT_LOWMEM_SIZE;
|
||||
+ base = VIRT_LOWMEM_BASE;
|
||||
+ gap = VIRT_LOWMEM_SIZE;
|
||||
+ numa_info = machine->numa_state->nodes;
|
||||
+ nodes = nb_numa_nodes;
|
||||
+ if (!nodes) {
|
||||
+ nodes = 1;
|
||||
}
|
||||
- if (mem_len)
|
||||
- build_srat_memory(table_data, mem_base, mem_len, 0, MEM_AFFINITY_ENABLED);
|
||||
-
|
||||
- /* Node1 - Nodemax */
|
||||
- if (nb_numa_nodes) {
|
||||
- mem_base += mem_len;
|
||||
- for (i = 1; i < nb_numa_nodes; ++i) {
|
||||
- if (machine->numa_state->nodes[i].node_mem > 0) {
|
||||
- build_srat_memory(table_data, mem_base,
|
||||
- machine->numa_state->nodes[i].node_mem, i,
|
||||
- MEM_AFFINITY_ENABLED);
|
||||
- mem_base += machine->numa_state->nodes[i].node_mem;
|
||||
- }
|
||||
+
|
||||
+ for (i = 0; i < nodes; i++) {
|
||||
+ if (nb_numa_nodes) {
|
||||
+ len = numa_info[i].node_mem;
|
||||
+ } else {
|
||||
+ len = machine->ram_size;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * memory for the node splited into two part
|
||||
+ * lowram: [base, +gap)
|
||||
+ * highram: [VIRT_HIGHMEM_BASE, +(len - gap))
|
||||
+ */
|
||||
+ if (len >= gap) {
|
||||
+ build_srat_memory(table_data, base, len, i, MEM_AFFINITY_ENABLED);
|
||||
+ len -= gap;
|
||||
+ base = VIRT_HIGHMEM_BASE;
|
||||
+ gap = machine->ram_size - VIRT_LOWMEM_SIZE;
|
||||
+ }
|
||||
+
|
||||
+ if (len) {
|
||||
+ build_srat_memory(table_data, base, len, i, MEM_AFFINITY_ENABLED);
|
||||
+ base += len;
|
||||
+ gap -= len;
|
||||
}
|
||||
}
|
||||
|
||||
if (machine->device_memory) {
|
||||
build_srat_memory(table_data, machine->device_memory->base,
|
||||
memory_region_size(&machine->device_memory->mr),
|
||||
- nb_numa_nodes - 1,
|
||||
+ nodes - 1,
|
||||
MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
|
||||
}
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
57
hw-loongarch-Refine-default-numa-id-calculation.patch
Normal file
57
hw-loongarch-Refine-default-numa-id-calculation.patch
Normal file
@ -0,0 +1,57 @@
|
||||
From a9f9a4a0a60596f2e738e6e434c20a3f5266fa17 Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Tue, 19 Mar 2024 10:26:06 +0800
|
||||
Subject: [PATCH 21/78] hw/loongarch: Refine default numa id calculation
|
||||
|
||||
With numa_test test case, there is subcase named test_def_cpu_split(),
|
||||
there are 8 sockets and 2 numa nodes. Here is command line:
|
||||
"-machine smp.cpus=8,smp.sockets=8 -numa node,memdev=ram -numa node"
|
||||
|
||||
The required result is:
|
||||
node 0 cpus: 0 2 4 6
|
||||
node 1 cpus: 1 3 5 7
|
||||
Test case numa_test fails on LoongArch, since the actual result is:
|
||||
node 0 cpus: 0 1 2 3
|
||||
node 1 cpus: 4 5 6 7
|
||||
|
||||
It will be better if all the cpus in one socket share the same numa
|
||||
node. Here socket id is used to calculate numa id in function
|
||||
virt_get_default_cpu_node_id().
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240319022606.2994565-1-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 11 +++++------
|
||||
1 file changed, 5 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index e39989193e..e82e3b6792 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -1278,15 +1278,14 @@ static CpuInstanceProperties virt_cpu_index_to_props(MachineState *ms,
|
||||
|
||||
static int64_t virt_get_default_cpu_node_id(const MachineState *ms, int idx)
|
||||
{
|
||||
- int64_t nidx = 0;
|
||||
+ int64_t socket_id;
|
||||
|
||||
if (ms->numa_state->num_nodes) {
|
||||
- nidx = idx / (ms->smp.cpus / ms->numa_state->num_nodes);
|
||||
- if (ms->numa_state->num_nodes <= nidx) {
|
||||
- nidx = ms->numa_state->num_nodes - 1;
|
||||
- }
|
||||
+ socket_id = ms->possible_cpus->cpus[idx].props.socket_id;
|
||||
+ return socket_id % ms->numa_state->num_nodes;
|
||||
+ } else {
|
||||
+ return 0;
|
||||
}
|
||||
- return nidx;
|
||||
}
|
||||
|
||||
static void virt_class_init(ObjectClass *oc, void *data)
|
||||
--
|
||||
2.39.1
|
||||
|
||||
106
hw-loongarch-Refine-fadt-memory-table-for-numa-memor.patch
Normal file
106
hw-loongarch-Refine-fadt-memory-table-for-numa-memor.patch
Normal file
@ -0,0 +1,106 @@
|
||||
From d39247ec5d4ef52a4b9422aaecccc284cbd1a5dd Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 15 May 2024 17:39:23 +0800
|
||||
Subject: [PATCH 24/78] hw/loongarch: Refine fadt memory table for numa memory
|
||||
|
||||
One LoongArch virt machine platform, there is limitation for memory
|
||||
map information. The minimum memory size is 256M and minimum memory
|
||||
size for numa node0 is 256M also. With qemu numa qtest, it is possible
|
||||
that memory size of numa node0 is 128M.
|
||||
|
||||
Limitations for minimum memory size for both total memory and numa
|
||||
node0 is removed for fadt numa memory table creation.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240515093927.3453674-3-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 46 ++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 43 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index c3514f9293..31a2598e7c 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -502,6 +502,48 @@ static void fdt_add_memory_node(MachineState *ms,
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
+static void fdt_add_memory_nodes(MachineState *ms)
|
||||
+{
|
||||
+ hwaddr base, size, ram_size, gap;
|
||||
+ int i, nb_numa_nodes, nodes;
|
||||
+ NodeInfo *numa_info;
|
||||
+
|
||||
+ ram_size = ms->ram_size;
|
||||
+ base = VIRT_LOWMEM_BASE;
|
||||
+ gap = VIRT_LOWMEM_SIZE;
|
||||
+ nodes = nb_numa_nodes = ms->numa_state->num_nodes;
|
||||
+ numa_info = ms->numa_state->nodes;
|
||||
+ if (!nodes) {
|
||||
+ nodes = 1;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < nodes; i++) {
|
||||
+ if (nb_numa_nodes) {
|
||||
+ size = numa_info[i].node_mem;
|
||||
+ } else {
|
||||
+ size = ram_size;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * memory for the node splited into two part
|
||||
+ * lowram: [base, +gap)
|
||||
+ * highram: [VIRT_HIGHMEM_BASE, +(len - gap))
|
||||
+ */
|
||||
+ if (size >= gap) {
|
||||
+ fdt_add_memory_node(ms, base, gap, i);
|
||||
+ size -= gap;
|
||||
+ base = VIRT_HIGHMEM_BASE;
|
||||
+ gap = ram_size - VIRT_LOWMEM_SIZE;
|
||||
+ }
|
||||
+
|
||||
+ if (size) {
|
||||
+ fdt_add_memory_node(ms, base, size, i);
|
||||
+ base += size;
|
||||
+ gap -= size;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void virt_build_smbios(LoongArchVirtMachineState *lvms)
|
||||
{
|
||||
MachineState *ms = MACHINE(lvms);
|
||||
@@ -1008,10 +1050,10 @@ static void virt_init(MachineState *machine)
|
||||
lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id;
|
||||
}
|
||||
fdt_add_cpu_nodes(lvms);
|
||||
+ fdt_add_memory_nodes(machine);
|
||||
|
||||
/* Node0 memory */
|
||||
memmap_add_entry(VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 1);
|
||||
- fdt_add_memory_node(machine, VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 0);
|
||||
memory_region_init_alias(&lvms->lowmem, NULL, "loongarch.node0.lowram",
|
||||
machine->ram, offset, VIRT_LOWMEM_SIZE);
|
||||
memory_region_add_subregion(address_space_mem, phyAddr, &lvms->lowmem);
|
||||
@@ -1025,7 +1067,6 @@ static void virt_init(MachineState *machine)
|
||||
}
|
||||
phyAddr = VIRT_HIGHMEM_BASE;
|
||||
memmap_add_entry(phyAddr, highram_size, 1);
|
||||
- fdt_add_memory_node(machine, phyAddr, highram_size, 0);
|
||||
memory_region_init_alias(&lvms->highmem, NULL, "loongarch.node0.highram",
|
||||
machine->ram, offset, highram_size);
|
||||
memory_region_add_subregion(address_space_mem, phyAddr, &lvms->highmem);
|
||||
@@ -1041,7 +1082,6 @@ static void virt_init(MachineState *machine)
|
||||
offset, numa_info[i].node_mem);
|
||||
memory_region_add_subregion(address_space_mem, phyAddr, nodemem);
|
||||
memmap_add_entry(phyAddr, numa_info[i].node_mem, 1);
|
||||
- fdt_add_memory_node(machine, phyAddr, numa_info[i].node_mem, i);
|
||||
offset += numa_info[i].node_mem;
|
||||
phyAddr += numa_info[i].node_mem;
|
||||
}
|
||||
--
|
||||
2.39.1
|
||||
|
||||
120
hw-loongarch-Refine-fwcfg-memory-map.patch
Normal file
120
hw-loongarch-Refine-fwcfg-memory-map.patch
Normal file
@ -0,0 +1,120 @@
|
||||
From 88b12e40d6a479dfb376fb6a91ef24e07a59d33a Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 15 May 2024 17:39:24 +0800
|
||||
Subject: [PATCH 25/78] hw/loongarch: Refine fwcfg memory map
|
||||
|
||||
Memory map table for fwcfg is used for UEFI BIOS, UEFI BIOS uses the first
|
||||
entry from fwcfg memory map as the first memory HOB, the second memory HOB
|
||||
will be used if the first memory HOB is used up.
|
||||
|
||||
Memory map table for fwcfg does not care about numa node, however in
|
||||
generic the first memory HOB is part of numa node0, so that runtime
|
||||
memory of UEFI which is allocated from the first memory HOB is located
|
||||
at numa node0.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240515093927.3453674-4-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 60 ++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 57 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 31a2598e7c..7e89921431 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -1005,6 +1005,62 @@ static const MemoryRegionOps virt_iocsr_misc_ops = {
|
||||
},
|
||||
};
|
||||
|
||||
+static void fw_cfg_add_memory(MachineState *ms)
|
||||
+{
|
||||
+ hwaddr base, size, ram_size, gap;
|
||||
+ int nb_numa_nodes, nodes;
|
||||
+ NodeInfo *numa_info;
|
||||
+
|
||||
+ ram_size = ms->ram_size;
|
||||
+ base = VIRT_LOWMEM_BASE;
|
||||
+ gap = VIRT_LOWMEM_SIZE;
|
||||
+ nodes = nb_numa_nodes = ms->numa_state->num_nodes;
|
||||
+ numa_info = ms->numa_state->nodes;
|
||||
+ if (!nodes) {
|
||||
+ nodes = 1;
|
||||
+ }
|
||||
+
|
||||
+ /* add fw_cfg memory map of node0 */
|
||||
+ if (nb_numa_nodes) {
|
||||
+ size = numa_info[0].node_mem;
|
||||
+ } else {
|
||||
+ size = ram_size;
|
||||
+ }
|
||||
+
|
||||
+ if (size >= gap) {
|
||||
+ memmap_add_entry(base, gap, 1);
|
||||
+ size -= gap;
|
||||
+ base = VIRT_HIGHMEM_BASE;
|
||||
+ gap = ram_size - VIRT_LOWMEM_SIZE;
|
||||
+ }
|
||||
+
|
||||
+ if (size) {
|
||||
+ memmap_add_entry(base, size, 1);
|
||||
+ base += size;
|
||||
+ }
|
||||
+
|
||||
+ if (nodes < 2) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* add fw_cfg memory map of other nodes */
|
||||
+ size = ram_size - numa_info[0].node_mem;
|
||||
+ gap = VIRT_LOWMEM_BASE + VIRT_LOWMEM_SIZE;
|
||||
+ if (base < gap && (base + size) > gap) {
|
||||
+ /*
|
||||
+ * memory map for the maining nodes splited into two part
|
||||
+ * lowram: [base, +(gap - base))
|
||||
+ * highram: [VIRT_HIGHMEM_BASE, +(size - (gap - base)))
|
||||
+ */
|
||||
+ memmap_add_entry(base, gap - base, 1);
|
||||
+ size -= gap - base;
|
||||
+ base = VIRT_HIGHMEM_BASE;
|
||||
+ }
|
||||
+
|
||||
+ if (size)
|
||||
+ memmap_add_entry(base, size, 1);
|
||||
+}
|
||||
+
|
||||
static void virt_init(MachineState *machine)
|
||||
{
|
||||
LoongArchCPU *lacpu;
|
||||
@@ -1051,9 +1107,9 @@ static void virt_init(MachineState *machine)
|
||||
}
|
||||
fdt_add_cpu_nodes(lvms);
|
||||
fdt_add_memory_nodes(machine);
|
||||
+ fw_cfg_add_memory(machine);
|
||||
|
||||
/* Node0 memory */
|
||||
- memmap_add_entry(VIRT_LOWMEM_BASE, VIRT_LOWMEM_SIZE, 1);
|
||||
memory_region_init_alias(&lvms->lowmem, NULL, "loongarch.node0.lowram",
|
||||
machine->ram, offset, VIRT_LOWMEM_SIZE);
|
||||
memory_region_add_subregion(address_space_mem, phyAddr, &lvms->lowmem);
|
||||
@@ -1066,7 +1122,6 @@ static void virt_init(MachineState *machine)
|
||||
highram_size = ram_size - VIRT_LOWMEM_SIZE;
|
||||
}
|
||||
phyAddr = VIRT_HIGHMEM_BASE;
|
||||
- memmap_add_entry(phyAddr, highram_size, 1);
|
||||
memory_region_init_alias(&lvms->highmem, NULL, "loongarch.node0.highram",
|
||||
machine->ram, offset, highram_size);
|
||||
memory_region_add_subregion(address_space_mem, phyAddr, &lvms->highmem);
|
||||
@@ -1081,7 +1136,6 @@ static void virt_init(MachineState *machine)
|
||||
memory_region_init_alias(nodemem, NULL, ramName, machine->ram,
|
||||
offset, numa_info[i].node_mem);
|
||||
memory_region_add_subregion(address_space_mem, phyAddr, nodemem);
|
||||
- memmap_add_entry(phyAddr, numa_info[i].node_mem, 1);
|
||||
offset += numa_info[i].node_mem;
|
||||
phyAddr += numa_info[i].node_mem;
|
||||
}
|
||||
--
|
||||
2.39.1
|
||||
|
||||
110
hw-loongarch-Refine-system-dram-memory-region.patch
Normal file
110
hw-loongarch-Refine-system-dram-memory-region.patch
Normal file
@ -0,0 +1,110 @@
|
||||
From 1a7f567308756a2a26020802b24fe7fd106cf84a Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 15 May 2024 17:39:25 +0800
|
||||
Subject: [PATCH 26/78] hw/loongarch: Refine system dram memory region
|
||||
|
||||
For system dram memory region, it is not necessary to use numa node
|
||||
information. There is only low memory region and high memory region.
|
||||
|
||||
Remove numa node information for ddr memory region here, it can reduce
|
||||
memory region number on LoongArch virt machine.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240515093927.3453674-5-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 53 +++++++++++++++------------------------------
|
||||
1 file changed, 17 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 7e89921431..96755f5deb 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -1065,14 +1065,10 @@ static void virt_init(MachineState *machine)
|
||||
{
|
||||
LoongArchCPU *lacpu;
|
||||
const char *cpu_model = machine->cpu_type;
|
||||
- ram_addr_t offset = 0;
|
||||
- ram_addr_t ram_size = machine->ram_size;
|
||||
- uint64_t highram_size = 0, phyAddr = 0;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
|
||||
- int nb_numa_nodes = machine->numa_state->num_nodes;
|
||||
- NodeInfo *numa_info = machine->numa_state->nodes;
|
||||
int i;
|
||||
+ hwaddr base, size, ram_size = machine->ram_size;
|
||||
const CPUArchIdList *possible_cpus;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
CPUState *cpu;
|
||||
@@ -1110,40 +1106,27 @@ static void virt_init(MachineState *machine)
|
||||
fw_cfg_add_memory(machine);
|
||||
|
||||
/* Node0 memory */
|
||||
- memory_region_init_alias(&lvms->lowmem, NULL, "loongarch.node0.lowram",
|
||||
- machine->ram, offset, VIRT_LOWMEM_SIZE);
|
||||
- memory_region_add_subregion(address_space_mem, phyAddr, &lvms->lowmem);
|
||||
-
|
||||
- offset += VIRT_LOWMEM_SIZE;
|
||||
- if (nb_numa_nodes > 0) {
|
||||
- assert(numa_info[0].node_mem > VIRT_LOWMEM_SIZE);
|
||||
- highram_size = numa_info[0].node_mem - VIRT_LOWMEM_SIZE;
|
||||
- } else {
|
||||
- highram_size = ram_size - VIRT_LOWMEM_SIZE;
|
||||
+ size = ram_size;
|
||||
+ base = VIRT_LOWMEM_BASE;
|
||||
+ if (size > VIRT_LOWMEM_SIZE) {
|
||||
+ size = VIRT_LOWMEM_SIZE;
|
||||
}
|
||||
- phyAddr = VIRT_HIGHMEM_BASE;
|
||||
- memory_region_init_alias(&lvms->highmem, NULL, "loongarch.node0.highram",
|
||||
- machine->ram, offset, highram_size);
|
||||
- memory_region_add_subregion(address_space_mem, phyAddr, &lvms->highmem);
|
||||
-
|
||||
- /* Node1 - Nodemax memory */
|
||||
- offset += highram_size;
|
||||
- phyAddr += highram_size;
|
||||
-
|
||||
- for (i = 1; i < nb_numa_nodes; i++) {
|
||||
- MemoryRegion *nodemem = g_new(MemoryRegion, 1);
|
||||
- g_autofree char *ramName = g_strdup_printf("loongarch.node%d.ram", i);
|
||||
- memory_region_init_alias(nodemem, NULL, ramName, machine->ram,
|
||||
- offset, numa_info[i].node_mem);
|
||||
- memory_region_add_subregion(address_space_mem, phyAddr, nodemem);
|
||||
- offset += numa_info[i].node_mem;
|
||||
- phyAddr += numa_info[i].node_mem;
|
||||
+
|
||||
+ memory_region_init_alias(&lvms->lowmem, NULL, "loongarch.lowram",
|
||||
+ machine->ram, base, size);
|
||||
+ memory_region_add_subregion(address_space_mem, base, &lvms->lowmem);
|
||||
+ base += size;
|
||||
+ if (ram_size - size) {
|
||||
+ base = VIRT_HIGHMEM_BASE;
|
||||
+ memory_region_init_alias(&lvms->highmem, NULL, "loongarch.highram",
|
||||
+ machine->ram, VIRT_LOWMEM_BASE + size, ram_size - size);
|
||||
+ memory_region_add_subregion(address_space_mem, base, &lvms->highmem);
|
||||
+ base += ram_size - size;
|
||||
}
|
||||
|
||||
/* initialize device memory address space */
|
||||
if (machine->ram_size < machine->maxram_size) {
|
||||
ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size;
|
||||
- hwaddr device_mem_base;
|
||||
|
||||
if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) {
|
||||
error_report("unsupported amount of memory slots: %"PRIu64,
|
||||
@@ -1157,9 +1140,7 @@ static void virt_init(MachineState *machine)
|
||||
"%d bytes", TARGET_PAGE_SIZE);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
- /* device memory base is the top of high memory address. */
|
||||
- device_mem_base = ROUND_UP(VIRT_HIGHMEM_BASE + highram_size, 1 * GiB);
|
||||
- machine_memory_devices_init(machine, device_mem_base, device_mem_size);
|
||||
+ machine_memory_devices_init(machine, base, device_mem_size);
|
||||
}
|
||||
|
||||
/* load the BIOS image. */
|
||||
--
|
||||
2.39.1
|
||||
|
||||
39
hw-loongarch-Remove-default-enable-with-VIRTIO_VGA-d.patch
Normal file
39
hw-loongarch-Remove-default-enable-with-VIRTIO_VGA-d.patch
Normal file
@ -0,0 +1,39 @@
|
||||
From 94fa0b75c098ca6fc987f103760c1e07695ffd1a Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Fri, 23 Aug 2024 15:30:50 +0800
|
||||
Subject: [PATCH 34/78] hw/loongarch: Remove default enable with VIRTIO_VGA
|
||||
device
|
||||
|
||||
For virtio VGA deivce libvirt will select VIRTIO_VGA firstly rather than
|
||||
VIRTIO_GPU, VIRTIO_VGA device supports frame buffer however it requires
|
||||
legacy VGA compatible support. Frame buffer area 0xa0000 -- 0xc0000
|
||||
conflicts with low memory area 0 -- 0x10000000.
|
||||
|
||||
Here remove default support for VIRTIO_VGA device, VIRTIO_GPU is prefered
|
||||
on LoongArch system. For frame buffer video card support, standard VGA can
|
||||
be used.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240823073050.2619484-1-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/Kconfig | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
|
||||
index b2a3adb7dc..40944a8365 100644
|
||||
--- a/hw/loongarch/Kconfig
|
||||
+++ b/hw/loongarch/Kconfig
|
||||
@@ -4,7 +4,6 @@ config LOONGARCH_VIRT
|
||||
depends on LOONGARCH64
|
||||
select PCI
|
||||
select PCI_EXPRESS_GENERIC_BRIDGE
|
||||
- imply VIRTIO_VGA
|
||||
imply PCI_DEVICES
|
||||
imply NVDIMM
|
||||
imply TPM_TIS_SYSBUS
|
||||
--
|
||||
2.39.1
|
||||
|
||||
46
hw-loongarch-Remove-minimum-and-default-memory-size.patch
Normal file
46
hw-loongarch-Remove-minimum-and-default-memory-size.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 858f16ea09fbbac9966ca73b6b86d290a36be6f5 Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 15 May 2024 17:39:26 +0800
|
||||
Subject: [PATCH 27/78] hw/loongarch: Remove minimum and default memory size
|
||||
|
||||
Some qtest test cases such as numa use default memory size of generic
|
||||
machine class, which is 128M by fault.
|
||||
|
||||
Here generic default memory size is used, and also remove minimum memory
|
||||
size which is 1G originally.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240515093927.3453674-6-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 5 -----
|
||||
1 file changed, 5 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 96755f5deb..11ba879e52 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -1077,10 +1077,6 @@ static void virt_init(MachineState *machine)
|
||||
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||
}
|
||||
|
||||
- if (ram_size < 1 * GiB) {
|
||||
- error_report("ram_size must be greater than 1G.");
|
||||
- exit(1);
|
||||
- }
|
||||
create_fdt(lvms);
|
||||
|
||||
/* Create IOCSR space */
|
||||
@@ -1369,7 +1365,6 @@ static void virt_class_init(ObjectClass *oc, void *data)
|
||||
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
|
||||
|
||||
mc->init = virt_init;
|
||||
- mc->default_ram_size = 1 * GiB;
|
||||
mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||
mc->default_ram_id = "loongarch.ram";
|
||||
mc->max_cpus = LOONGARCH_MAX_CPUS;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
188
hw-loongarch-Rename-LOONGARCH_MACHINE-with-LOONGARCH.patch
Normal file
188
hw-loongarch-Rename-LOONGARCH_MACHINE-with-LOONGARCH.patch
Normal file
@ -0,0 +1,188 @@
|
||||
From 8e2986a6fc5dda2afbe33f723efdacd01f147b7a Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 8 May 2024 11:11:06 +0800
|
||||
Subject: [PATCH 19/78] hw/loongarch: Rename LOONGARCH_MACHINE with
|
||||
LOONGARCH_VIRT_MACHINE
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
On LoongArch system, there is only virt machine type now, name
|
||||
LOONGARCH_MACHINE is confused, rename it with LOONGARCH_VIRT_MACHINE.
|
||||
Machine name about Other real hw boards can be added in future.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Message-ID: <20240508031110.2507477-2-maobibo@loongson.cn>
|
||||
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/acpi-build.c | 8 ++++----
|
||||
hw/loongarch/boot.c | 2 +-
|
||||
hw/loongarch/virt.c | 19 +++++++++----------
|
||||
include/hw/loongarch/virt.h | 4 ++--
|
||||
4 files changed, 16 insertions(+), 17 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
|
||||
index f990405d04..fff3497c62 100644
|
||||
--- a/hw/loongarch/acpi-build.c
|
||||
+++ b/hw/loongarch/acpi-build.c
|
||||
@@ -167,7 +167,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
int i, arch_id, node_id;
|
||||
uint64_t mem_len, mem_base;
|
||||
int nb_numa_nodes = machine->numa_state->num_nodes;
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(lams);
|
||||
const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(machine);
|
||||
AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = lams->oem_id,
|
||||
@@ -279,7 +279,7 @@ static void
|
||||
build_la_ged_aml(Aml *dsdt, MachineState *machine)
|
||||
{
|
||||
uint32_t event;
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
|
||||
|
||||
build_ged_aml(dsdt, "\\_SB."GED_DEVICE,
|
||||
HOTPLUG_HANDLER(lams->acpi_ged),
|
||||
@@ -391,7 +391,7 @@ static void
|
||||
build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
{
|
||||
Aml *dsdt, *scope, *pkg;
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
|
||||
AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lams->oem_id,
|
||||
.oem_table_id = lams->oem_table_id };
|
||||
|
||||
@@ -421,7 +421,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
|
||||
static void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
|
||||
GArray *table_offsets;
|
||||
AcpiFadtData fadt_data;
|
||||
unsigned facs, rsdt, dsdt;
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index 03f6301a77..e37512729d 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -319,7 +319,7 @@ static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
|
||||
void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(ms);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(ms);
|
||||
int i;
|
||||
|
||||
/* register reset function */
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 76b36539e2..cca220cb5b 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -970,7 +970,7 @@ static void loongarch_init(MachineState *machine)
|
||||
ram_addr_t ram_size = machine->ram_size;
|
||||
uint64_t highram_size = 0, phyAddr = 0;
|
||||
MemoryRegion *address_space_mem = get_system_memory();
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(machine);
|
||||
int nb_numa_nodes = machine->numa_state->num_nodes;
|
||||
NodeInfo *numa_info = machine->numa_state->nodes;
|
||||
int i;
|
||||
@@ -1121,7 +1121,7 @@ bool loongarch_is_acpi_enabled(LoongArchMachineState *lams)
|
||||
static void loongarch_get_acpi(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(obj);
|
||||
OnOffAuto acpi = lams->acpi;
|
||||
|
||||
visit_type_OnOffAuto(v, name, &acpi, errp);
|
||||
@@ -1130,14 +1130,14 @@ static void loongarch_get_acpi(Object *obj, Visitor *v, const char *name,
|
||||
static void loongarch_set_acpi(Object *obj, Visitor *v, const char *name,
|
||||
void *opaque, Error **errp)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(obj);
|
||||
|
||||
visit_type_OnOffAuto(v, name, &lams->acpi, errp);
|
||||
}
|
||||
|
||||
static void loongarch_machine_initfn(Object *obj)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(obj);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(obj);
|
||||
|
||||
if (tcg_enabled()) {
|
||||
lams->veiointc = ON_OFF_AUTO_OFF;
|
||||
@@ -1172,7 +1172,7 @@ static void virt_machine_device_pre_plug(HotplugHandler *hotplug_dev,
|
||||
static void virt_mem_unplug_request(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(hotplug_dev);
|
||||
|
||||
/* the acpi ged is always exist */
|
||||
hotplug_handler_unplug_request(HOTPLUG_HANDLER(lams->acpi_ged), dev,
|
||||
@@ -1190,7 +1190,7 @@ static void virt_machine_device_unplug_request(HotplugHandler *hotplug_dev,
|
||||
static void virt_mem_unplug(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(hotplug_dev);
|
||||
|
||||
hotplug_handler_unplug(HOTPLUG_HANDLER(lams->acpi_ged), dev, errp);
|
||||
pc_dimm_unplug(PC_DIMM(dev), MACHINE(lams));
|
||||
@@ -1208,7 +1208,7 @@ static void virt_machine_device_unplug(HotplugHandler *hotplug_dev,
|
||||
static void virt_mem_plug(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(hotplug_dev);
|
||||
|
||||
pc_dimm_plug(PC_DIMM(dev), MACHINE(lams));
|
||||
hotplug_handler_plug(HOTPLUG_HANDLER(lams->acpi_ged),
|
||||
@@ -1218,7 +1218,7 @@ static void virt_mem_plug(HotplugHandler *hotplug_dev,
|
||||
static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
- LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev);
|
||||
+ LoongArchMachineState *lams = LOONGARCH_VIRT_MACHINE(hotplug_dev);
|
||||
MachineClass *mc = MACHINE_GET_CLASS(lams);
|
||||
|
||||
if (device_is_dynamic_sysbus(mc, dev)) {
|
||||
@@ -1300,7 +1300,6 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
|
||||
MachineClass *mc = MACHINE_CLASS(oc);
|
||||
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
|
||||
|
||||
- mc->desc = "Loongson-3A5000 LS7A1000 machine";
|
||||
mc->init = loongarch_init;
|
||||
mc->default_ram_size = 1 * GiB;
|
||||
mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||
@@ -1341,7 +1340,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
|
||||
|
||||
static const TypeInfo loongarch_machine_types[] = {
|
||||
{
|
||||
- .name = TYPE_LOONGARCH_MACHINE,
|
||||
+ .name = TYPE_LOONGARCH_VIRT_MACHINE,
|
||||
.parent = TYPE_MACHINE,
|
||||
.instance_size = sizeof(LoongArchMachineState),
|
||||
.class_init = loongarch_class_init,
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 36158c758f..0509b9a9af 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -66,8 +66,8 @@ struct LoongArchMachineState {
|
||||
struct loongarch_boot_info bootinfo;
|
||||
};
|
||||
|
||||
-#define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt")
|
||||
-OBJECT_DECLARE_SIMPLE_TYPE(LoongArchMachineState, LOONGARCH_MACHINE)
|
||||
+#define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
|
||||
+OBJECT_DECLARE_SIMPLE_TYPE(LoongArchMachineState, LOONGARCH_VIRT_MACHINE)
|
||||
bool loongarch_is_acpi_enabled(LoongArchMachineState *lams);
|
||||
void loongarch_acpi_setup(LoongArchMachineState *lams);
|
||||
#endif
|
||||
--
|
||||
2.39.1
|
||||
|
||||
1324
hw-loongarch-Rename-LoongArchMachineState-with-Loong.patch
Normal file
1324
hw-loongarch-Rename-LoongArchMachineState-with-Loong.patch
Normal file
File diff suppressed because it is too large
Load Diff
47
hw-loongarch-boot-Use-warn_report-when-no-kernel-fil.patch
Normal file
47
hw-loongarch-boot-Use-warn_report-when-no-kernel-fil.patch
Normal file
@ -0,0 +1,47 @@
|
||||
From b7217c8f9b3f1d611485bad1263e109484a743e3 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Wed, 30 Oct 2024 09:23:59 +0800
|
||||
Subject: [PATCH 77/78] hw/loongarch/boot: Use warn_report when no kernel
|
||||
filename
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
When we run “qemu-system-loongarch64 -qmp stdio -vnc none -S”,
|
||||
we get an error message “Need kernel filename” and then we can't use qmp cmd to query some information.
|
||||
So, we just throw a warning and then the cpus starts running from address VIRT_FLASH0_BASE.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Message-ID: <20241030012359.4040817-1-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 5 ++---
|
||||
1 file changed, 2 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index cb668703bd..f258eefe9a 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -278,7 +278,7 @@ static void init_boot_rom(struct loongarch_boot_info *info, void *p)
|
||||
static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
{
|
||||
void *p, *bp;
|
||||
- int64_t kernel_addr = 0;
|
||||
+ int64_t kernel_addr = VIRT_FLASH0_BASE;
|
||||
LoongArchCPU *lacpu;
|
||||
CPUState *cs;
|
||||
|
||||
@@ -286,8 +286,7 @@ static void loongarch_direct_kernel_boot(struct loongarch_boot_info *info)
|
||||
kernel_addr = load_kernel_info(info);
|
||||
} else {
|
||||
if(!qtest_enabled()) {
|
||||
- error_report("Need kernel filename\n");
|
||||
- exit(1);
|
||||
+ warn_report("No kernel provided, booting from flash drive.");
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
35
hw-loongarch-boot.c-fix-out-of-bound-reading.patch
Normal file
35
hw-loongarch-boot.c-fix-out-of-bound-reading.patch
Normal file
@ -0,0 +1,35 @@
|
||||
From f9cc704bbcf8bb8a06095289921dc88944d0fe94 Mon Sep 17 00:00:00 2001
|
||||
From: Dmitry Frolov <frolov@swemel.ru>
|
||||
Date: Fri, 28 Jun 2024 15:39:10 +0300
|
||||
Subject: [PATCH 30/78] hw/loongarch/boot.c: fix out-of-bound reading
|
||||
|
||||
memcpy() is trying to READ 512 bytes from memory,
|
||||
pointed by info->kernel_cmdline,
|
||||
which was (presumable) allocated by g_strdup("");
|
||||
Found with ASAN, making check with enabled sanitizers.
|
||||
|
||||
Signed-off-by: Dmitry Frolov <frolov@swemel.ru>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240628123910.577740-1-frolov@swemel.ru>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index b8e1aa18d5..cb668703bd 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -163,7 +163,7 @@ static void init_cmdline(struct loongarch_boot_info *info, void *p, void *start)
|
||||
info->a0 = 1;
|
||||
info->a1 = cmdline_addr;
|
||||
|
||||
- memcpy(p, info->kernel_cmdline, COMMAND_LINE_SIZE);
|
||||
+ g_strlcpy(p, info->kernel_cmdline, COMMAND_LINE_SIZE);
|
||||
}
|
||||
|
||||
static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
|
||||
--
|
||||
2.39.1
|
||||
|
||||
197
hw-loongarch-clean-code.patch
Normal file
197
hw-loongarch-clean-code.patch
Normal file
@ -0,0 +1,197 @@
|
||||
From 4a74147e1b2e276eb2ad2855bafc3c0136bc18a3 Mon Sep 17 00:00:00 2001
|
||||
From: gaosong <gaosong@loongson.cn>
|
||||
Date: Sun, 8 Sep 2024 22:34:57 +0800
|
||||
Subject: [PATCH 76/78] hw/loongarch: clean code
|
||||
|
||||
remove some unused code
|
||||
|
||||
Signed-off-by: gaosong <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
target/loongarch/kvm/kvm.c | 103 ---------------------------
|
||||
target/loongarch/kvm/kvm_loongarch.h | 2 -
|
||||
target/loongarch/machine.c | 20 ------
|
||||
3 files changed, 125 deletions(-)
|
||||
|
||||
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
|
||||
index ab1ea3d4fd..0acdd5c4c1 100644
|
||||
--- a/target/loongarch/kvm/kvm.c
|
||||
+++ b/target/loongarch/kvm/kvm.c
|
||||
@@ -684,53 +684,6 @@ static int kvm_check_cpucfg2(CPUState *cs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int kvm_check_cpucfg6(CPUState *cs)
|
||||
-{
|
||||
- int ret;
|
||||
- uint64_t val;
|
||||
- struct kvm_device_attr attr = {
|
||||
- .group = KVM_LOONGARCH_VCPU_CPUCFG,
|
||||
- .attr = 6,
|
||||
- .addr = (uint64_t)&val,
|
||||
- };
|
||||
- LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
- CPULoongArchState *env = &cpu->env;
|
||||
-
|
||||
- ret = kvm_vcpu_ioctl(cs, KVM_HAS_DEVICE_ATTR, &attr);
|
||||
- if (!ret) {
|
||||
- kvm_vcpu_ioctl(cs, KVM_GET_DEVICE_ATTR, &attr);
|
||||
-
|
||||
- if (FIELD_EX32(env->cpucfg[6], CPUCFG6, PMP)) {
|
||||
- /* Check PMP */
|
||||
- if (!FIELD_EX32(val, CPUCFG6, PMP)) {
|
||||
- error_report("'pmu' feature not supported by KVM on this host"
|
||||
- " Please disable 'pmu' with "
|
||||
- "'... -cpu XXX,pmu=off ...'\n");
|
||||
- exit(EXIT_FAILURE);
|
||||
- }
|
||||
- /* Check PMNUM */
|
||||
- int guest_pmnum = FIELD_EX32(env->cpucfg[6], CPUCFG6, PMNUM);
|
||||
- int host_pmnum = FIELD_EX32(val, CPUCFG6, PMNUM);
|
||||
- if (guest_pmnum > host_pmnum){
|
||||
- warn_report("The guest pmnum %d larger than KVM support %d\n",
|
||||
- guest_pmnum, host_pmnum);
|
||||
- env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6,
|
||||
- PMNUM, host_pmnum);
|
||||
- }
|
||||
- /* Check PMBITS */
|
||||
- int guest_pmbits = FIELD_EX32(env->cpucfg[6], CPUCFG6, PMBITS);
|
||||
- int host_pmbits = FIELD_EX32(val, CPUCFG6, PMBITS);
|
||||
- if (guest_pmbits != host_pmbits) {
|
||||
- warn_report("The host not support PMBITS %d\n", guest_pmbits);
|
||||
- env->cpucfg[6] = FIELD_DP32(env->cpucfg[6], CPUCFG6,
|
||||
- PMBITS, host_pmbits);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
static int kvm_loongarch_put_cpucfg(CPUState *cs)
|
||||
{
|
||||
int i, ret = 0;
|
||||
@@ -745,12 +698,6 @@ static int kvm_loongarch_put_cpucfg(CPUState *cs)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
- if (i == 6) {
|
||||
- ret = kvm_check_cpucfg6(cs);
|
||||
- if (ret) {
|
||||
- return ret;
|
||||
- }
|
||||
- }
|
||||
val = env->cpucfg[i];
|
||||
ret = kvm_set_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
|
||||
if (ret < 0) {
|
||||
@@ -760,56 +707,6 @@ static int kvm_loongarch_put_cpucfg(CPUState *cs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-int kvm_loongarch_put_pvtime(LoongArchCPU *cpu)
|
||||
-{
|
||||
- CPULoongArchState *env = &cpu->env;
|
||||
- int err;
|
||||
- struct kvm_device_attr attr = {
|
||||
- .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
|
||||
- .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
|
||||
- .addr = (uint64_t)&env->st.guest_addr,
|
||||
- };
|
||||
-
|
||||
- err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr);
|
||||
- if (err != 0) {
|
||||
- /* It's ok even though kvm has not such attr */
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- err = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_DEVICE_ATTR, attr);
|
||||
- if (err != 0) {
|
||||
- error_report("PVTIME IPA: KVM_SET_DEVICE_ATTR: %s", strerror(-err));
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-int kvm_loongarch_get_pvtime(LoongArchCPU *cpu)
|
||||
-{
|
||||
- CPULoongArchState *env = &cpu->env;
|
||||
- int err;
|
||||
- struct kvm_device_attr attr = {
|
||||
- .group = KVM_LOONGARCH_VCPU_PVTIME_CTRL,
|
||||
- .attr = KVM_LOONGARCH_VCPU_PVTIME_GPA,
|
||||
- .addr = (uint64_t)&env->st.guest_addr,
|
||||
- };
|
||||
-
|
||||
- err = kvm_vcpu_ioctl(CPU(cpu), KVM_HAS_DEVICE_ATTR, attr);
|
||||
- if (err != 0) {
|
||||
- /* It's ok even though kvm has not such attr */
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- err = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_DEVICE_ATTR, attr);
|
||||
- if (err != 0) {
|
||||
- error_report("PVTIME IPA: KVM_GET_DEVICE_ATTR: %s", strerror(-err));
|
||||
- return err;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
int kvm_arch_get_registers(CPUState *cs)
|
||||
{
|
||||
int ret;
|
||||
diff --git a/target/loongarch/kvm/kvm_loongarch.h b/target/loongarch/kvm/kvm_loongarch.h
|
||||
index 8482f9308d..1051a341ec 100644
|
||||
--- a/target/loongarch/kvm/kvm_loongarch.h
|
||||
+++ b/target/loongarch/kvm/kvm_loongarch.h
|
||||
@@ -11,8 +11,6 @@
|
||||
#define QEMU_KVM_LOONGARCH_H
|
||||
|
||||
int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
|
||||
-int kvm_loongarch_put_pvtime(LoongArchCPU *cpu);
|
||||
-int kvm_loongarch_get_pvtime(LoongArchCPU *cpu);
|
||||
void kvm_arch_reset_vcpu(CPUState *cs);
|
||||
|
||||
#endif
|
||||
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
|
||||
index fd69ea05dc..57abdddc09 100644
|
||||
--- a/target/loongarch/machine.c
|
||||
+++ b/target/loongarch/machine.c
|
||||
@@ -112,24 +112,6 @@ static const VMStateDescription vmstate_lasx = {
|
||||
},
|
||||
};
|
||||
|
||||
-static int cpu_post_load(void *opaque, int version_id)
|
||||
-{
|
||||
-#ifdef CONFIG_KVM
|
||||
- LoongArchCPU *cpu = opaque;
|
||||
- kvm_loongarch_put_pvtime(cpu);
|
||||
-#endif
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int cpu_pre_save(void *opaque)
|
||||
-{
|
||||
-#ifdef CONFIG_KVM
|
||||
- LoongArchCPU *cpu = opaque;
|
||||
- kvm_loongarch_get_pvtime(cpu);
|
||||
-#endif
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static bool lbt_needed(void *opaque)
|
||||
{
|
||||
LoongArchCPU *cpu = opaque;
|
||||
@@ -190,8 +172,6 @@ const VMStateDescription vmstate_loongarch_cpu = {
|
||||
.name = "cpu",
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 3,
|
||||
- .post_load = cpu_post_load,
|
||||
- .pre_save = cpu_pre_save,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
|
||||
VMSTATE_UINTTL(env.pc, LoongArchCPU),
|
||||
--
|
||||
2.39.1
|
||||
|
||||
91
hw-loongarch-fdt-adds-Extend-I-O-Interrupt-Controlle.patch
Normal file
91
hw-loongarch-fdt-adds-Extend-I-O-Interrupt-Controlle.patch
Normal file
@ -0,0 +1,91 @@
|
||||
From ed42940a2d943fd0e666e46bbc9b599b9ed1bd75 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:45 +0800
|
||||
Subject: [PATCH 10/78] hw/loongarch: fdt adds Extend I/O Interrupt Controller
|
||||
|
||||
fdt adds Extend I/O Interrupt Controller,
|
||||
we use 'loongson,ls2k2000-eiointc'.
|
||||
|
||||
See:
|
||||
https://github.com/torvalds/linux/blob/v6.7/drivers/irqchip/irq-loongson-eiointc.c
|
||||
https://lore.kernel.org/r/764e02d924094580ac0f1d15535f4b98308705c6.1683279769.git.zhoubinbin@loongson.cn
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-12-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 30 +++++++++++++++++++++++++++++-
|
||||
include/hw/intc/loongarch_extioi.h | 1 +
|
||||
2 files changed, 30 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index fdc4a5d708..820eb52cba 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -150,6 +150,31 @@ static void fdt_add_cpuic_node(LoongArchMachineState *lams,
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
+static void fdt_add_eiointc_node(LoongArchMachineState *lams,
|
||||
+ uint32_t *cpuintc_phandle,
|
||||
+ uint32_t *eiointc_phandle)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(lams);
|
||||
+ char *nodename;
|
||||
+ hwaddr extioi_base = APIC_BASE;
|
||||
+ hwaddr extioi_size = EXTIOI_SIZE;
|
||||
+
|
||||
+ *eiointc_phandle = qemu_fdt_alloc_phandle(ms->fdt);
|
||||
+ nodename = g_strdup_printf("/eiointc@%" PRIx64, extioi_base);
|
||||
+ qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", *eiointc_phandle);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
|
||||
+ "loongson,ls2k2000-eiointc");
|
||||
+ qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 1);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
|
||||
+ *cpuintc_phandle);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupts", 3);
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0x0,
|
||||
+ extioi_base, 0x0, extioi_size);
|
||||
+ g_free(nodename);
|
||||
+}
|
||||
+
|
||||
static void fdt_add_flash_node(LoongArchMachineState *lams)
|
||||
{
|
||||
MachineState *ms = MACHINE(lams);
|
||||
@@ -574,7 +599,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
CPULoongArchState *env;
|
||||
CPUState *cpu_state;
|
||||
int cpu, pin, i, start, num;
|
||||
- uint32_t cpuintc_phandle;
|
||||
+ uint32_t cpuintc_phandle, eiointc_phandle;
|
||||
|
||||
/*
|
||||
* The connection of interrupts:
|
||||
@@ -652,6 +677,9 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* Add Extend I/O Interrupt Controller node */
|
||||
+ fdt_add_eiointc_node(lams, &cpuintc_phandle, &eiointc_phandle);
|
||||
+
|
||||
pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
|
||||
num = VIRT_PCH_PIC_IRQ_NUM;
|
||||
qdev_prop_set_uint32(pch_pic, "pch_pic_irq_num", num);
|
||||
diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
|
||||
index 98f348c49d..722ffee1bc 100644
|
||||
--- a/include/hw/intc/loongarch_extioi.h
|
||||
+++ b/include/hw/intc/loongarch_extioi.h
|
||||
@@ -39,6 +39,7 @@
|
||||
#define EXTIOI_COREISR_END (0xB20 - APIC_OFFSET)
|
||||
#define EXTIOI_COREMAP_START (0xC00 - APIC_OFFSET)
|
||||
#define EXTIOI_COREMAP_END (0xD00 - APIC_OFFSET)
|
||||
+#define EXTIOI_SIZE 0x800
|
||||
|
||||
#define EXTIOI_VIRT_BASE (0x40000000)
|
||||
#define EXTIOI_VIRT_SIZE (0x1000)
|
||||
--
|
||||
2.39.1
|
||||
|
||||
69
hw-loongarch-fdt-adds-cpu-interrupt-controller-node.patch
Normal file
69
hw-loongarch-fdt-adds-cpu-interrupt-controller-node.patch
Normal file
@ -0,0 +1,69 @@
|
||||
From cd506fbf0d9a00aa0f25de1e7bd26ad4335c8257 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:44 +0800
|
||||
Subject: [PATCH 09/78] hw/loongarch: fdt adds cpu interrupt controller node
|
||||
|
||||
fdt adds cpu interrupt controller node,
|
||||
we use 'loongson,cpu-interrupt-controller'.
|
||||
|
||||
See:
|
||||
https://github.com/torvalds/linux/blob/v6.7/drivers/irqchip/irq-loongarch-cpu.c
|
||||
https://lore.kernel.org/r/20221114113824.1880-2-liupeibao@loongson.cn
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-11-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 21 +++++++++++++++++++++
|
||||
1 file changed, 21 insertions(+)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 99a3dc8696..fdc4a5d708 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -133,6 +133,23 @@ static void virt_flash_map(LoongArchMachineState *lams,
|
||||
virt_flash_map1(flash1, VIRT_FLASH1_BASE, VIRT_FLASH1_SIZE, sysmem);
|
||||
}
|
||||
|
||||
+static void fdt_add_cpuic_node(LoongArchMachineState *lams,
|
||||
+ uint32_t *cpuintc_phandle)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(lams);
|
||||
+ char *nodename;
|
||||
+
|
||||
+ *cpuintc_phandle = qemu_fdt_alloc_phandle(ms->fdt);
|
||||
+ nodename = g_strdup_printf("/cpuic");
|
||||
+ qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", *cpuintc_phandle);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
|
||||
+ "loongson,cpu-interrupt-controller");
|
||||
+ qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 1);
|
||||
+ g_free(nodename);
|
||||
+}
|
||||
+
|
||||
static void fdt_add_flash_node(LoongArchMachineState *lams)
|
||||
{
|
||||
MachineState *ms = MACHINE(lams);
|
||||
@@ -557,6 +574,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
CPULoongArchState *env;
|
||||
CPUState *cpu_state;
|
||||
int cpu, pin, i, start, num;
|
||||
+ uint32_t cpuintc_phandle;
|
||||
|
||||
/*
|
||||
* The connection of interrupts:
|
||||
@@ -591,6 +609,9 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
memory_region_add_subregion(&lams->system_iocsr, MAIL_SEND_ADDR,
|
||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi), 1));
|
||||
|
||||
+ /* Add cpu interrupt-controller */
|
||||
+ fdt_add_cpuic_node(lams, &cpuintc_phandle);
|
||||
+
|
||||
for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
|
||||
cpu_state = qemu_get_cpu(cpu);
|
||||
cpudev = DEVICE(cpu_state);
|
||||
--
|
||||
2.39.1
|
||||
|
||||
93
hw-loongarch-fdt-adds-pch_msi-Controller.patch
Normal file
93
hw-loongarch-fdt-adds-pch_msi-Controller.patch
Normal file
@ -0,0 +1,93 @@
|
||||
From ea34d3896abfaf67cdf7fdb3cb205cc5a0e2e708 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:47 +0800
|
||||
Subject: [PATCH 12/78] hw/loongarch: fdt adds pch_msi Controller
|
||||
|
||||
fdt adds pch msi controller, we use 'loongson,pch-msi-1.0'.
|
||||
|
||||
See:
|
||||
https://github.com/torvalds/linux/blob/v6.7/drivers/irqchip/irq-loongson-pch-msi.c
|
||||
https://lore.kernel.org/r/20200528152757.1028711-6-jiaxun.yang@flygoat.com
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-14-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 33 ++++++++++++++++++++++++++++++++-
|
||||
include/hw/pci-host/ls7a.h | 1 +
|
||||
2 files changed, 33 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 36fcfd12eb..032106ebad 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -200,6 +200,34 @@ static void fdt_add_pch_pic_node(LoongArchMachineState *lams,
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
+static void fdt_add_pch_msi_node(LoongArchMachineState *lams,
|
||||
+ uint32_t *eiointc_phandle,
|
||||
+ uint32_t *pch_msi_phandle)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(lams);
|
||||
+ char *nodename;
|
||||
+ hwaddr pch_msi_base = VIRT_PCH_MSI_ADDR_LOW;
|
||||
+ hwaddr pch_msi_size = VIRT_PCH_MSI_SIZE;
|
||||
+
|
||||
+ *pch_msi_phandle = qemu_fdt_alloc_phandle(ms->fdt);
|
||||
+ nodename = g_strdup_printf("/msi@%" PRIx64, pch_msi_base);
|
||||
+ qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", *pch_msi_phandle);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
|
||||
+ "loongson,pch-msi-1.0");
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg",
|
||||
+ 0, pch_msi_base,
|
||||
+ 0, pch_msi_size);
|
||||
+ qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
|
||||
+ *eiointc_phandle);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "loongson,msi-base-vec",
|
||||
+ VIRT_PCH_PIC_IRQ_NUM);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "loongson,msi-num-vecs",
|
||||
+ EXTIOI_IRQS - VIRT_PCH_PIC_IRQ_NUM);
|
||||
+ g_free(nodename);
|
||||
+}
|
||||
+
|
||||
static void fdt_add_flash_node(LoongArchMachineState *lams)
|
||||
{
|
||||
MachineState *ms = MACHINE(lams);
|
||||
@@ -624,7 +652,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
CPULoongArchState *env;
|
||||
CPUState *cpu_state;
|
||||
int cpu, pin, i, start, num;
|
||||
- uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle;
|
||||
+ uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle, pch_msi_phandle;
|
||||
|
||||
/*
|
||||
* The connection of interrupts:
|
||||
@@ -741,6 +769,9 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
qdev_get_gpio_in(extioi, i + start));
|
||||
}
|
||||
|
||||
+ /* Add PCH MSI node */
|
||||
+ fdt_add_pch_msi_node(lams, &eiointc_phandle, &pch_msi_phandle);
|
||||
+
|
||||
loongarch_devices_init(pch_pic, lams);
|
||||
}
|
||||
|
||||
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
|
||||
index fe260f0183..cd7c9ec7bc 100644
|
||||
--- a/include/hw/pci-host/ls7a.h
|
||||
+++ b/include/hw/pci-host/ls7a.h
|
||||
@@ -25,6 +25,7 @@
|
||||
#define VIRT_IOAPIC_REG_BASE (VIRT_PCH_REG_BASE)
|
||||
#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL
|
||||
#define VIRT_PCH_REG_SIZE 0x400
|
||||
+#define VIRT_PCH_MSI_SIZE 0x8
|
||||
|
||||
/*
|
||||
* GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot
|
||||
--
|
||||
2.39.1
|
||||
|
||||
90
hw-loongarch-fdt-adds-pch_pic-Controller.patch
Normal file
90
hw-loongarch-fdt-adds-pch_pic-Controller.patch
Normal file
@ -0,0 +1,90 @@
|
||||
From 78222abb3bde044b4520f23c6fc2f0f0bd805d2a Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:46 +0800
|
||||
Subject: [PATCH 11/78] hw/loongarch: fdt adds pch_pic Controller
|
||||
|
||||
fdt adds pch pic controller, we use 'loongson,pch-pic-1.0'
|
||||
|
||||
See:
|
||||
https://github.com/torvalds/linux/blob/v6.7/drivers/irqchip/irq-loongson-pch-pic.c
|
||||
https://lore.kernel.org/r/20200528152757.1028711-4-jiaxun.yang@flygoat.com
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-13-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 30 +++++++++++++++++++++++++++++-
|
||||
include/hw/pci-host/ls7a.h | 1 +
|
||||
2 files changed, 30 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 820eb52cba..36fcfd12eb 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -175,6 +175,31 @@ static void fdt_add_eiointc_node(LoongArchMachineState *lams,
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
+static void fdt_add_pch_pic_node(LoongArchMachineState *lams,
|
||||
+ uint32_t *eiointc_phandle,
|
||||
+ uint32_t *pch_pic_phandle)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(lams);
|
||||
+ char *nodename;
|
||||
+ hwaddr pch_pic_base = VIRT_PCH_REG_BASE;
|
||||
+ hwaddr pch_pic_size = VIRT_PCH_REG_SIZE;
|
||||
+
|
||||
+ *pch_pic_phandle = qemu_fdt_alloc_phandle(ms->fdt);
|
||||
+ nodename = g_strdup_printf("/platic@%" PRIx64, pch_pic_base);
|
||||
+ qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", *pch_pic_phandle);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
|
||||
+ "loongson,pch-pic-1.0");
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0,
|
||||
+ pch_pic_base, 0, pch_pic_size);
|
||||
+ qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 2);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
|
||||
+ *eiointc_phandle);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, nodename, "loongson,pic-base-vec", 0);
|
||||
+ g_free(nodename);
|
||||
+}
|
||||
+
|
||||
static void fdt_add_flash_node(LoongArchMachineState *lams)
|
||||
{
|
||||
MachineState *ms = MACHINE(lams);
|
||||
@@ -599,7 +624,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
CPULoongArchState *env;
|
||||
CPUState *cpu_state;
|
||||
int cpu, pin, i, start, num;
|
||||
- uint32_t cpuintc_phandle, eiointc_phandle;
|
||||
+ uint32_t cpuintc_phandle, eiointc_phandle, pch_pic_phandle;
|
||||
|
||||
/*
|
||||
* The connection of interrupts:
|
||||
@@ -699,6 +724,9 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
qdev_connect_gpio_out(DEVICE(d), i, qdev_get_gpio_in(extioi, i));
|
||||
}
|
||||
|
||||
+ /* Add PCH PIC node */
|
||||
+ fdt_add_pch_pic_node(lams, &eiointc_phandle, &pch_pic_phandle);
|
||||
+
|
||||
pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
|
||||
start = num;
|
||||
num = EXTIOI_IRQS - start;
|
||||
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
|
||||
index e753449593..fe260f0183 100644
|
||||
--- a/include/hw/pci-host/ls7a.h
|
||||
+++ b/include/hw/pci-host/ls7a.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#define VIRT_PCH_REG_BASE 0x10000000UL
|
||||
#define VIRT_IOAPIC_REG_BASE (VIRT_PCH_REG_BASE)
|
||||
#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL
|
||||
+#define VIRT_PCH_REG_SIZE 0x400
|
||||
|
||||
/*
|
||||
* GSI_BASE is hard-coded with 64 in linux kernel, else kernel fails to boot
|
||||
--
|
||||
2.39.1
|
||||
|
||||
137
hw-loongarch-fdt-adds-pcie-irq_map-node.patch
Normal file
137
hw-loongarch-fdt-adds-pcie-irq_map-node.patch
Normal file
@ -0,0 +1,137 @@
|
||||
From 1325effbd595781b9ab75dceab9f87944156c606 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:48 +0800
|
||||
Subject: [PATCH 13/78] hw/loongarch: fdt adds pcie irq_map node
|
||||
|
||||
This patch adds pcie irq_map node for FDT.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-15-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 73 ++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 69 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 032106ebad..c32cc3c818 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -379,7 +379,62 @@ static void fdt_add_fw_cfg_node(const LoongArchMachineState *lams)
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
-static void fdt_add_pcie_node(const LoongArchMachineState *lams)
|
||||
+static void fdt_add_pcie_irq_map_node(const LoongArchMachineState *lams,
|
||||
+ char *nodename,
|
||||
+ uint32_t *pch_pic_phandle)
|
||||
+{
|
||||
+ int pin, dev;
|
||||
+ uint32_t irq_map_stride = 0;
|
||||
+ uint32_t full_irq_map[GPEX_NUM_IRQS *GPEX_NUM_IRQS * 10] = {};
|
||||
+ uint32_t *irq_map = full_irq_map;
|
||||
+ const MachineState *ms = MACHINE(lams);
|
||||
+
|
||||
+ /* This code creates a standard swizzle of interrupts such that
|
||||
+ * each device's first interrupt is based on it's PCI_SLOT number.
|
||||
+ * (See pci_swizzle_map_irq_fn())
|
||||
+ *
|
||||
+ * We only need one entry per interrupt in the table (not one per
|
||||
+ * possible slot) seeing the interrupt-map-mask will allow the table
|
||||
+ * to wrap to any number of devices.
|
||||
+ */
|
||||
+
|
||||
+ for (dev = 0; dev < GPEX_NUM_IRQS; dev++) {
|
||||
+ int devfn = dev * 0x8;
|
||||
+
|
||||
+ for (pin = 0; pin < GPEX_NUM_IRQS; pin++) {
|
||||
+ int irq_nr = 16 + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS);
|
||||
+ int i = 0;
|
||||
+
|
||||
+ /* Fill PCI address cells */
|
||||
+ irq_map[i] = cpu_to_be32(devfn << 8);
|
||||
+ i += 3;
|
||||
+
|
||||
+ /* Fill PCI Interrupt cells */
|
||||
+ irq_map[i] = cpu_to_be32(pin + 1);
|
||||
+ i += 1;
|
||||
+
|
||||
+ /* Fill interrupt controller phandle and cells */
|
||||
+ irq_map[i++] = cpu_to_be32(*pch_pic_phandle);
|
||||
+ irq_map[i++] = cpu_to_be32(irq_nr);
|
||||
+
|
||||
+ if (!irq_map_stride) {
|
||||
+ irq_map_stride = i;
|
||||
+ }
|
||||
+ irq_map += irq_map_stride;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+
|
||||
+ qemu_fdt_setprop(ms->fdt, nodename, "interrupt-map", full_irq_map,
|
||||
+ GPEX_NUM_IRQS * GPEX_NUM_IRQS *
|
||||
+ irq_map_stride * sizeof(uint32_t));
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupt-map-mask",
|
||||
+ 0x1800, 0, 0, 0x7);
|
||||
+}
|
||||
+
|
||||
+static void fdt_add_pcie_node(const LoongArchMachineState *lams,
|
||||
+ uint32_t *pch_pic_phandle,
|
||||
+ uint32_t *pch_msi_phandle)
|
||||
{
|
||||
char *nodename;
|
||||
hwaddr base_mmio = VIRT_PCI_MEM_BASE;
|
||||
@@ -410,6 +465,11 @@ static void fdt_add_pcie_node(const LoongArchMachineState *lams)
|
||||
2, base_pio, 2, size_pio,
|
||||
1, FDT_PCI_RANGE_MMIO, 2, base_mmio,
|
||||
2, base_mmio, 2, size_mmio);
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "msi-map",
|
||||
+ 0, *pch_msi_phandle, 0, 0x10000);
|
||||
+
|
||||
+ fdt_add_pcie_irq_map_node(lams, nodename, pch_pic_phandle);
|
||||
+
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
@@ -569,7 +629,10 @@ static DeviceState *create_platform_bus(DeviceState *pch_pic)
|
||||
return dev;
|
||||
}
|
||||
|
||||
-static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *lams)
|
||||
+static void loongarch_devices_init(DeviceState *pch_pic,
|
||||
+ LoongArchMachineState *lams,
|
||||
+ uint32_t *pch_pic_phandle,
|
||||
+ uint32_t *pch_msi_phandle)
|
||||
{
|
||||
MachineClass *mc = MACHINE_GET_CLASS(lams);
|
||||
DeviceState *gpex_dev;
|
||||
@@ -615,6 +678,9 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *
|
||||
gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
|
||||
}
|
||||
|
||||
+ /* Add pcie node */
|
||||
+ fdt_add_pcie_node(lams, pch_pic_phandle, pch_msi_phandle);
|
||||
+
|
||||
serial_mm_init(get_system_memory(), VIRT_UART_BASE, 0,
|
||||
qdev_get_gpio_in(pch_pic,
|
||||
VIRT_UART_IRQ - VIRT_GSI_BASE),
|
||||
@@ -772,7 +838,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
|
||||
/* Add PCH MSI node */
|
||||
fdt_add_pch_msi_node(lams, &eiointc_phandle, &pch_msi_phandle);
|
||||
|
||||
- loongarch_devices_init(pch_pic, lams);
|
||||
+ loongarch_devices_init(pch_pic, lams, &pch_pic_phandle, &pch_msi_phandle);
|
||||
}
|
||||
|
||||
static void loongarch_firmware_init(LoongArchMachineState *lams)
|
||||
@@ -1048,7 +1114,6 @@ static void loongarch_init(MachineState *machine)
|
||||
lams->powerdown_notifier.notify = virt_powerdown_req;
|
||||
qemu_register_powerdown_notifier(&lams->powerdown_notifier);
|
||||
|
||||
- fdt_add_pcie_node(lams);
|
||||
/*
|
||||
* Since lowmem region starts from 0 and Linux kernel legacy start address
|
||||
* at 2 MiB, FDT base address is located at 1 MiB to avoid NULL pointer
|
||||
--
|
||||
2.39.1
|
||||
|
||||
67
hw-loongarch-fdt-remove-unused-irqchip-node.patch
Normal file
67
hw-loongarch-fdt-remove-unused-irqchip-node.patch
Normal file
@ -0,0 +1,67 @@
|
||||
From e87697c72641ab2209d4004f573f47283d118235 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Fri, 26 Apr 2024 17:15:49 +0800
|
||||
Subject: [PATCH 14/78] hw/loongarch: fdt remove unused irqchip node
|
||||
|
||||
This patch removes the unused fdt irqchip node.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240426091551.2397867-16-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 31 +------------------------------
|
||||
1 file changed, 1 insertion(+), 30 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index c32cc3c818..ff9513034b 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -473,34 +473,6 @@ static void fdt_add_pcie_node(const LoongArchMachineState *lams,
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
-static void fdt_add_irqchip_node(LoongArchMachineState *lams)
|
||||
-{
|
||||
- MachineState *ms = MACHINE(lams);
|
||||
- char *nodename;
|
||||
- uint32_t irqchip_phandle;
|
||||
-
|
||||
- irqchip_phandle = qemu_fdt_alloc_phandle(ms->fdt);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, "/", "interrupt-parent", irqchip_phandle);
|
||||
-
|
||||
- nodename = g_strdup_printf("/intc@%lx", VIRT_IOAPIC_REG_BASE);
|
||||
- qemu_fdt_add_subnode(ms->fdt, nodename);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 3);
|
||||
- qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x2);
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 0x2);
|
||||
- qemu_fdt_setprop(ms->fdt, nodename, "ranges", NULL, 0);
|
||||
-
|
||||
- qemu_fdt_setprop_string(ms->fdt, nodename, "compatible",
|
||||
- "loongarch,ls7a");
|
||||
-
|
||||
- qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg",
|
||||
- 2, VIRT_IOAPIC_REG_BASE,
|
||||
- 2, PCH_PIC_ROUTE_ENTRY_OFFSET);
|
||||
-
|
||||
- qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", irqchip_phandle);
|
||||
- g_free(nodename);
|
||||
-}
|
||||
-
|
||||
static void fdt_add_memory_node(MachineState *ms,
|
||||
uint64_t base, uint64_t size, int node_id)
|
||||
{
|
||||
@@ -1103,8 +1075,7 @@ static void loongarch_init(MachineState *machine)
|
||||
|
||||
/* Initialize the IO interrupt subsystem */
|
||||
loongarch_irq_init(lams);
|
||||
- fdt_add_irqchip_node(lams);
|
||||
- platform_bus_add_all_fdt_nodes(machine->fdt, "/intc",
|
||||
+ platform_bus_add_all_fdt_nodes(machine->fdt, "/platic",
|
||||
VIRT_PLATFORM_BUS_BASEADDRESS,
|
||||
VIRT_PLATFORM_BUS_SIZE,
|
||||
VIRT_PLATFORM_BUS_IRQ);
|
||||
--
|
||||
2.39.1
|
||||
|
||||
51
hw-loongarch-fix-cpu-hotplug-reset.patch
Normal file
51
hw-loongarch-fix-cpu-hotplug-reset.patch
Normal file
@ -0,0 +1,51 @@
|
||||
From f3f7b49a8a323ebfe2be176985336aaf2c97c6c2 Mon Sep 17 00:00:00 2001
|
||||
From: gaosong <gaosong@loongson.cn>
|
||||
Date: Mon, 9 Sep 2024 04:14:49 +0800
|
||||
Subject: [PATCH 78/78] hw/loongarch: fix cpu hotplug reset
|
||||
|
||||
Signed-off-by: gaosong <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/boot.c | 2 +-
|
||||
hw/loongarch/virt.c | 1 +
|
||||
include/hw/loongarch/virt.h | 1 +
|
||||
3 files changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index f258eefe9a..53dcefbb55 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -216,7 +216,7 @@ static int64_t load_kernel_info(struct loongarch_boot_info *info)
|
||||
return kernel_entry;
|
||||
}
|
||||
|
||||
-static void reset_load_elf(void *opaque)
|
||||
+void reset_load_elf(void *opaque)
|
||||
{
|
||||
LoongArchCPU *cpu = opaque;
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 5b0468f6cb..0c24e632bb 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -1494,6 +1494,7 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev,
|
||||
env = &(cpu->env);
|
||||
env->address_space_iocsr = &lvms->as_iocsr;
|
||||
|
||||
+ qemu_register_reset(reset_load_elf, LOONGARCH_CPU(qemu_get_cpu(cs->cpu_index)));
|
||||
env->ipistate = lvms->ipi;
|
||||
if (!(kvm_enabled() && kvm_irqchip_in_kernel())) {
|
||||
/* connect ipi irq to cpu irq, logic cpu index used here */
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 168b40c31b..a79ad41663 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -86,4 +86,5 @@ struct LoongArchVirtMachineState {
|
||||
#define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(LoongArchVirtMachineState, LOONGARCH_VIRT_MACHINE)
|
||||
void loongarch_acpi_setup(LoongArchVirtMachineState *lvms);
|
||||
+void reset_load_elf(void *opaque);
|
||||
#endif
|
||||
--
|
||||
2.39.1
|
||||
|
||||
113
hw-loongarch-move-memory-map-to-boot.c.patch
Normal file
113
hw-loongarch-move-memory-map-to-boot.c.patch
Normal file
@ -0,0 +1,113 @@
|
||||
From 5e4d612de23539499b9a22986bebe9a3007edae1 Mon Sep 17 00:00:00 2001
|
||||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Tue, 7 May 2024 16:51:35 +0200
|
||||
Subject: [PATCH 18/78] hw/loongarch: move memory map to boot.c
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Ensure that it can be used even if virt.c is not included in the build, as
|
||||
is the case for --without-default-devices.
|
||||
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Acked-by: Richard Henderson <richard.henderson@linaro.org>
|
||||
Message-ID: <20240507145135.270803-1-pbonzini@redhat.com>
|
||||
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
.gitlab-ci.d/buildtest.yml | 5 +++--
|
||||
hw/loongarch/boot.c | 3 +++
|
||||
hw/loongarch/virt.c | 3 ---
|
||||
include/hw/loongarch/boot.h | 10 ++++++++++
|
||||
include/hw/loongarch/virt.h | 10 ----------
|
||||
5 files changed, 16 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
|
||||
index 3fb99e79e9..983c3c132e 100644
|
||||
--- a/.gitlab-ci.d/buildtest.yml
|
||||
+++ b/.gitlab-ci.d/buildtest.yml
|
||||
@@ -579,8 +579,9 @@ build-tci:
|
||||
- make check-tcg
|
||||
|
||||
# Check our reduced build configurations
|
||||
-# requires libfdt: aarch64, arm, i386, loongarch64, x86_64
|
||||
-# does not build without boards: i386, loongarch64, x86_64
|
||||
+# requires libfdt: aarch64, arm, i386, loongarch64, microblaze, microblazeel,
|
||||
+# mips64el, or1k, ppc, ppc64, riscv32, riscv64, rx, x86_64
|
||||
+# does not build without boards: i386, s390x, sh4, sh4eb, x86_64
|
||||
build-without-defaults:
|
||||
extends: .native_build_job_template
|
||||
needs:
|
||||
diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c
|
||||
index 7d1630b2e7..03f6301a77 100644
|
||||
--- a/hw/loongarch/boot.c
|
||||
+++ b/hw/loongarch/boot.c
|
||||
@@ -15,6 +15,9 @@
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/qtest.h"
|
||||
|
||||
+struct memmap_entry *memmap_table;
|
||||
+unsigned memmap_entries;
|
||||
+
|
||||
ram_addr_t initrd_offset;
|
||||
uint64_t initrd_size;
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 0972ebd150..76b36539e2 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -543,9 +543,6 @@ static void virt_powerdown_req(Notifier *notifier, void *opaque)
|
||||
acpi_send_event(s->acpi_ged, ACPI_POWER_DOWN_STATUS);
|
||||
}
|
||||
|
||||
-struct memmap_entry *memmap_table;
|
||||
-unsigned memmap_entries;
|
||||
-
|
||||
static void memmap_add_entry(uint64_t address, uint64_t length, uint32_t type)
|
||||
{
|
||||
/* Ensure there are no duplicate entries. */
|
||||
diff --git a/include/hw/loongarch/boot.h b/include/hw/loongarch/boot.h
|
||||
index 4ebcc89dcf..b3b870df1f 100644
|
||||
--- a/include/hw/loongarch/boot.h
|
||||
+++ b/include/hw/loongarch/boot.h
|
||||
@@ -104,6 +104,16 @@ struct loongarch_boot_info {
|
||||
uint64_t a0, a1, a2;
|
||||
};
|
||||
|
||||
+extern struct memmap_entry *memmap_table;
|
||||
+extern unsigned memmap_entries;
|
||||
+
|
||||
+struct memmap_entry {
|
||||
+ uint64_t address;
|
||||
+ uint64_t length;
|
||||
+ uint32_t type;
|
||||
+ uint32_t reserved;
|
||||
+};
|
||||
+
|
||||
void loongarch_load_kernel(MachineState *ms, struct loongarch_boot_info *info);
|
||||
|
||||
#endif /* HW_LOONGARCH_BOOT_H */
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 673b57aa2b..36158c758f 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -37,16 +37,6 @@
|
||||
|
||||
#define FDT_BASE 0x100000
|
||||
|
||||
-extern struct memmap_entry *memmap_table;
|
||||
-extern unsigned memmap_entries;
|
||||
-
|
||||
-struct memmap_entry {
|
||||
- uint64_t address;
|
||||
- uint64_t length;
|
||||
- uint32_t type;
|
||||
- uint32_t reserved;
|
||||
-};
|
||||
-
|
||||
struct LoongArchMachineState {
|
||||
/*< private >*/
|
||||
MachineState parent_obj;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
278
hw-loongarch-virt-Add-CPU-topology-support.patch
Normal file
278
hw-loongarch-virt-Add-CPU-topology-support.patch
Normal file
@ -0,0 +1,278 @@
|
||||
From 8d440efd992fd6be0aca55118a9b60c224f6eade Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 23 Oct 2024 15:13:10 +0800
|
||||
Subject: [PATCH 69/78] hw/loongarch/virt: Add CPU topology support
|
||||
|
||||
Add topological relationships for Loongarch VCPU and initialize
|
||||
topology member variables. Also physical cpu id calculation
|
||||
method comes from its topo information.
|
||||
|
||||
Co-developed-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-ID: <20241023071312.881866-2-maobibo@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
docs/system/loongarch/virt.rst | 31 +++++++++++++
|
||||
hw/loongarch/virt.c | 82 ++++++++++++++++++++++++++++------
|
||||
target/loongarch/cpu.c | 12 +++++
|
||||
target/loongarch/cpu.h | 11 +++++
|
||||
4 files changed, 122 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/docs/system/loongarch/virt.rst b/docs/system/loongarch/virt.rst
|
||||
index c37268b404..aa4719d4bd 100644
|
||||
--- a/docs/system/loongarch/virt.rst
|
||||
+++ b/docs/system/loongarch/virt.rst
|
||||
@@ -28,6 +28,37 @@ The ``qemu-system-loongarch64`` provides emulation for virt
|
||||
machine. You can specify the machine type ``virt`` and
|
||||
cpu type ``la464``.
|
||||
|
||||
+CPU Topology
|
||||
+------------
|
||||
+
|
||||
+The ``LA464`` type CPUs have the concept of Socket Core and Thread.
|
||||
+
|
||||
+For example:
|
||||
+
|
||||
+``-smp 1,maxcpus=M,sockets=S,cores=C,threads=T``
|
||||
+
|
||||
+The above parameters indicate that the machine has a maximum of ``M`` vCPUs and
|
||||
+``S`` sockets, each socket has ``C`` cores, each core has ``T`` threads,
|
||||
+and each thread corresponds to a vCPU.
|
||||
+
|
||||
+Then ``M`` ``S`` ``C`` ``T`` has the following relationship:
|
||||
+
|
||||
+``M = S * C * T``
|
||||
+
|
||||
+In the CPU topology relationship, When we know the ``socket_id`` ``core_id``
|
||||
+and ``thread_id`` of the CPU, we can calculate its ``arch_id``:
|
||||
+
|
||||
+``arch_id = (socket_id * S) + (core_id * C) + (thread_id * T)``
|
||||
+
|
||||
+Similarly, when we know the ``arch_id`` of the CPU,
|
||||
+we can also get its ``socket_id`` ``core_id`` and ``thread_id``:
|
||||
+
|
||||
+``socket_id = arch_id / (C * T)``
|
||||
+
|
||||
+``core_id = (arch_id / T) % C``
|
||||
+
|
||||
+``thread_id = arch_id % T``
|
||||
+
|
||||
Boot options
|
||||
------------
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 9510aa7a7e..8d1e53ff62 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -1123,9 +1123,7 @@ static void virt_init(MachineState *machine)
|
||||
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
|
||||
int i;
|
||||
hwaddr base, size, ram_size = machine->ram_size;
|
||||
- const CPUArchIdList *possible_cpus;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
- CPUState *cpu;
|
||||
|
||||
if (!cpu_model) {
|
||||
cpu_model = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||
@@ -1143,14 +1141,39 @@ static void virt_init(MachineState *machine)
|
||||
memory_region_add_subregion(&lvms->system_iocsr, 0, &lvms->iocsr_mem);
|
||||
|
||||
/* Init CPUs */
|
||||
- possible_cpus = mc->possible_cpu_arch_ids(machine);
|
||||
- for (i = 0; i < possible_cpus->len; i++) {
|
||||
- cpu = cpu_create(machine->cpu_type);
|
||||
- cpu->cpu_index = i;
|
||||
- machine->possible_cpus->cpus[i].cpu = OBJECT(cpu);
|
||||
- lacpu = LOONGARCH_CPU(cpu);
|
||||
+ mc->possible_cpu_arch_ids(machine);
|
||||
+ for (i = 0; i < machine->smp.cpus; i++) {
|
||||
+ Object *cpuobj;
|
||||
+ cpuobj = object_new(machine->cpu_type);
|
||||
+ lacpu = LOONGARCH_CPU(cpuobj);
|
||||
+
|
||||
lacpu->phy_id = machine->possible_cpus->cpus[i].arch_id;
|
||||
+ object_property_set_int(cpuobj, "socket-id",
|
||||
+ machine->possible_cpus->cpus[i].props.socket_id,
|
||||
+ NULL);
|
||||
+ object_property_set_int(cpuobj, "core-id",
|
||||
+ machine->possible_cpus->cpus[i].props.core_id,
|
||||
+ NULL);
|
||||
+ object_property_set_int(cpuobj, "thread-id",
|
||||
+ machine->possible_cpus->cpus[i].props.thread_id,
|
||||
+ NULL);
|
||||
+ /*
|
||||
+ * The CPU in place at the time of machine startup will also enter
|
||||
+ * the CPU hot-plug process when it is created, but at this time,
|
||||
+ * the GED device has not been created, resulting in exit in the CPU
|
||||
+ * hot-plug process, which can avoid the incumbent CPU repeatedly
|
||||
+ * applying for resources.
|
||||
+ *
|
||||
+ * The interrupt resource of the in-place CPU will be requested at
|
||||
+ * the current function call loongarch_irq_init().
|
||||
+ *
|
||||
+ * The interrupt resource of the subsequently inserted CPU will be
|
||||
+ * requested in the CPU hot-plug process.
|
||||
+ */
|
||||
+ qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
|
||||
+ object_unref(cpuobj);
|
||||
}
|
||||
+
|
||||
fdt_add_cpu_nodes(lvms);
|
||||
fdt_add_memory_nodes(machine);
|
||||
fw_cfg_add_memory(machine);
|
||||
@@ -1266,6 +1289,27 @@ static void virt_initfn(Object *obj)
|
||||
virt_flash_create(lvms);
|
||||
}
|
||||
|
||||
+static int virt_get_arch_id_from_topo(MachineState *ms, LoongArchCPUTopo *topo)
|
||||
+{
|
||||
+ int arch_id, sock_vcpu_num, core_vcpu_num;
|
||||
+
|
||||
+ /*
|
||||
+ * calculate total logical cpus across socket/core/thread.
|
||||
+ * For more information on how to calculate the arch_id,
|
||||
+ * you can refer to the CPU Topology chapter of the
|
||||
+ * docs/system/loongarch/virt.rst document.
|
||||
+ */
|
||||
+ sock_vcpu_num = topo->socket_id * (ms->smp.threads * ms->smp.cores);
|
||||
+ core_vcpu_num = topo->core_id * ms->smp.threads;
|
||||
+
|
||||
+ /* get vcpu-id(logical cpu index) for this vcpu from this topology */
|
||||
+ arch_id = (sock_vcpu_num + core_vcpu_num) + topo->thread_id;
|
||||
+
|
||||
+ assert(arch_id >= 0 && arch_id < ms->possible_cpus->len);
|
||||
+
|
||||
+ return arch_id;
|
||||
+}
|
||||
+
|
||||
static bool memhp_type_supported(DeviceState *dev)
|
||||
{
|
||||
/* we only support pc dimm now */
|
||||
@@ -1363,10 +1407,19 @@ static HotplugHandler *virt_get_hotplug_handler(MachineState *machine,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static void virt_get_cpu_topo_from_index(MachineState *ms,
|
||||
+ LoongArchCPUTopo *topo, int index)
|
||||
+{
|
||||
+ topo->socket_id = index / (ms->smp.cores * ms->smp.threads);
|
||||
+ topo->core_id = index / ms->smp.threads % ms->smp.cores;
|
||||
+ topo->thread_id = index % ms->smp.threads;
|
||||
+}
|
||||
+
|
||||
static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
||||
{
|
||||
int n;
|
||||
unsigned int max_cpus = ms->smp.max_cpus;
|
||||
+ LoongArchCPUTopo topo;
|
||||
|
||||
if (ms->possible_cpus) {
|
||||
assert(ms->possible_cpus->len == max_cpus);
|
||||
@@ -1377,17 +1430,18 @@ static const CPUArchIdList *virt_possible_cpu_arch_ids(MachineState *ms)
|
||||
sizeof(CPUArchId) * max_cpus);
|
||||
ms->possible_cpus->len = max_cpus;
|
||||
for (n = 0; n < ms->possible_cpus->len; n++) {
|
||||
+ ms->possible_cpus->cpus[n].vcpus_count = ms->smp.threads;
|
||||
ms->possible_cpus->cpus[n].type = ms->cpu_type;
|
||||
- ms->possible_cpus->cpus[n].arch_id = n;
|
||||
+ virt_get_cpu_topo_from_index(ms, &topo, n);
|
||||
|
||||
ms->possible_cpus->cpus[n].props.has_socket_id = true;
|
||||
- ms->possible_cpus->cpus[n].props.socket_id =
|
||||
- n / (ms->smp.cores * ms->smp.threads);
|
||||
+ ms->possible_cpus->cpus[n].props.socket_id = topo.socket_id;
|
||||
ms->possible_cpus->cpus[n].props.has_core_id = true;
|
||||
- ms->possible_cpus->cpus[n].props.core_id =
|
||||
- n / ms->smp.threads % ms->smp.cores;
|
||||
+ ms->possible_cpus->cpus[n].props.core_id = topo.core_id;
|
||||
ms->possible_cpus->cpus[n].props.has_thread_id = true;
|
||||
- ms->possible_cpus->cpus[n].props.thread_id = n % ms->smp.threads;
|
||||
+ ms->possible_cpus->cpus[n].props.thread_id = topo.thread_id;
|
||||
+ ms->possible_cpus->cpus[n].arch_id =
|
||||
+ virt_get_arch_id_from_topo(ms, &topo);
|
||||
}
|
||||
return ms->possible_cpus;
|
||||
}
|
||||
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
|
||||
index 2ee1d63989..673ed8ea18 100644
|
||||
--- a/target/loongarch/cpu.c
|
||||
+++ b/target/loongarch/cpu.c
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "kvm/kvm_loongarch.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "cpu.h"
|
||||
+#include "hw/qdev-properties.h"
|
||||
#include "internals.h"
|
||||
#include "fpu/softfloat-helpers.h"
|
||||
#include "cpu-csr.h"
|
||||
@@ -860,6 +861,15 @@ static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
|
||||
}
|
||||
#endif
|
||||
|
||||
+static Property loongarch_cpu_properties[] = {
|
||||
+ DEFINE_PROP_INT32("socket-id", LoongArchCPU, socket_id, 0),
|
||||
+ DEFINE_PROP_INT32("core-id", LoongArchCPU, core_id, 0),
|
||||
+ DEFINE_PROP_INT32("thread-id", LoongArchCPU, thread_id, 0),
|
||||
+ DEFINE_PROP_INT32("node-id", LoongArchCPU, node_id, CPU_UNSET_NUMA_NODE_ID),
|
||||
+
|
||||
+ DEFINE_PROP_END_OF_LIST()
|
||||
+};
|
||||
+
|
||||
static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
||||
{
|
||||
LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
|
||||
@@ -867,6 +877,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
||||
DeviceClass *dc = DEVICE_CLASS(c);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(c);
|
||||
|
||||
+ device_class_set_props(dc, loongarch_cpu_properties);
|
||||
device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
|
||||
&lacc->parent_realize);
|
||||
resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, NULL,
|
||||
@@ -890,6 +901,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
||||
#ifdef CONFIG_TCG
|
||||
cc->tcg_ops = &loongarch_tcg_ops;
|
||||
#endif
|
||||
+ dc->user_creatable = true;
|
||||
}
|
||||
|
||||
static const gchar *loongarch32_gdb_arch_name(CPUState *cs)
|
||||
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
|
||||
index 4c90cf9ef3..9af622aba5 100644
|
||||
--- a/target/loongarch/cpu.h
|
||||
+++ b/target/loongarch/cpu.h
|
||||
@@ -398,6 +398,12 @@ typedef struct CPUArchState {
|
||||
} st;
|
||||
} CPULoongArchState;
|
||||
|
||||
+typedef struct LoongArchCPUTopo {
|
||||
+ int32_t socket_id; /* socket-id of this VCPU */
|
||||
+ int32_t core_id; /* core-id of this VCPU */
|
||||
+ int32_t thread_id; /* thread-id of this VCPU */
|
||||
+} LoongArchCPUTopo;
|
||||
+
|
||||
/**
|
||||
* LoongArchCPU:
|
||||
* @env: #CPULoongArchState
|
||||
@@ -412,6 +418,10 @@ struct ArchCPU {
|
||||
uint32_t phy_id;
|
||||
OnOffAuto lbt;
|
||||
OnOffAuto pmu;
|
||||
+ int32_t socket_id; /* socket-id of this VCPU */
|
||||
+ int32_t core_id; /* core-id of this VCPU */
|
||||
+ int32_t thread_id; /* thread-id of this VCPU */
|
||||
+ int32_t node_id; /* NUMA node this CPU belongs to */
|
||||
|
||||
/* 'compatible' string for this CPU for Linux device trees */
|
||||
const char *dtb_compatible;
|
||||
@@ -430,6 +440,7 @@ struct LoongArchCPUClass {
|
||||
CPUClass parent_class;
|
||||
|
||||
DeviceRealize parent_realize;
|
||||
+ DeviceUnrealize parent_unrealize;
|
||||
ResettablePhases parent_phases;
|
||||
};
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
84
hw-loongarch-virt-Add-FDT-table-support-with-acpi-ge.patch
Normal file
84
hw-loongarch-virt-Add-FDT-table-support-with-acpi-ge.patch
Normal file
@ -0,0 +1,84 @@
|
||||
From fa276847efb3fd47a730d279f1b14705fe3991b1 Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 18 Sep 2024 09:42:06 +0800
|
||||
Subject: [PATCH 39/78] hw/loongarch/virt: Add FDT table support with acpi ged
|
||||
pm register
|
||||
|
||||
ACPI ged is used for power management on LoongArch virt platform, in
|
||||
general it is parsed from acpi table. However if system boot directly from
|
||||
elf kernel, no UEFI bios is provided and acpi table cannot be used also.
|
||||
|
||||
Here acpi ged pm register is exposed with FDT table, it is compatbile
|
||||
with syscon method in FDT table, only that acpi ged pm register is accessed
|
||||
with 8-bit mode, rather with 32-bit mode.
|
||||
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Tested-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240918014206.2165821-3-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 39 +++++++++++++++++++++++++++++++++++++++
|
||||
1 file changed, 39 insertions(+)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 9f47107379..9510aa7a7e 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -281,6 +281,44 @@ static void fdt_add_rtc_node(LoongArchVirtMachineState *lvms,
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
+static void fdt_add_ged_reset(LoongArchVirtMachineState *lvms)
|
||||
+{
|
||||
+ char *name;
|
||||
+ uint32_t ged_handle;
|
||||
+ MachineState *ms = MACHINE(lvms);
|
||||
+ hwaddr base = VIRT_GED_REG_ADDR;
|
||||
+ hwaddr size = ACPI_GED_REG_COUNT;
|
||||
+
|
||||
+ ged_handle = qemu_fdt_alloc_phandle(ms->fdt);
|
||||
+ name = g_strdup_printf("/ged@%" PRIx64, base);
|
||||
+ qemu_fdt_add_subnode(ms->fdt, name);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon");
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, name, "reg", 0x0, base, 0x0, size);
|
||||
+ /* 8 bit registers */
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "reg-shift", 0);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "reg-io-width", 1);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "phandle", ged_handle);
|
||||
+ ged_handle = qemu_fdt_get_phandle(ms->fdt, name);
|
||||
+ g_free(name);
|
||||
+
|
||||
+ name = g_strdup_printf("/reboot");
|
||||
+ qemu_fdt_add_subnode(ms->fdt, name);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon-reboot");
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "regmap", ged_handle);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "offset", ACPI_GED_REG_RESET);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "value", ACPI_GED_RESET_VALUE);
|
||||
+ g_free(name);
|
||||
+
|
||||
+ name = g_strdup_printf("/poweroff");
|
||||
+ qemu_fdt_add_subnode(ms->fdt, name);
|
||||
+ qemu_fdt_setprop_string(ms->fdt, name, "compatible", "syscon-poweroff");
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "regmap", ged_handle);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "offset", ACPI_GED_REG_SLEEP_CTL);
|
||||
+ qemu_fdt_setprop_cell(ms->fdt, name, "value", ACPI_GED_SLP_EN |
|
||||
+ (ACPI_GED_SLP_TYP_S5 << ACPI_GED_SLP_TYP_POS));
|
||||
+ g_free(name);
|
||||
+}
|
||||
+
|
||||
static void fdt_add_uart_node(LoongArchVirtMachineState *lvms,
|
||||
uint32_t *pch_pic_phandle, hwaddr base,
|
||||
int irq, bool chosen)
|
||||
@@ -739,6 +777,7 @@ static void virt_devices_init(DeviceState *pch_pic,
|
||||
qdev_get_gpio_in(pch_pic,
|
||||
VIRT_RTC_IRQ - VIRT_GSI_BASE));
|
||||
fdt_add_rtc_node(lvms, pch_pic_phandle);
|
||||
+ fdt_add_ged_reset(lvms);
|
||||
|
||||
/* acpi ged */
|
||||
lvms->acpi_ged = create_acpi_ged(pch_pic, lvms);
|
||||
--
|
||||
2.39.1
|
||||
|
||||
346
hw-loongarch-virt-Add-basic-CPU-plug-support.patch
Normal file
346
hw-loongarch-virt-Add-basic-CPU-plug-support.patch
Normal file
@ -0,0 +1,346 @@
|
||||
From 212ea93178ad1e65e625ec6942ee9aff93dd5321 Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 23 Oct 2024 15:13:11 +0800
|
||||
Subject: [PATCH 70/78] hw/loongarch/virt: Add basic CPU plug support
|
||||
|
||||
Implement interface for cpu hotplug function, and enable cpu hotplug
|
||||
feature on virt machine.
|
||||
|
||||
Co-developed-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-ID: <20241023071312.881866-3-maobibo@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/Kconfig | 1 +
|
||||
hw/loongarch/virt.c | 193 +++++++++++++++++++++++++++++++++++-
|
||||
include/hw/loongarch/virt.h | 1 +
|
||||
target/loongarch/cpu.c | 13 +++
|
||||
4 files changed, 206 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
|
||||
index 40944a8365..b42a8573d4 100644
|
||||
--- a/hw/loongarch/Kconfig
|
||||
+++ b/hw/loongarch/Kconfig
|
||||
@@ -16,6 +16,7 @@ config LOONGARCH_VIRT
|
||||
select LOONGARCH_EXTIOI
|
||||
select LS7A_RTC
|
||||
select SMBIOS
|
||||
+ select ACPI_CPU_HOTPLUG
|
||||
select ACPI_PCI
|
||||
select ACPI_HW_REDUCED
|
||||
select FW_CFG_DMA
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 8d1e53ff62..e7734ed3c0 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -821,7 +821,7 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
||||
|
||||
/* Create IPI device */
|
||||
ipi = qdev_new(TYPE_LOONGARCH_IPI);
|
||||
- qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.cpus);
|
||||
+ qdev_prop_set_uint32(ipi, "num-cpu", ms->smp.max_cpus);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
|
||||
|
||||
/* IPI iocsr memory region */
|
||||
@@ -845,9 +845,11 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
||||
env->ipistate = ipi;
|
||||
}
|
||||
|
||||
+ lvms->ipi = ipi;
|
||||
+
|
||||
/* Create EXTIOI device */
|
||||
extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
|
||||
- qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.cpus);
|
||||
+ qdev_prop_set_uint32(extioi, "num-cpu", ms->smp.max_cpus);
|
||||
if (virt_is_veiointc_enabled(lvms)) {
|
||||
qdev_prop_set_bit(extioi, "has-virtualization-extension", true);
|
||||
}
|
||||
@@ -873,6 +875,8 @@ static void virt_irq_init(LoongArchVirtMachineState *lvms)
|
||||
}
|
||||
}
|
||||
|
||||
+ lvms->extioi = extioi;
|
||||
+
|
||||
/* Add Extend I/O Interrupt Controller node */
|
||||
fdt_add_eiointc_node(lvms, &cpuintc_phandle, &eiointc_phandle);
|
||||
|
||||
@@ -1310,6 +1314,181 @@ static int virt_get_arch_id_from_topo(MachineState *ms, LoongArchCPUTopo *topo)
|
||||
return arch_id;
|
||||
}
|
||||
|
||||
+/* find cpu slot in machine->possible_cpus by arch_id */
|
||||
+static CPUArchId *virt_find_cpu_slot(MachineState *ms, int arch_id, int *index)
|
||||
+{
|
||||
+ int n;
|
||||
+ for (n = 0; n < ms->possible_cpus->len; n++) {
|
||||
+ if (ms->possible_cpus->cpus[n].arch_id == arch_id) {
|
||||
+ if (index) {
|
||||
+ *index = n;
|
||||
+ }
|
||||
+ return &ms->possible_cpus->cpus[n];
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+static void virt_cpu_pre_plug(HotplugHandler *hotplug_dev,
|
||||
+ DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ MachineState *ms = MACHINE(OBJECT(hotplug_dev));
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
|
||||
+ LoongArchCPU *cpu = LOONGARCH_CPU(dev);
|
||||
+ CPUState *cs = CPU(dev);
|
||||
+ CPUArchId *cpu_slot;
|
||||
+ Error *local_err = NULL;
|
||||
+ LoongArchCPUTopo topo;
|
||||
+ int arch_id, index;
|
||||
+
|
||||
+ if (dev->hotplugged && !mc->has_hotpluggable_cpus) {
|
||||
+ error_setg(&local_err, "CPU hotplug not supported for this machine");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* sanity check the cpu */
|
||||
+ if (!object_dynamic_cast(OBJECT(cpu), ms->cpu_type)) {
|
||||
+ error_setg(&local_err, "Invalid CPU type, expected cpu type: '%s'",
|
||||
+ ms->cpu_type);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((cpu->thread_id < 0) || (cpu->thread_id >= ms->smp.threads)) {
|
||||
+ error_setg(&local_err,
|
||||
+ "Invalid thread-id %u specified, must be in range 1:%u",
|
||||
+ cpu->thread_id, ms->smp.threads - 1);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((cpu->core_id < 0) || (cpu->core_id >= ms->smp.cores)) {
|
||||
+ error_setg(&local_err,
|
||||
+ "Invalid core-id %u specified, must be in range 1:%u",
|
||||
+ cpu->core_id, ms->smp.cores - 1);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((cpu->socket_id < 0) || (cpu->socket_id >= ms->smp.sockets)) {
|
||||
+ error_setg(&local_err,
|
||||
+ "Invalid socket-id %u specified, must be in range 1:%u",
|
||||
+ cpu->socket_id, ms->smp.sockets - 1);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ topo.socket_id = cpu->socket_id;
|
||||
+ topo.core_id = cpu->core_id;
|
||||
+ topo.thread_id = cpu->thread_id;
|
||||
+ arch_id = virt_get_arch_id_from_topo(ms, &topo);
|
||||
+ cpu_slot = virt_find_cpu_slot(ms, arch_id, &index);
|
||||
+ if (CPU(cpu_slot->cpu)) {
|
||||
+ error_setg(&local_err,
|
||||
+ "cpu(id%d=%d:%d:%d) with arch-id %" PRIu64 " exists",
|
||||
+ cs->cpu_index, cpu->socket_id, cpu->core_id,
|
||||
+ cpu->thread_id, cpu_slot->arch_id);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ cpu->phy_id = arch_id;
|
||||
+ /*
|
||||
+ * update cpu_index calculation method since it is easily used as index
|
||||
+ * with possible_cpus array by function virt_cpu_index_to_props
|
||||
+ */
|
||||
+ cs->cpu_index = index;
|
||||
+ numa_cpu_pre_plug(cpu_slot, dev, &local_err);
|
||||
+ return ;
|
||||
+
|
||||
+out:
|
||||
+ error_propagate(errp, local_err);
|
||||
+}
|
||||
+
|
||||
+static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev,
|
||||
+ DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
|
||||
+ Error *local_err = NULL;
|
||||
+ HotplugHandlerClass *hhc;
|
||||
+ LoongArchCPU *cpu = LOONGARCH_CPU(dev);
|
||||
+ CPUState *cs = CPU(dev);
|
||||
+
|
||||
+ if (!lvms->acpi_ged) {
|
||||
+ error_setg(&local_err, "CPU hot unplug not supported without ACPI");
|
||||
+ error_propagate(errp, local_err);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (cs->cpu_index == 0) {
|
||||
+ error_setg(&local_err,
|
||||
+ "hot-unplug of boot cpu(id%d=%d:%d:%d) not supported",
|
||||
+ cs->cpu_index, cpu->socket_id,
|
||||
+ cpu->core_id, cpu->thread_id);
|
||||
+ error_propagate(errp, local_err);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ hhc = HOTPLUG_HANDLER_GET_CLASS(lvms->acpi_ged);
|
||||
+ hhc->unplug_request(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &local_err);
|
||||
+}
|
||||
+
|
||||
+static void virt_cpu_unplug(HotplugHandler *hotplug_dev,
|
||||
+ DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ CPUArchId *cpu_slot;
|
||||
+ HotplugHandlerClass *hhc;
|
||||
+ Error *local_err = NULL;
|
||||
+ LoongArchCPU *cpu = LOONGARCH_CPU(dev);
|
||||
+ LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
|
||||
+
|
||||
+ hhc = HOTPLUG_HANDLER_GET_CLASS(lvms->acpi_ged);
|
||||
+ hhc->unplug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &local_err);
|
||||
+ if (local_err) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ cpu_slot = virt_find_cpu_slot(MACHINE(lvms), cpu->phy_id, NULL);
|
||||
+ cpu_slot->cpu = NULL;
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void virt_cpu_plug(HotplugHandler *hotplug_dev,
|
||||
+ DeviceState *dev, Error **errp)
|
||||
+{
|
||||
+ CPUArchId *cpu_slot;
|
||||
+ HotplugHandlerClass *hhc;
|
||||
+ Error *local_err = NULL;
|
||||
+ LoongArchCPU *cpu = LOONGARCH_CPU(dev);
|
||||
+ CPUState *cs = CPU(cpu);
|
||||
+ CPULoongArchState *env;
|
||||
+ LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(hotplug_dev);
|
||||
+ int pin;
|
||||
+
|
||||
+ if (lvms->acpi_ged) {
|
||||
+ env = &(cpu->env);
|
||||
+ env->address_space_iocsr = &lvms->as_iocsr;
|
||||
+
|
||||
+ env->ipistate = lvms->ipi;
|
||||
+ if (!(kvm_enabled() && kvm_irqchip_in_kernel())) {
|
||||
+ /* connect ipi irq to cpu irq, logic cpu index used here */
|
||||
+ qdev_connect_gpio_out(lvms->ipi, cs->cpu_index,
|
||||
+ qdev_get_gpio_in(dev, IRQ_IPI));
|
||||
+
|
||||
+ for (pin = 0; pin < LS3A_INTC_IP; pin++) {
|
||||
+ qdev_connect_gpio_out(lvms->extioi, (cs->cpu_index * 8 + pin),
|
||||
+ qdev_get_gpio_in(dev, pin + 2));
|
||||
+ }
|
||||
+ }
|
||||
+ hhc = HOTPLUG_HANDLER_GET_CLASS(lvms->acpi_ged);
|
||||
+ hhc->plug(HOTPLUG_HANDLER(lvms->acpi_ged), dev, &local_err);
|
||||
+ if (local_err) {
|
||||
+ error_propagate(errp, local_err);
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ cpu_slot = virt_find_cpu_slot(MACHINE(lvms), cpu->phy_id, NULL);
|
||||
+ cpu_slot->cpu = OBJECT(dev);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
static bool memhp_type_supported(DeviceState *dev)
|
||||
{
|
||||
/* we only support pc dimm now */
|
||||
@@ -1328,6 +1507,8 @@ static void virt_device_pre_plug(HotplugHandler *hotplug_dev,
|
||||
{
|
||||
if (memhp_type_supported(dev)) {
|
||||
virt_mem_pre_plug(hotplug_dev, dev, errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) {
|
||||
+ virt_cpu_pre_plug(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1346,6 +1527,8 @@ static void virt_device_unplug_request(HotplugHandler *hotplug_dev,
|
||||
{
|
||||
if (memhp_type_supported(dev)) {
|
||||
virt_mem_unplug_request(hotplug_dev, dev, errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) {
|
||||
+ virt_cpu_unplug_request(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1364,6 +1547,8 @@ static void virt_device_unplug(HotplugHandler *hotplug_dev,
|
||||
{
|
||||
if (memhp_type_supported(dev)) {
|
||||
virt_mem_unplug(hotplug_dev, dev, errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) {
|
||||
+ virt_cpu_unplug(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1391,6 +1576,8 @@ static void virt_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||
}
|
||||
} else if (memhp_type_supported(dev)) {
|
||||
virt_mem_plug(hotplug_dev, dev, errp);
|
||||
+ } else if (object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU)) {
|
||||
+ virt_cpu_plug(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1400,6 +1587,7 @@ static HotplugHandler *virt_get_hotplug_handler(MachineState *machine,
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
|
||||
if (device_is_dynamic_sysbus(mc, dev) ||
|
||||
+ object_dynamic_cast(OBJECT(dev), TYPE_LOONGARCH_CPU) ||
|
||||
object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
|
||||
memhp_type_supported(dev)) {
|
||||
return HOTPLUG_HANDLER(machine);
|
||||
@@ -1489,6 +1677,7 @@ static void virt_class_init(ObjectClass *oc, void *data)
|
||||
mc->numa_mem_supported = true;
|
||||
mc->auto_enable_numa_with_memhp = true;
|
||||
mc->auto_enable_numa_with_memdev = true;
|
||||
+ mc->has_hotpluggable_cpus = true;
|
||||
mc->get_hotplug_handler = virt_get_hotplug_handler;
|
||||
mc->default_nic = "virtio-net-pci";
|
||||
hc->plug = virt_device_plug_cb;
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 0a4d9a25f0..27c52af9f3 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -64,6 +64,7 @@ struct LoongArchVirtMachineState {
|
||||
AddressSpace as_iocsr;
|
||||
int features;
|
||||
struct loongarch_boot_info bootinfo;
|
||||
+ DeviceState *ipi;
|
||||
};
|
||||
|
||||
#define TYPE_LOONGARCH_VIRT_MACHINE MACHINE_TYPE_NAME("virt")
|
||||
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
|
||||
index 673ed8ea18..ee764f0bc7 100644
|
||||
--- a/target/loongarch/cpu.c
|
||||
+++ b/target/loongarch/cpu.c
|
||||
@@ -644,6 +644,17 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
lacc->parent_realize(dev, errp);
|
||||
}
|
||||
|
||||
+static void loongarch_cpu_unrealizefn(DeviceState *dev)
|
||||
+{
|
||||
+ LoongArchCPUClass *mcc = LOONGARCH_CPU_GET_CLASS(dev);
|
||||
+
|
||||
+#ifndef CONFIG_USER_ONLY
|
||||
+ cpu_remove_sync(CPU(dev));
|
||||
+#endif
|
||||
+
|
||||
+ mcc->parent_unrealize(dev);
|
||||
+}
|
||||
+
|
||||
static bool loongarch_get_lsx(Object *obj, Error **errp)
|
||||
{
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
|
||||
@@ -880,6 +891,8 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
|
||||
device_class_set_props(dc, loongarch_cpu_properties);
|
||||
device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
|
||||
&lacc->parent_realize);
|
||||
+ device_class_set_parent_unrealize(dc, loongarch_cpu_unrealizefn,
|
||||
+ &lacc->parent_unrealize);
|
||||
resettable_class_set_parent_phases(rc, NULL, loongarch_cpu_reset_hold, NULL,
|
||||
&lacc->parent_phases);
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
46
hw-loongarch-virt-Add-description-for-virt-machine-t.patch
Normal file
46
hw-loongarch-virt-Add-description-for-virt-machine-t.patch
Normal file
@ -0,0 +1,46 @@
|
||||
From 080ca7865257d70b6be671cbc17a97c5ebffbd68 Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Fri, 13 Sep 2024 17:52:02 +0800
|
||||
Subject: [PATCH 38/78] hw/loongarch/virt: Add description for virt machine
|
||||
type
|
||||
|
||||
The description about virt machine type is removed by mistake, add
|
||||
new description here. Here is output result with command
|
||||
"./qemu-system-loongarch64 -M help"
|
||||
|
||||
Supported machines are:
|
||||
none empty machine
|
||||
virt QEMU LoongArch Virtual Machine (default)
|
||||
x-remote Experimental remote machine
|
||||
|
||||
Without the patch, it shows as follows:
|
||||
Supported machines are:
|
||||
none empty machine
|
||||
virt (null) (default)
|
||||
x-remote Experimental remote machine
|
||||
|
||||
Fixes: ef2f11454c(hw/loongarch/virt: Replace Loongson IPI with LoongArch IPI)
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||||
Reviewed-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 79b16953d2..9f47107379 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -1383,6 +1383,7 @@ static void virt_class_init(ObjectClass *oc, void *data)
|
||||
mc->init = virt_init;
|
||||
mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("la464");
|
||||
mc->default_ram_id = "loongarch.ram";
|
||||
+ mc->desc = "QEMU LoongArch Virtual Machine";
|
||||
mc->max_cpus = LOONGARCH_MAX_CPUS;
|
||||
mc->is_default = 1;
|
||||
mc->default_kernel_irqchip_split = false;
|
||||
--
|
||||
2.39.1
|
||||
|
||||
33
hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch
Normal file
33
hw-loongarch-virt-Remove-unnecessary-cpu.h-inclusion.patch
Normal file
@ -0,0 +1,33 @@
|
||||
From cbd62b91ecdd0ec5f4ccb4c726e0adcdd2808270 Mon Sep 17 00:00:00 2001
|
||||
From: Susanooo <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 24 Oct 2024 10:34:17 +0800
|
||||
Subject: [PATCH] hw/loongarch/virt: Remove unnecessary 'cpu.h' inclusion
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Thomas Huth <thuth@redhat.com>
|
||||
Message-Id: <20240927213254.17552-2-philmd@linaro.org>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: zhangchujun <zhangchujun_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
include/hw/loongarch/virt.h | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 99447fd1d6..17a792e596 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -8,7 +8,6 @@
|
||||
#ifndef HW_LOONGARCH_H
|
||||
#define HW_LOONGARCH_H
|
||||
|
||||
-#include "target/loongarch/cpu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "hw/intc/loongarch_ipi.h"
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
59
hw-loongarch-virt-Remove-unused-assignment.patch
Normal file
59
hw-loongarch-virt-Remove-unused-assignment.patch
Normal file
@ -0,0 +1,59 @@
|
||||
From 5e0ec61ac98a025124912fc47552550b471ab638 Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 12 Jun 2024 11:36:37 +0800
|
||||
Subject: [PATCH 32/78] hw/loongarch/virt: Remove unused assignment
|
||||
|
||||
There is abuse usage about local variable gap. Remove
|
||||
duplicated assignment and solve Coverity reported error.
|
||||
|
||||
Resolves: Coverity CID 1546441
|
||||
Fixes: 3cc451cbce ("hw/loongarch: Refine fwcfg memory map")
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240612033637.167787-1-maobibo@loongson.cn>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 15 +++++++--------
|
||||
1 file changed, 7 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index 12816c6023..a7283e6755 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -1034,7 +1034,6 @@ static void fw_cfg_add_memory(MachineState *ms)
|
||||
memmap_add_entry(base, gap, 1);
|
||||
size -= gap;
|
||||
base = VIRT_HIGHMEM_BASE;
|
||||
- gap = ram_size - VIRT_LOWMEM_SIZE;
|
||||
}
|
||||
|
||||
if (size) {
|
||||
@@ -1047,17 +1046,17 @@ static void fw_cfg_add_memory(MachineState *ms)
|
||||
}
|
||||
|
||||
/* add fw_cfg memory map of other nodes */
|
||||
- size = ram_size - numa_info[0].node_mem;
|
||||
- gap = VIRT_LOWMEM_BASE + VIRT_LOWMEM_SIZE;
|
||||
- if (base < gap && (base + size) > gap) {
|
||||
+ if (numa_info[0].node_mem < gap && ram_size > gap) {
|
||||
/*
|
||||
* memory map for the maining nodes splited into two part
|
||||
- * lowram: [base, +(gap - base))
|
||||
- * highram: [VIRT_HIGHMEM_BASE, +(size - (gap - base)))
|
||||
+ * lowram: [base, +(gap - numa_info[0].node_mem))
|
||||
+ * highram: [VIRT_HIGHMEM_BASE, +(ram_size - gap))
|
||||
*/
|
||||
- memmap_add_entry(base, gap - base, 1);
|
||||
- size -= gap - base;
|
||||
+ memmap_add_entry(base, gap - numa_info[0].node_mem, 1);
|
||||
+ size = ram_size - gap;
|
||||
base = VIRT_HIGHMEM_BASE;
|
||||
+ } else {
|
||||
+ size = ram_size - numa_info[0].node_mem;
|
||||
}
|
||||
|
||||
if (size)
|
||||
--
|
||||
2.39.1
|
||||
|
||||
143
hw-loongarch-virt-Update-the-ACPI-table-for-hotplug-.patch
Normal file
143
hw-loongarch-virt-Update-the-ACPI-table-for-hotplug-.patch
Normal file
@ -0,0 +1,143 @@
|
||||
From a3728999125cd9fc9e3e841b66a1677663933c27 Mon Sep 17 00:00:00 2001
|
||||
From: Bibo Mao <maobibo@loongson.cn>
|
||||
Date: Wed, 23 Oct 2024 15:13:12 +0800
|
||||
Subject: [PATCH 71/78] hw/loongarch/virt: Update the ACPI table for hotplug
|
||||
cpu
|
||||
|
||||
On LoongArch virt machine, ACPI GED hardware is used for cpu
|
||||
hotplug, here cpu hotplug support feature is added on GED device,
|
||||
also cpu scan and reject method is added about CPU device in
|
||||
DSDT table.
|
||||
|
||||
Co-developed-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-ID: <20241023071312.881866-4-maobibo@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/acpi-build.c | 35 +++++++++++++++++++++++++++++++++--
|
||||
hw/loongarch/virt.c | 10 ++++++++++
|
||||
include/hw/loongarch/virt.h | 1 +
|
||||
3 files changed, 44 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
|
||||
index bcdec2e1cb..a54c5e0e70 100644
|
||||
--- a/hw/loongarch/acpi-build.c
|
||||
+++ b/hw/loongarch/acpi-build.c
|
||||
@@ -47,6 +47,22 @@
|
||||
#define ACPI_BUILD_DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
+static void virt_madt_cpu_entry(int uid,
|
||||
+ const CPUArchIdList *apic_ids,
|
||||
+ GArray *entry, bool force_enabled)
|
||||
+{
|
||||
+ uint32_t flags, apic_id = apic_ids->cpus[uid].arch_id;
|
||||
+
|
||||
+ flags = apic_ids->cpus[uid].cpu || force_enabled ? 1 /* Enabled */ : 0;
|
||||
+
|
||||
+ /* Rev 1.0b, Table 5-13 Processor Local APIC Structure */
|
||||
+ build_append_int_noprefix(entry, 0, 1); /* Type */
|
||||
+ build_append_int_noprefix(entry, 8, 1); /* Length */
|
||||
+ build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */
|
||||
+ build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */
|
||||
+ build_append_int_noprefix(entry, flags, 4); /* Flags */
|
||||
+}
|
||||
+
|
||||
/* build FADT */
|
||||
static void init_common_fadt_data(AcpiFadtData *data)
|
||||
{
|
||||
@@ -123,15 +139,17 @@ build_madt(GArray *table_data, BIOSLinker *linker,
|
||||
build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
|
||||
|
||||
for (i = 0; i < arch_ids->len; i++) {
|
||||
+ uint32_t flags;
|
||||
+
|
||||
/* Processor Core Interrupt Controller Structure */
|
||||
arch_id = arch_ids->cpus[i].arch_id;
|
||||
-
|
||||
+ flags = arch_ids->cpus[i].cpu ? 1 : 0;
|
||||
build_append_int_noprefix(table_data, 17, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 15, 1); /* Length */
|
||||
build_append_int_noprefix(table_data, 1, 1); /* Version */
|
||||
build_append_int_noprefix(table_data, i, 4); /* ACPI Processor ID */
|
||||
build_append_int_noprefix(table_data, arch_id, 4); /* Core ID */
|
||||
- build_append_int_noprefix(table_data, 1, 4); /* Flags */
|
||||
+ build_append_int_noprefix(table_data, flags, 4); /* Flags */
|
||||
}
|
||||
|
||||
/* Extend I/O Interrupt Controller Structure */
|
||||
@@ -334,6 +352,7 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
|
||||
{
|
||||
uint32_t event;
|
||||
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
|
||||
+ CPUHotplugFeatures opts;
|
||||
|
||||
build_ged_aml(dsdt, "\\_SB."GED_DEVICE,
|
||||
HOTPLUG_HANDLER(lvms->acpi_ged),
|
||||
@@ -346,6 +365,18 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine)
|
||||
AML_SYSTEM_MEMORY,
|
||||
VIRT_GED_MEM_ADDR);
|
||||
}
|
||||
+
|
||||
+ if (event & ACPI_GED_CPU_HOTPLUG_EVT) {
|
||||
+ opts.acpi_1_compatible = false;
|
||||
+ opts.has_legacy_cphp = false;
|
||||
+ opts.fw_unplugs_cpu = false;
|
||||
+ opts.smi_path = NULL;
|
||||
+
|
||||
+ build_cpus_aml(dsdt, machine, opts, virt_madt_cpu_entry, NULL,
|
||||
+ VIRT_GED_CPUHP_ADDR, "\\_SB",
|
||||
+ NULL, AML_SYSTEM_MEMORY);
|
||||
+ }
|
||||
+
|
||||
acpi_dsdt_add_power_button(dsdt);
|
||||
}
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index e7734ed3c0..6159fd9470 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -652,11 +652,17 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic,
|
||||
{
|
||||
DeviceState *dev;
|
||||
MachineState *ms = MACHINE(lvms);
|
||||
+ MachineClass *mc = MACHINE_GET_CLASS(lvms);
|
||||
uint32_t event = ACPI_GED_PWR_DOWN_EVT;
|
||||
|
||||
if (ms->ram_slots) {
|
||||
event |= ACPI_GED_MEM_HOTPLUG_EVT;
|
||||
}
|
||||
+
|
||||
+ if (mc->has_hotpluggable_cpus) {
|
||||
+ event |= ACPI_GED_CPU_HOTPLUG_EVT;
|
||||
+ }
|
||||
+
|
||||
dev = qdev_new(TYPE_ACPI_GED);
|
||||
qdev_prop_set_uint32(dev, "ged-event", event);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
@@ -668,6 +674,10 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic,
|
||||
/* ged regs used for reset and power down */
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_GED_REG_ADDR);
|
||||
|
||||
+ if (mc->has_hotpluggable_cpus) {
|
||||
+ sysbus_mmio_map(SYS_BUS_DEVICE(dev), 3, VIRT_GED_CPUHP_ADDR);
|
||||
+ }
|
||||
+
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0,
|
||||
qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - VIRT_GSI_BASE));
|
||||
return dev;
|
||||
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
|
||||
index 27c52af9f3..98c990327b 100644
|
||||
--- a/include/hw/loongarch/virt.h
|
||||
+++ b/include/hw/loongarch/virt.h
|
||||
@@ -32,6 +32,7 @@
|
||||
#define VIRT_GED_EVT_ADDR 0x100e0000
|
||||
#define VIRT_GED_MEM_ADDR (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN)
|
||||
#define VIRT_GED_REG_ADDR (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN)
|
||||
+#define VIRT_GED_CPUHP_ADDR (VIRT_GED_REG_ADDR + ACPI_GED_REG_COUNT)
|
||||
|
||||
#define COMMAND_LINE_SIZE 512
|
||||
|
||||
--
|
||||
2.39.1
|
||||
|
||||
77
hw-loongarch-virt-Use-MemTxAttrs-interface-for-misc-.patch
Normal file
77
hw-loongarch-virt-Use-MemTxAttrs-interface-for-misc-.patch
Normal file
@ -0,0 +1,77 @@
|
||||
From b63b7b0b6c9bed8e1a316f3838aab7db2e8f2037 Mon Sep 17 00:00:00 2001
|
||||
From: Song Gao <gaosong@loongson.cn>
|
||||
Date: Tue, 28 May 2024 16:38:54 +0800
|
||||
Subject: [PATCH 29/78] hw/loongarch/virt: Use MemTxAttrs interface for misc
|
||||
ops
|
||||
|
||||
Use MemTxAttrs interface read_with_attrs/write_with_attrs
|
||||
for virt_iocsr_misc_ops.
|
||||
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Reviewed-by: Bibo Mao <maobibo@loongson.cn>
|
||||
Message-Id: <20240528083855.1912757-3-gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 18 ++++++++++--------
|
||||
1 file changed, 10 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index f7874bccf9..12816c6023 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -915,8 +915,8 @@ static void virt_firmware_init(LoongArchVirtMachineState *lvms)
|
||||
}
|
||||
|
||||
|
||||
-static MemTxResult loongarch_qemu_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
- unsigned size, MemTxAttrs attrs)
|
||||
+static MemTxResult virt_iocsr_misc_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
+ unsigned size, MemTxAttrs attrs)
|
||||
{
|
||||
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(opaque);
|
||||
uint64_t features;
|
||||
@@ -945,9 +945,9 @@ static MemTxResult loongarch_qemu_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
return MEMTX_OK;
|
||||
}
|
||||
|
||||
-static MemTxResult loongarch_qemu_read(void *opaque, hwaddr addr,
|
||||
- uint64_t *data,
|
||||
- unsigned size, MemTxAttrs attrs)
|
||||
+static MemTxResult virt_iocsr_misc_read(void *opaque, hwaddr addr,
|
||||
+ uint64_t *data,
|
||||
+ unsigned size, MemTxAttrs attrs)
|
||||
{
|
||||
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(opaque);
|
||||
uint64_t ret = 0;
|
||||
@@ -962,7 +962,7 @@ static MemTxResult loongarch_qemu_read(void *opaque, hwaddr addr,
|
||||
if (kvm_enabled()) {
|
||||
ret |= BIT(IOCSRF_VM);
|
||||
}
|
||||
- return ret;
|
||||
+ break;
|
||||
case VENDOR_REG:
|
||||
ret = 0x6e6f73676e6f6f4cULL; /* "Loongson" */
|
||||
break;
|
||||
@@ -986,6 +986,8 @@ static MemTxResult loongarch_qemu_read(void *opaque, hwaddr addr,
|
||||
ret |= BIT_ULL(IOCSRM_EXTIOI_INT_ENCODE);
|
||||
}
|
||||
break;
|
||||
+ default:
|
||||
+ g_assert_not_reached();
|
||||
}
|
||||
|
||||
*data = ret;
|
||||
@@ -993,8 +995,8 @@ static MemTxResult loongarch_qemu_read(void *opaque, hwaddr addr,
|
||||
}
|
||||
|
||||
static const MemoryRegionOps virt_iocsr_misc_ops = {
|
||||
- .read_with_attrs = loongarch_qemu_read,
|
||||
- .write_with_attrs = loongarch_qemu_write,
|
||||
+ .read_with_attrs = virt_iocsr_misc_read,
|
||||
+ .write_with_attrs = virt_iocsr_misc_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
--
|
||||
2.39.1
|
||||
|
||||
66
hw-loongarch-virt-pass-random-seed-to-fdt.patch
Normal file
66
hw-loongarch-virt-pass-random-seed-to-fdt.patch
Normal file
@ -0,0 +1,66 @@
|
||||
From 573f3bec8137caf829457620380d794165c96a92 Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Thu, 5 Sep 2024 17:33:16 +0200
|
||||
Subject: [PATCH 36/78] hw/loongarch: virt: pass random seed to fdt
|
||||
|
||||
If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to
|
||||
initialize early. Set this using the usual guest random number
|
||||
generation function.
|
||||
|
||||
This is the same procedure that's done in b91b6b5a2c ("hw/microblaze:
|
||||
pass random seed to fdt"), e4b4f0b71c ("hw/riscv: virt: pass random seed
|
||||
to fdt"), c6fe3e6b4c ("hw/openrisc: virt: pass random seed to fdt"),
|
||||
67f7e426e5 ("hw/i386: pass RNG seed via setup_data entry"), c287941a4d
|
||||
("hw/rx: pass random seed to fdt"), 5e19cc68fb ("hw/mips: boston: pass
|
||||
random seed to fdt"), 6b23a67916 ("hw/nios2: virt: pass random seed to fdt")
|
||||
c4b075318e ("hw/ppc: pass random seed to fdt"), and 5242876f37
|
||||
("hw/arm/virt: dt: add rng-seed property").
|
||||
|
||||
These earlier commits later were amended to rerandomize the RNG seed on
|
||||
snapshot load, but the LoongArch code somehow already does that, despite
|
||||
not having this patch here, presumably due to some lucky copy and
|
||||
pasting.
|
||||
|
||||
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
||||
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240905153316.2038769-1-Jason@zx2c4.com>
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/virt.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index a6e9309064..79b16953d2 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "hw/block/flash.h"
|
||||
#include "hw/virtio/virtio-iommu.h"
|
||||
#include "qemu/error-report.h"
|
||||
+#include "qemu/guest-random.h"
|
||||
|
||||
static bool virt_is_veiointc_enabled(LoongArchVirtMachineState *lvms)
|
||||
{
|
||||
@@ -304,6 +305,7 @@ static void fdt_add_uart_node(LoongArchVirtMachineState *lvms,
|
||||
static void create_fdt(LoongArchVirtMachineState *lvms)
|
||||
{
|
||||
MachineState *ms = MACHINE(lvms);
|
||||
+ uint8_t rng_seed[32];
|
||||
|
||||
ms->fdt = create_device_tree(&lvms->fdt_size);
|
||||
if (!ms->fdt) {
|
||||
@@ -317,6 +319,10 @@ static void create_fdt(LoongArchVirtMachineState *lvms)
|
||||
qemu_fdt_setprop_cell(ms->fdt, "/", "#address-cells", 0x2);
|
||||
qemu_fdt_setprop_cell(ms->fdt, "/", "#size-cells", 0x2);
|
||||
qemu_fdt_add_subnode(ms->fdt, "/chosen");
|
||||
+
|
||||
+ /* Pass seed to RNG */
|
||||
+ qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed));
|
||||
+ qemu_fdt_setprop(ms->fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed));
|
||||
}
|
||||
|
||||
static void fdt_add_cpu_nodes(const LoongArchVirtMachineState *lvms)
|
||||
--
|
||||
2.39.1
|
||||
|
||||
172
hw-loongarch-virt-support-up-to-4-serial-ports.patch
Normal file
172
hw-loongarch-virt-support-up-to-4-serial-ports.patch
Normal file
@ -0,0 +1,172 @@
|
||||
From 04895c794652c5da1ece0cad82741bed9aa8ad02 Mon Sep 17 00:00:00 2001
|
||||
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
||||
Date: Sat, 7 Sep 2024 16:34:39 +0200
|
||||
Subject: [PATCH 35/78] hw/loongarch: virt: support up to 4 serial ports
|
||||
|
||||
In order to support additional channels of communication using
|
||||
`-serial`, add several serial ports, up to the standard 4 generally
|
||||
supported by the 8250 driver.
|
||||
|
||||
Fixed: https://lore.kernel.org/all/20240907143439.2792924-1-Jason@zx2c4.com/
|
||||
|
||||
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
||||
Tested-by: Bibo Mao <maobibo@loongson.cn>
|
||||
[gaosong: ACPI uart need't reverse order]
|
||||
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
||||
Message-Id: <20240907143439.2792924-1-Jason@zx2c4.com>
|
||||
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
|
||||
---
|
||||
hw/loongarch/acpi-build.c | 23 +++++++++++++++--------
|
||||
hw/loongarch/virt.c | 27 +++++++++++++++++----------
|
||||
include/hw/pci-host/ls7a.h | 9 +++++----
|
||||
3 files changed, 37 insertions(+), 22 deletions(-)
|
||||
|
||||
diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c
|
||||
index 1a9d25fc51..33a92223d8 100644
|
||||
--- a/hw/loongarch/acpi-build.c
|
||||
+++ b/hw/loongarch/acpi-build.c
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "hw/acpi/generic_event_device.h"
|
||||
#include "hw/pci-host/gpex.h"
|
||||
+#include "sysemu/sysemu.h"
|
||||
#include "sysemu/tpm.h"
|
||||
#include "hw/platform-bus.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
@@ -252,23 +253,27 @@ struct AcpiBuildState {
|
||||
MemoryRegion *linker_mr;
|
||||
} AcpiBuildState;
|
||||
|
||||
-static void build_uart_device_aml(Aml *table)
|
||||
+static void build_uart_device_aml(Aml *table, int index)
|
||||
{
|
||||
Aml *dev;
|
||||
Aml *crs;
|
||||
Aml *pkg0, *pkg1, *pkg2;
|
||||
- uint32_t uart_irq = VIRT_UART_IRQ;
|
||||
-
|
||||
- Aml *scope = aml_scope("_SB");
|
||||
- dev = aml_device("COMA");
|
||||
+ Aml *scope;
|
||||
+ uint32_t uart_irq;
|
||||
+ uint64_t base;
|
||||
+
|
||||
+ uart_irq = VIRT_UART_IRQ + index;
|
||||
+ base = VIRT_UART_BASE + index * VIRT_UART_SIZE;
|
||||
+ scope = aml_scope("_SB");
|
||||
+ dev = aml_device("COM%d", index);
|
||||
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0501")));
|
||||
- aml_append(dev, aml_name_decl("_UID", aml_int(0)));
|
||||
+ aml_append(dev, aml_name_decl("_UID", aml_int(index)));
|
||||
aml_append(dev, aml_name_decl("_CCA", aml_int(1)));
|
||||
crs = aml_resource_template();
|
||||
aml_append(crs,
|
||||
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
|
||||
AML_NON_CACHEABLE, AML_READ_WRITE,
|
||||
- 0, VIRT_UART_BASE, VIRT_UART_BASE + VIRT_UART_SIZE - 1,
|
||||
+ 0, base, base + VIRT_UART_SIZE - 1,
|
||||
0, VIRT_UART_SIZE));
|
||||
aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
|
||||
AML_SHARED, &uart_irq, 1));
|
||||
@@ -401,6 +406,7 @@ static void acpi_dsdt_add_tpm(Aml *scope, LoongArchVirtMachineState *vms)
|
||||
static void
|
||||
build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
{
|
||||
+ int i;
|
||||
Aml *dsdt, *scope, *pkg;
|
||||
LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(machine);
|
||||
AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lvms->oem_id,
|
||||
@@ -408,7 +414,8 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
dsdt = init_aml_allocator();
|
||||
- build_uart_device_aml(dsdt);
|
||||
+ for (i = 0; i < VIRT_UART_COUNT; i++)
|
||||
+ build_uart_device_aml(dsdt, i);
|
||||
build_pci_device_aml(dsdt, lvms);
|
||||
build_la_ged_aml(dsdt, machine);
|
||||
build_flash_aml(dsdt, lvms);
|
||||
diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c
|
||||
index a7283e6755..a6e9309064 100644
|
||||
--- a/hw/loongarch/virt.c
|
||||
+++ b/hw/loongarch/virt.c
|
||||
@@ -281,10 +281,10 @@ static void fdt_add_rtc_node(LoongArchVirtMachineState *lvms,
|
||||
}
|
||||
|
||||
static void fdt_add_uart_node(LoongArchVirtMachineState *lvms,
|
||||
- uint32_t *pch_pic_phandle)
|
||||
+ uint32_t *pch_pic_phandle, hwaddr base,
|
||||
+ int irq, bool chosen)
|
||||
{
|
||||
char *nodename;
|
||||
- hwaddr base = VIRT_UART_BASE;
|
||||
hwaddr size = VIRT_UART_SIZE;
|
||||
MachineState *ms = MACHINE(lvms);
|
||||
|
||||
@@ -293,9 +293,9 @@ static void fdt_add_uart_node(LoongArchVirtMachineState *lvms,
|
||||
qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "ns16550a");
|
||||
qemu_fdt_setprop_cells(ms->fdt, nodename, "reg", 0x0, base, 0x0, size);
|
||||
qemu_fdt_setprop_cell(ms->fdt, nodename, "clock-frequency", 100000000);
|
||||
- qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
|
||||
- qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts",
|
||||
- VIRT_UART_IRQ - VIRT_GSI_BASE, 0x4);
|
||||
+ if (chosen)
|
||||
+ qemu_fdt_setprop_string(ms->fdt, "/chosen", "stdout-path", nodename);
|
||||
+ qemu_fdt_setprop_cells(ms->fdt, nodename, "interrupts", irq, 0x4);
|
||||
qemu_fdt_setprop_cell(ms->fdt, nodename, "interrupt-parent",
|
||||
*pch_pic_phandle);
|
||||
g_free(nodename);
|
||||
@@ -706,11 +706,18 @@ static void virt_devices_init(DeviceState *pch_pic,
|
||||
/* Add pcie node */
|
||||
fdt_add_pcie_node(lvms, pch_pic_phandle, pch_msi_phandle);
|
||||
|
||||
- serial_mm_init(get_system_memory(), VIRT_UART_BASE, 0,
|
||||
- qdev_get_gpio_in(pch_pic,
|
||||
- VIRT_UART_IRQ - VIRT_GSI_BASE),
|
||||
- 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
|
||||
- fdt_add_uart_node(lvms, pch_pic_phandle);
|
||||
+ /*
|
||||
+ * Create uart fdt node in reverse order so that they appear
|
||||
+ * in the finished device tree lowest address first
|
||||
+ */
|
||||
+ for (i = VIRT_UART_COUNT; i --> 0;) {
|
||||
+ hwaddr base = VIRT_UART_BASE + i * VIRT_UART_SIZE;
|
||||
+ int irq = VIRT_UART_IRQ + i - VIRT_GSI_BASE;
|
||||
+ serial_mm_init(get_system_memory(), base, 0,
|
||||
+ qdev_get_gpio_in(pch_pic, irq),
|
||||
+ 115200, serial_hd(i), DEVICE_LITTLE_ENDIAN);
|
||||
+ fdt_add_uart_node(lvms, pch_pic_phandle, base, irq, i == 0);
|
||||
+ }
|
||||
|
||||
/* Network init */
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
|
||||
index cd7c9ec7bc..79d4ea8501 100644
|
||||
--- a/include/hw/pci-host/ls7a.h
|
||||
+++ b/include/hw/pci-host/ls7a.h
|
||||
@@ -36,17 +36,18 @@
|
||||
#define VIRT_PCH_PIC_IRQ_NUM 32
|
||||
#define VIRT_GSI_BASE 64
|
||||
#define VIRT_DEVICE_IRQS 16
|
||||
+#define VIRT_UART_COUNT 4
|
||||
#define VIRT_UART_IRQ (VIRT_GSI_BASE + 2)
|
||||
#define VIRT_UART_BASE 0x1fe001e0
|
||||
-#define VIRT_UART_SIZE 0X100
|
||||
-#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 3)
|
||||
+#define VIRT_UART_SIZE 0x100
|
||||
+#define VIRT_RTC_IRQ (VIRT_GSI_BASE + 6)
|
||||
#define VIRT_MISC_REG_BASE (VIRT_PCH_REG_BASE + 0x00080000)
|
||||
#define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100)
|
||||
#define VIRT_RTC_LEN 0x100
|
||||
-#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 4)
|
||||
+#define VIRT_SCI_IRQ (VIRT_GSI_BASE + 7)
|
||||
|
||||
#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000
|
||||
#define VIRT_PLATFORM_BUS_SIZE 0x2000000
|
||||
#define VIRT_PLATFORM_BUS_NUM_IRQS 2
|
||||
-#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 5)
|
||||
+#define VIRT_PLATFORM_BUS_IRQ (VIRT_GSI_BASE + 8)
|
||||
#endif
|
||||
--
|
||||
2.39.1
|
||||
|
||||
212
hw-misc-psp-Pin-the-hugepage-memory-specified-by-mem.patch
Normal file
212
hw-misc-psp-Pin-the-hugepage-memory-specified-by-mem.patch
Normal 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
|
||||
|
||||
123
hw-misc-support-tkm-use-mem2-memory.patch
Normal file
123
hw-misc-support-tkm-use-mem2-memory.patch
Normal 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
|
||||
|
||||
43
hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch
Normal file
43
hw-net-can-sja1000-fix-bug-for-single-acceptance-fil.patch
Normal file
@ -0,0 +1,43 @@
|
||||
From 0b89dd1ae05d17f0bacbd34218799f00d04c8174 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
Date: Thu, 17 Oct 2024 11:13:06 +0800
|
||||
Subject: [PATCH] hw/net/can/sja1000: fix bug for single acceptance filter and
|
||||
standard frame
|
||||
|
||||
cheery-pick from 25145a7d7735344a469551946fc2a7f19eb4aa3d
|
||||
|
||||
A CAN sja1000 standard frame filter mask has been computed and applied
|
||||
incorrectly for standard frames when single Acceptance Filter Mode
|
||||
(MOD_AFM = 1) has been selected. The problem has not been found
|
||||
by Linux kernel testing because it uses dual filter mode (MOD_AFM = 0)
|
||||
and leaves falters fully open.
|
||||
|
||||
The problem has been noticed by Grant Ramsay when testing with Zephyr
|
||||
RTOS which uses single filter mode.
|
||||
|
||||
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
|
||||
Reported-by: Grant Ramsay <gramsay@enphaseenergy.com>
|
||||
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2028
|
||||
Fixes: 733210e754 ("hw/net/can: SJA1000 chip register level emulation")
|
||||
Message-ID: <20240103231426.5685-1-pisa@fel.cvut.cz>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/net/can/can_sja1000.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/net/can/can_sja1000.c b/hw/net/can/can_sja1000.c
|
||||
index 73201f9139..575df7d2f8 100644
|
||||
--- a/hw/net/can/can_sja1000.c
|
||||
+++ b/hw/net/can/can_sja1000.c
|
||||
@@ -108,7 +108,7 @@ void can_sja_single_filter(struct qemu_can_filter *filter,
|
||||
}
|
||||
|
||||
filter->can_mask = (uint32_t)amr[0] << 3;
|
||||
- filter->can_mask |= (uint32_t)amr[1] << 5;
|
||||
+ filter->can_mask |= (uint32_t)amr[1] >> 5;
|
||||
filter->can_mask = ~filter->can_mask & QEMU_CAN_SFF_MASK;
|
||||
if (!(amr[1] & 0x10)) {
|
||||
filter->can_mask |= QEMU_CAN_RTR_FLAG;
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
102
hw-nvme-fix-handling-of-over-committed-queues.patch
Normal file
102
hw-nvme-fix-handling-of-over-committed-queues.patch
Normal 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
|
||||
|
||||
52
hw-pci-Add-parenthesis-to-PCI_BUILD_BDF-macro.patch
Normal file
52
hw-pci-Add-parenthesis-to-PCI_BUILD_BDF-macro.patch
Normal file
@ -0,0 +1,52 @@
|
||||
From 3c108b874b8b142a42939d785d6706a44e7035d7 Mon Sep 17 00:00:00 2001
|
||||
From: Roque Arcudia Hernandez <roqueh@google.com>
|
||||
Date: Fri, 1 Nov 2024 21:59:23 +0000
|
||||
Subject: [PATCH] hw/pci: Add parenthesis to PCI_BUILD_BDF macro
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The bus parameter in the macro PCI_BUILD_BDF is not surrounded by
|
||||
parenthesis. This can create a compile error when warnings are
|
||||
treated as errors or can potentially create runtime errors due to the
|
||||
operator precedence.
|
||||
|
||||
For instance:
|
||||
|
||||
file.c:x:32: error: suggest parentheses around '-' inside '<<'
|
||||
[-Werror=parentheses]
|
||||
171 | uint16_t bdf = PCI_BUILD_BDF(a - b, sdev->devfn);
|
||||
| ~~^~~
|
||||
include/hw/pci/pci.h:19:41: note: in definition of macro
|
||||
'PCI_BUILD_BDF'
|
||||
19 | #define PCI_BUILD_BDF(bus, devfn) ((bus << 8) | (devfn))
|
||||
| ^~~
|
||||
cc1: all warnings being treated as errors
|
||||
|
||||
Signed-off-by: Roque Arcudia Hernandez <roqueh@google.com>
|
||||
Reviewed-by: Nabih Estefan <nabihestefan@google.com>
|
||||
Message-Id: <20241101215923.3399311-1-roqueh@google.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
||||
Signed-off-by: Zhongrui Tang <tangzhongrui_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
include/hw/pci/pci.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
|
||||
index fa6313aabc..7cf7b5619a 100644
|
||||
--- a/include/hw/pci/pci.h
|
||||
+++ b/include/hw/pci/pci.h
|
||||
@@ -15,7 +15,7 @@ extern bool pci_available;
|
||||
#define PCI_BUS_NUM(x) (((x) >> 8) & 0xff)
|
||||
#define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f)
|
||||
#define PCI_FUNC(devfn) ((devfn) & 0x07)
|
||||
-#define PCI_BUILD_BDF(bus, devfn) ((bus << 8) | (devfn))
|
||||
+#define PCI_BUILD_BDF(bus, devfn) (((bus) << 8) | (devfn))
|
||||
#define PCI_BDF_TO_DEVFN(x) ((x) & 0xff)
|
||||
#define PCI_BUS_MAX 256
|
||||
#define PCI_DEVFN_MAX 256
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
50
hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch
Normal file
50
hw-pci-bridge-Add-a-Kconfig-switch-for-the-normal-PC.patch
Normal file
@ -0,0 +1,50 @@
|
||||
From 55ea1e473095ea5be692bb4ba2e44131a4a88e73 Mon Sep 17 00:00:00 2001
|
||||
From: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
Date: Wed, 23 Oct 2024 13:40:51 +0800
|
||||
Subject: [PATCH] hw/pci-bridge: Add a Kconfig switch for the normal PCI bridge
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
cheery-pick from e779e5c05ad5d8237e2a7d8ba8b432cd24c1708b
|
||||
|
||||
The pci-bridge device is not usable on s390x, so introduce a Kconfig
|
||||
switch that allows to disable it.
|
||||
|
||||
Message-ID: <20240913144844.427899-1-thuth@redhat.com>
|
||||
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
|
||||
Reviewed-by: Cédric Le Goater <clg@redhat.com>
|
||||
Signed-off-by: Thomas Huth <thuth@redhat.com>
|
||||
Signed-off-by: Zhang Jiao <zhangjiao2_yewu@cmss.chinamobile.com>
|
||||
---
|
||||
hw/pci-bridge/Kconfig | 5 +++++
|
||||
hw/pci-bridge/meson.build | 2 +-
|
||||
2 files changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/hw/pci-bridge/Kconfig b/hw/pci-bridge/Kconfig
|
||||
index 67077366cc..449ec98643 100644
|
||||
--- a/hw/pci-bridge/Kconfig
|
||||
+++ b/hw/pci-bridge/Kconfig
|
||||
@@ -1,3 +1,8 @@
|
||||
+config PCI_BRIDGE
|
||||
+ bool
|
||||
+ default y if PCI_DEVICES
|
||||
+ depends on PCI
|
||||
+
|
||||
config PCIE_PORT
|
||||
bool
|
||||
default y if PCI_DEVICES
|
||||
diff --git a/hw/pci-bridge/meson.build b/hw/pci-bridge/meson.build
|
||||
index 6d5ad9f37b..a8b88e9099 100644
|
||||
--- a/hw/pci-bridge/meson.build
|
||||
+++ b/hw/pci-bridge/meson.build
|
||||
@@ -1,5 +1,5 @@
|
||||
pci_ss = ss.source_set()
|
||||
-pci_ss.add(files('pci_bridge_dev.c'))
|
||||
+pci_ss.add(when: 'CONFIG_PCI_BRIDGE', if_true: files('pci_bridge_dev.c'))
|
||||
pci_ss.add(when: 'CONFIG_I82801B11', if_true: files('i82801b11.c'))
|
||||
pci_ss.add(when: 'CONFIG_IOH3420', if_true: files('ioh3420.c'))
|
||||
pci_ss.add(when: 'CONFIG_PCIE_PORT', if_true: files('pcie_root_port.c', 'gen_pcie_root_port.c'))
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
44
hw-ppc-e500-Add-missing-device-tree-properties-to-i2.patch
Normal file
44
hw-ppc-e500-Add-missing-device-tree-properties-to-i2.patch
Normal 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
|
||||
|
||||
44
hw-ppc-e500-Prefer-QOM-cast.patch
Normal file
44
hw-ppc-e500-Prefer-QOM-cast.patch
Normal 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
|
||||
|
||||
44
hw-ppc-e500-Remove-unused-irqs-parameter.patch
Normal file
44
hw-ppc-e500-Remove-unused-irqs-parameter.patch
Normal 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
|
||||
|
||||
593
hw-vfio-add-device-hct-based-on-vfio.patch
Normal file
593
hw-vfio-add-device-hct-based-on-vfio.patch
Normal file
@ -0,0 +1,593 @@
|
||||
From ebafa8d737b5f08e787803375d6e942ecdaef1a9 Mon Sep 17 00:00:00 2001
|
||||
From: Yabin Li <liyabin@hygon.cn>
|
||||
Date: Fri, 4 Aug 2023 21:09:08 +0800
|
||||
Subject: [PATCH] hw/vfio: add device hct based on vfio.
|
||||
|
||||
add hct device based on vfio, used to simulate ccp devices
|
||||
|
||||
Signed-off-by: Yabin Li <liyabin@hygon.cn>
|
||||
Signed-off-by: yangdepei <yangdepei@hygon.cn>
|
||||
---
|
||||
hw/vfio/Kconfig | 6 +
|
||||
hw/vfio/hct.c | 543 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
hw/vfio/meson.build | 1 +
|
||||
3 files changed, 550 insertions(+)
|
||||
create mode 100644 hw/vfio/hct.c
|
||||
|
||||
diff --git a/hw/vfio/Kconfig b/hw/vfio/Kconfig
|
||||
index 7cdba0560a..5f0d3c2d2b 100644
|
||||
--- a/hw/vfio/Kconfig
|
||||
+++ b/hw/vfio/Kconfig
|
||||
@@ -41,3 +41,9 @@ config VFIO_IGD
|
||||
bool
|
||||
default y if PC_PCI
|
||||
depends on VFIO_PCI
|
||||
+
|
||||
+config VFIO_HCT
|
||||
+ bool
|
||||
+ default y
|
||||
+ select VFIO
|
||||
+ depends on LINUX && PCI
|
||||
diff --git a/hw/vfio/hct.c b/hw/vfio/hct.c
|
||||
new file mode 100644
|
||||
index 0000000000..476e86c61d
|
||||
--- /dev/null
|
||||
+++ b/hw/vfio/hct.c
|
||||
@@ -0,0 +1,543 @@
|
||||
+/*
|
||||
+ * vfio based mediated ccp(hct) assignment support
|
||||
+ *
|
||||
+ * Copyright 2023 HYGON Corp.
|
||||
+ *
|
||||
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at
|
||||
+ * your option) any later version. See the COPYING file in the top-level
|
||||
+ * directory.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/vfio.h>
|
||||
+#include <sys/ioctl.h>
|
||||
+#include <sys/mman.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <fcntl.h>
|
||||
+
|
||||
+#include "qemu/osdep.h"
|
||||
+#include "qemu/queue.h"
|
||||
+#include "qemu/main-loop.h"
|
||||
+#include "qemu/log.h"
|
||||
+#include "trace.h"
|
||||
+#include "hw/pci/pci.h"
|
||||
+#include "hw/vfio/pci.h"
|
||||
+#include "qemu/range.h"
|
||||
+#include "sysemu/kvm.h"
|
||||
+#include "hw/pci/msi.h"
|
||||
+#include "qemu/error-report.h"
|
||||
+#include "qapi/error.h"
|
||||
+#include "hw/qdev-properties.h"
|
||||
+
|
||||
+#define MAX_CCP_CNT 16
|
||||
+#define PAGE_SIZE 4096
|
||||
+#define HCT_SHARED_MEMORY_SIZE (PAGE_SIZE * MAX_CCP_CNT)
|
||||
+#define CCP_INDEX_BYTES 4
|
||||
+#define PATH_MAX 4096
|
||||
+#define TYPE_HCT_DEV "hct"
|
||||
+#define PCI_HCT_DEV(obj) OBJECT_CHECK(HCTDevState, (obj), TYPE_HCT_DEV)
|
||||
+#define HCT_MMIO_SIZE (1 << 20)
|
||||
+#define HCT_MAX_PASID (1 << 8)
|
||||
+
|
||||
+#define PCI_VENDOR_ID_HYGON_CCP 0x1d94
|
||||
+#define PCI_DEVICE_ID_HYGON_CCP 0x1468
|
||||
+
|
||||
+#define HCT_SHARE_DEV "/dev/hct_share"
|
||||
+
|
||||
+#define HCT_VERSION_STRING "0.2"
|
||||
+#define DEF_VERSION_STRING "0.1"
|
||||
+#define VERSION_SIZE 16
|
||||
+
|
||||
+#define HCT_SHARE_IOC_TYPE 'C'
|
||||
+#define HCT_SHARE_OP_TYPE 0x01
|
||||
+#define HCT_SHARE_OP _IOWR(HCT_SHARE_IOC_TYPE, \
|
||||
+ HCT_SHARE_OP_TYPE, \
|
||||
+ struct hct_dev_ctrl)
|
||||
+#define HCT_SHARE_OP_DMA_MAP 0x01
|
||||
+#define HCT_SHARE_OP_GET_ID 0x03
|
||||
+#define HCT_SHARE_OP_GET_PASID 0x04
|
||||
+#define HCT_SHARE_OP_DMA_UNMAP 0x05
|
||||
+#define HCT_SHARE_OP_GET_VERSION 0x06
|
||||
+
|
||||
+/* BARS */
|
||||
+#define HCT_REG_BAR_IDX 2
|
||||
+#define HCT_SHARED_BAR_IDX 3
|
||||
+#define HCT_PASID_BAR_IDX 4
|
||||
+
|
||||
+#define PASID_OFFSET 40
|
||||
+
|
||||
+static volatile struct hct_data {
|
||||
+ int init;
|
||||
+ int hct_fd;
|
||||
+ unsigned long pasid;
|
||||
+ uint8_t *pasid_memory;
|
||||
+ uint8_t *hct_shared_memory;
|
||||
+ uint8_t ccp_index[MAX_CCP_CNT];
|
||||
+ uint8_t ccp_cnt;
|
||||
+} hct_data;
|
||||
+
|
||||
+typedef struct SharedDevice {
|
||||
+ PCIDevice dev;
|
||||
+ int shared_memory_offset;
|
||||
+} SharedDevice;
|
||||
+
|
||||
+typedef struct HctDevState {
|
||||
+ SharedDevice sdev;
|
||||
+ VFIODevice vdev;
|
||||
+ MemoryRegion mmio;
|
||||
+ MemoryRegion shared;
|
||||
+ MemoryRegion pasid;
|
||||
+ void *maps[PCI_NUM_REGIONS];
|
||||
+} HCTDevState;
|
||||
+
|
||||
+struct hct_dev_ctrl {
|
||||
+ unsigned char op;
|
||||
+ unsigned char rsvd[3];
|
||||
+ union {
|
||||
+ unsigned char version[VERSION_SIZE];
|
||||
+ struct {
|
||||
+ unsigned long vaddr;
|
||||
+ unsigned long iova;
|
||||
+ unsigned long size;
|
||||
+ };
|
||||
+ unsigned int id;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+static int pasid_get_and_init(HCTDevState *state)
|
||||
+{
|
||||
+ struct hct_dev_ctrl ctrl;
|
||||
+ int ret;
|
||||
+
|
||||
+ ctrl.op = HCT_SHARE_OP_GET_PASID;
|
||||
+ ctrl.id = -1;
|
||||
+ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl);
|
||||
+ if (ret < 0) {
|
||||
+ ret = -errno;
|
||||
+ error_report("GET_PASID fail: %d", -errno);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ *hct_data.pasid_memory = ctrl.id;
|
||||
+ hct_data.pasid = ctrl.id;
|
||||
+
|
||||
+out:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static const MemoryRegionOps hct_mmio_ops = {
|
||||
+ .endianness = DEVICE_NATIVE_ENDIAN,
|
||||
+ .valid =
|
||||
+ {
|
||||
+ .min_access_size = 4,
|
||||
+ .max_access_size = 4,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void vfio_hct_detach_device(HCTDevState *state)
|
||||
+{
|
||||
+ vfio_detach_device(&state->vdev);
|
||||
+ g_free(state->vdev.name);
|
||||
+}
|
||||
+
|
||||
+static void vfio_hct_exit(PCIDevice *dev)
|
||||
+{
|
||||
+ HCTDevState *state = PCI_HCT_DEV(dev);
|
||||
+
|
||||
+ vfio_hct_detach_device(state);
|
||||
+
|
||||
+ if (hct_data.hct_fd) {
|
||||
+ qemu_close(hct_data.hct_fd);
|
||||
+ hct_data.hct_fd = 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static Property vfio_hct_properties[] = {
|
||||
+ DEFINE_PROP_STRING("sysfsdev", HCTDevState, vdev.sysfsdev),
|
||||
+ DEFINE_PROP_END_OF_LIST(),
|
||||
+};
|
||||
+
|
||||
+static void vfio_ccp_compute_needs_reset(VFIODevice *vdev)
|
||||
+{
|
||||
+ vdev->needs_reset = false;
|
||||
+}
|
||||
+
|
||||
+struct VFIODeviceOps vfio_ccp_ops = {
|
||||
+ .vfio_compute_needs_reset = vfio_ccp_compute_needs_reset,
|
||||
+};
|
||||
+
|
||||
+/* create BAR2, BAR3 and BAR4 space for the virtual machine. */
|
||||
+static int vfio_hct_region_mmap(HCTDevState *state)
|
||||
+{
|
||||
+ int ret;
|
||||
+ int i;
|
||||
+ struct vfio_region_info *info;
|
||||
+
|
||||
+ for (i = 0; i < PCI_ROM_SLOT; i++) {
|
||||
+ ret = vfio_get_region_info(&state->vdev, i, &info);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
+ if (info->size) {
|
||||
+ state->maps[i] = mmap(NULL, info->size, PROT_READ | PROT_WRITE,
|
||||
+ MAP_SHARED, state->vdev.fd, info->offset);
|
||||
+ if (state->maps[i] == MAP_FAILED) {
|
||||
+ ret = -errno;
|
||||
+ g_free(info);
|
||||
+ error_report("vfio mmap fail\n");
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ g_free(info);
|
||||
+ }
|
||||
+
|
||||
+ memory_region_init_io(&state->mmio, OBJECT(state), &hct_mmio_ops, state,
|
||||
+ "hct mmio", HCT_MMIO_SIZE);
|
||||
+ memory_region_init_ram_device_ptr(&state->mmio, OBJECT(state), "hct mmio",
|
||||
+ HCT_MMIO_SIZE,
|
||||
+ state->maps[HCT_REG_BAR_IDX]);
|
||||
+
|
||||
+ memory_region_init_io(&state->shared, OBJECT(state), &hct_mmio_ops, state,
|
||||
+ "hct shared memory", PAGE_SIZE);
|
||||
+ memory_region_init_ram_device_ptr(
|
||||
+ &state->shared, OBJECT(state), "hct shared memory", PAGE_SIZE,
|
||||
+ (void *)hct_data.hct_shared_memory +
|
||||
+ state->sdev.shared_memory_offset * PAGE_SIZE);
|
||||
+
|
||||
+ memory_region_init_io(&state->pasid, OBJECT(state), &hct_mmio_ops, state,
|
||||
+ "hct pasid", PAGE_SIZE);
|
||||
+ memory_region_init_ram_device_ptr(&state->pasid, OBJECT(state), "hct pasid",
|
||||
+ PAGE_SIZE, hct_data.pasid_memory);
|
||||
+
|
||||
+ pci_register_bar(&state->sdev.dev, HCT_REG_BAR_IDX,
|
||||
+ PCI_BASE_ADDRESS_SPACE_MEMORY, &state->mmio);
|
||||
+ pci_register_bar(&state->sdev.dev, HCT_SHARED_BAR_IDX,
|
||||
+ PCI_BASE_ADDRESS_SPACE_MEMORY, &state->shared);
|
||||
+ pci_register_bar(&state->sdev.dev, HCT_PASID_BAR_IDX,
|
||||
+ PCI_BASE_ADDRESS_SPACE_MEMORY, &state->pasid);
|
||||
+out:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int hct_check_duplicated_index(int index)
|
||||
+{
|
||||
+ int cnt;
|
||||
+ for (cnt = 0; cnt < hct_data.ccp_cnt; cnt++) {
|
||||
+ if (hct_data.ccp_index[cnt] == index) {
|
||||
+ error_report("many mdev shouldn't be mapped to one ccp in a "
|
||||
+ "virtual machine!\n");
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ hct_data.ccp_index[hct_data.ccp_cnt++] = index;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int hct_get_ccp_index(HCTDevState *state)
|
||||
+{
|
||||
+ char path[PATH_MAX];
|
||||
+ char buf[CCP_INDEX_BYTES];
|
||||
+ int fd;
|
||||
+ int ret;
|
||||
+ int ccp_index;
|
||||
+
|
||||
+ snprintf(path, PATH_MAX, "%s/vendor/id", state->vdev.sysfsdev);
|
||||
+ fd = qemu_open_old(path, O_RDONLY);
|
||||
+ if (fd < 0) {
|
||||
+ error_report("open %s fail\n", path);
|
||||
+ return -errno;
|
||||
+ }
|
||||
+
|
||||
+ ret = read(fd, buf, sizeof(buf));
|
||||
+ if (ret < 0) {
|
||||
+ ret = -errno;
|
||||
+ error_report("read %s fail\n", path);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (1 != sscanf(buf, "%d", &ccp_index)) {
|
||||
+ ret = -errno;
|
||||
+ error_report("format addr %s fail\n", buf);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (!hct_check_duplicated_index(ccp_index)) {
|
||||
+ state->sdev.shared_memory_offset = ccp_index;
|
||||
+ } else {
|
||||
+ ret = -1;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ qemu_close(fd);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int hct_api_version_check(void)
|
||||
+{
|
||||
+ struct hct_dev_ctrl ctrl;
|
||||
+ int ret;
|
||||
+
|
||||
+ ctrl.op = HCT_SHARE_OP_GET_VERSION;
|
||||
+ memcpy(ctrl.version, DEF_VERSION_STRING, sizeof(DEF_VERSION_STRING));
|
||||
+ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl);
|
||||
+ if (ret < 0) {
|
||||
+ error_report("ret %d, errno %d: fail to get hct.ko version, please "
|
||||
+ "update hct.ko to version 0.2.\n",
|
||||
+ ret, errno);
|
||||
+ return -1;
|
||||
+ } else if (memcmp(ctrl.version, HCT_VERSION_STRING,
|
||||
+ sizeof(HCT_VERSION_STRING)) < 0) {
|
||||
+ error_report("The API version %s is larger than hct.ko version %s, "
|
||||
+ "please update hct.ko to version 0.2\n",
|
||||
+ HCT_VERSION_STRING, ctrl.version);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int hct_shared_memory_init(void)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ hct_data.hct_shared_memory =
|
||||
+ mmap(NULL, HCT_SHARED_MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
+ hct_data.hct_fd, 0);
|
||||
+ if (hct_data.hct_shared_memory == MAP_FAILED) {
|
||||
+ ret = -errno;
|
||||
+ error_report("map hct shared memory fail\n");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void hct_listener_region_add(MemoryListener *listener,
|
||||
+ MemoryRegionSection *section)
|
||||
+{
|
||||
+ struct hct_dev_ctrl ctrl;
|
||||
+ hwaddr iova;
|
||||
+ Int128 llend, llsize;
|
||||
+ void *vaddr;
|
||||
+ int ret;
|
||||
+
|
||||
+ iova = REAL_HOST_PAGE_ALIGN(section->offset_within_address_space);
|
||||
+ llend = int128_make64(section->offset_within_address_space);
|
||||
+ llend = int128_add(llend, section->size);
|
||||
+ llend = int128_add(llend, int128_exts64(qemu_real_host_page_mask()));
|
||||
+
|
||||
+ if (int128_ge(int128_make64(iova), llend)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!section->mr->ram) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ vaddr = memory_region_get_ram_ptr(section->mr) +
|
||||
+ section->offset_within_region +
|
||||
+ (iova - section->offset_within_address_space);
|
||||
+ llsize = int128_sub(llend, int128_make64(iova));
|
||||
+
|
||||
+ ctrl.op = HCT_SHARE_OP_DMA_MAP;
|
||||
+ ctrl.iova = iova | (hct_data.pasid << PASID_OFFSET);
|
||||
+ ctrl.vaddr = (uint64_t)vaddr;
|
||||
+ ctrl.size = llsize;
|
||||
+ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl);
|
||||
+ if (ret < 0)
|
||||
+ error_report("VFIO_MAP_DMA: %d, iova=%lx", -errno, iova);
|
||||
+}
|
||||
+
|
||||
+static void hct_listener_region_del(MemoryListener *listener,
|
||||
+ MemoryRegionSection *section)
|
||||
+{
|
||||
+ struct hct_dev_ctrl ctrl;
|
||||
+ hwaddr iova;
|
||||
+ Int128 llend, llsize;
|
||||
+ int ret;
|
||||
+
|
||||
+ iova = REAL_HOST_PAGE_ALIGN(section->offset_within_address_space);
|
||||
+ llend = int128_make64(section->offset_within_address_space);
|
||||
+ llend = int128_add(llend, section->size);
|
||||
+ llend = int128_add(llend, int128_exts64(qemu_real_host_page_mask()));
|
||||
+
|
||||
+ if (int128_ge(int128_make64(iova), llend)) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (!section->mr->ram) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ llsize = int128_sub(llend, int128_make64(iova));
|
||||
+
|
||||
+ ctrl.op = HCT_SHARE_OP_DMA_UNMAP;
|
||||
+ ctrl.iova = iova | (hct_data.pasid << PASID_OFFSET);
|
||||
+ ctrl.size = llsize;
|
||||
+ ret = ioctl(hct_data.hct_fd, HCT_SHARE_OP, &ctrl);
|
||||
+ if (ret < 0)
|
||||
+ error_report("VFIO_UNMAP_DMA: %d", -errno);
|
||||
+}
|
||||
+
|
||||
+static MemoryListener hct_memory_listener = {
|
||||
+ .region_add = hct_listener_region_add,
|
||||
+ .region_del = hct_listener_region_del,
|
||||
+};
|
||||
+
|
||||
+static void hct_data_uninit(HCTDevState *state)
|
||||
+{
|
||||
+ if (hct_data.hct_fd) {
|
||||
+ qemu_close(hct_data.hct_fd);
|
||||
+ hct_data.hct_fd = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (hct_data.pasid) {
|
||||
+ hct_data.pasid = 0;
|
||||
+ }
|
||||
+
|
||||
+ if (hct_data.pasid_memory) {
|
||||
+ munmap(hct_data.pasid_memory, PAGE_SIZE);
|
||||
+ hct_data.pasid_memory = NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (hct_data.hct_shared_memory) {
|
||||
+ munmap((void *)hct_data.hct_shared_memory, HCT_SHARED_MEMORY_SIZE);
|
||||
+ hct_data.hct_shared_memory = NULL;
|
||||
+ }
|
||||
+
|
||||
+ memory_listener_unregister(&hct_memory_listener);
|
||||
+}
|
||||
+
|
||||
+static int hct_data_init(HCTDevState *state)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ if (hct_data.init == 0) {
|
||||
+
|
||||
+ hct_data.hct_fd = qemu_open_old(HCT_SHARE_DEV, O_RDWR);
|
||||
+ if (hct_data.hct_fd < 0) {
|
||||
+ error_report("fail to open %s, errno %d.", HCT_SHARE_DEV, errno);
|
||||
+ ret = -errno;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* The hct.ko version number needs not to be less than 0.2. */
|
||||
+ ret = hct_api_version_check();
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
+ /* assign a page to the virtual BAR3 of each CCP. */
|
||||
+ ret = hct_shared_memory_init();
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
+ hct_data.pasid_memory = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
+ if (hct_data.pasid_memory < 0)
|
||||
+ goto unmap_shared_memory_exit;
|
||||
+
|
||||
+ /* assign a unique pasid to each virtual machine. */
|
||||
+ ret = pasid_get_and_init(state);
|
||||
+ if (ret < 0)
|
||||
+ goto unmap_pasid_memory_exit;
|
||||
+
|
||||
+ /* perform DMA_MAP and DMA_UNMAP operations on all memories of the
|
||||
+ * virtual machine. */
|
||||
+ memory_listener_register(&hct_memory_listener, &address_space_memory);
|
||||
+
|
||||
+ hct_data.init = 1;
|
||||
+ }
|
||||
+
|
||||
+ return hct_get_ccp_index(state);
|
||||
+
|
||||
+unmap_pasid_memory_exit:
|
||||
+ munmap(hct_data.pasid_memory, PAGE_SIZE);
|
||||
+
|
||||
+unmap_shared_memory_exit:
|
||||
+ munmap((void *)hct_data.hct_shared_memory, HCT_SHARED_MEMORY_SIZE);
|
||||
+
|
||||
+out:
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* When device is loaded */
|
||||
+static void vfio_hct_realize(PCIDevice *pci_dev, Error **errp)
|
||||
+{
|
||||
+ int ret;
|
||||
+ char *mdevid;
|
||||
+ Error *err = NULL;
|
||||
+ HCTDevState *state = PCI_HCT_DEV(pci_dev);
|
||||
+
|
||||
+ /* parsing mdev device name from startup scripts */
|
||||
+ mdevid = g_path_get_basename(state->vdev.sysfsdev);
|
||||
+ state->vdev.name = g_strdup_printf("%s", mdevid);
|
||||
+
|
||||
+ ret = hct_data_init(state);
|
||||
+ if (ret < 0) {
|
||||
+ g_free(state->vdev.name);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ ret = vfio_attach_device(state->vdev.name, &state->vdev,
|
||||
+ pci_device_iommu_address_space(pci_dev), &err);
|
||||
+
|
||||
+ if (ret) {
|
||||
+ error_report("attach device failed, name = %s", state->vdev.name);
|
||||
+ goto data_uninit_out;
|
||||
+ }
|
||||
+
|
||||
+ state->vdev.ops = &vfio_ccp_ops;
|
||||
+ state->vdev.dev = &state->sdev.dev.qdev;
|
||||
+
|
||||
+ ret = vfio_hct_region_mmap(state);
|
||||
+ if (ret < 0)
|
||||
+ goto detach_device_out;
|
||||
+
|
||||
+ return;
|
||||
+
|
||||
+detach_device_out:
|
||||
+ vfio_hct_detach_device(state);
|
||||
+
|
||||
+data_uninit_out:
|
||||
+ hct_data_uninit(state);
|
||||
+
|
||||
+out:
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void hct_dev_class_init(ObjectClass *klass, void *data)
|
||||
+{
|
||||
+ DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
+ PCIDeviceClass *pdc = PCI_DEVICE_CLASS(klass);
|
||||
+
|
||||
+ dc->desc = "HCT Device";
|
||||
+ device_class_set_props(dc, vfio_hct_properties);
|
||||
+
|
||||
+ pdc->realize = vfio_hct_realize;
|
||||
+ pdc->exit = vfio_hct_exit;
|
||||
+ pdc->vendor_id = PCI_VENDOR_ID_HYGON_CCP;
|
||||
+ pdc->device_id = PCI_DEVICE_ID_HYGON_CCP;
|
||||
+ pdc->class_id = PCI_CLASS_CRYPT_OTHER;
|
||||
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static const TypeInfo pci_hct_info = {
|
||||
+ .name = TYPE_HCT_DEV,
|
||||
+ .parent = TYPE_PCI_DEVICE,
|
||||
+ .instance_size = sizeof(HCTDevState),
|
||||
+ .class_init = hct_dev_class_init,
|
||||
+ .interfaces =
|
||||
+ (InterfaceInfo[]){
|
||||
+ {INTERFACE_CONVENTIONAL_PCI_DEVICE},
|
||||
+ {},
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static void hct_register_types(void) {
|
||||
+ type_register_static(&pci_hct_info);
|
||||
+}
|
||||
+
|
||||
+type_init(hct_register_types);
|
||||
diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
|
||||
index 2a6912c940..b1db4c8605 100644
|
||||
--- a/hw/vfio/meson.build
|
||||
+++ b/hw/vfio/meson.build
|
||||
@@ -17,5 +17,6 @@ vfio_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c'))
|
||||
vfio_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c'))
|
||||
vfio_ss.add(when: 'CONFIG_VFIO_AP', if_true: files('ap.c'))
|
||||
vfio_ss.add(when: 'CONFIG_VFIO_IGD', if_true: files('igd.c'))
|
||||
+vfio_ss.add(when: 'CONFIG_VFIO_HCT', if_true: files('hct.c'))
|
||||
|
||||
specific_ss.add_all(when: 'CONFIG_VFIO', if_true: vfio_ss)
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
28
hw-vfio-hct-fix-ccp_index-error-caused-by-uninitiali.patch
Normal file
28
hw-vfio-hct-fix-ccp_index-error-caused-by-uninitiali.patch
Normal file
@ -0,0 +1,28 @@
|
||||
From 360bd43ff3c4e4938ee8af1a5ccf981152f7ca95 Mon Sep 17 00:00:00 2001
|
||||
From: yangdepei <yangdepei@hygon.cn>
|
||||
Date: Mon, 26 Aug 2024 15:40:25 +0800
|
||||
Subject: [PATCH] hw/vfio/hct: fix ccp_index error caused by uninitialized buf
|
||||
|
||||
Signed-off-by: yangdepei <yangdepei@hygon.cn>
|
||||
---
|
||||
hw/vfio/hct.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/hw/vfio/hct.c b/hw/vfio/hct.c
|
||||
index 790bb78439..9374e95e85 100644
|
||||
--- a/hw/vfio/hct.c
|
||||
+++ b/hw/vfio/hct.c
|
||||
@@ -235,8 +235,8 @@ static int hct_check_duplicated_index(int index)
|
||||
|
||||
static int hct_get_ccp_index(HCTDevState *state)
|
||||
{
|
||||
- char path[PATH_MAX];
|
||||
- char buf[CCP_INDEX_BYTES];
|
||||
+ char path[PATH_MAX] = {0};
|
||||
+ char buf[CCP_INDEX_BYTES] = {0};
|
||||
int fd;
|
||||
int ret;
|
||||
int ccp_index;
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
79
hw-vfio-hct-qemu-startup-terminate-once-error-happen.patch
Normal file
79
hw-vfio-hct-qemu-startup-terminate-once-error-happen.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From 32855e315c3050f09388f1335c0869bba065fbae Mon Sep 17 00:00:00 2001
|
||||
From: yangdepei <yangdepei@hygon.cn>
|
||||
Date: Fri, 27 Sep 2024 17:08:08 +0800
|
||||
Subject: [PATCH] hw/vfio/hct: qemu startup terminate once error happened in
|
||||
hct
|
||||
|
||||
Signed-off-by: yangdepei <yangdepei@hygon.cn>
|
||||
---
|
||||
hw/vfio/hct.c | 19 ++++++++++++++-----
|
||||
1 file changed, 14 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/hw/vfio/hct.c b/hw/vfio/hct.c
|
||||
index 9374e95e85..7fd3977182 100644
|
||||
--- a/hw/vfio/hct.c
|
||||
+++ b/hw/vfio/hct.c
|
||||
@@ -136,7 +136,9 @@ static const MemoryRegionOps hct_mmio_ops = {
|
||||
static void vfio_hct_detach_device(HCTDevState *state)
|
||||
{
|
||||
vfio_detach_device(&state->vdev);
|
||||
- g_free(state->vdev.name);
|
||||
+
|
||||
+ if (state->vdev.name)
|
||||
+ g_free(state->vdev.name);
|
||||
}
|
||||
|
||||
static void vfio_hct_exit(PCIDevice *dev)
|
||||
@@ -413,7 +415,6 @@ static int hct_data_init(HCTDevState *state)
|
||||
int ret;
|
||||
|
||||
if (hct_data.init == 0) {
|
||||
-
|
||||
hct_data.hct_fd = qemu_open_old(HCT_SHARE_DEV, O_RDWR);
|
||||
if (hct_data.hct_fd < 0) {
|
||||
error_report("fail to open %s, errno %d.", HCT_SHARE_DEV, errno);
|
||||
@@ -465,7 +466,6 @@ static void vfio_hct_realize(PCIDevice *pci_dev, Error **errp)
|
||||
{
|
||||
int ret;
|
||||
char *mdevid;
|
||||
- Error *err = NULL;
|
||||
HCTDevState *state = PCI_HCT_DEV(pci_dev);
|
||||
|
||||
/* parsing mdev device name from startup scripts */
|
||||
@@ -475,14 +475,18 @@ static void vfio_hct_realize(PCIDevice *pci_dev, Error **errp)
|
||||
ret = hct_data_init(state);
|
||||
if (ret < 0) {
|
||||
g_free(state->vdev.name);
|
||||
+ state->vdev.name = NULL;
|
||||
+ error_setg(errp, "hct data init failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = vfio_attach_device(state->vdev.name, &state->vdev,
|
||||
- pci_device_iommu_address_space(pci_dev), &err);
|
||||
+ pci_device_iommu_address_space(pci_dev), errp);
|
||||
|
||||
if (ret) {
|
||||
- error_report("attach device failed, name = %s", state->vdev.name);
|
||||
+ g_free(state->vdev.name);
|
||||
+ state->vdev.name = NULL;
|
||||
+ error_setg(errp, "attach device failed, name = %s", state->vdev.name);
|
||||
goto data_uninit_out;
|
||||
}
|
||||
|
||||
@@ -491,7 +495,12 @@ static void vfio_hct_realize(PCIDevice *pci_dev, Error **errp)
|
||||
|
||||
ret = vfio_hct_region_mmap(state);
|
||||
if (ret < 0)
|
||||
+ {
|
||||
+ g_free(state->vdev.name);
|
||||
+ state->vdev.name = NULL;
|
||||
+ error_setg(errp, "region mmap failed, name = %s", state->vdev.name);
|
||||
goto detach_device_out;
|
||||
+ }
|
||||
|
||||
return;
|
||||
|
||||
--
|
||||
2.41.0.windows.1
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user