Re: [PATCH 1/2] riscv: zicond: make non-experimental
On 8/10/23 10:14, Alistair Francis wrote: On Tue, Aug 8, 2023 at 2:18 PM Vineet Gupta wrote: zicond is now codegen supported in both llvm and gcc. This change allows seamless enabling/testing of zicond in downstream projects. e.g. currently riscv-gnu-toolchain parses elf attributes to create a cmdline for qemu but fails short of enabling it because of the "x-" prefix. Signed-off-by: Vineet Gupta Reviewed-by: Alistair Francis Alistair Gentle ping to remind that this lands in some -next tree and not forgotten ! Thx, -Vineet --- target/riscv/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6b93b04453c8..022bd9d01223 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1816,6 +1816,7 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("zcf", RISCVCPU, cfg.ext_zcf, false), DEFINE_PROP_BOOL("zcmp", RISCVCPU, cfg.ext_zcmp, false), DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false), +DEFINE_PROP_BOOL("zicond", RISCVCPU, cfg.ext_zicond, false), /* Vendor-specific custom extensions */ DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false), @@ -1832,7 +1833,6 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false), /* These are experimental so mark with 'x-' */ -DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false), /* ePMP 0.9.3 */ DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false), -- 2.34.1
Re: [PATCH v2] linux-user: ppoll: eliminate large alloca
On 24/8/23 19:51, Michael Tokarev wrote: do_ppoll() in linux-user/syscall.c uses alloca() to allocate an array of struct pullfds on the stack. The only upper boundary for number of entries for this array is so that whole thing fits in INT_MAX. But this is definitely too much for a stack allocation. Use heap allocation instead. This, together with previous patch for getgroups(), eliminates all large on-stack allocations from qemu-user/syscall.c. What's left are actually small ones. While at it, also fix missing unlock_user() in two places, and consolidate target_to_host_timespec*() calls into time64?_timespec():_timespec64() construct. Signed-off-by: Michael Tokarev --- v1: https://patchwork.ozlabs.org/project/qemu-devel/patch/20221216192220.2881898-1-...@msgid.tls.msk.ru/ v2: remove alloca() optimization for smaller number of fds linux-user/syscall.c | 45 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 9353268cc1..e79594bcd5 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1487,14 +1487,12 @@ static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3, static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5, bool ppoll, bool time64) { -struct target_pollfd *target_pfd; +struct target_pollfd *target_pfd = NULL; unsigned int nfds = arg2; -struct pollfd *pfd; +struct pollfd *pfd = NULL; unsigned int i; abi_long ret; -pfd = NULL; -target_pfd = NULL; if (nfds) { if (nfds > (INT_MAX / sizeof(struct target_pollfd))) { return -TARGET_EINVAL; @@ -1505,7 +1503,11 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, return -TARGET_EFAULT; } -pfd = alloca(sizeof(struct pollfd) * nfds); +pfd = g_try_new(struct pollfd, nfds); +if (!pfd) { +ret = -TARGET_ENOMEM; +goto out; +} for (i = 0; i < nfds; i++) { pfd[i].fd = tswap32(target_pfd[i].fd); pfd[i].events = tswap16(target_pfd[i].events); @@ -1516,16 +1518,11 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, sigset_t *set = NULL; if (arg3) { -if (time64) { -if (target_to_host_timespec64(timeout_ts, arg3)) { -unlock_user(target_pfd, arg1, 0); So this changes unlock(sz=0) ... -return -TARGET_EFAULT; -} -} else { -if (target_to_host_timespec(timeout_ts, arg3)) { -unlock_user(target_pfd, arg1, 0); -return -TARGET_EFAULT; -} +if (time64 +? target_to_host_timespec64(timeout_ts, arg3) +: target_to_host_timespec(timeout_ts, arg3)) { +ret = -TARGET_EFAULT; +goto out; ... to unlock(sz=pollfd*nfds). Is that also part of your "While at it" comment? Having one patch for each logical change eases review / cherry-pick / backport. } } else { timeout_ts = NULL; @@ -1534,8 +1531,7 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, if (arg4) { ret = process_sigsuspend_mask(, arg4, arg5); if (ret != 0) { -unlock_user(target_pfd, arg1, 0); (Ditto) -return ret; +goto out; } } @@ -1546,14 +1542,11 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, finish_sigsuspend_mask(ret); } if (!is_error(ret) && arg3) { -if (time64) { -if (host_to_target_timespec64(arg3, timeout_ts)) { -return -TARGET_EFAULT; -} -} else { -if (host_to_target_timespec(arg3, timeout_ts)) { -return -TARGET_EFAULT; -} +if (time64 +? host_to_target_timespec64(arg3, timeout_ts) +: host_to_target_timespec(arg3, timeout_ts)) { +ret = -TARGET_EFAULT; +goto out; } } } else { @@ -1576,6 +1569,8 @@ static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3, target_pfd[i].revents = tswap16(pfd[i].revents); } } +out: +g_free(pfd); unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds); return ret; }
Re: [PATCH] hw/usb/hcd-xhci: Avoid variable-length array in xhci_get_port_bandwidth()
On 24/8/23 18:48, Peter Maydell wrote: In xhci_get_port_bandwidth(), we use a variable-length array to construct the buffer to send back to the guest. Avoid the VLA by using dma_memory_set() to directly request the memory system to fill the guest memory with a string of '80's. The codebase has very few VLAs, and if we can get rid of them all we can make the compiler error on new additions. This is a defensive measure against security bugs where an on-stack dynamic allocation isn't correctly size-checked (e.g. CVE-2021-3527). Signed-off-by: Peter Maydell --- Use of dma_memory_set() is a suggestion from RTH from Philippe's original attempt. If we ever do anything about the "use real values" TODO we'll need to do something else (eg heap-allocated array), but since we haven't done so since the code was written in 2012 it doesn't seem very likely we'll ever do so. --- hw/usb/hcd-xhci.c | 10 -- 1 file changed, 4 insertions(+), 6 deletions(-) Thanks! Reviewed-by: Philippe Mathieu-Daudé
Re: [PATCH v12 0/9] rutabaga_gfx + gfxstream
On 2023/08/25 8:40, Gurchetan Singh wrote: From: Gurchetan Singh Prior versions: Changes since v11: - Incorporated review feedback How to build both rutabaga and gfxstream guest/host libs: https://crosvm.dev/book/appendix/rutabaga_gfx.html Branch containing this patch series (now on QEMU Gitlab): https://gitlab.com/gurchetansingh/qemu/-/commits/qemu-gfxstream-v12 Antonio Caggiano (2): virtio-gpu: CONTEXT_INIT feature virtio-gpu: blob prep Dr. David Alan Gilbert (1): virtio: Add shared memory capability Gerd Hoffmann (1): virtio-gpu: hostmem Gurchetan Singh (5): gfxstream + rutabaga prep: added need defintions, fields, and options gfxstream + rutabaga: add initial support for gfxstream gfxstream + rutabaga: meson support gfxstream + rutabaga: enable rutabaga docs/system: add basic virtio-gpu documentation docs/system/device-emulation.rst |1 + docs/system/devices/virtio-gpu.rst | 112 +++ hw/display/meson.build | 22 + hw/display/virtio-gpu-base.c |6 +- hw/display/virtio-gpu-pci-rutabaga.c | 47 ++ hw/display/virtio-gpu-pci.c | 14 + hw/display/virtio-gpu-rutabaga.c | 1119 ++ hw/display/virtio-gpu.c | 16 +- hw/display/virtio-vga-rutabaga.c | 50 ++ hw/display/virtio-vga.c | 33 +- hw/virtio/virtio-pci.c | 18 + include/hw/virtio/virtio-gpu-bswap.h | 15 + include/hw/virtio/virtio-gpu.h | 41 + include/hw/virtio/virtio-pci.h |4 + meson.build |7 + meson_options.txt|2 + scripts/meson-buildoptions.sh|3 + softmmu/qdev-monitor.c |3 + softmmu/vl.c |1 + 19 files changed, 1495 insertions(+), 19 deletions(-) create mode 100644 docs/system/devices/virtio-gpu.rst create mode 100644 hw/display/virtio-gpu-pci-rutabaga.c create mode 100644 hw/display/virtio-gpu-rutabaga.c create mode 100644 hw/display/virtio-vga-rutabaga.c Thanks for keeping working on this. For the entire series: Reviewed-by: Akihiko Odaki Tested-by: Akihiko Odaki
Re: [PULL 00/12] First batch of s390x patches for QEMU 8.2
On 24/8/23 18:10, Thomas Huth wrote: On 24/08/2023 16.51, Stefan Hajnoczi wrote: On Thu, 24 Aug 2023 at 02:53, Thomas Huth wrote: On 23/08/2023 18.34, Stefan Hajnoczi wrote: On Wed, Aug 23, 2023 at 01:45:32PM +0200, Thomas Huth wrote: The following changes since commit b0dd9a7d6dd15a6898e9c585b521e6bec79b25aa: Open 8.2 development tree (2023-08-22 07:14:07 -0700) are available in the Git repository at: https://gitlab.com/thuth/qemu.git tags/pull-request-2023-08-23 for you to fetch changes up to 6c49f685d30ffe81cfa47da2c258904ad28ac368: tests/tcg/s390x: Test VSTRS (2023-08-23 12:07:30 +0200) Hi Thomas, Please take a look at the following ubuntu-20.04-s390x-all CI failure: https://gitlab.com/qemu-project/qemu/-/jobs/4931341536 It says: "TimeoutError: Timeout waiting for job to pause" ... could you please check the load on that host? ... I think that s390x runner is known for being too slow some times, so I assume that problem should go away if you re-run the job when it is less loaded. I ran it again and it timed out. I've merged the PR and assume the test is just flaky. I think someone needs to look at the runner to see whether there is still old stuff taking CPU time or something similar. Would reporting the runner load on failure help in some way?
Re: [PATCH] tests/qtest/netdev-socket: Avoid variable-length array in inet_get_free_port_multiple()
On 24/8/23 18:45, Peter Maydell wrote: We use a variable-length array in inet_get_free_port_multiple(). This is only test code called at the start of a test, so switch to a heap allocation instead. The codebase has very few VLAs, and if we can get rid of them all we can make the compiler error on new additions. This is a defensive measure against security bugs where an on-stack dynamic allocation isn't correctly size-checked (e.g. CVE-2021-3527). Signed-off-by: Peter Maydell --- tests/qtest/netdev-socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) Reviewed-by: Philippe Mathieu-Daudé
[PATCH v2] block/file-posix: fix update_zones_wp() caller
When the zoned request fail, it needs to update only the wp of the target zones for not disrupting the in-flight writes on these other zones. The wp is updated successfully after the request completes. Fixed the callers with right offset and nr_zones. Signed-off-by: Sam Li --- block/file-posix.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index b16e9c21a1..55e7f06a2f 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -2522,7 +2522,8 @@ out: } } else { if (type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) { -update_zones_wp(bs, s->fd, 0, 1); +/* write and append write are not allowed to cross zone bounaries */ +update_zones_wp(bs, s->fd, offset, 1); } } @@ -3472,7 +3473,7 @@ static int coroutine_fn raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, len >> BDRV_SECTOR_BITS); ret = raw_thread_pool_submit(handle_aiocb_zone_mgmt, ); if (ret != 0) { -update_zones_wp(bs, s->fd, offset, i); +update_zones_wp(bs, s->fd, offset, nrz); error_report("ioctl %s failed %d", op_name, ret); return ret; } -- 2.40.1
Re: [PATCH] block/file-posix: fix update_zones_wp() caller
Damien Le Moal 于2023年8月25日周五 11:32写道: > > On 8/25/23 12:05, Sam Li wrote: > > Damien Le Moal 于2023年8月25日周五 07:49写道: > >> > >> On 8/25/23 02:39, Sam Li wrote: > >>> When the zoned requests that may change wp fail, it needs to > >>> update only wps of the zones within the range of the requests > >>> for not disrupting the other in-flight requests. The wp is updated > >>> successfully after the request completes. > >>> > >>> Fixed the callers with right offset and nr_zones. > >>> > >>> Signed-off-by: Sam Li > >>> --- > >>> block/file-posix.c | 5 +++-- > >>> 1 file changed, 3 insertions(+), 2 deletions(-) > >>> > >>> diff --git a/block/file-posix.c b/block/file-posix.c > >>> index b16e9c21a1..22559d6c2d 100644 > >>> --- a/block/file-posix.c > >>> +++ b/block/file-posix.c > >>> @@ -2522,7 +2522,8 @@ out: > >>> } > >>> } else { > >>> if (type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) { > >>> -update_zones_wp(bs, s->fd, 0, 1); > >>> +update_zones_wp(bs, s->fd, offset, > >>> +ROUND_UP(bytes, bs->bl.zone_size)); > >> > >> Write and zone append operations are not allowed to cross zone boundaries. > >> So I > >> the number of zones should always be 1. The above changes a number of > >> zones to a > >> number of bytes, which seems wrong. The correct fix is I think: > >> > >> update_zones_wp(bs, s->fd, offset, 1); > >> > > > > I see. I forgot this constraint. > > > >>> } > >>> } > >>> > >>> @@ -3472,7 +3473,7 @@ static int coroutine_fn > >>> raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, > >>> len >> BDRV_SECTOR_BITS); > >>> ret = raw_thread_pool_submit(handle_aiocb_zone_mgmt, ); > >>> if (ret != 0) { > >>> -update_zones_wp(bs, s->fd, offset, i); > >>> +update_zones_wp(bs, s->fd, offset, nrz); > >> > >> Same here. Why would you need to update all zones wp ? This will affect > >> zones > >> that do not have a write error and potentially change there correct > >> in-memory wp > >> to a wrong value. I think this also should be: > >> > >>update_zones_wp(bs, s->fd, offset, 1); > >> > > > > Is update_zones_wp for cancelling the writes on invalid zones or > > updating corrupted write pointers caused by caller (write, append or > > zone_mgmt)? > > > > My thought is based on the latter. Zone_mgmt can manage multiple zones > > with a single request. When the request fails, it's hard to tell which > > zone is corrupted. The relation between the req (zone_mgmt) and > > update_zones_wp is: if req succeeds, no updates; if req fails, > > consider the req never happens and do again. > > You should update the wp of the zones that were touched by the operation that > failed. No other zone should have its wp updated as that could cause > corruptions > of the wp if there are on-going writes on these other zones. > > so the call should be "update_zones_wp(bs, s->fd, offset, n);" > > with n being the number of zones that the operation targeted. Yes, so it's nrz in zone_mgmt. Thanks! > > > > > If the former is right, then it assumes only the first zone may > > contain an error. I am not sure it's right. > > > >>> error_report("ioctl %s failed %d", op_name, ret); > >>> return ret; > >>> } > >> > >> -- > >> Damien Le Moal > >> Western Digital Research > >> > > -- > Damien Le Moal > Western Digital Research >
Re: [PATCH] block/file-posix: fix update_zones_wp() caller
On 8/25/23 12:05, Sam Li wrote: > Damien Le Moal 于2023年8月25日周五 07:49写道: >> >> On 8/25/23 02:39, Sam Li wrote: >>> When the zoned requests that may change wp fail, it needs to >>> update only wps of the zones within the range of the requests >>> for not disrupting the other in-flight requests. The wp is updated >>> successfully after the request completes. >>> >>> Fixed the callers with right offset and nr_zones. >>> >>> Signed-off-by: Sam Li >>> --- >>> block/file-posix.c | 5 +++-- >>> 1 file changed, 3 insertions(+), 2 deletions(-) >>> >>> diff --git a/block/file-posix.c b/block/file-posix.c >>> index b16e9c21a1..22559d6c2d 100644 >>> --- a/block/file-posix.c >>> +++ b/block/file-posix.c >>> @@ -2522,7 +2522,8 @@ out: >>> } >>> } else { >>> if (type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) { >>> -update_zones_wp(bs, s->fd, 0, 1); >>> +update_zones_wp(bs, s->fd, offset, >>> +ROUND_UP(bytes, bs->bl.zone_size)); >> >> Write and zone append operations are not allowed to cross zone boundaries. >> So I >> the number of zones should always be 1. The above changes a number of zones >> to a >> number of bytes, which seems wrong. The correct fix is I think: >> >> update_zones_wp(bs, s->fd, offset, 1); >> > > I see. I forgot this constraint. > >>> } >>> } >>> >>> @@ -3472,7 +3473,7 @@ static int coroutine_fn >>> raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, >>> len >> BDRV_SECTOR_BITS); >>> ret = raw_thread_pool_submit(handle_aiocb_zone_mgmt, ); >>> if (ret != 0) { >>> -update_zones_wp(bs, s->fd, offset, i); >>> +update_zones_wp(bs, s->fd, offset, nrz); >> >> Same here. Why would you need to update all zones wp ? This will affect zones >> that do not have a write error and potentially change there correct >> in-memory wp >> to a wrong value. I think this also should be: >> >>update_zones_wp(bs, s->fd, offset, 1); >> > > Is update_zones_wp for cancelling the writes on invalid zones or > updating corrupted write pointers caused by caller (write, append or > zone_mgmt)? > > My thought is based on the latter. Zone_mgmt can manage multiple zones > with a single request. When the request fails, it's hard to tell which > zone is corrupted. The relation between the req (zone_mgmt) and > update_zones_wp is: if req succeeds, no updates; if req fails, > consider the req never happens and do again. You should update the wp of the zones that were touched by the operation that failed. No other zone should have its wp updated as that could cause corruptions of the wp if there are on-going writes on these other zones. so the call should be "update_zones_wp(bs, s->fd, offset, n);" with n being the number of zones that the operation targeted. > > If the former is right, then it assumes only the first zone may > contain an error. I am not sure it's right. > >>> error_report("ioctl %s failed %d", op_name, ret); >>> return ret; >>> } >> >> -- >> Damien Le Moal >> Western Digital Research >> -- Damien Le Moal Western Digital Research
[PATCH 15/16] tests: bios-tables-test: Add test for smbios type4 thread count2
From: Zhao Liu This tests the commit 7298fd7de5551 ("hw/smbios: Fix thread count in type4"). Add this test to cover 2 cases: 1. Test thread count2 field with multiple sockets and multiple dies to confirm this field could correctly calculate threads per sockets. 2. Confirm that field calculation could correctly recognize the difference between "-smp maxcpus" and "-smp cpus". Suggested-by: Igor Mammedov Signed-off-by: Zhao Liu --- tests/qtest/bios-tables-test.c | 33 + 1 file changed, 33 insertions(+) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 26474d376633..1b0c27e95d26 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -96,6 +96,7 @@ typedef struct { uint8_t smbios_core_count; uint16_t smbios_core_count2; uint8_t smbios_thread_count; +uint16_t smbios_thread_count2; uint8_t *required_struct_types; int required_struct_types_len; int type4_count; @@ -644,6 +645,7 @@ static void smbios_cpu_test(test_data *data, uint32_t addr, uint8_t thread_count, expected_thread_count = data->smbios_thread_count; uint16_t speed, expected_speed[2]; uint16_t core_count2, expected_core_count2 = data->smbios_core_count2; +uint16_t thread_count2, expected_thread_count2 = data->smbios_thread_count2; int offset[2]; int i; @@ -673,6 +675,8 @@ static void smbios_cpu_test(test_data *data, uint32_t addr, } if (ep_type == SMBIOS_ENTRY_POINT_TYPE_64) { +uint64_t thread_count2_addr; + core_count2 = qtest_readw(data->qts, addr + offsetof(struct smbios_type_4, core_count2)); @@ -680,6 +684,15 @@ static void smbios_cpu_test(test_data *data, uint32_t addr, if (expected_core_count == 0xFF && expected_core_count2) { g_assert_cmpuint(core_count2, ==, expected_core_count2); } + +thread_count2_addr = addr + + offsetof(struct smbios_type_4, thread_count2); +thread_count2 = qtest_readw(data->qts, thread_count2_addr); + +/* Thread Count has reached its limit, checking Thread Count 2 */ +if (expected_thread_count == 0xFF && expected_thread_count2) { +g_assert_cmpuint(thread_count2, ==, expected_thread_count2); +} } } @@ -1050,6 +1063,7 @@ static void test_acpi_q35_tcg_thread_count(void) .required_struct_types = base_required_struct_types, .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), .smbios_thread_count = 27, +.smbios_thread_count2 = 27, }; test_acpi_one("-machine smbios-entry-point-type=64 " @@ -1058,6 +1072,23 @@ static void test_acpi_q35_tcg_thread_count(void) free_test_data(); } +static void test_acpi_q35_tcg_thread_count2(void) +{ +test_data data = { +.machine = MACHINE_Q35, +.variant = ".thread-count2", +.required_struct_types = base_required_struct_types, +.required_struct_types_len = ARRAY_SIZE(base_required_struct_types), +.smbios_thread_count = 0xFF, +.smbios_thread_count2 = 260, +}; + +test_acpi_one("-machine smbios-entry-point-type=64 " + "-smp cpus=210,maxcpus=520,sockets=2,dies=2,cores=65,threads=2", + ); +free_test_data(); +} + static void test_acpi_q35_tcg_bridge(void) { test_data data = {}; @@ -2216,6 +2247,8 @@ int main(int argc, char *argv[]) test_acpi_q35_tcg_core_count2); qtest_add_func("acpi/q35/thread-count", test_acpi_q35_tcg_thread_count); +qtest_add_func("acpi/q35/thread-count2", + test_acpi_q35_tcg_thread_count2); } qtest_add_func("acpi/q35/viot", test_acpi_q35_viot); #ifdef CONFIG_POSIX -- 2.34.1
[PATCH 04/16] tests: bios-tables-test: Add ACPI table binaries for type4 count test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 5 and 6. Changes in the tables: FACP: +/* + * Intel ACPI Component Architecture + * AML/ASL+ Disassembler version 20200925 (64-bit version) + * Copyright (c) 2000 - 2020 Intel Corporation + * + * Disassembly of /tmp/aml-W37791, Wed Aug 23 10:36:32 2023 + * + * ACPI Data Table [FACP] + * + * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue + */ + +[000h 4]Signature : "FACP"[Fixed ACPI Description Table (FADT)] +[004h 0004 4] Table Length : 00F4 +[008h 0008 1] Revision : 03 +[009h 0009 1] Checksum : B3 +[00Ah 0010 6] Oem ID : "BOCHS " +[010h 0016 8] Oem Table ID : "BXPC" +[018h 0024 4] Oem Revision : 0001 +[01Ch 0028 4] Asl Compiler ID : "BXPC" +[020h 0032 4]Asl Compiler Revision : 0001 + +[024h 0036 4] FACS Address : +[028h 0040 4] DSDT Address : +[02Ch 0044 1]Model : 01 +[02Dh 0045 1] PM Profile : 00 [Unspecified] +[02Eh 0046 2]SCI Interrupt : 0009 +[030h 0048 4] SMI Command Port : 00B2 +[034h 0052 1]ACPI Enable Value : 02 +[035h 0053 1] ACPI Disable Value : 03 +[036h 0054 1] S4BIOS Command : 00 +[037h 0055 1] P-State Control : 00 +[038h 0056 4] PM1A Event Block Address : 0600 +[03Ch 0060 4] PM1B Event Block Address : +[040h 0064 4] PM1A Control Block Address : 0604 +[044h 0068 4] PM1B Control Block Address : +[048h 0072 4]PM2 Control Block Address : +[04Ch 0076 4] PM Timer Block Address : 0608 +[050h 0080 4] GPE0 Block Address : 0620 +[054h 0084 4] GPE1 Block Address : +[058h 0088 1] PM1 Event Block Length : 04 +[059h 0089 1] PM1 Control Block Length : 02 +[05Ah 0090 1] PM2 Control Block Length : 00 +[05Bh 0091 1]PM Timer Block Length : 04 +[05Ch 0092 1]GPE0 Block Length : 10 +[05Dh 0093 1]GPE1 Block Length : 00 +[05Eh 0094 1] GPE1 Base Offset : 00 +[05Fh 0095 1] _CST Support : 00 +[060h 0096 2] C2 Latency : 0FFF +[062h 0098 2] C3 Latency : 0FFF +[064h 0100 2] CPU Cache Size : +[066h 0102 2] Cache Flush Stride : +[068h 0104 1]Duty Cycle Offset : 00 +[069h 0105 1] Duty Cycle Width : 00 +[06Ah 0106 1] RTC Day Alarm Index : 00 +[06Bh 0107 1]RTC Month Alarm Index : 00 +[06Ch 0108 1]RTC Century Index : 32 +[06Dh 0109 2] Boot Flags (decoded below) : 0002 + Legacy Devices Supported (V2) : 0 +8042 Present on ports 60/64 (V2) : 1 +VGA Not Present (V4) : 0 + MSI Not Supported (V4) : 0 +PCIe ASPM Not Supported (V4) : 0 + CMOS RTC Not Present (V5) : 0 +[06Fh 0111 1] Reserved : 00 +[070h 0112 4]Flags (decoded below) : 000484A5 + WBINVD instruction is operational (V1) : 1 + WBINVD flushes all caches (V1) : 0 +All CPUs support C1 (V1) : 1 + C2 works on MP system (V1) : 0 +Control Method Power Button (V1) : 0 +Control Method Sleep Button (V1) : 1 +RTC wake not in fixed reg space (V1) : 0 +RTC can wake system from S4 (V1) : 1 +32-bit PM Timer (V1) : 0 + Docking Supported (V1) : 0 + Reset Register Supported (V2) : 1 +Sealed Case (V3) : 0 +Headless - No Video (V3) : 0 +Use native instr after SLP_TYPx (V3) : 0 + PCIEXP_WAK Bits Supported (V4) : 0 + Use Platform Timer (V4) : 1 + RTC_STS valid on S4 wake (V4) : 0 +Remote Power-on capable (V4) : 0 + Use APIC Cluster Model (V4) : 1 + Use APIC Physical Destination Mode (V4) : 0 + Hardware Reduced (V5) : 0 + Low Power S0 Idle (V5) : 0 + +[074h 0116 12] Reset Register : [Generic Address Structure] +[074h 0116 1] Space ID : 01 [SystemIO] +[075h 0117 1]Bit Width : 08 +[076h 0118 1] Bit Offset : 00 +[077h 0119 1] Encoded Access Width : 00 [Undefined/Legacy] +[078h 0120 8] Address : 0CF9 + +[080h 0128 1] Value to cause reset : 0F +[081h 0129 2]ARM Flags (decoded below) : + PSCI Compliant : 0 +
[PATCH 14/16] tests: bios-tables-test: Prepare the ACPI table change for type4 thread count2 test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 1 - 3. List the ACPI tables that will be added to test the thread count2 field of smbios type4 table. Signed-off-by: Zhao Liu --- tests/data/acpi/q35/APIC.thread-count2 | 0 tests/data/acpi/q35/DSDT.thread-count2 | 0 tests/data/acpi/q35/FACP.thread-count2 | 0 tests/qtest/bios-tables-test-allowed-diff.h | 3 +++ 4 files changed, 3 insertions(+) create mode 100644 tests/data/acpi/q35/APIC.thread-count2 create mode 100644 tests/data/acpi/q35/DSDT.thread-count2 create mode 100644 tests/data/acpi/q35/FACP.thread-count2 diff --git a/tests/data/acpi/q35/APIC.thread-count2 b/tests/data/acpi/q35/APIC.thread-count2 new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/data/acpi/q35/DSDT.thread-count2 b/tests/data/acpi/q35/DSDT.thread-count2 new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/data/acpi/q35/FACP.thread-count2 b/tests/data/acpi/q35/FACP.thread-count2 new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8bf4..d17d80e21ab9 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,4 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/APIC.thread-count2", +"tests/data/acpi/q35/DSDT.thread-count2", +"tests/data/acpi/q35/FACP.thread-count2", -- 2.34.1
[PATCH 03/16] tests: bios-tables-test: Add test for smbios type4 count
From: Zhao Liu This tests the commit d79a284a44bb7 ("hw/smbios: Fix smbios_smp_sockets calculation"). Test the count of type4 tables for multiple sockets case. Suggested-by: Igor Mammedov Signed-off-by: Zhao Liu --- tests/qtest/bios-tables-test.c | 33 - 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 47ba20b9579b..8679255449cf 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -97,6 +97,7 @@ typedef struct { uint16_t smbios_core_count2; uint8_t *required_struct_types; int required_struct_types_len; +int type4_count; QTestState *qts; } test_data; @@ -673,12 +674,21 @@ static void smbios_cpu_test(test_data *data, uint32_t addr, } } +static void smbios_type4_count_test(test_data *data, int type4_count) +{ +int expected_type4_count = data->type4_count; + +if (expected_type4_count) { +g_assert_cmpuint(type4_count, ==, expected_type4_count); +} +} + static void test_smbios_structs(test_data *data, SmbiosEntryPointType ep_type) { DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 }; SmbiosEntryPoint *ep_table = >smbios_ep_table; -int i = 0, len, max_len = 0; +int i = 0, len, max_len = 0, type4_count = 0; uint8_t type, prv, crt; uint64_t addr; @@ -704,6 +714,7 @@ static void test_smbios_structs(test_data *data, SmbiosEntryPointType ep_type) if (type == 4) { smbios_cpu_test(data, addr, ep_type); +type4_count++; } /* seek to end of unformatted string area of this struct ("\0\0") */ @@ -747,6 +758,8 @@ static void test_smbios_structs(test_data *data, SmbiosEntryPointType ep_type) for (i = 0; i < data->required_struct_types_len; i++) { g_assert(test_bit(data->required_struct_types[i], struct_bitmap)); } + +smbios_type4_count_test(data, type4_count); } static void test_acpi_load_tables(test_data *data) @@ -970,6 +983,22 @@ static void test_acpi_q35_tcg(void) free_test_data(); } +static void test_acpi_q35_tcg_type4_count(void) +{ +test_data data = { +.machine = MACHINE_Q35, +.variant = ".type4-count", +.required_struct_types = base_required_struct_types, +.required_struct_types_len = ARRAY_SIZE(base_required_struct_types), +.type4_count = 5, +}; + +test_acpi_one("-machine smbios-entry-point-type=64 " + "-smp cpus=100,maxcpus=120,sockets=5," + "dies=2,cores=4,threads=3", ); +free_test_data(); +} + static void test_acpi_q35_tcg_core_count2(void) { test_data data = { @@ -2135,6 +2164,8 @@ int main(int argc, char *argv[]) if (has_kvm) { qtest_add_func("acpi/q35/kvm/xapic", test_acpi_q35_kvm_xapic); qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar); +qtest_add_func("acpi/q35/type4-count", + test_acpi_q35_tcg_type4_count); qtest_add_func("acpi/q35/core-count2", test_acpi_q35_tcg_core_count2); } -- 2.34.1
[PATCH 13/16] tests: bios-tables-test: Add ACPI table binaries for type4 thread count test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 5 and 6. Changes in the tables: FACP: +/* + * Intel ACPI Component Architecture + * AML/ASL+ Disassembler version 20200925 (64-bit version) + * Copyright (c) 2000 - 2020 Intel Corporation + * + * Disassembly of /tmp/aml-1NP791, Wed Aug 23 21:51:31 2023 + * + * ACPI Data Table [FACP] + * + * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue + */ + +[000h 4]Signature : "FACP"[Fixed ACPI Description Table (FADT)] +[004h 0004 4] Table Length : 00F4 +[008h 0008 1] Revision : 03 +[009h 0009 1] Checksum : B3 +[00Ah 0010 6] Oem ID : "BOCHS " +[010h 0016 8] Oem Table ID : "BXPC" +[018h 0024 4] Oem Revision : 0001 +[01Ch 0028 4] Asl Compiler ID : "BXPC" +[020h 0032 4]Asl Compiler Revision : 0001 + +[024h 0036 4] FACS Address : +[028h 0040 4] DSDT Address : +[02Ch 0044 1]Model : 01 +[02Dh 0045 1] PM Profile : 00 [Unspecified] +[02Eh 0046 2]SCI Interrupt : 0009 +[030h 0048 4] SMI Command Port : 00B2 +[034h 0052 1]ACPI Enable Value : 02 +[035h 0053 1] ACPI Disable Value : 03 +[036h 0054 1] S4BIOS Command : 00 +[037h 0055 1] P-State Control : 00 +[038h 0056 4] PM1A Event Block Address : 0600 +[03Ch 0060 4] PM1B Event Block Address : +[040h 0064 4] PM1A Control Block Address : 0604 +[044h 0068 4] PM1B Control Block Address : +[048h 0072 4]PM2 Control Block Address : +[04Ch 0076 4] PM Timer Block Address : 0608 +[050h 0080 4] GPE0 Block Address : 0620 +[054h 0084 4] GPE1 Block Address : +[058h 0088 1] PM1 Event Block Length : 04 +[059h 0089 1] PM1 Control Block Length : 02 +[05Ah 0090 1] PM2 Control Block Length : 00 +[05Bh 0091 1]PM Timer Block Length : 04 +[05Ch 0092 1]GPE0 Block Length : 10 +[05Dh 0093 1]GPE1 Block Length : 00 +[05Eh 0094 1] GPE1 Base Offset : 00 +[05Fh 0095 1] _CST Support : 00 +[060h 0096 2] C2 Latency : 0FFF +[062h 0098 2] C3 Latency : 0FFF +[064h 0100 2] CPU Cache Size : +[066h 0102 2] Cache Flush Stride : +[068h 0104 1]Duty Cycle Offset : 00 +[069h 0105 1] Duty Cycle Width : 00 +[06Ah 0106 1] RTC Day Alarm Index : 00 +[06Bh 0107 1]RTC Month Alarm Index : 00 +[06Ch 0108 1]RTC Century Index : 32 +[06Dh 0109 2] Boot Flags (decoded below) : 0002 + Legacy Devices Supported (V2) : 0 +8042 Present on ports 60/64 (V2) : 1 +VGA Not Present (V4) : 0 + MSI Not Supported (V4) : 0 +PCIe ASPM Not Supported (V4) : 0 + CMOS RTC Not Present (V5) : 0 +[06Fh 0111 1] Reserved : 00 +[070h 0112 4]Flags (decoded below) : 000484A5 + WBINVD instruction is operational (V1) : 1 + WBINVD flushes all caches (V1) : 0 +All CPUs support C1 (V1) : 1 + C2 works on MP system (V1) : 0 +Control Method Power Button (V1) : 0 +Control Method Sleep Button (V1) : 1 +RTC wake not in fixed reg space (V1) : 0 +RTC can wake system from S4 (V1) : 1 +32-bit PM Timer (V1) : 0 + Docking Supported (V1) : 0 + Reset Register Supported (V2) : 1 +Sealed Case (V3) : 0 +Headless - No Video (V3) : 0 +Use native instr after SLP_TYPx (V3) : 0 + PCIEXP_WAK Bits Supported (V4) : 0 + Use Platform Timer (V4) : 1 + RTC_STS valid on S4 wake (V4) : 0 +Remote Power-on capable (V4) : 0 + Use APIC Cluster Model (V4) : 1 + Use APIC Physical Destination Mode (V4) : 0 + Hardware Reduced (V5) : 0 + Low Power S0 Idle (V5) : 0 + +[074h 0116 12] Reset Register : [Generic Address Structure] +[074h 0116 1] Space ID : 01 [SystemIO] +[075h 0117 1]Bit Width : 08 +[076h 0118 1] Bit Offset : 00 +[077h 0119 1] Encoded Access Width : 00 [Undefined/Legacy] +[078h 0120 8] Address : 0CF9 + +[080h 0128 1] Value to cause reset : 0F +[081h 0129 2]ARM Flags (decoded below) : + PSCI Compliant : 0 +
[PATCH 07/16] tests: bios-tables-test: Add ACPI table binaries for type4 core count test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 5 and 6. Changes in the tables: FACP: +/* + * Intel ACPI Component Architecture + * AML/ASL+ Disassembler version 20200925 (64-bit version) + * Copyright (c) 2000 - 2020 Intel Corporation + * + * Disassembly of /tmp/aml-Y6WW91, Wed Aug 23 15:43:43 2023 + * + * ACPI Data Table [FACP] + * + * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue + */ + +[000h 4]Signature : "FACP"[Fixed ACPI Description Table (FADT)] +[004h 0004 4] Table Length : 00F4 +[008h 0008 1] Revision : 03 +[009h 0009 1] Checksum : B3 +[00Ah 0010 6] Oem ID : "BOCHS " +[010h 0016 8] Oem Table ID : "BXPC" +[018h 0024 4] Oem Revision : 0001 +[01Ch 0028 4] Asl Compiler ID : "BXPC" +[020h 0032 4]Asl Compiler Revision : 0001 + +[024h 0036 4] FACS Address : +[028h 0040 4] DSDT Address : +[02Ch 0044 1]Model : 01 +[02Dh 0045 1] PM Profile : 00 [Unspecified] +[02Eh 0046 2]SCI Interrupt : 0009 +[030h 0048 4] SMI Command Port : 00B2 +[034h 0052 1]ACPI Enable Value : 02 +[035h 0053 1] ACPI Disable Value : 03 +[036h 0054 1] S4BIOS Command : 00 +[037h 0055 1] P-State Control : 00 +[038h 0056 4] PM1A Event Block Address : 0600 +[03Ch 0060 4] PM1B Event Block Address : +[040h 0064 4] PM1A Control Block Address : 0604 +[044h 0068 4] PM1B Control Block Address : +[048h 0072 4]PM2 Control Block Address : +[04Ch 0076 4] PM Timer Block Address : 0608 +[050h 0080 4] GPE0 Block Address : 0620 +[054h 0084 4] GPE1 Block Address : +[058h 0088 1] PM1 Event Block Length : 04 +[059h 0089 1] PM1 Control Block Length : 02 +[05Ah 0090 1] PM2 Control Block Length : 00 +[05Bh 0091 1]PM Timer Block Length : 04 +[05Ch 0092 1]GPE0 Block Length : 10 +[05Dh 0093 1]GPE1 Block Length : 00 +[05Eh 0094 1] GPE1 Base Offset : 00 +[05Fh 0095 1] _CST Support : 00 +[060h 0096 2] C2 Latency : 0FFF +[062h 0098 2] C3 Latency : 0FFF +[064h 0100 2] CPU Cache Size : +[066h 0102 2] Cache Flush Stride : +[068h 0104 1]Duty Cycle Offset : 00 +[069h 0105 1] Duty Cycle Width : 00 +[06Ah 0106 1] RTC Day Alarm Index : 00 +[06Bh 0107 1]RTC Month Alarm Index : 00 +[06Ch 0108 1]RTC Century Index : 32 +[06Dh 0109 2] Boot Flags (decoded below) : 0002 + Legacy Devices Supported (V2) : 0 +8042 Present on ports 60/64 (V2) : 1 +VGA Not Present (V4) : 0 + MSI Not Supported (V4) : 0 +PCIe ASPM Not Supported (V4) : 0 + CMOS RTC Not Present (V5) : 0 +[06Fh 0111 1] Reserved : 00 +[070h 0112 4]Flags (decoded below) : 000484A5 + WBINVD instruction is operational (V1) : 1 + WBINVD flushes all caches (V1) : 0 +All CPUs support C1 (V1) : 1 + C2 works on MP system (V1) : 0 +Control Method Power Button (V1) : 0 +Control Method Sleep Button (V1) : 1 +RTC wake not in fixed reg space (V1) : 0 +RTC can wake system from S4 (V1) : 1 +32-bit PM Timer (V1) : 0 + Docking Supported (V1) : 0 + Reset Register Supported (V2) : 1 +Sealed Case (V3) : 0 +Headless - No Video (V3) : 0 +Use native instr after SLP_TYPx (V3) : 0 + PCIEXP_WAK Bits Supported (V4) : 0 + Use Platform Timer (V4) : 1 + RTC_STS valid on S4 wake (V4) : 0 +Remote Power-on capable (V4) : 0 + Use APIC Cluster Model (V4) : 1 + Use APIC Physical Destination Mode (V4) : 0 + Hardware Reduced (V5) : 0 + Low Power S0 Idle (V5) : 0 + +[074h 0116 12] Reset Register : [Generic Address Structure] +[074h 0116 1] Space ID : 01 [SystemIO] +[075h 0117 1]Bit Width : 08 +[076h 0118 1] Bit Offset : 00 +[077h 0119 1] Encoded Access Width : 00 [Undefined/Legacy] +[078h 0120 8] Address : 0CF9 + +[080h 0128 1] Value to cause reset : 0F +[081h 0129 2]ARM Flags (decoded below) : + PSCI Compliant : 0 +
[PATCH 10/16] tests: bios-tables-test: Update ACPI table binaries for core count2 test
From: Zhao Liu Change the core count2 from 275 to 260. Following the guidelines in tests/qtest/bios-tables-test.c, this is step 5 and 6. Changes in the tables: APIC: /* * Intel ACPI Component Architecture * AML/ASL+ Disassembler version 20200925 (64-bit version) * Copyright (c) 2000 - 2020 Intel Corporation * - * Disassembly of tests/data/acpi/q35/APIC.core-count2, Wed Aug 23 16:29:51 2023 + * Disassembly of /tmp/aml-KQDX91, Wed Aug 23 16:29:51 2023 * * ACPI Data Table [APIC] * * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue */ [000h 4]Signature : "APIC"[Multiple APIC Description Table (MADT)] -[004h 0004 4] Table Length : 09AE +[004h 0004 4] Table Length : 0CA6 [008h 0008 1] Revision : 03 -[009h 0009 1] Checksum : CE +[009h 0009 1] Checksum : FA [00Ah 0010 6] Oem ID : "BOCHS " [010h 0016 8] Oem Table ID : "BXPC" [018h 0024 4] Oem Revision : 0001 [01Ch 0028 4] Asl Compiler ID : "BXPC" [020h 0032 4]Asl Compiler Revision : 0001 [024h 0036 4] Local Apic Address : FEE0 [028h 0040 4]Flags (decoded below) : 0001 PC-AT Compatibility : 1 [02Ch 0044 1]Subtable Type : 00 [Processor Local APIC] [02Dh 0045 1] Length : 08 [02Eh 0046 1] Processor ID : 00 [02Fh 0047 1]Local Apic ID : 00 [030h 0048 4]Flags (decoded below) : 0001 Processor Enabled : 1 @@ -1051,1256 +1051,1136 @@ [42Ch 1068 1]Subtable Type : 00 [Processor Local APIC] [42Dh 1069 1] Length : 08 [42Eh 1070 1] Processor ID : 80 [42Fh 1071 1]Local Apic ID : 80 [430h 1072 4]Flags (decoded below) : 0001 Processor Enabled : 1 Runtime Online Capable : 0 [434h 1076 1]Subtable Type : 00 [Processor Local APIC] [435h 1077 1] Length : 08 [436h 1078 1] Processor ID : 81 [437h 1079 1]Local Apic ID : 81 [438h 1080 4]Flags (decoded below) : 0001 Processor Enabled : 1 Runtime Online Capable : 0 -[43Ch 1084 1]Subtable Type : 00 [Processor Local APIC] -[43Dh 1085 1] Length : 08 -[43Eh 1086 1] Processor ID : 82 -[43Fh 1087 1]Local Apic ID : 82 -[440h 1088 4]Flags (decoded below) : 0001 - Processor Enabled : 1 - Runtime Online Capable : 0 - -[444h 1092 1]Subtable Type : 00 [Processor Local APIC] -[445h 1093 1] Length : 08 -[446h 1094 1] Processor ID : 83 -[447h 1095 1]Local Apic ID : 83 -[448h 1096 4]Flags (decoded below) : 0001 - Processor Enabled : 1 - Runtime Online Capable : 0 [snip] - -[964h 2404 1]Subtable Type : 01 [I/O APIC] -[965h 2405 1] Length : 0C -[966h 2406 1] I/O Apic ID : 00 -[967h 2407 1] Reserved : 00 -[968h 2408 4] Address : FEC0 -[96Ch 2412 4]Interrupt : - -[970h 2416 1]Subtable Type : 02 [Interrupt Source Override] -[971h 2417 1] Length : 0A -[972h 2418 1] Bus : 00 -[973h 2419 1] Source : 00 -[974h 2420 4]Interrupt : 0002 -[978h 2424 2]Flags (decoded below) : +[43Ch 1084 1]Subtable Type : 09 [Processor Local x2APIC] +[43Dh 1085 1] Length : 10 +[43Eh 1086 2] Reserved : +[440h 1088 4] Processor x2Apic ID : 0100 +[444h 1092 4]Flags (decoded below) : 0001 + Processor Enabled : 1 +[448h 1096 4]Processor UID : 0082 + +[44Ch 1100 1]Subtable Type : 09 [Processor Local x2APIC] +[44Dh 1101 1] Length : 10 +[44Eh 1102 2] Reserved : +[450h 1104 4] Processor x2Apic ID : 0101 +[454h 1108 4]Flags (decoded below) : 0001 + Processor Enabled : 1 +[458h 1112 4]Processor UID : 0083 + [snip] + +[C68h 3176 1]Subtable Type : 02 [Interrupt Source Override] +[C69h 3177 1] Length : 0A +[C6Ah 3178 1] Bus : 00 +[C6Bh 3179
[PATCH 11/16] tests: bios-tables-test: Prepare the ACPI table change for type4 thread count test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 1 - 3. List the ACPI tables that will be added to test the thread count field of smbios type4 table. Signed-off-by: Zhao Liu --- tests/data/acpi/q35/APIC.thread-count | 0 tests/data/acpi/q35/DSDT.thread-count | 0 tests/data/acpi/q35/FACP.thread-count | 0 tests/qtest/bios-tables-test-allowed-diff.h | 3 +++ 4 files changed, 3 insertions(+) create mode 100644 tests/data/acpi/q35/APIC.thread-count create mode 100644 tests/data/acpi/q35/DSDT.thread-count create mode 100644 tests/data/acpi/q35/FACP.thread-count diff --git a/tests/data/acpi/q35/APIC.thread-count b/tests/data/acpi/q35/APIC.thread-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/data/acpi/q35/DSDT.thread-count b/tests/data/acpi/q35/DSDT.thread-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/data/acpi/q35/FACP.thread-count b/tests/data/acpi/q35/FACP.thread-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8bf4..4d139d7f6b7e 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,4 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/APIC.thread-count", +"tests/data/acpi/q35/DSDT.thread-count", +"tests/data/acpi/q35/FACP.thread-count", -- 2.34.1
[PATCH 05/16] tests: bios-tables-test: Prepare the ACPI table change for type4 core count test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 1 - 3. List the ACPI tables that will be added to test the type 4 core count field. Signed-off-by: Zhao Liu --- tests/data/acpi/q35/APIC.core-count | 0 tests/data/acpi/q35/DSDT.core-count | 0 tests/data/acpi/q35/FACP.core-count | 0 tests/qtest/bios-tables-test-allowed-diff.h | 3 +++ 4 files changed, 3 insertions(+) create mode 100644 tests/data/acpi/q35/APIC.core-count create mode 100644 tests/data/acpi/q35/DSDT.core-count create mode 100644 tests/data/acpi/q35/FACP.core-count diff --git a/tests/data/acpi/q35/APIC.core-count b/tests/data/acpi/q35/APIC.core-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/data/acpi/q35/DSDT.core-count b/tests/data/acpi/q35/DSDT.core-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/data/acpi/q35/FACP.core-count b/tests/data/acpi/q35/FACP.core-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8bf4..b9bc1961309a 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,4 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/APIC.core-count", +"tests/data/acpi/q35/DSDT.core-count", +"tests/data/acpi/q35/FACP.core-count", -- 2.34.1
[PATCH 16/16] tests: bios-tables-test: Add ACPI table binaries for type4 thread count2 test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 5 and 6. Changes in the tables: FACP: +/* + * Intel ACPI Component Architecture + * AML/ASL+ Disassembler version 20200925 (64-bit version) + * Copyright (c) 2000 - 2020 Intel Corporation + * + * Disassembly of /tmp/aml-WOA191, Wed Aug 23 22:29:53 2023 + * + * ACPI Data Table [FACP] + * + * Format: [HexOffset DecimalOffset ByteLength] FieldName : FieldValue + */ + +[000h 4]Signature : "FACP"[Fixed ACPI Description Table (FADT)] +[004h 0004 4] Table Length : 00F4 +[008h 0008 1] Revision : 03 +[009h 0009 1] Checksum : B3 +[00Ah 0010 6] Oem ID : "BOCHS " +[010h 0016 8] Oem Table ID : "BXPC" +[018h 0024 4] Oem Revision : 0001 +[01Ch 0028 4] Asl Compiler ID : "BXPC" +[020h 0032 4]Asl Compiler Revision : 0001 + +[024h 0036 4] FACS Address : +[028h 0040 4] DSDT Address : +[02Ch 0044 1]Model : 01 +[02Dh 0045 1] PM Profile : 00 [Unspecified] +[02Eh 0046 2]SCI Interrupt : 0009 +[030h 0048 4] SMI Command Port : 00B2 +[034h 0052 1]ACPI Enable Value : 02 +[035h 0053 1] ACPI Disable Value : 03 +[036h 0054 1] S4BIOS Command : 00 +[037h 0055 1] P-State Control : 00 +[038h 0056 4] PM1A Event Block Address : 0600 +[03Ch 0060 4] PM1B Event Block Address : +[040h 0064 4] PM1A Control Block Address : 0604 +[044h 0068 4] PM1B Control Block Address : +[048h 0072 4]PM2 Control Block Address : +[04Ch 0076 4] PM Timer Block Address : 0608 +[050h 0080 4] GPE0 Block Address : 0620 +[054h 0084 4] GPE1 Block Address : +[058h 0088 1] PM1 Event Block Length : 04 +[059h 0089 1] PM1 Control Block Length : 02 +[05Ah 0090 1] PM2 Control Block Length : 00 +[05Bh 0091 1]PM Timer Block Length : 04 +[05Ch 0092 1]GPE0 Block Length : 10 +[05Dh 0093 1]GPE1 Block Length : 00 +[05Eh 0094 1] GPE1 Base Offset : 00 +[05Fh 0095 1] _CST Support : 00 +[060h 0096 2] C2 Latency : 0FFF +[062h 0098 2] C3 Latency : 0FFF +[064h 0100 2] CPU Cache Size : +[066h 0102 2] Cache Flush Stride : +[068h 0104 1]Duty Cycle Offset : 00 +[069h 0105 1] Duty Cycle Width : 00 +[06Ah 0106 1] RTC Day Alarm Index : 00 +[06Bh 0107 1]RTC Month Alarm Index : 00 +[06Ch 0108 1]RTC Century Index : 32 +[06Dh 0109 2] Boot Flags (decoded below) : 0002 + Legacy Devices Supported (V2) : 0 +8042 Present on ports 60/64 (V2) : 1 +VGA Not Present (V4) : 0 + MSI Not Supported (V4) : 0 +PCIe ASPM Not Supported (V4) : 0 + CMOS RTC Not Present (V5) : 0 +[06Fh 0111 1] Reserved : 00 +[070h 0112 4]Flags (decoded below) : 000484A5 + WBINVD instruction is operational (V1) : 1 + WBINVD flushes all caches (V1) : 0 +All CPUs support C1 (V1) : 1 + C2 works on MP system (V1) : 0 +Control Method Power Button (V1) : 0 +Control Method Sleep Button (V1) : 1 +RTC wake not in fixed reg space (V1) : 0 +RTC can wake system from S4 (V1) : 1 +32-bit PM Timer (V1) : 0 + Docking Supported (V1) : 0 + Reset Register Supported (V2) : 1 +Sealed Case (V3) : 0 +Headless - No Video (V3) : 0 +Use native instr after SLP_TYPx (V3) : 0 + PCIEXP_WAK Bits Supported (V4) : 0 + Use Platform Timer (V4) : 1 + RTC_STS valid on S4 wake (V4) : 0 +Remote Power-on capable (V4) : 0 + Use APIC Cluster Model (V4) : 1 + Use APIC Physical Destination Mode (V4) : 0 + Hardware Reduced (V5) : 0 + Low Power S0 Idle (V5) : 0 + +[074h 0116 12] Reset Register : [Generic Address Structure] +[074h 0116 1] Space ID : 01 [SystemIO] +[075h 0117 1]Bit Width : 08 +[076h 0118 1] Bit Offset : 00 +[077h 0119 1] Encoded Access Width : 00 [Undefined/Legacy] +[078h 0120 8] Address : 0CF9 + +[080h 0128 1] Value to cause reset : 0F +[081h 0129 2]ARM Flags (decoded below) : + PSCI Compliant : 0 +
[PATCH 06/16] tests: bios-tables-test: Add test for smbios type4 core count
From: Zhao Liu This tests the commit 196ea60a734c3 ("hw/smbios: Fix core count in type4"). Test the core count field of type4 table for multiple sockets/dies case. Suggested-by: Igor Mammedov Signed-off-by: Zhao Liu --- tests/qtest/bios-tables-test.c | 19 +++ 1 file changed, 19 insertions(+) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 8679255449cf..a35c753a3a00 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -999,6 +999,23 @@ static void test_acpi_q35_tcg_type4_count(void) free_test_data(); } +static void test_acpi_q35_tcg_core_count(void) +{ +test_data data = { +.machine = MACHINE_Q35, +.variant = ".core-count", +.required_struct_types = base_required_struct_types, +.required_struct_types_len = ARRAY_SIZE(base_required_struct_types), +.smbios_core_count = 9, +.smbios_core_count2 = 9, +}; + +test_acpi_one("-machine smbios-entry-point-type=64 " + "-smp 54,sockets=2,dies=3,cores=3,threads=3", + ); +free_test_data(); +} + static void test_acpi_q35_tcg_core_count2(void) { test_data data = { @@ -2166,6 +2183,8 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar); qtest_add_func("acpi/q35/type4-count", test_acpi_q35_tcg_type4_count); +qtest_add_func("acpi/q35/core-count", + test_acpi_q35_tcg_core_count); qtest_add_func("acpi/q35/core-count2", test_acpi_q35_tcg_core_count2); } -- 2.34.1
[PATCH 09/16] tests: bios-tables-test: Extend core count2 test to cover general topology
From: Zhao Liu Currently, this case just covers the topology with only core and smt levels, and doesn't consider more topology layers between socket and core. To cover the fixed case in the commit 196ea60a734c3 ("hw/smbios: Fix core count in type4"), add the "die" level in "-smp" as the more general topology case. Suggested-by: Igor Mammedov Signed-off-by: Zhao Liu --- tests/qtest/bios-tables-test.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index a35c753a3a00..8cba1d8126f2 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1024,10 +1024,12 @@ static void test_acpi_q35_tcg_core_count2(void) .required_struct_types = base_required_struct_types, .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), .smbios_core_count = 0xFF, -.smbios_core_count2 = 275, +.smbios_core_count2 = 260, }; -test_acpi_one("-machine smbios-entry-point-type=64 -smp 275", ); +test_acpi_one("-machine smbios-entry-point-type=64 " + "-smp 260,dies=2,cores=130,threads=1", + ); free_test_data(); } -- 2.34.1
[PATCH 00/16] tests: Add CPU topology related smbios test cases
From: Zhao Liu Hi all, This patchset is the follow up tests of previous topology fixes in smbios [1]. In this patchset, add these test cases: 1. Add the case to test 2 newly added topology helpers (patch 1): * machine_topo_get_cores_per_socket() * machine_topo_get_threads_per_socket() 2. Add the cases in bios-tables-test.c to: * test smbios type4 table count (patch 2-4). * test smbios type4 core count field (patch 5-7). * update the test of smbios type4 core count2 field (patch 8-10). * test smbios type4 thread count (patch 11-13). * test smbios type4 thread count2 (patch 14-16). With the above new cases, cover all commits of [1] in test. [1]: https://lists.gnu.org/archive/html/qemu-devel/2023-06/msg06225.html Regards, Zhao --- Zhao Liu (16): tests: test-smp-parse: Add the test for cores/threads per socket helpers tests: bios-tables-test: Prepare the ACPI table change for type4 count test tests: bios-tables-test: Add test for smbios type4 count tests: bios-tables-test: Add ACPI table binaries for type4 count test tests: bios-tables-test: Prepare the ACPI table change for type4 core count test tests: bios-tables-test: Add test for smbios type4 core count tests: bios-tables-test: Add ACPI table binaries for type4 core count test tests: bios-tables-test: Prepare the ACPI table change for type4 core count2 test tests: bios-tables-test: Extend core count2 test to cover general topology tests: bios-tables-test: Update ACPI table binaries for core count2 test tests: bios-tables-test: Prepare the ACPI table change for type4 thread count test tests: bios-tables-test: Add test for smbios type4 thread count tests: bios-tables-test: Add ACPI table binaries for type4 thread count test tests: bios-tables-test: Prepare the ACPI table change for type4 thread count2 test tests: bios-tables-test: Add test for smbios type4 thread count2 tests: bios-tables-test: Add ACPI table binaries for type4 thread count2 test tests/data/acpi/q35/APIC.core-count| Bin 0 -> 544 bytes tests/data/acpi/q35/APIC.core-count2 | Bin 2478 -> 3238 bytes tests/data/acpi/q35/APIC.thread-count | Bin 0 -> 544 bytes tests/data/acpi/q35/APIC.thread-count2 | Bin 0 -> 7398 bytes tests/data/acpi/q35/APIC.type4-count | Bin 0 -> 1072 bytes tests/data/acpi/q35/DSDT.core-count| Bin 0 -> 12913 bytes tests/data/acpi/q35/DSDT.core-count2 | Bin 32495 -> 33770 bytes tests/data/acpi/q35/DSDT.thread-count | Bin 0 -> 12913 bytes tests/data/acpi/q35/DSDT.thread-count2 | Bin 0 -> 63671 bytes tests/data/acpi/q35/DSDT.type4-count | Bin 0 -> 18589 bytes tests/data/acpi/q35/FACP.core-count| Bin 0 -> 244 bytes tests/data/acpi/q35/FACP.thread-count | Bin 0 -> 244 bytes tests/data/acpi/q35/FACP.thread-count2 | Bin 0 -> 244 bytes tests/data/acpi/q35/FACP.type4-count | Bin 0 -> 244 bytes tests/qtest/bios-tables-test.c | 118 - tests/unit/test-smp-parse.c| 67 +++--- 16 files changed, 169 insertions(+), 16 deletions(-) create mode 100644 tests/data/acpi/q35/APIC.core-count create mode 100644 tests/data/acpi/q35/APIC.thread-count create mode 100644 tests/data/acpi/q35/APIC.thread-count2 create mode 100644 tests/data/acpi/q35/APIC.type4-count create mode 100644 tests/data/acpi/q35/DSDT.core-count create mode 100644 tests/data/acpi/q35/DSDT.thread-count create mode 100644 tests/data/acpi/q35/DSDT.thread-count2 create mode 100644 tests/data/acpi/q35/DSDT.type4-count create mode 100644 tests/data/acpi/q35/FACP.core-count create mode 100644 tests/data/acpi/q35/FACP.thread-count create mode 100644 tests/data/acpi/q35/FACP.thread-count2 create mode 100644 tests/data/acpi/q35/FACP.type4-count -- 2.34.1
[PATCH 01/16] tests: test-smp-parse: Add the test for cores/threads per socket helpers
From: Zhao Liu Use the different ways to calculate cores/threads per socket, so that the new CPU topology levels won't be missed in these 2 helpes: * machine_topo_get_cores_per_socket() * machine_topo_get_threads_per_socket() Test the commit a1d027be95bc3 ("machine: Add helpers to get cores/ threads per socket"). Suggested-by: Igor Mammedov Signed-off-by: Zhao Liu --- tests/unit/test-smp-parse.c | 67 ++--- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/tests/unit/test-smp-parse.c b/tests/unit/test-smp-parse.c index fdc39a846ca6..24972666a74d 100644 --- a/tests/unit/test-smp-parse.c +++ b/tests/unit/test-smp-parse.c @@ -394,20 +394,47 @@ static char *smp_config_to_string(const SMPConfiguration *config) config->has_maxcpus ? "true" : "false", config->maxcpus); } -static char *cpu_topology_to_string(const CpuTopology *topo) +/* Use the different calculation than machine_topo_get_threads_per_socket(). */ +static unsigned int cpu_topology_get_threads_per_socket(const CpuTopology *topo) +{ +/* Check the divisor to avoid invalid topology examples causing SIGFPE. */ +if (!topo->sockets) { +return 0; +} else { +return topo->max_cpus / topo->sockets; +} +} + +/* Use the different calculation than machine_topo_get_cores_per_socket(). */ +static unsigned int cpu_topology_get_cores_per_socket(const CpuTopology *topo) +{ +/* Check the divisor to avoid invalid topology examples causing SIGFPE. */ +if (!topo->threads) { +return 0; +} else { +return cpu_topology_get_threads_per_socket(topo) / topo->threads; +} +} + +static char *cpu_topology_to_string(const CpuTopology *topo, +unsigned int threads_per_socket, +unsigned int cores_per_socket) { return g_strdup_printf( "(CpuTopology) {\n" -".cpus = %u,\n" -".sockets = %u,\n" -".dies = %u,\n" -".clusters = %u,\n" -".cores= %u,\n" -".threads = %u,\n" -".max_cpus = %u,\n" +".cpus = %u,\n" +".sockets= %u,\n" +".dies = %u,\n" +".clusters = %u,\n" +".cores = %u,\n" +".threads= %u,\n" +".max_cpus = %u,\n" +".threads_per_socket = %u,\n" +".cores_per_socket = %u,\n" "}", topo->cpus, topo->sockets, topo->dies, topo->clusters, -topo->cores, topo->threads, topo->max_cpus); +topo->cores, topo->threads, topo->max_cpus, +threads_per_socket, cores_per_socket); } static void check_parse(MachineState *ms, const SMPConfiguration *config, @@ -415,14 +442,26 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config, bool is_valid) { g_autofree char *config_str = smp_config_to_string(config); -g_autofree char *expect_topo_str = cpu_topology_to_string(expect_topo); -g_autofree char *output_topo_str = NULL; +g_autofree char *expect_topo_str = NULL, *output_topo_str = NULL; +unsigned int expect_threads_per_socket, expect_cores_per_socket; +unsigned int ms_threads_per_socket, ms_cores_per_socket; Error *err = NULL; +expect_threads_per_socket = +cpu_topology_get_threads_per_socket(expect_topo); +expect_cores_per_socket = +cpu_topology_get_cores_per_socket(expect_topo); +expect_topo_str = cpu_topology_to_string(expect_topo, + expect_threads_per_socket, + expect_cores_per_socket); + /* call the generic parser */ machine_parse_smp_config(ms, config, ); -output_topo_str = cpu_topology_to_string(>smp); +ms_threads_per_socket = machine_topo_get_threads_per_socket(ms); +ms_cores_per_socket = machine_topo_get_cores_per_socket(ms); +output_topo_str = cpu_topology_to_string(>smp, ms_threads_per_socket, + ms_cores_per_socket); /* when the configuration is supposed to be valid */ if (is_valid) { @@ -433,7 +472,9 @@ static void check_parse(MachineState *ms, const SMPConfiguration *config, (ms->smp.clusters == expect_topo->clusters) && (ms->smp.cores == expect_topo->cores) && (ms->smp.threads == expect_topo->threads) && -(ms->smp.max_cpus == expect_topo->max_cpus)) { +(ms->smp.max_cpus == expect_topo->max_cpus) && +(ms_threads_per_socket == expect_threads_per_socket) && +(ms_cores_per_socket == expect_cores_per_socket)) { return; } -- 2.34.1
[PATCH 12/16] tests: bios-tables-test: Add test for smbios type4 thread count
From: Zhao Liu This tests the commit 7298fd7de5551 ("hw/smbios: Fix thread count in type4"). Add this test to cover 2 cases: 1. Test thread count field with multiple sockets and multiple dies to confirm this field could correctly calculate threads per sockets. 2. Confirm that field calculation could correctly recognize the difference between "-smp maxcpus" and "-smp cpus". Suggested-by: Igor Mammedov Signed-off-by: Zhao Liu --- tests/qtest/bios-tables-test.c | 27 +++ 1 file changed, 27 insertions(+) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 8cba1d8126f2..26474d376633 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -95,6 +95,7 @@ typedef struct { uint16_t smbios_cpu_curr_speed; uint8_t smbios_core_count; uint16_t smbios_core_count2; +uint8_t smbios_thread_count; uint8_t *required_struct_types; int required_struct_types_len; int type4_count; @@ -640,6 +641,7 @@ static void smbios_cpu_test(test_data *data, uint32_t addr, SmbiosEntryPointType ep_type) { uint8_t core_count, expected_core_count = data->smbios_core_count; +uint8_t thread_count, expected_thread_count = data->smbios_thread_count; uint16_t speed, expected_speed[2]; uint16_t core_count2, expected_core_count2 = data->smbios_core_count2; int offset[2]; @@ -663,6 +665,13 @@ static void smbios_cpu_test(test_data *data, uint32_t addr, g_assert_cmpuint(core_count, ==, expected_core_count); } +thread_count = qtest_readb(data->qts, + addr + offsetof(struct smbios_type_4, thread_count)); + +if (expected_thread_count) { +g_assert_cmpuint(thread_count, ==, expected_thread_count); +} + if (ep_type == SMBIOS_ENTRY_POINT_TYPE_64) { core_count2 = qtest_readw(data->qts, addr + offsetof(struct smbios_type_4, core_count2)); @@ -1033,6 +1042,22 @@ static void test_acpi_q35_tcg_core_count2(void) free_test_data(); } +static void test_acpi_q35_tcg_thread_count(void) +{ +test_data data = { +.machine = MACHINE_Q35, +.variant = ".thread-count", +.required_struct_types = base_required_struct_types, +.required_struct_types_len = ARRAY_SIZE(base_required_struct_types), +.smbios_thread_count = 27, +}; + +test_acpi_one("-machine smbios-entry-point-type=64 " + "-smp cpus=15,maxcpus=54,sockets=2,dies=3,cores=3,threads=3", + ); +free_test_data(); +} + static void test_acpi_q35_tcg_bridge(void) { test_data data = {}; @@ -2189,6 +2214,8 @@ int main(int argc, char *argv[]) test_acpi_q35_tcg_core_count); qtest_add_func("acpi/q35/core-count2", test_acpi_q35_tcg_core_count2); +qtest_add_func("acpi/q35/thread-count", + test_acpi_q35_tcg_thread_count); } qtest_add_func("acpi/q35/viot", test_acpi_q35_viot); #ifdef CONFIG_POSIX -- 2.34.1
[PATCH 08/16] tests: bios-tables-test: Prepare the ACPI table change for type4 core count2 test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 1 - 3. List the ACPI tables that will be changed about the type 4 core count2 test case. Signed-off-by: Zhao Liu --- tests/qtest/bios-tables-test-allowed-diff.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8bf4..0f95d1344b2c 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,3 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/APIC.core-count2", +"tests/data/acpi/q35/DSDT.core-count2", -- 2.34.1
[PATCH 02/16] tests: bios-tables-test: Prepare the ACPI table change for type4 count test
From: Zhao Liu Following the guidelines in tests/qtest/bios-tables-test.c, this is step 1 - 3. List the ACPI tables that will be added to test the type 4 count. Signed-off-by: Zhao Liu --- tests/data/acpi/q35/APIC.type4-count| 0 tests/data/acpi/q35/DSDT.type4-count| 0 tests/data/acpi/q35/FACP.type4-count| 0 tests/qtest/bios-tables-test-allowed-diff.h | 3 +++ 4 files changed, 3 insertions(+) create mode 100644 tests/data/acpi/q35/APIC.type4-count create mode 100644 tests/data/acpi/q35/DSDT.type4-count create mode 100644 tests/data/acpi/q35/FACP.type4-count diff --git a/tests/data/acpi/q35/APIC.type4-count b/tests/data/acpi/q35/APIC.type4-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/data/acpi/q35/DSDT.type4-count b/tests/data/acpi/q35/DSDT.type4-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/data/acpi/q35/FACP.type4-count b/tests/data/acpi/q35/FACP.type4-count new file mode 100644 index ..e69de29bb2d1 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8bf4..0ce6f8fc72ee 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,4 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/q35/APIC.type4-count", +"tests/data/acpi/q35/DSDT.type4-count", +"tests/data/acpi/q35/FACP.type4-count", -- 2.34.1
Re: [PATCH] block/file-posix: fix update_zones_wp() caller
Damien Le Moal 于2023年8月25日周五 07:49写道: > > On 8/25/23 02:39, Sam Li wrote: > > When the zoned requests that may change wp fail, it needs to > > update only wps of the zones within the range of the requests > > for not disrupting the other in-flight requests. The wp is updated > > successfully after the request completes. > > > > Fixed the callers with right offset and nr_zones. > > > > Signed-off-by: Sam Li > > --- > > block/file-posix.c | 5 +++-- > > 1 file changed, 3 insertions(+), 2 deletions(-) > > > > diff --git a/block/file-posix.c b/block/file-posix.c > > index b16e9c21a1..22559d6c2d 100644 > > --- a/block/file-posix.c > > +++ b/block/file-posix.c > > @@ -2522,7 +2522,8 @@ out: > > } > > } else { > > if (type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) { > > -update_zones_wp(bs, s->fd, 0, 1); > > +update_zones_wp(bs, s->fd, offset, > > +ROUND_UP(bytes, bs->bl.zone_size)); > > Write and zone append operations are not allowed to cross zone boundaries. So > I > the number of zones should always be 1. The above changes a number of zones > to a > number of bytes, which seems wrong. The correct fix is I think: > > update_zones_wp(bs, s->fd, offset, 1); > I see. I forgot this constraint. > > } > > } > > > > @@ -3472,7 +3473,7 @@ static int coroutine_fn > > raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, > > len >> BDRV_SECTOR_BITS); > > ret = raw_thread_pool_submit(handle_aiocb_zone_mgmt, ); > > if (ret != 0) { > > -update_zones_wp(bs, s->fd, offset, i); > > +update_zones_wp(bs, s->fd, offset, nrz); > > Same here. Why would you need to update all zones wp ? This will affect zones > that do not have a write error and potentially change there correct in-memory > wp > to a wrong value. I think this also should be: > >update_zones_wp(bs, s->fd, offset, 1); > Is update_zones_wp for cancelling the writes on invalid zones or updating corrupted write pointers caused by caller (write, append or zone_mgmt)? My thought is based on the latter. Zone_mgmt can manage multiple zones with a single request. When the request fails, it's hard to tell which zone is corrupted. The relation between the req (zone_mgmt) and update_zones_wp is: if req succeeds, no updates; if req fails, consider the req never happens and do again. If the former is right, then it assumes only the first zone may contain an error. I am not sure it's right. > > error_report("ioctl %s failed %d", op_name, ret); > > return ret; > > } > > -- > Damien Le Moal > Western Digital Research >
Re: [PATCH v2 2/2] softmmu/dirtylimit: Convert free to g_free
On Fri, Aug 25, 2023 at 10:33 AM wrote: > From: alloc > > Convert free to g_free to match g_new and g_malloc functions. > > Signed-off-by: alloc > --- > softmmu/dirtylimit.c | 10 +- > 1 file changed, 5 insertions(+), 5 deletions(-) > > diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c > index e3ff53b8fc..fa959d7743 100644 > --- a/softmmu/dirtylimit.c > +++ b/softmmu/dirtylimit.c > @@ -100,7 +100,7 @@ static void vcpu_dirty_rate_stat_collect(void) > stat.rates[i].dirty_rate; > } > > -free(stat.rates); > +g_free(stat.rates); > } > > static void *vcpu_dirty_rate_stat_thread(void *opaque) > @@ -171,10 +171,10 @@ void vcpu_dirty_rate_stat_initialize(void) > > void vcpu_dirty_rate_stat_finalize(void) > { > -free(vcpu_dirty_rate_stat->stat.rates); > +g_free(vcpu_dirty_rate_stat->stat.rates); > vcpu_dirty_rate_stat->stat.rates = NULL; > > -free(vcpu_dirty_rate_stat); > +g_free(vcpu_dirty_rate_stat); > vcpu_dirty_rate_stat = NULL; > } > > @@ -220,10 +220,10 @@ void dirtylimit_state_initialize(void) > > void dirtylimit_state_finalize(void) > { > -free(dirtylimit_state->states); > +g_free(dirtylimit_state->states); > dirtylimit_state->states = NULL; > > -free(dirtylimit_state); > +g_free(dirtylimit_state); > dirtylimit_state = NULL; > > trace_dirtylimit_state_finalize(); > -- > 2.39.3 > > Reviewed-by: Hyman Huang -- Best regards
[PATCH v2 0/2] softmmu/dirtylimit: Fix memory leak issue
From: alloc Changes in v2: - Split into two patches, one fixing memory leak issue and another converting free to g_free. - Fix typos alloc (1): softmmu/dirtylimit: Convert free to g_free alloc.young (1): softmmu: Fix dirtylimit memory leak softmmu/dirtylimit.c | 26 -- 1 file changed, 12 insertions(+), 14 deletions(-) -- 2.39.3
[PATCH v2 2/2] softmmu/dirtylimit: Convert free to g_free
From: alloc Convert free to g_free to match g_new and g_malloc functions. Signed-off-by: alloc --- softmmu/dirtylimit.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c index e3ff53b8fc..fa959d7743 100644 --- a/softmmu/dirtylimit.c +++ b/softmmu/dirtylimit.c @@ -100,7 +100,7 @@ static void vcpu_dirty_rate_stat_collect(void) stat.rates[i].dirty_rate; } -free(stat.rates); +g_free(stat.rates); } static void *vcpu_dirty_rate_stat_thread(void *opaque) @@ -171,10 +171,10 @@ void vcpu_dirty_rate_stat_initialize(void) void vcpu_dirty_rate_stat_finalize(void) { -free(vcpu_dirty_rate_stat->stat.rates); +g_free(vcpu_dirty_rate_stat->stat.rates); vcpu_dirty_rate_stat->stat.rates = NULL; -free(vcpu_dirty_rate_stat); +g_free(vcpu_dirty_rate_stat); vcpu_dirty_rate_stat = NULL; } @@ -220,10 +220,10 @@ void dirtylimit_state_initialize(void) void dirtylimit_state_finalize(void) { -free(dirtylimit_state->states); +g_free(dirtylimit_state->states); dirtylimit_state->states = NULL; -free(dirtylimit_state); +g_free(dirtylimit_state); dirtylimit_state = NULL; trace_dirtylimit_state_finalize(); -- 2.39.3
[PATCH v2 1/2] softmmu: Fix dirtylimit memory leak
From: "alloc.young" Fix memory leak in hmp_info_vcpu_dirty_limit,use g_autoptr to handle memory deallocation. Signed-off-by: alloc.young --- softmmu/dirtylimit.c | 16 +++- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c index 3c275ee55b..e3ff53b8fc 100644 --- a/softmmu/dirtylimit.c +++ b/softmmu/dirtylimit.c @@ -653,7 +653,8 @@ struct DirtyLimitInfoList *qmp_query_vcpu_dirty_limit(Error **errp) void hmp_info_vcpu_dirty_limit(Monitor *mon, const QDict *qdict) { -DirtyLimitInfoList *limit, *head, *info = NULL; +DirtyLimitInfoList *info; +g_autoptr(DirtyLimitInfoList) head = NULL; Error *err = NULL; if (!dirtylimit_in_service()) { @@ -661,20 +662,17 @@ void hmp_info_vcpu_dirty_limit(Monitor *mon, const QDict *qdict) return; } -info = qmp_query_vcpu_dirty_limit(); +head = qmp_query_vcpu_dirty_limit(); if (err) { hmp_handle_error(mon, err); return; } -head = info; -for (limit = head; limit != NULL; limit = limit->next) { +for (info = head; info != NULL; info = info->next) { monitor_printf(mon, "vcpu[%"PRIi64"], limit rate %"PRIi64 " (MB/s)," " current rate %"PRIi64 " (MB/s)\n", -limit->value->cpu_index, -limit->value->limit_rate, -limit->value->current_rate); +info->value->cpu_index, +info->value->limit_rate, +info->value->current_rate); } - -g_free(info); } -- 2.39.3
Re: constructor vs. __constructor__
Thanks for your reply. On Thu, Aug 24, 2023 at 5:33 PM Peter Maydell wrote: > On Thu, 24 Aug 2023 at 06:55, Markus Armbruster wrote: > > > > Liu Jaloo writes: > > > > > What's the difference between "__attribute__((constructor))" and > > > "__attribute__((__constructor__))" in qemu source? > > > > Reading the fine manual helps: > > > > You may optionally specify attribute names with ‘__’ preceding and > > following the name. This allows you to use them in header files > > without being concerned about a possible macro of the same name. For > > example, you may use the attribute name __noreturn__ instead of > > noreturn. > > As usual in the QEMU sources, we are not particularly consistent > about using one version compared to the other. However we > mostly use the "__attribute__((foo))" form rather than > "__attribute__((__foo__))" so if you're writing new code then > prefer the former. > > We also have a handful of uses of "__attribute((foo))" and > "__attribute((__foo__))". Definitely don't add more of those :-) > > thanks > -- PMM >
[PATCH 3/5] target/hppa: Do not use hardcoded value for tlb_flush_*()
From: Helge Deller Avoid using hardcoded values when calling the tlb_flush*() functions. Instead define the correct mask (HPPA_MMU_FLUSH_MASK) and use it. Skip flushing the MMU for physical addresses. Signed-off-by: Helge Deller --- target/hppa/cpu.h| 5 + target/hppa/helper.c | 2 +- target/hppa/mem_helper.c | 7 +++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 50b513f0ea..6623712644 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -41,6 +41,11 @@ #define TARGET_INSN_START_EXTRA_WORDS 1 +/* No need to flush MMU_PHYS_IDX */ +#define HPPA_MMU_FLUSH_MASK \ +(1 << MMU_KERNEL_IDX | 1 << MMU_PL1_IDX | \ + 1 << MMU_PL2_IDX| 1 << MMU_USER_IDX) + /* Hardware exceptions, interrupts, faults, and traps. */ #define EXCP_HPMC1 /* high priority machine check */ #define EXCP_POWER_FAIL 2 diff --git a/target/hppa/helper.c b/target/hppa/helper.c index 74b8747083..a8d3f456ee 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -71,7 +71,7 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw) /* If PSW_P changes, it affects how we translate addresses. */ if ((psw ^ old_psw) & PSW_P) { #ifndef CONFIG_USER_ONLY -tlb_flush_by_mmuidx(env_cpu(env), 0xf); +tlb_flush_by_mmuidx(env_cpu(env), HPPA_MMU_FLUSH_MASK); #endif } } diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 5046cc8f9d..6f04c101dd 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -50,8 +50,7 @@ static void hppa_flush_tlb_ent(CPUHPPAState *env, hppa_tlb_entry *ent) trace_hppa_tlb_flush_ent(env, ent, ent->va_b, ent->va_e, ent->pa); for (i = 0; i < n; ++i, addr += TARGET_PAGE_SIZE) { -/* Do not flush MMU_PHYS_IDX. */ -tlb_flush_page_by_mmuidx(cs, addr, 0xf); +tlb_flush_page_by_mmuidx(cs, addr, HPPA_MMU_FLUSH_MASK); } memset(ent, 0, sizeof(*ent)); @@ -335,13 +334,13 @@ void HELPER(ptlbe)(CPUHPPAState *env) { trace_hppa_tlb_ptlbe(env); memset(env->tlb, 0, sizeof(env->tlb)); -tlb_flush_by_mmuidx(env_cpu(env), 0xf); +tlb_flush_by_mmuidx(env_cpu(env), HPPA_MMU_FLUSH_MASK); } void cpu_hppa_change_prot_id(CPUHPPAState *env) { if (env->psw & PSW_P) { -tlb_flush_by_mmuidx(env_cpu(env), 0xf); +tlb_flush_by_mmuidx(env_cpu(env), HPPA_MMU_FLUSH_MASK); } } -- 2.41.0
[PATCH 0/5] target/hppa: Clean up conversion from/to MMU index and priviledge level
From: Helge Deller Make the conversion between priviledge level and QEMU MMU index consitent, and afterwards switch to MMU indices 11-15. Signed-off-by: Helge Deller Helge Deller (5): target/hppa: Add missing PL1 and PL2 priviledge levels target/hppa: Add priviledge to MMU index conversion helpers target/hppa: Do not use hardcoded value for tlb_flush_*() target/hppa: Use privilege helper in hppa_get_physical_address() target/hppa: Switch to use MMU indices 11-15 target/hppa/cpu.h| 19 +++ target/hppa/helper.c | 2 +- target/hppa/mem_helper.c | 16 target/hppa/translate.c | 9 + 4 files changed, 29 insertions(+), 17 deletions(-) -- 2.41.0
[PATCH 5/5] target/hppa: Switch to use MMU indices 11-15
From: Helge Deller The MMU indices 9-15 will use shorter assembler instructions when run on a x86-64 host. So, switch over to those to get smaller code and maybe minimally faster emulation. Signed-off-by: Helge Deller --- target/hppa/cpu.h | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 6623712644..fa13694dab 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -30,14 +30,14 @@ basis. It's probably easier to fall back to a strong memory model. */ #define TCG_GUEST_DEFAULT_MOTCG_MO_ALL -#define MMU_KERNEL_IDX 0 -#define MMU_PL1_IDX 1 -#define MMU_PL2_IDX 2 -#define MMU_USER_IDX 3 -#define MMU_PHYS_IDX 4 - -#define PRIV_TO_MMU_IDX(priv)(priv) -#define MMU_IDX_TO_PRIV(mmu_idx) (mmu_idx) +#define MMU_KERNEL_IDX 11 +#define MMU_PL1_IDX 12 +#define MMU_PL2_IDX 13 +#define MMU_USER_IDX 14 +#define MMU_PHYS_IDX 15 + +#define PRIV_TO_MMU_IDX(priv)(MMU_KERNEL_IDX + (priv)) +#define MMU_IDX_TO_PRIV(mmu_idx) ((mmu_idx) - MMU_KERNEL_IDX) #define TARGET_INSN_START_EXTRA_WORDS 1 -- 2.41.0
[PATCH 1/5] target/hppa: Add missing PL1 and PL2 priviledge levels
From: Helge Deller The hppa CPU has 4 priviledge levels (0-3). Mention the missing PL1 and PL2 levels, although the Linux kernel uses only 0 (KERNEL) and 3 (USER). Not sure about HP-UX. Signed-off-by: Helge Deller --- target/hppa/cpu.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 75c5c0ccf7..6c5b0e67c8 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -31,8 +31,11 @@ #define TCG_GUEST_DEFAULT_MOTCG_MO_ALL #define MMU_KERNEL_IDX 0 +#define MMU_PL1_IDX 1 +#define MMU_PL2_IDX 2 #define MMU_USER_IDX 3 #define MMU_PHYS_IDX 4 + #define TARGET_INSN_START_EXTRA_WORDS 1 /* Hardware exceptions, interrupts, faults, and traps. */ -- 2.41.0
[PATCH 4/5] target/hppa: Use privilege helper in hppa_get_physical_address()
From: Helge Deller Convert hppa_get_physical_address() to use the privilege helper macro. Signed-off-by: Helge Deller --- target/hppa/mem_helper.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c index 6f04c101dd..66cf84a0d9 100644 --- a/target/hppa/mem_helper.c +++ b/target/hppa/mem_helper.c @@ -73,7 +73,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int type, hwaddr *pphys, int *pprot) { hwaddr phys; -int prot, r_prot, w_prot, x_prot; +int prot, r_prot, w_prot, x_prot, mmu_priv; hppa_tlb_entry *ent; int ret = -1; @@ -97,9 +97,10 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, phys = ent->pa + (addr & ~TARGET_PAGE_MASK); /* Map TLB access_rights field to QEMU protection. */ -r_prot = (mmu_idx <= ent->ar_pl1) * PAGE_READ; -w_prot = (mmu_idx <= ent->ar_pl2) * PAGE_WRITE; -x_prot = (ent->ar_pl2 <= mmu_idx && mmu_idx <= ent->ar_pl1) * PAGE_EXEC; +mmu_priv = MMU_IDX_TO_PRIV(mmu_idx); +r_prot = (mmu_priv <= ent->ar_pl1) * PAGE_READ; +w_prot = (mmu_priv <= ent->ar_pl2) * PAGE_WRITE; +x_prot = (ent->ar_pl2 <= mmu_priv && mmu_priv <= ent->ar_pl1) * PAGE_EXEC; switch (ent->ar_type) { case 0: /* read-only: data page */ prot = r_prot; -- 2.41.0
[PATCH 2/5] target/hppa: Add priviledge to MMU index conversion helpers
From: Helge Deller Add two macros which convert priviledge level to/from MMU index: - PRIV_TO_MMU_IDX(priv) returns the MMU index for the given priviledge level - MMU_IDX_TO_PRIV(mmu_idx) returns the corresponding priviledge level for this MMU index The introduction of those macros make the code easier to read and will help to improve performance in follow-up patch. Signed-off-by: Helge Deller --- target/hppa/cpu.h | 5 - target/hppa/translate.c | 9 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/target/hppa/cpu.h b/target/hppa/cpu.h index 6c5b0e67c8..50b513f0ea 100644 --- a/target/hppa/cpu.h +++ b/target/hppa/cpu.h @@ -36,6 +36,9 @@ #define MMU_USER_IDX 3 #define MMU_PHYS_IDX 4 +#define PRIV_TO_MMU_IDX(priv)(priv) +#define MMU_IDX_TO_PRIV(mmu_idx) (mmu_idx) + #define TARGET_INSN_START_EXTRA_WORDS 1 /* Hardware exceptions, interrupts, faults, and traps. */ @@ -236,7 +239,7 @@ static inline int cpu_mmu_index(CPUHPPAState *env, bool ifetch) return MMU_USER_IDX; #else if (env->psw & (ifetch ? PSW_C : PSW_D)) { -return env->iaoq_f & 3; +return PRIV_TO_MMU_IDX(env->iaoq_f & 3); } return MMU_PHYS_IDX; /* mmu disabled */ #endif diff --git a/target/hppa/translate.c b/target/hppa/translate.c index d66fcb3e6a..e3af668252 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -4057,14 +4057,15 @@ static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->tb_flags = ctx->base.tb->flags; #ifdef CONFIG_USER_ONLY -ctx->privilege = MMU_USER_IDX; +ctx->privilege = MMU_IDX_TO_PRIV(MMU_USER_IDX); ctx->mmu_idx = MMU_USER_IDX; -ctx->iaoq_f = ctx->base.pc_first | MMU_USER_IDX; -ctx->iaoq_b = ctx->base.tb->cs_base | MMU_USER_IDX; +ctx->iaoq_f = ctx->base.pc_first | ctx->privilege; +ctx->iaoq_b = ctx->base.tb->cs_base | ctx->privilege; ctx->unalign = (ctx->tb_flags & TB_FLAG_UNALIGN ? MO_UNALN : MO_ALIGN); #else ctx->privilege = (ctx->tb_flags >> TB_FLAG_PRIV_SHIFT) & 3; -ctx->mmu_idx = (ctx->tb_flags & PSW_D ? ctx->privilege : MMU_PHYS_IDX); +ctx->mmu_idx = (ctx->tb_flags & PSW_D ? +PRIV_TO_MMU_IDX(ctx->privilege) : MMU_PHYS_IDX); /* Recover the IAOQ values from the GVA + PRIV. */ uint64_t cs_base = ctx->base.tb->cs_base; -- 2.41.0
Re: [PATCH v11 0/9] rutabaga_gfx + gfxstream
On Wed, Aug 23, 2023 at 4:07 AM Alyssa Ross wrote: > Gurchetan Singh writes: > > > - Official "release commits" issued for rutabaga_gfx_ffi, > > gfxstream, aemu-base. For example, see crrev.com/c/4778941 > > > > - The release commits can make packaging easier, though once > > again all known users will likely just build from sources > > anyways > > It's a small thing, but could there be actual tags, rather than just > blessed commits? It'd just make them easier to find, and save a bit of > time in review for packages. > I added: https://crosvm.dev/book/appendix/rutabaga_gfx.html#latest-releases-for-potential-packaging Tags are possible, but I want to clarify the use case before packaging. Where are you thinking of packaging it for (Debian??)? Are you mostly interested in Wayland passthrough (my guess) or gfxstream too? Depending your use case, we may be able to minimize the work involved.
Re: [PATCH v7 6/9] gfxstream + rutabaga: add initial support for gfxstream
On Wed, Aug 23, 2023 at 8:03 AM Mark Cave-Ayland < mark.cave-ayl...@ilande.co.uk> wrote: > On 17/08/2023 03:23, Gurchetan Singh wrote: > > > From: Gurchetan Singh > > > > This adds initial support for gfxstream and cross-domain. Both > > features rely on virtio-gpu blob resources and context types, which > > are also implemented in this patch. > > > > gfxstream has a long and illustrious history in Android graphics > > paravirtualization. It has been powering graphics in the Android > > Studio Emulator for more than a decade, which is the main developer > > platform. > > > > Originally conceived by Jesse Hall, it was first known as "EmuGL" [a]. > > The key design characteristic was a 1:1 threading model and > > auto-generation, which fit nicely with the OpenGLES spec. It also > > allowed easy layering with ANGLE on the host, which provides the GLES > > implementations on Windows or MacOS enviroments. > > > > gfxstream has traditionally been maintained by a single engineer, and > > between 2015 to 2021, the goldfish throne passed to Frank Yang. > > Historians often remark this glorious reign ("pax gfxstreama" is the > > academic term) was comparable to that of Augustus and both Queen > > Elizabeths. Just to name a few accomplishments in a resplendent > > panoply: higher versions of GLES, address space graphics, snapshot > > support and CTS compliant Vulkan [b]. > > > > One major drawback was the use of out-of-tree goldfish drivers. > > Android engineers didn't know much about DRM/KMS and especially TTM so > > a simple guest to host pipe was conceived. > > > > Luckily, virtio-gpu 3D started to emerge in 2016 due to the work of > > the Mesa/virglrenderer communities. In 2018, the initial virtio-gpu > > port of gfxstream was done by Cuttlefish enthusiast Alistair Delva. > > It was a symbol compatible replacement of virglrenderer [c] and named > > "AVDVirglrenderer". This implementation forms the basis of the > > current gfxstream host implementation still in use today. > > > > cross-domain support follows a similar arc. Originally conceived by > > Wayland aficionado David Reveman and crosvm enjoyer Zach Reizner in > > 2018, it initially relied on the downstream "virtio-wl" device. > > > > In 2020 and 2021, virtio-gpu was extended to include blob resources > > and multiple timelines by yours truly, features gfxstream/cross-domain > > both require to function correctly. > > > > Right now, we stand at the precipice of a truly fantastic possibility: > > the Android Emulator powered by upstream QEMU and upstream Linux > > kernel. gfxstream will then be packaged properfully, and app > > developers can even fix gfxstream bugs on their own if they encounter > > them. > > > > It's been quite the ride, my friends. Where will gfxstream head next, > > nobody really knows. I wouldn't be surprised if it's around for > > another decade, maintained by a new generation of Android graphics > > enthusiasts. > > > > Technical details: > >- Very simple initial display integration: just used Pixman > >- Largely, 1:1 mapping of virtio-gpu hypercalls to rutabaga function > > calls > > > > Next steps for Android VMs: > >- The next step would be improving display integration and UI > interfaces > > with the goal of the QEMU upstream graphics being in an emulator > > release [d]. > > > > Next steps for Linux VMs for display virtualization: > >- For widespread distribution, someone needs to package Sommelier or > the > > wayland-proxy-virtwl [e] ideally into Debian main. In addition, > newer > > versions of the Linux kernel come with DRM_VIRTIO_GPU_KMS option, > > which allows disabling KMS hypercalls. If anyone cares enough, > it'll > > probably be possible to build a custom VM variant that uses this > display > > virtualization strategy. > > > > [a] > https://android-review.googlesource.com/c/platform/development/+/34470 > > [b] > https://android-review.googlesource.com/q/topic:%22vulkan-hostconnection-start%22 > > [c] > https://android-review.googlesource.com/c/device/generic/goldfish-opengl/+/761927 > > [d] https://developer.android.com/studio/releases/emulator > > [e] https://github.com/talex5/wayland-proxy-virtwl > > > > Signed-off-by: Gurchetan Singh > > Tested-by: Alyssa Ross > > Tested-by: Emmanouil Pitsidianakis > > Reviewed-by: Emmanouil Pitsidianakis > > --- > > v1: Incorported various suggestions by Akihiko Odaki and Bernard Berschow > > - Removed GET_VIRTIO_GPU_GL / GET_RUTABAGA macros > > - Used error_report(..) > > - Used g_autofree to fix leaks on error paths > > - Removed unnecessary casts > > - added virtio-gpu-pci-rutabaga.c + virtio-vga-rutabaga.c files > > > > v2: Incorported various suggestions by Akihiko Odaki, Marc-André Lureau > and > > Bernard Berschow: > > - Parenthesis in CHECK macro > > - CHECK_RESULT(result, ..) --> CHECK(!result, ..) > > - delay until g->parent_obj.enable = 1 > > -
Re: [PATCH] block/file-posix: fix update_zones_wp() caller
On 8/25/23 02:39, Sam Li wrote: > When the zoned requests that may change wp fail, it needs to > update only wps of the zones within the range of the requests > for not disrupting the other in-flight requests. The wp is updated > successfully after the request completes. > > Fixed the callers with right offset and nr_zones. > > Signed-off-by: Sam Li > --- > block/file-posix.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/block/file-posix.c b/block/file-posix.c > index b16e9c21a1..22559d6c2d 100644 > --- a/block/file-posix.c > +++ b/block/file-posix.c > @@ -2522,7 +2522,8 @@ out: > } > } else { > if (type & (QEMU_AIO_WRITE | QEMU_AIO_ZONE_APPEND)) { > -update_zones_wp(bs, s->fd, 0, 1); > +update_zones_wp(bs, s->fd, offset, > +ROUND_UP(bytes, bs->bl.zone_size)); Write and zone append operations are not allowed to cross zone boundaries. So I the number of zones should always be 1. The above changes a number of zones to a number of bytes, which seems wrong. The correct fix is I think: update_zones_wp(bs, s->fd, offset, 1); > } > } > > @@ -3472,7 +3473,7 @@ static int coroutine_fn > raw_co_zone_mgmt(BlockDriverState *bs, BlockZoneOp op, > len >> BDRV_SECTOR_BITS); > ret = raw_thread_pool_submit(handle_aiocb_zone_mgmt, ); > if (ret != 0) { > -update_zones_wp(bs, s->fd, offset, i); > +update_zones_wp(bs, s->fd, offset, nrz); Same here. Why would you need to update all zones wp ? This will affect zones that do not have a write error and potentially change there correct in-memory wp to a wrong value. I think this also should be: update_zones_wp(bs, s->fd, offset, 1); > error_report("ioctl %s failed %d", op_name, ret); > return ret; > } -- Damien Le Moal Western Digital Research
Re: [PATCH v7 5/9] gfxstream + rutabaga prep: added need defintions, fields, and options
On Wed, Aug 23, 2023 at 7:32 AM Mark Cave-Ayland < mark.cave-ayl...@ilande.co.uk> wrote: > On 17/08/2023 03:23, Gurchetan Singh wrote: > > > From: Gurchetan Singh > > > > This modifies the common virtio-gpu.h file have the fields and > > defintions needed by gfxstream/rutabaga, by VirtioGpuRutabaga. > > > > Signed-off-by: Gurchetan Singh > > Tested-by: Alyssa Ross > > Tested-by: Emmanouil Pitsidianakis > > Reviewed-by: Emmanouil Pitsidianakis > > --- > > v1: void *rutabaga --> struct rutabaga *rutabaga (Akihiko) > > have a separate rutabaga device instead of using GL device (Bernard) > > > > v2: VirtioGpuRutabaga --> VirtIOGPURutabaga (Akihiko) > > move MemoryRegionInfo into VirtIOGPURutabaga (Akihiko) > > remove 'ctx' field (Akihiko) > > remove 'rutabaga_active' > > > > v6: remove command from commit message, refer to docs instead (Manos) > > > > include/hw/virtio/virtio-gpu.h | 28 > > 1 file changed, 28 insertions(+) > > > > diff --git a/include/hw/virtio/virtio-gpu.h > b/include/hw/virtio/virtio-gpu.h > > index 55973e112f..e2a07e68d9 100644 > > --- a/include/hw/virtio/virtio-gpu.h > > +++ b/include/hw/virtio/virtio-gpu.h > > @@ -38,6 +38,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUGL, VIRTIO_GPU_GL) > > #define TYPE_VHOST_USER_GPU "vhost-user-gpu" > > OBJECT_DECLARE_SIMPLE_TYPE(VhostUserGPU, VHOST_USER_GPU) > > > > +#define TYPE_VIRTIO_GPU_RUTABAGA "virtio-gpu-rutabaga-device" > > +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPURutabaga, VIRTIO_GPU_RUTABAGA) > > + > > struct virtio_gpu_simple_resource { > > uint32_t resource_id; > > uint32_t width; > > @@ -94,6 +97,7 @@ enum virtio_gpu_base_conf_flags { > > VIRTIO_GPU_FLAG_DMABUF_ENABLED, > > VIRTIO_GPU_FLAG_BLOB_ENABLED, > > VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED, > > +VIRTIO_GPU_FLAG_RUTABAGA_ENABLED, > > }; > > > > #define virtio_gpu_virgl_enabled(_cfg) \ > > @@ -108,6 +112,8 @@ enum virtio_gpu_base_conf_flags { > > (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED)) > > #define virtio_gpu_context_init_enabled(_cfg) \ > > (_cfg.flags & (1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED)) > > +#define virtio_gpu_rutabaga_enabled(_cfg) \ > > +(_cfg.flags & (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED)) > > #define virtio_gpu_hostmem_enabled(_cfg) \ > > (_cfg.hostmem > 0) > > > > @@ -232,6 +238,28 @@ struct VhostUserGPU { > > bool backend_blocked; > > }; > > > > +#define MAX_SLOTS 4096 > > + > > +struct MemoryRegionInfo { > > +int used; > > +MemoryRegion mr; > > +uint32_t resource_id; > > +}; > > + > > +struct rutabaga; > > + > > +struct VirtIOGPURutabaga { > > +struct VirtIOGPU parent_obj; > > The QOM macro should define a typedef for you, so you can drop the > "struct" here. > > > + > > +struct MemoryRegionInfo memory_regions[MAX_SLOTS]; > > +char *capset_names; > > +char *wayland_socket_path; > > +char *wsi; > > +bool headless; > > +uint32_t num_capsets; > > +struct rutabaga *rutabaga; > > +}; > > + > > Shouldn't the VIRTIO_GPU_RUTABAGA QOM declaration and this structure be in > a separate > virtio-gpu-rutabaga header file which also includes the header defining > struct > rutabaga? The fact that you're having to pre-declare struct rutabaga in > this header > when rutabaga support is an optional dependency doesn't seem right. > It is the prevailing style of the virtio-gpu code. For example, we do have "virtio_gpu_virgl_*" functions, vhost-user, and udmabuf stubs in the same file. So for now, I didn't add an extra header file in v12. In the future, separating out optional dependencies into constituent header files could be future refactoring/cleanup. > > > #define VIRTIO_GPU_FILL_CMD(out) do { > \ > > size_t s; > \ > > s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, > \ > > > ATB, > > Mark. > >
[PATCH v12 6/9] gfxstream + rutabaga: add initial support for gfxstream
This adds initial support for gfxstream and cross-domain. Both features rely on virtio-gpu blob resources and context types, which are also implemented in this patch. gfxstream has a long and illustrious history in Android graphics paravirtualization. It has been powering graphics in the Android Studio Emulator for more than a decade, which is the main developer platform. Originally conceived by Jesse Hall, it was first known as "EmuGL" [a]. The key design characteristic was a 1:1 threading model and auto-generation, which fit nicely with the OpenGLES spec. It also allowed easy layering with ANGLE on the host, which provides the GLES implementations on Windows or MacOS enviroments. gfxstream has traditionally been maintained by a single engineer, and between 2015 to 2021, the goldfish throne passed to Frank Yang. Historians often remark this glorious reign ("pax gfxstreama" is the academic term) was comparable to that of Augustus and both Queen Elizabeths. Just to name a few accomplishments in a resplendent panoply: higher versions of GLES, address space graphics, snapshot support and CTS compliant Vulkan [b]. One major drawback was the use of out-of-tree goldfish drivers. Android engineers didn't know much about DRM/KMS and especially TTM so a simple guest to host pipe was conceived. Luckily, virtio-gpu 3D started to emerge in 2016 due to the work of the Mesa/virglrenderer communities. In 2018, the initial virtio-gpu port of gfxstream was done by Cuttlefish enthusiast Alistair Delva. It was a symbol compatible replacement of virglrenderer [c] and named "AVDVirglrenderer". This implementation forms the basis of the current gfxstream host implementation still in use today. cross-domain support follows a similar arc. Originally conceived by Wayland aficionado David Reveman and crosvm enjoyer Zach Reizner in 2018, it initially relied on the downstream "virtio-wl" device. In 2020 and 2021, virtio-gpu was extended to include blob resources and multiple timelines by yours truly, features gfxstream/cross-domain both require to function correctly. Right now, we stand at the precipice of a truly fantastic possibility: the Android Emulator powered by upstream QEMU and upstream Linux kernel. gfxstream will then be packaged properfully, and app developers can even fix gfxstream bugs on their own if they encounter them. It's been quite the ride, my friends. Where will gfxstream head next, nobody really knows. I wouldn't be surprised if it's around for another decade, maintained by a new generation of Android graphics enthusiasts. Technical details: - Very simple initial display integration: just used Pixman - Largely, 1:1 mapping of virtio-gpu hypercalls to rutabaga function calls Next steps for Android VMs: - The next step would be improving display integration and UI interfaces with the goal of the QEMU upstream graphics being in an emulator release [d]. Next steps for Linux VMs for display virtualization: - For widespread distribution, someone needs to package Sommelier or the wayland-proxy-virtwl [e] ideally into Debian main. In addition, newer versions of the Linux kernel come with DRM_VIRTIO_GPU_KMS option, which allows disabling KMS hypercalls. If anyone cares enough, it'll probably be possible to build a custom VM variant that uses this display virtualization strategy. [a] https://android-review.googlesource.com/c/platform/development/+/34470 [b] https://android-review.googlesource.com/q/topic:%22vulkan-hostconnection-start%22 [c] https://android-review.googlesource.com/c/device/generic/goldfish-opengl/+/761927 [d] https://developer.android.com/studio/releases/emulator [e] https://github.com/talex5/wayland-proxy-virtwl Signed-off-by: Gurchetan Singh Tested-by: Alyssa Ross Tested-by: Emmanouil Pitsidianakis Reviewed-by: Emmanouil Pitsidianakis --- v1: Incorported various suggestions by Akihiko Odaki and Bernard Berschow - Removed GET_VIRTIO_GPU_GL / GET_RUTABAGA macros - Used error_report(..) - Used g_autofree to fix leaks on error paths - Removed unnecessary casts - added virtio-gpu-pci-rutabaga.c + virtio-vga-rutabaga.c files v2: Incorported various suggestions by Akihiko Odaki, Marc-André Lureau and Bernard Berschow: - Parenthesis in CHECK macro - CHECK_RESULT(result, ..) --> CHECK(!result, ..) - delay until g->parent_obj.enable = 1 - Additional cast fixes - initialize directly in virtio_gpu_rutabaga_realize(..) - add debug callback to hook into QEMU error's APIs v3: Incorporated feedback from Akihiko Odaki and Alyssa Ross: - Autodetect Wayland socket when not explicitly specified - Fix map_blob error paths - Add comment why we need both `res` and `resource` in create blob - Cast and whitespace fixes - Big endian check comes before virtio_gpu_rutabaga_init(). - VirtIOVGARUTABAGA --> VirtIOVGARutabaga v4: Incorporated feedback from Akihiko Odaki and Alyssa Ross:
[PATCH v12 5/9] gfxstream + rutabaga prep: added need defintions, fields, and options
This modifies the common virtio-gpu.h file have the fields and defintions needed by gfxstream/rutabaga, by VirtioGpuRutabaga. Signed-off-by: Gurchetan Singh Tested-by: Alyssa Ross Tested-by: Emmanouil Pitsidianakis Reviewed-by: Emmanouil Pitsidianakis --- v1: void *rutabaga --> struct rutabaga *rutabaga (Akihiko) have a separate rutabaga device instead of using GL device (Bernard) v2: VirtioGpuRutabaga --> VirtIOGPURutabaga (Akihiko) move MemoryRegionInfo into VirtIOGPURutabaga (Akihiko) remove 'ctx' field (Akihiko) remove 'rutabaga_active' v6: remove command from commit message, refer to docs instead (Manos) v12: Drop unnecessary "struct" (Mark) include/hw/virtio/virtio-gpu.h | 28 1 file changed, 28 insertions(+) diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 55973e112f..de06bcdba4 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -38,6 +38,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPUGL, VIRTIO_GPU_GL) #define TYPE_VHOST_USER_GPU "vhost-user-gpu" OBJECT_DECLARE_SIMPLE_TYPE(VhostUserGPU, VHOST_USER_GPU) +#define TYPE_VIRTIO_GPU_RUTABAGA "virtio-gpu-rutabaga-device" +OBJECT_DECLARE_SIMPLE_TYPE(VirtIOGPURutabaga, VIRTIO_GPU_RUTABAGA) + struct virtio_gpu_simple_resource { uint32_t resource_id; uint32_t width; @@ -94,6 +97,7 @@ enum virtio_gpu_base_conf_flags { VIRTIO_GPU_FLAG_DMABUF_ENABLED, VIRTIO_GPU_FLAG_BLOB_ENABLED, VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED, +VIRTIO_GPU_FLAG_RUTABAGA_ENABLED, }; #define virtio_gpu_virgl_enabled(_cfg) \ @@ -108,6 +112,8 @@ enum virtio_gpu_base_conf_flags { (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED)) #define virtio_gpu_context_init_enabled(_cfg) \ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED)) +#define virtio_gpu_rutabaga_enabled(_cfg) \ +(_cfg.flags & (1 << VIRTIO_GPU_FLAG_RUTABAGA_ENABLED)) #define virtio_gpu_hostmem_enabled(_cfg) \ (_cfg.hostmem > 0) @@ -232,6 +238,28 @@ struct VhostUserGPU { bool backend_blocked; }; +#define MAX_SLOTS 4096 + +struct MemoryRegionInfo { +int used; +MemoryRegion mr; +uint32_t resource_id; +}; + +struct rutabaga; + +struct VirtIOGPURutabaga { +VirtIOGPU parent_obj; + +struct MemoryRegionInfo memory_regions[MAX_SLOTS]; +char *capset_names; +char *wayland_socket_path; +char *wsi; +bool headless; +uint32_t num_capsets; +struct rutabaga *rutabaga; +}; + #define VIRTIO_GPU_FILL_CMD(out) do { \ size_t s; \ s = iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \ -- 2.42.0.rc2.253.gd59a3bf2b4-goog
[PATCH v12 2/9] virtio-gpu: CONTEXT_INIT feature
From: Antonio Caggiano The feature can be enabled when a backend wants it. Signed-off-by: Antonio Caggiano Reviewed-by: Marc-André Lureau Signed-off-by: Gurchetan Singh Tested-by: Alyssa Ross Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Akihiko Odaki --- hw/display/virtio-gpu-base.c | 3 +++ include/hw/virtio/virtio-gpu.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index ca1fb7b16f..4f2b0ba1f3 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -232,6 +232,9 @@ virtio_gpu_base_get_features(VirtIODevice *vdev, uint64_t features, if (virtio_gpu_blob_enabled(g->conf)) { features |= (1 << VIRTIO_GPU_F_RESOURCE_BLOB); } +if (virtio_gpu_context_init_enabled(g->conf)) { +features |= (1 << VIRTIO_GPU_F_CONTEXT_INIT); +} return features; } diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 390c4642b8..8377c365ef 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -93,6 +93,7 @@ enum virtio_gpu_base_conf_flags { VIRTIO_GPU_FLAG_EDID_ENABLED, VIRTIO_GPU_FLAG_DMABUF_ENABLED, VIRTIO_GPU_FLAG_BLOB_ENABLED, +VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED, }; #define virtio_gpu_virgl_enabled(_cfg) \ @@ -105,6 +106,8 @@ enum virtio_gpu_base_conf_flags { (_cfg.flags & (1 << VIRTIO_GPU_FLAG_DMABUF_ENABLED)) #define virtio_gpu_blob_enabled(_cfg) \ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED)) +#define virtio_gpu_context_init_enabled(_cfg) \ +(_cfg.flags & (1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED)) struct virtio_gpu_base_conf { uint32_t max_outputs; -- 2.42.0.rc2.253.gd59a3bf2b4-goog
[PATCH v12 8/9] gfxstream + rutabaga: enable rutabaga
This change enables rutabaga to receive virtio-gpu-3d hypercalls when it is active. Signed-off-by: Gurchetan Singh Tested-by: Alyssa Ross Tested-by: Emmanouil Pitsidianakis Reviewed-by: Emmanouil Pitsidianakis --- v3: Whitespace fix (Akihiko) v9: reorder virtio_gpu_have_udmabuf() after checking if rutabaga is enabled to avoid spurious warnings (Akihiko) hw/display/virtio-gpu-base.c | 3 ++- hw/display/virtio-gpu.c | 5 +++-- softmmu/qdev-monitor.c | 3 +++ softmmu/vl.c | 1 + 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/display/virtio-gpu-base.c b/hw/display/virtio-gpu-base.c index 4f2b0ba1f3..50c5373b65 100644 --- a/hw/display/virtio-gpu-base.c +++ b/hw/display/virtio-gpu-base.c @@ -223,7 +223,8 @@ virtio_gpu_base_get_features(VirtIODevice *vdev, uint64_t features, { VirtIOGPUBase *g = VIRTIO_GPU_BASE(vdev); -if (virtio_gpu_virgl_enabled(g->conf)) { +if (virtio_gpu_virgl_enabled(g->conf) || +virtio_gpu_rutabaga_enabled(g->conf)) { features |= (1 << VIRTIO_GPU_F_VIRGL); } if (virtio_gpu_edid_enabled(g->conf)) { diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 3e658f1fef..fe094addef 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1361,8 +1361,9 @@ void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) VirtIOGPU *g = VIRTIO_GPU(qdev); if (virtio_gpu_blob_enabled(g->parent_obj.conf)) { -if (!virtio_gpu_have_udmabuf()) { -error_setg(errp, "cannot enable blob resources without udmabuf"); +if (!virtio_gpu_rutabaga_enabled(g->parent_obj.conf) && +!virtio_gpu_have_udmabuf()) { +error_setg(errp, "need rutabaga or udmabuf for blob resources"); return; } diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c index 74f4e41338..1b8005ae55 100644 --- a/softmmu/qdev-monitor.c +++ b/softmmu/qdev-monitor.c @@ -86,6 +86,9 @@ static const QDevAlias qdev_alias_table[] = { { "virtio-gpu-pci", "virtio-gpu", QEMU_ARCH_VIRTIO_PCI }, { "virtio-gpu-gl-device", "virtio-gpu-gl", QEMU_ARCH_VIRTIO_MMIO }, { "virtio-gpu-gl-pci", "virtio-gpu-gl", QEMU_ARCH_VIRTIO_PCI }, +{ "virtio-gpu-rutabaga-device", "virtio-gpu-rutabaga", + QEMU_ARCH_VIRTIO_MMIO }, +{ "virtio-gpu-rutabaga-pci", "virtio-gpu-rutabaga", QEMU_ARCH_VIRTIO_PCI }, { "virtio-input-host-device", "virtio-input-host", QEMU_ARCH_VIRTIO_MMIO }, { "virtio-input-host-ccw", "virtio-input-host", QEMU_ARCH_VIRTIO_CCW }, { "virtio-input-host-pci", "virtio-input-host", QEMU_ARCH_VIRTIO_PCI }, diff --git a/softmmu/vl.c b/softmmu/vl.c index b0b96f67fa..2f98eefdf3 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -216,6 +216,7 @@ static struct { { .driver = "ati-vga", .flag = _vga }, { .driver = "vhost-user-vga", .flag = _vga }, { .driver = "virtio-vga-gl",.flag = _vga }, +{ .driver = "virtio-vga-rutabaga", .flag = _vga }, }; static QemuOptsList qemu_rtc_opts = { -- 2.42.0.rc2.253.gd59a3bf2b4-goog
[PATCH v12 7/9] gfxstream + rutabaga: meson support
- Add meson detection of rutabaga_gfx - Build virtio-gpu-rutabaga.c + associated vga/pci files when present Signed-off-by: Gurchetan Singh Tested-by: Alyssa Ross Tested-by: Emmanouil Pitsidianakis Reviewed-by: Emmanouil Pitsidianakis --- v3: Fix alignment issues (Akihiko) hw/display/meson.build| 22 ++ meson.build | 7 +++ meson_options.txt | 2 ++ scripts/meson-buildoptions.sh | 3 +++ 4 files changed, 34 insertions(+) diff --git a/hw/display/meson.build b/hw/display/meson.build index 413ba4ab24..e362d625dd 100644 --- a/hw/display/meson.build +++ b/hw/display/meson.build @@ -79,6 +79,13 @@ if config_all_devices.has_key('CONFIG_VIRTIO_GPU') if_true: [files('virtio-gpu-gl.c', 'virtio-gpu-virgl.c'), pixman, virgl]) hw_display_modules += {'virtio-gpu-gl': virtio_gpu_gl_ss} endif + + if rutabaga.found() +virtio_gpu_rutabaga_ss = ss.source_set() +virtio_gpu_rutabaga_ss.add(when: ['CONFIG_VIRTIO_GPU', rutabaga], + if_true: [files('virtio-gpu-rutabaga.c'), pixman]) +hw_display_modules += {'virtio-gpu-rutabaga': virtio_gpu_rutabaga_ss} + endif endif if config_all_devices.has_key('CONFIG_VIRTIO_PCI') @@ -95,6 +102,12 @@ if config_all_devices.has_key('CONFIG_VIRTIO_PCI') if_true: [files('virtio-gpu-pci-gl.c'), pixman]) hw_display_modules += {'virtio-gpu-pci-gl': virtio_gpu_pci_gl_ss} endif + if rutabaga.found() +virtio_gpu_pci_rutabaga_ss = ss.source_set() +virtio_gpu_pci_rutabaga_ss.add(when: ['CONFIG_VIRTIO_GPU', 'CONFIG_VIRTIO_PCI', rutabaga], + if_true: [files('virtio-gpu-pci-rutabaga.c'), pixman]) +hw_display_modules += {'virtio-gpu-pci-rutabaga': virtio_gpu_pci_rutabaga_ss} + endif endif if config_all_devices.has_key('CONFIG_VIRTIO_VGA') @@ -113,6 +126,15 @@ if config_all_devices.has_key('CONFIG_VIRTIO_VGA') virtio_vga_gl_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-vga.c'), if_false: files('acpi-vga-stub.c')) hw_display_modules += {'virtio-vga-gl': virtio_vga_gl_ss} + + if rutabaga.found() +virtio_vga_rutabaga_ss = ss.source_set() +virtio_vga_rutabaga_ss.add(when: ['CONFIG_VIRTIO_VGA', rutabaga], + if_true: [files('virtio-vga-rutabaga.c'), pixman]) +virtio_vga_rutabaga_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-vga.c'), +if_false: files('acpi-vga-stub.c')) +hw_display_modules += {'virtio-vga-rutabaga': virtio_vga_rutabaga_ss} + endif endif system_ss.add(when: 'CONFIG_OMAP', if_true: files('omap_lcdc.c')) diff --git a/meson.build b/meson.build index 98e68ef0b1..293f388e53 100644 --- a/meson.build +++ b/meson.build @@ -1069,6 +1069,12 @@ if not get_option('virglrenderer').auto() or have_system or have_vhost_user_gpu dependencies: virgl)) endif endif +rutabaga = not_found +if not get_option('rutabaga_gfx').auto() or have_system or have_vhost_user_gpu + rutabaga = dependency('rutabaga_gfx_ffi', + method: 'pkg-config', + required: get_option('rutabaga_gfx')) +endif blkio = not_found if not get_option('blkio').auto() or have_block blkio = dependency('blkio', @@ -4272,6 +4278,7 @@ summary_info += {'libtasn1': tasn1} summary_info += {'PAM': pam} summary_info += {'iconv support': iconv} summary_info += {'virgl support': virgl} +summary_info += {'rutabaga support': rutabaga} summary_info += {'blkio support': blkio} summary_info += {'curl support': curl} summary_info += {'Multipath support': mpathpersist} diff --git a/meson_options.txt b/meson_options.txt index aaea5ddd77..dea3bf7d9c 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -224,6 +224,8 @@ option('vmnet', type : 'feature', value : 'auto', description: 'vmnet.framework network backend support') option('virglrenderer', type : 'feature', value : 'auto', description: 'virgl rendering support') +option('rutabaga_gfx', type : 'feature', value : 'auto', + description: 'rutabaga_gfx support') option('png', type : 'feature', value : 'auto', description: 'PNG support with libpng') option('vnc', type : 'feature', value : 'auto', diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 9da3fe299b..9a95b4f782 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -154,6 +154,7 @@ meson_options_help() { printf "%s\n" ' rbd Ceph block device driver' printf "%s\n" ' rdmaEnable RDMA-based migration' printf "%s\n" ' replication replication support' + printf "%s\n" ' rutabaga-gfxrutabaga_gfx support' printf "%s\n" ' sdl SDL user interface' printf "%s\n" ' sdl-image
[PATCH v12 1/9] virtio: Add shared memory capability
From: "Dr. David Alan Gilbert" Define a new capability type 'VIRTIO_PCI_CAP_SHARED_MEMORY_CFG' to allow defining shared memory regions with sizes and offsets of 2^32 and more. Multiple instances of the capability are allowed and distinguished by a device-specific 'id'. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Antonio Caggiano Reviewed-by: Gurchetan Singh Signed-off-by: Gurchetan Singh Tested-by: Alyssa Ross Acked-by: Huang Rui Tested-by: Huang Rui Reviewed-by: Akihiko Odaki --- hw/virtio/virtio-pci.c | 18 ++ include/hw/virtio/virtio-pci.h | 4 2 files changed, 22 insertions(+) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index edbc0daa18..da8c9ea12d 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1435,6 +1435,24 @@ static int virtio_pci_add_mem_cap(VirtIOPCIProxy *proxy, return offset; } +int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy, + uint8_t bar, uint64_t offset, uint64_t length, + uint8_t id) +{ +struct virtio_pci_cap64 cap = { +.cap.cap_len = sizeof cap, +.cap.cfg_type = VIRTIO_PCI_CAP_SHARED_MEMORY_CFG, +}; + +cap.cap.bar = bar; +cap.cap.length = cpu_to_le32(length); +cap.length_hi = cpu_to_le32(length >> 32); +cap.cap.offset = cpu_to_le32(offset); +cap.offset_hi = cpu_to_le32(offset >> 32); +cap.cap.id = id; +return virtio_pci_add_mem_cap(proxy, ); +} + static uint64_t virtio_pci_common_read(void *opaque, hwaddr addr, unsigned size) { diff --git a/include/hw/virtio/virtio-pci.h b/include/hw/virtio/virtio-pci.h index ab2051b64b..5a3f182f99 100644 --- a/include/hw/virtio/virtio-pci.h +++ b/include/hw/virtio/virtio-pci.h @@ -264,4 +264,8 @@ unsigned virtio_pci_optimal_num_queues(unsigned fixed_queues); void virtio_pci_set_guest_notifier_fd_handler(VirtIODevice *vdev, VirtQueue *vq, int n, bool assign, bool with_irqfd); + +int virtio_pci_add_shm_cap(VirtIOPCIProxy *proxy, uint8_t bar, uint64_t offset, + uint64_t length, uint8_t id); + #endif -- 2.42.0.rc2.253.gd59a3bf2b4-goog
[PATCH v12 0/9] rutabaga_gfx + gfxstream
From: Gurchetan Singh Prior versions: Changes since v11: - Incorporated review feedback How to build both rutabaga and gfxstream guest/host libs: https://crosvm.dev/book/appendix/rutabaga_gfx.html Branch containing this patch series (now on QEMU Gitlab): https://gitlab.com/gurchetansingh/qemu/-/commits/qemu-gfxstream-v12 Antonio Caggiano (2): virtio-gpu: CONTEXT_INIT feature virtio-gpu: blob prep Dr. David Alan Gilbert (1): virtio: Add shared memory capability Gerd Hoffmann (1): virtio-gpu: hostmem Gurchetan Singh (5): gfxstream + rutabaga prep: added need defintions, fields, and options gfxstream + rutabaga: add initial support for gfxstream gfxstream + rutabaga: meson support gfxstream + rutabaga: enable rutabaga docs/system: add basic virtio-gpu documentation docs/system/device-emulation.rst |1 + docs/system/devices/virtio-gpu.rst | 112 +++ hw/display/meson.build | 22 + hw/display/virtio-gpu-base.c |6 +- hw/display/virtio-gpu-pci-rutabaga.c | 47 ++ hw/display/virtio-gpu-pci.c | 14 + hw/display/virtio-gpu-rutabaga.c | 1119 ++ hw/display/virtio-gpu.c | 16 +- hw/display/virtio-vga-rutabaga.c | 50 ++ hw/display/virtio-vga.c | 33 +- hw/virtio/virtio-pci.c | 18 + include/hw/virtio/virtio-gpu-bswap.h | 15 + include/hw/virtio/virtio-gpu.h | 41 + include/hw/virtio/virtio-pci.h |4 + meson.build |7 + meson_options.txt|2 + scripts/meson-buildoptions.sh|3 + softmmu/qdev-monitor.c |3 + softmmu/vl.c |1 + 19 files changed, 1495 insertions(+), 19 deletions(-) create mode 100644 docs/system/devices/virtio-gpu.rst create mode 100644 hw/display/virtio-gpu-pci-rutabaga.c create mode 100644 hw/display/virtio-gpu-rutabaga.c create mode 100644 hw/display/virtio-vga-rutabaga.c -- 2.42.0.rc2.253.gd59a3bf2b4-goog
[PATCH v12 9/9] docs/system: add basic virtio-gpu documentation
This adds basic documentation for virtio-gpu. Suggested-by: Akihiko Odaki Signed-off-by: Gurchetan Singh Tested-by: Alyssa Ross Tested-by: Emmanouil Pitsidianakis Reviewed-by: Emmanouil Pitsidianakis --- v2: - Incorporated suggestions by Akihiko Odaki - Listed the currently supported capset_names (Bernard) v3: - Incorporated suggestions by Akihiko Odaki and Alyssa Ross v4: - Incorporated suggestions by Akihiko Odaki v5: - Removed pci suffix from examples - Verified that -device virtio-gpu-rutabaga works. Strangely enough, I don't remember changing anything, and I remember it not working. I did rebase to top of tree though. - Fixed meson examples in crosvm docs v8: - Remove different links for "rutabaga_gfx" and "gfxstream-enabled rutabaga" (Akihiko) v11: - Use GPL-2.0-or-later license (Phillippe) docs/system/device-emulation.rst | 1 + docs/system/devices/virtio-gpu.rst | 112 + 2 files changed, 113 insertions(+) create mode 100644 docs/system/devices/virtio-gpu.rst diff --git a/docs/system/device-emulation.rst b/docs/system/device-emulation.rst index 4491c4cbf7..1167f3a9f2 100644 --- a/docs/system/device-emulation.rst +++ b/docs/system/device-emulation.rst @@ -91,6 +91,7 @@ Emulated Devices devices/nvme.rst devices/usb.rst devices/vhost-user.rst + devices/virtio-gpu.rst devices/virtio-pmem.rst devices/vhost-user-rng.rst devices/canokey.rst diff --git a/docs/system/devices/virtio-gpu.rst b/docs/system/devices/virtio-gpu.rst new file mode 100644 index 00..21465e4ce2 --- /dev/null +++ b/docs/system/devices/virtio-gpu.rst @@ -0,0 +1,112 @@ +.. + SPDX-License-Identifier: GPL-2.0-or-later + +virtio-gpu +== + +This document explains the setup and usage of the virtio-gpu device. +The virtio-gpu device paravirtualizes the GPU and display controller. + +Linux kernel support + + +virtio-gpu requires a guest Linux kernel built with the +``CONFIG_DRM_VIRTIO_GPU`` option. + +QEMU virtio-gpu variants + + +QEMU virtio-gpu device variants come in the following form: + + * ``virtio-vga[-BACKEND]`` + * ``virtio-gpu[-BACKEND][-INTERFACE]`` + * ``vhost-user-vga`` + * ``vhost-user-pci`` + +**Backends:** QEMU provides a 2D virtio-gpu backend, and two accelerated +backends: virglrenderer ('gl' device label) and rutabaga_gfx ('rutabaga' +device label). There is a vhost-user backend that runs the graphics stack +in a separate process for improved isolation. + +**Interfaces:** QEMU further categorizes virtio-gpu device variants based +on the interface exposed to the guest. The interfaces can be classified +into VGA and non-VGA variants. The VGA ones are prefixed with virtio-vga +or vhost-user-vga while the non-VGA ones are prefixed with virtio-gpu or +vhost-user-gpu. + +The VGA ones always use the PCI interface, but for the non-VGA ones, the +user can further pick between MMIO or PCI. For MMIO, the user can suffix +the device name with -device, though vhost-user-gpu does not support MMIO. +For PCI, the user can suffix it with -pci. Without these suffixes, the +platform default will be chosen. + +virtio-gpu 2d +- + +The default 2D backend only performs 2D operations. The guest needs to +employ a software renderer for 3D graphics. + +Typically, the software renderer is provided by `Mesa`_ or `SwiftShader`_. +Mesa's implementations (LLVMpipe, Lavapipe and virgl below) work out of box +on typical modern Linux distributions. + +.. parsed-literal:: +-device virtio-gpu + +.. _Mesa: https://www.mesa3d.org/ +.. _SwiftShader: https://github.com/google/swiftshader + +virtio-gpu virglrenderer + + +When using virgl accelerated graphics mode in the guest, OpenGL API calls +are translated into an intermediate representation (see `Gallium3D`_). The +intermediate representation is communicated to the host and the +`virglrenderer`_ library on the host translates the intermediate +representation back to OpenGL API calls. + +.. parsed-literal:: +-device virtio-gpu-gl + +.. _Gallium3D: https://www.freedesktop.org/wiki/Software/gallium/ +.. _virglrenderer: https://gitlab.freedesktop.org/virgl/virglrenderer/ + +virtio-gpu rutabaga +--- + +virtio-gpu can also leverage rutabaga_gfx to provide `gfxstream`_ +rendering and `Wayland display passthrough`_. With the gfxstream rendering +mode, GLES and Vulkan calls are forwarded to the host with minimal +modification. + +The crosvm book provides directions on how to build a `gfxstream-enabled +rutabaga`_ and launch a `guest Wayland proxy`_. + +This device does require host blob support (``hostmem`` field below). The +``hostmem`` field specifies the size of virtio-gpu host memory window. +This is typically between 256M and 8G. + +At least one capset (see colon separated ``capset_names`` below) must be +specified when starting the device. The currently supported +``capset_names`` are
[PATCH v12 4/9] virtio-gpu: blob prep
From: Antonio Caggiano This adds preparatory functions needed to: - decode blob cmds - tracking iovecs Signed-off-by: Antonio Caggiano Signed-off-by: Dmitry Osipenko Signed-off-by: Gurchetan Singh Tested-by: Alyssa Ross Tested-by: Emmanouil Pitsidianakis Reviewed-by: Emmanouil Pitsidianakis --- hw/display/virtio-gpu.c | 10 +++--- include/hw/virtio/virtio-gpu-bswap.h | 15 +++ include/hw/virtio/virtio-gpu.h | 5 + 3 files changed, 23 insertions(+), 7 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 48ef0d9fad..3e658f1fef 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -33,15 +33,11 @@ #define VIRTIO_GPU_VM_VERSION 1 -static struct virtio_gpu_simple_resource* -virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); static struct virtio_gpu_simple_resource * virtio_gpu_find_check_resource(VirtIOGPU *g, uint32_t resource_id, bool require_backing, const char *caller, uint32_t *error); -static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, - struct virtio_gpu_simple_resource *res); static void virtio_gpu_reset_bh(void *opaque); void virtio_gpu_update_cursor_data(VirtIOGPU *g, @@ -116,7 +112,7 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor) cursor->resource_id ? 1 : 0); } -static struct virtio_gpu_simple_resource * +struct virtio_gpu_simple_resource * virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id) { struct virtio_gpu_simple_resource *res; @@ -904,8 +900,8 @@ void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, g_free(iov); } -static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, - struct virtio_gpu_simple_resource *res) +void virtio_gpu_cleanup_mapping(VirtIOGPU *g, +struct virtio_gpu_simple_resource *res) { virtio_gpu_cleanup_mapping_iov(g, res->iov, res->iov_cnt); res->iov = NULL; diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h index 637a0585d0..dd1975e2d4 100644 --- a/include/hw/virtio/virtio-gpu-bswap.h +++ b/include/hw/virtio/virtio-gpu-bswap.h @@ -70,6 +70,21 @@ virtio_gpu_create_blob_bswap(struct virtio_gpu_resource_create_blob *cblob) le64_to_cpus(>size); } +static inline void +virtio_gpu_map_blob_bswap(struct virtio_gpu_resource_map_blob *mblob) +{ +virtio_gpu_ctrl_hdr_bswap(>hdr); +le32_to_cpus(>resource_id); +le64_to_cpus(>offset); +} + +static inline void +virtio_gpu_unmap_blob_bswap(struct virtio_gpu_resource_unmap_blob *ublob) +{ +virtio_gpu_ctrl_hdr_bswap(>hdr); +le32_to_cpus(>resource_id); +} + static inline void virtio_gpu_scanout_blob_bswap(struct virtio_gpu_set_scanout_blob *ssb) { diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index de4f624e94..55973e112f 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -257,6 +257,9 @@ void virtio_gpu_base_fill_display_info(VirtIOGPUBase *g, void virtio_gpu_base_generate_edid(VirtIOGPUBase *g, int scanout, struct virtio_gpu_resp_edid *edid); /* virtio-gpu.c */ +struct virtio_gpu_simple_resource * +virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); + void virtio_gpu_ctrl_response(VirtIOGPU *g, struct virtio_gpu_ctrl_command *cmd, struct virtio_gpu_ctrl_hdr *resp, @@ -275,6 +278,8 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, uint32_t *niov); void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, struct iovec *iov, uint32_t count); +void virtio_gpu_cleanup_mapping(VirtIOGPU *g, +struct virtio_gpu_simple_resource *res); void virtio_gpu_process_cmdq(VirtIOGPU *g); void virtio_gpu_device_realize(DeviceState *qdev, Error **errp); void virtio_gpu_reset(VirtIODevice *vdev); -- 2.42.0.rc2.253.gd59a3bf2b4-goog
[PATCH v12 3/9] virtio-gpu: hostmem
From: Gerd Hoffmann Use VIRTIO_GPU_SHM_ID_HOST_VISIBLE as id for virtio-gpu. Signed-off-by: Antonio Caggiano Tested-by: Alyssa Ross Acked-by: Michael S. Tsirkin --- hw/display/virtio-gpu-pci.c| 14 ++ hw/display/virtio-gpu.c| 1 + hw/display/virtio-vga.c| 33 - include/hw/virtio/virtio-gpu.h | 5 + 4 files changed, 44 insertions(+), 9 deletions(-) diff --git a/hw/display/virtio-gpu-pci.c b/hw/display/virtio-gpu-pci.c index 93f214ff58..da6a99f038 100644 --- a/hw/display/virtio-gpu-pci.c +++ b/hw/display/virtio-gpu-pci.c @@ -33,6 +33,20 @@ static void virtio_gpu_pci_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) DeviceState *vdev = DEVICE(g); int i; +if (virtio_gpu_hostmem_enabled(g->conf)) { +vpci_dev->msix_bar_idx = 1; +vpci_dev->modern_mem_bar_idx = 2; +memory_region_init(>hostmem, OBJECT(g), "virtio-gpu-hostmem", + g->conf.hostmem); +pci_register_bar(_dev->pci_dev, 4, + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_PREFETCH | + PCI_BASE_ADDRESS_MEM_TYPE_64, + >hostmem); +virtio_pci_add_shm_cap(vpci_dev, 4, 0, g->conf.hostmem, + VIRTIO_GPU_SHM_ID_HOST_VISIBLE); +} + virtio_pci_force_virtio_1(vpci_dev); if (!qdev_realize(vdev, BUS(_dev->bus), errp)) { return; diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index bbd5c6561a..48ef0d9fad 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -1509,6 +1509,7 @@ static Property virtio_gpu_properties[] = { 256 * MiB), DEFINE_PROP_BIT("blob", VirtIOGPU, parent_obj.conf.flags, VIRTIO_GPU_FLAG_BLOB_ENABLED, false), +DEFINE_PROP_SIZE("hostmem", VirtIOGPU, parent_obj.conf.hostmem, 0), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c index e6fb0aa876..c8552ff760 100644 --- a/hw/display/virtio-vga.c +++ b/hw/display/virtio-vga.c @@ -115,17 +115,32 @@ static void virtio_vga_base_realize(VirtIOPCIProxy *vpci_dev, Error **errp) pci_register_bar(_dev->pci_dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, >vram); -/* - * Configure virtio bar and regions - * - * We use bar #2 for the mmio regions, to be compatible with stdvga. - * virtio regions are moved to the end of bar #2, to make room for - * the stdvga mmio registers at the start of bar #2. - */ -vpci_dev->modern_mem_bar_idx = 2; -vpci_dev->msix_bar_idx = 4; vpci_dev->modern_io_bar_idx = 5; +if (!virtio_gpu_hostmem_enabled(g->conf)) { +/* + * Configure virtio bar and regions + * + * We use bar #2 for the mmio regions, to be compatible with stdvga. + * virtio regions are moved to the end of bar #2, to make room for + * the stdvga mmio registers at the start of bar #2. + */ +vpci_dev->modern_mem_bar_idx = 2; +vpci_dev->msix_bar_idx = 4; +} else { +vpci_dev->msix_bar_idx = 1; +vpci_dev->modern_mem_bar_idx = 2; +memory_region_init(>hostmem, OBJECT(g), "virtio-gpu-hostmem", + g->conf.hostmem); +pci_register_bar(_dev->pci_dev, 4, + PCI_BASE_ADDRESS_SPACE_MEMORY | + PCI_BASE_ADDRESS_MEM_PREFETCH | + PCI_BASE_ADDRESS_MEM_TYPE_64, + >hostmem); +virtio_pci_add_shm_cap(vpci_dev, 4, 0, g->conf.hostmem, + VIRTIO_GPU_SHM_ID_HOST_VISIBLE); +} + if (!(vpci_dev->flags & VIRTIO_PCI_FLAG_PAGE_PER_VQ)) { /* * with page-per-vq=off there is no padding space we can use diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h index 8377c365ef..de4f624e94 100644 --- a/include/hw/virtio/virtio-gpu.h +++ b/include/hw/virtio/virtio-gpu.h @@ -108,12 +108,15 @@ enum virtio_gpu_base_conf_flags { (_cfg.flags & (1 << VIRTIO_GPU_FLAG_BLOB_ENABLED)) #define virtio_gpu_context_init_enabled(_cfg) \ (_cfg.flags & (1 << VIRTIO_GPU_FLAG_CONTEXT_INIT_ENABLED)) +#define virtio_gpu_hostmem_enabled(_cfg) \ +(_cfg.hostmem > 0) struct virtio_gpu_base_conf { uint32_t max_outputs; uint32_t flags; uint32_t xres; uint32_t yres; +uint64_t hostmem; }; struct virtio_gpu_ctrl_command { @@ -137,6 +140,8 @@ struct VirtIOGPUBase { int renderer_blocked; int enable; +MemoryRegion hostmem; + struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS]; int enabled_output_bitmask; -- 2.42.0.rc2.253.gd59a3bf2b4-goog
[PATCH RESEND v8 13/20] target/riscv/cpu.c: use offset in isa_ext_is_enabled/update_enabled
We'll have future usage for a function where, given an offset of the struct RISCVCPUConfig, the flag is updated to a certain val. Change all existing callers to use edata->ext_enable_offset instead of 'edata'. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 913b64264f..cbf8ceec54 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -162,18 +162,17 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps), }; -static bool isa_ext_is_enabled(RISCVCPU *cpu, - const struct isa_ext_data *edata) +static bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset) { -bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset; +bool *ext_enabled = (void *)>cfg + ext_offset; return *ext_enabled; } -static void isa_ext_update_enabled(RISCVCPU *cpu, - const struct isa_ext_data *edata, bool en) +static void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, + bool en) { -bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset; +bool *ext_enabled = (void *)>cfg + ext_offset; *ext_enabled = en; } @@ -1045,9 +1044,10 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) /* Force disable extensions if priv spec version does not match */ for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) { -if (isa_ext_is_enabled(cpu, _edata_arr[i]) && +if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset) && (env->priv_ver < isa_edata_arr[i].min_version)) { -isa_ext_update_enabled(cpu, _edata_arr[i], false); +isa_ext_update_enabled(cpu, isa_edata_arr[i].ext_enable_offset, + false); #ifndef CONFIG_USER_ONLY warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx " because privilege spec version does not match", @@ -2337,7 +2337,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int i; for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) { -if (isa_ext_is_enabled(cpu, _edata_arr[i])) { +if (isa_ext_is_enabled(cpu, isa_edata_arr[i].ext_enable_offset)) { new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL); g_free(old); old = new; -- 2.41.0
[PATCH RESEND v8 12/20] target/riscv: deprecate the 'any' CPU type
The 'any' CPU type was introduced in commit dc5bd18fa5725 ("RISC-V CPU Core Definition"), being around since the beginning. It's not an easy CPU to use: it's undocumented and its name doesn't tell users much about what the CPU is supposed to bring. 'git log' doesn't help us either in knowing what was the original design of this CPU type. The closest we have is a comment from Alistair [1] where he recalls from memory that the 'any' CPU is supposed to behave like the newly added 'max' CPU. He also suggested that the 'any' CPU should be removed. The default CPUs are rv32 and rv64, so removing the 'any' CPU will have impact only on users that might have a script that uses '-cpu any'. And those users are better off using the default CPUs or the new 'max' CPU. We would love to just remove the code and be done with it, but one does not simply remove a feature in QEMU. We'll put the CPU in quarantine first, letting users know that we have the intent of removing it in the future. [1] https://lists.gnu.org/archive/html/qemu-devel/2023-07/msg02891.html Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- docs/about/deprecated.rst | 12 target/riscv/cpu.c| 5 + 2 files changed, 17 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 92a2bafd2b..4ced7427ac 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -371,6 +371,18 @@ QEMU's ``vhost`` feature, which would eliminate the high latency costs under which the 9p ``proxy`` backend currently suffers. However as of to date nobody has indicated plans for such kind of reimplementation unfortunately. +RISC-V 'any' CPU type ``-cpu any`` (since 8.2) +^^ + +The 'any' CPU type was introduced back in 2018 and has been around since the +initial RISC-V QEMU port. Its usage has always been unclear: users don't know +what to expect from a CPU called 'any', and in fact the CPU does not do anything +special that aren't already done by the default CPUs rv32/rv64. + +After the introduction of the 'max' CPU type RISC-V now has a good coverage +of generic CPUs: rv32 and rv64 as default CPUs and 'max' as a feature complete +CPU for both 32 and 64 bit builds. Users are then discouraged to use the 'any' +CPU type starting in 8.2. Block device options diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8dc85f75bb..913b64264f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1522,6 +1522,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); Error *local_err = NULL; +if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_CPU_ANY) != NULL) { +warn_report("The 'any' CPU is deprecated and will be " +"removed in the future."); +} + cpu_exec_realizefn(cs, _err); if (local_err != NULL) { error_propagate(errp, local_err); -- 2.41.0
[PATCH RESEND v8 14/20] target/riscv: make CPUCFG() macro public
The RISC-V KVM driver uses a CPUCFG() macro that calculates the offset of a certain field in the struct RISCVCPUConfig. We're going to use this macro in target/riscv/cpu.c as well in the next patches. Make it public. Rename it to CPU_CFG_OFFSET() for more clarity while we're at it. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 2 +- target/riscv/cpu.h | 2 ++ target/riscv/kvm.c | 8 +++- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index cbf8ceec54..ddbf82f859 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -48,7 +48,7 @@ struct isa_ext_data { }; #define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ -{#_name, _min_ver, offsetof(struct RISCVCPUConfig, _prop)} +{#_name, _min_ver, CPU_CFG_OFFSET(_prop)} /* * From vector_helper.c diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6ea22e0eea..577abcd724 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -62,6 +62,8 @@ const char *riscv_get_misa_ext_name(uint32_t bit); const char *riscv_get_misa_ext_description(uint32_t bit); +#define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop) + /* Privileged specification version */ enum { PRIV_VERSION_1_10_0 = 0, diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index faee8536ef..7c6dec05e3 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -200,10 +200,8 @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs) } } -#define CPUCFG(_prop) offsetof(struct RISCVCPUConfig, _prop) - #define KVM_EXT_CFG(_name, _prop, _reg_id) \ -{.name = _name, .offset = CPUCFG(_prop), \ +{.name = _name, .offset = CPU_CFG_OFFSET(_prop), \ .kvm_reg_id = _reg_id} static KVMCPUConfig kvm_multi_ext_cfgs[] = { @@ -280,13 +278,13 @@ static void kvm_cpu_set_multi_ext_cfg(Object *obj, Visitor *v, static KVMCPUConfig kvm_cbom_blocksize = { .name = "cbom_blocksize", -.offset = CPUCFG(cbom_blocksize), +.offset = CPU_CFG_OFFSET(cbom_blocksize), .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicbom_block_size) }; static KVMCPUConfig kvm_cboz_blocksize = { .name = "cboz_blocksize", -.offset = CPUCFG(cboz_blocksize), +.offset = CPU_CFG_OFFSET(cboz_blocksize), .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicboz_block_size) }; -- 2.41.0
[PATCH RESEND v8 19/20] target/riscv/cpu.c: honor user choice in cpu_cfg_ext_auto_update()
Add a new cpu_cfg_ext_is_user_set() helper to check if an extension was set by the user in the command line. Use it inside cpu_cfg_ext_auto_update() to verify if the user set a certain extension and, if that's the case, do not change its value. This will make us honor user choice instead of overwriting the values. Users will then be informed whether they're using an incompatible set of extensions instead of QEMU setting a magic value that works. For example, we'll now error out if the user explictly set 'zce' to true and 'zca' to false: $ ./build/qemu-system-riscv64 -M virt -cpu rv64,zce=true,zca=false -nographic qemu-system-riscv64: Zcf/Zcd/Zcb/Zcmp/Zcmt extensions require Zca extension This didn't happen before because we were enabling 'zca' if 'zce' was enabled regardless if the user explictly set 'zca' to false. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 10 ++ 1 file changed, 10 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ae8c35402f..e07b2c73e7 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -196,6 +196,12 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset) return PRIV_VERSION_1_10_0; } +static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) +{ +return g_hash_table_contains(multi_ext_user_opts, + GUINT_TO_POINTER(ext_offset)); +} + static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset, bool value) { @@ -207,6 +213,10 @@ static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset, return; } +if (cpu_cfg_ext_is_user_set(ext_offset)) { +return; +} + if (value && env->priv_ver != PRIV_VERSION_LATEST) { /* Do not enable it if priv_ver is older than min_version */ min_version = cpu_cfg_ext_get_min_version(ext_offset); -- 2.41.0
[PATCH RESEND v8 16/20] target/riscv/cpu.c: use cpu_cfg_ext_auto_update() during realize()
Let's change the other instances in realize() where we're enabling an extension based on a certain criteria (e.g. it's a dependency of another extension). We're leaving icsr and ifencei being enabled during RVG for later - we'll want to error out in that case. Every other extension enablement during realize is now done via cpu_cfg_ext_auto_update(). The end goal is that only cpu init() functions will handle extension flags directly via "cpu->cfg.ext_N = true|false". Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 50 +++--- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c56abf8395..0fe2ce0add 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1194,7 +1194,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } if (cpu->cfg.ext_zfh) { -cpu->cfg.ext_zfhmin = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zfhmin), true); } if (cpu->cfg.ext_zfhmin && !riscv_has_ext(env, RVF)) { @@ -1220,17 +1220,17 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } /* The V vector extension depends on the Zve64d extension */ -cpu->cfg.ext_zve64d = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64d), true); } /* The Zve64d extension depends on the Zve64f extension */ if (cpu->cfg.ext_zve64d) { -cpu->cfg.ext_zve64f = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve64f), true); } /* The Zve64f extension depends on the Zve32f extension */ if (cpu->cfg.ext_zve64f) { -cpu->cfg.ext_zve32f = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zve32f), true); } if (cpu->cfg.ext_zve64d && !riscv_has_ext(env, RVD)) { @@ -1244,7 +1244,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } if (cpu->cfg.ext_zvfh) { -cpu->cfg.ext_zvfhmin = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zvfhmin), true); } if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) { @@ -1274,7 +1274,7 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) /* Set the ISA extensions, checks should have happened above */ if (cpu->cfg.ext_zhinx) { -cpu->cfg.ext_zhinxmin = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true); } if ((cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) && !cpu->cfg.ext_zfinx) { @@ -1295,12 +1295,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } if (cpu->cfg.ext_zce) { -cpu->cfg.ext_zca = true; -cpu->cfg.ext_zcb = true; -cpu->cfg.ext_zcmp = true; -cpu->cfg.ext_zcmt = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcb), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmp), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcmt), true); if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) { -cpu->cfg.ext_zcf = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true); } } @@ -1368,26 +1368,26 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } if (cpu->cfg.ext_zk) { -cpu->cfg.ext_zkn = true; -cpu->cfg.ext_zkr = true; -cpu->cfg.ext_zkt = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkn), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkr), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkt), true); } if (cpu->cfg.ext_zkn) { -cpu->cfg.ext_zbkb = true; -cpu->cfg.ext_zbkc = true; -cpu->cfg.ext_zbkx = true; -cpu->cfg.ext_zkne = true; -cpu->cfg.ext_zknd = true; -cpu->cfg.ext_zknh = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zkne), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknd), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zknh), true); } if (cpu->cfg.ext_zks) { -cpu->cfg.ext_zbkb = true; -cpu->cfg.ext_zbkc = true; -cpu->cfg.ext_zbkx = true; -cpu->cfg.ext_zksed = true; -cpu->cfg.ext_zksh = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkb), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkc), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zbkx), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zksed), true); +
[PATCH RESEND v8 07/20] target/riscv/cpu.c: add riscv_cpu_add_qdev_prop_array()
The code inside riscv_cpu_add_user_properties() became quite repetitive after recent changes. Add a helper to hide the repetition away. Signed-off-by: Daniel Henrique Barboza --- target/riscv/cpu.c | 27 +++ 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 668522db01..4608fa2378 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1946,6 +1946,13 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, } #endif +static void riscv_cpu_add_qdev_prop_array(DeviceState *dev, Property *array) +{ +for (Property *prop = array; prop && prop->name; prop++) { +qdev_property_add_static(dev, prop); +} +} + #ifndef CONFIG_USER_ONLY static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) { @@ -2002,7 +2009,6 @@ static void riscv_cpu_add_kvm_properties(Object *obj) */ static void riscv_cpu_add_user_properties(Object *obj) { -Property *prop; DeviceState *dev = DEVICE(obj); #ifndef CONFIG_USER_ONLY @@ -2016,21 +2022,10 @@ static void riscv_cpu_add_user_properties(Object *obj) riscv_cpu_add_misa_properties(obj); -for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { -qdev_property_add_static(dev, prop); -} - -for (prop = riscv_cpu_options; prop && prop->name; prop++) { -qdev_property_add_static(dev, prop); -} - -for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) { -qdev_property_add_static(dev, prop); -} - -for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) { -qdev_property_add_static(dev, prop); -} +riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_extensions); +riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_options); +riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_vendor_exts); +riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_experimental_exts); } static Property riscv_cpu_properties[] = { -- 2.41.0
[PATCH RESEND v8 18/20] target/riscv: use isa_ext_update_enabled() in init_max_cpu_extensions()
Before adding support to detect if an extension was user set we need to handle how we're enabling extensions in riscv_init_max_cpu_extensions(). object_property_set_bool() calls the set() callback for the property, and we're going to use this callback to set the 'multi_ext_user_opts' hash. This means that, as is today, all extensions we're setting for the 'max' CPU will be seen as user set in the future. Let's change set_bool() to isa_ext_update_enabled() that will just enable/disable the flag on a certain offset. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index adfe671bd4..ae8c35402f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2163,24 +2163,24 @@ static void riscv_init_max_cpu_extensions(Object *obj) set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV); for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { -object_property_set_bool(obj, prop->name, true, NULL); +isa_ext_update_enabled(cpu, prop->offset, true); } /* set vector version */ env->vext_ver = VEXT_VERSION_1_00_0; /* Zfinx is not compatible with F. Disable it */ -object_property_set_bool(obj, "zfinx", false, NULL); -object_property_set_bool(obj, "zdinx", false, NULL); -object_property_set_bool(obj, "zhinx", false, NULL); -object_property_set_bool(obj, "zhinxmin", false, NULL); +isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zfinx), false); +isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zdinx), false); +isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinx), false); +isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zhinxmin), false); -object_property_set_bool(obj, "zce", false, NULL); -object_property_set_bool(obj, "zcmp", false, NULL); -object_property_set_bool(obj, "zcmt", false, NULL); +isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zce), false); +isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmp), false); +isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcmt), false); if (env->misa_mxl != MXL_RV32) { -object_property_set_bool(obj, "zcf", false, NULL); +isa_ext_update_enabled(cpu, CPU_CFG_OFFSET(ext_zcf), false); } } -- 2.41.0
[PATCH RESEND v8 11/20] avocado, risc-v: add opensbi tests for 'max' CPU
Add smoke tests to ensure that we'll not break the 'max' CPU type when adding new ratified extensions to be enabled. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- tests/avocado/riscv_opensbi.py | 16 1 file changed, 16 insertions(+) diff --git a/tests/avocado/riscv_opensbi.py b/tests/avocado/riscv_opensbi.py index bfff9cc3c3..15fd57fe51 100644 --- a/tests/avocado/riscv_opensbi.py +++ b/tests/avocado/riscv_opensbi.py @@ -61,3 +61,19 @@ def test_riscv64_virt(self): :avocado: tags=machine:virt """ self.boot_opensbi() + +def test_riscv32_virt_maxcpu(self): +""" +:avocado: tags=arch:riscv32 +:avocado: tags=machine:virt +:avocado: tags=cpu:max +""" +self.boot_opensbi() + +def test_riscv64_virt_maxcpu(self): +""" +:avocado: tags=arch:riscv64 +:avocado: tags=machine:virt +:avocado: tags=cpu:max +""" +self.boot_opensbi() -- 2.41.0
[PATCH RESEND v8 02/20] target/riscv/cpu.c: skip 'bool' check when filtering KVM props
After the introduction of riscv_cpu_options[] all properties in riscv_cpu_extensions[] are booleans. This check is now obsolete. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 14 -- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6a4f95991d..6aac3ba1d1 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1970,17 +1970,11 @@ static void riscv_cpu_add_user_properties(Object *obj) * Set the default to disabled for every extension * unknown to KVM and error out if the user attempts * to enable any of them. - * - * We're giving a pass for non-bool properties since they're - * not related to the availability of extensions and can be - * safely ignored as is. */ -if (prop->info == _prop_bool) { -object_property_add(obj, prop->name, "bool", -NULL, cpu_set_cfg_unavailable, -NULL, (void *)prop->name); -continue; -} +object_property_add(obj, prop->name, "bool", +NULL, cpu_set_cfg_unavailable, +NULL, (void *)prop->name); +continue; } #endif qdev_property_add_static(dev, prop); -- 2.41.0
[PATCH RESEND v8 06/20] target/riscv/cpu.c: split vendor exts from riscv_cpu_extensions[]
Our goal is to make riscv_cpu_extensions[] hold only ratified, non-vendor extensions. Create a new riscv_cpu_vendor_exts[] array for them, changing riscv_cpu_add_user_properties() and riscv_cpu_add_kvm_properties() accordingly. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 13 - 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 78eb2ac6bd..668522db01 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1860,7 +1860,10 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("zcmp", RISCVCPU, cfg.ext_zcmp, false), DEFINE_PROP_BOOL("zcmt", RISCVCPU, cfg.ext_zcmt, false), -/* Vendor-specific custom extensions */ +DEFINE_PROP_END_OF_LIST(), +}; + +static Property riscv_cpu_vendor_exts[] = { DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false), DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false), DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false), @@ -1973,6 +1976,10 @@ static void riscv_cpu_add_kvm_properties(Object *obj) riscv_cpu_add_kvm_unavail_prop(obj, prop->name); } +for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) { +riscv_cpu_add_kvm_unavail_prop(obj, prop->name); +} + for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) { riscv_cpu_add_kvm_unavail_prop(obj, prop->name); } @@ -2017,6 +2024,10 @@ static void riscv_cpu_add_user_properties(Object *obj) qdev_property_add_static(dev, prop); } +for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) { +qdev_property_add_static(dev, prop); +} + for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) { qdev_property_add_static(dev, prop); } -- 2.41.0
[PATCH RESEND v8 10/20] target/riscv: add 'max' CPU type
The 'max' CPU type is used by tooling to determine what's the most capable CPU a current QEMU version implements. Other archs such as ARM implements this type. Let's add it to RISC-V. What we consider "most capable CPU" in this context are related to ratified, non-vendor extensions. This means that we want the 'max' CPU to enable all (possible) ratified extensions by default. The reasoning behind this design is (1) vendor extensions can conflict with each other and we won't play favorities deciding which one is default or not and (2) non-ratified extensions are always prone to changes, not being stable enough to be enabled by default. All this said, we're still not able to enable all ratified extensions due to conflicts between them. Zfinx and all its dependencies aren't enabled because of a conflict with RVF. zce, zcmp and zcmt are also disabled due to RVD conflicts. When running with 64 bits we're also disabling zcf. MISA bits RVG, RVJ and RVV are also being set manually since they're default disabled. This is the resulting 'riscv,isa' DT for this new CPU: rv64imafdcvh_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_ zfh_zfhmin_zca_zcb_zcd_zba_zbb_zbc_zbkb_zbkc_zbkx_zbs_zk_zkn_zknd_ zkne_zknh_zkr_zks_zksed_zksh_zkt_zve32f_zve64f_zve64d_ smstateen_sscofpmf_sstc_svadu_svinval_svnapot_svpbmt Signed-off-by: Daniel Henrique Barboza Reviewed-by: Weiwei Li Reviewed-by: Alistair Francis --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 56 ++ 2 files changed, 57 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 04af50983e..f3fbe37a2c 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -30,6 +30,7 @@ #define CPU_RESOLVING_TYPE TYPE_RISCV_CPU #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any") +#define TYPE_RISCV_CPU_MAX RISCV_CPU_TYPE_NAME("max") #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 5eb2d7f6da..8dc85f75bb 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -259,6 +259,7 @@ static const char * const riscv_intr_names[] = { }; static void riscv_cpu_add_user_properties(Object *obj); +static void riscv_init_max_cpu_extensions(Object *obj); const char *riscv_cpu_get_trap_name(target_ulong cause, bool async) { @@ -396,6 +397,25 @@ static void riscv_any_cpu_init(Object *obj) cpu->cfg.pmp = true; } +static void riscv_max_cpu_init(Object *obj) +{ +RISCVCPU *cpu = RISCV_CPU(obj); +CPURISCVState *env = >env; +RISCVMXL mlx = MXL_RV64; + +#ifdef TARGET_RISCV32 +mlx = MXL_RV32; +#endif +set_misa(env, mlx, 0); +riscv_cpu_add_user_properties(obj); +riscv_init_max_cpu_extensions(obj); +env->priv_ver = PRIV_VERSION_LATEST; +#ifndef CONFIG_USER_ONLY +set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ? +VM_1_10_SV32 : VM_1_10_SV57); +#endif +} + #if defined(TARGET_RISCV64) static void rv64_base_cpu_init(Object *obj) { @@ -2027,6 +2047,41 @@ static void riscv_cpu_add_user_properties(Object *obj) riscv_cpu_add_qdev_prop_array(dev, riscv_cpu_experimental_exts); } +/* + * The 'max' type CPU will have all possible ratified + * non-vendor extensions enabled. + */ +static void riscv_init_max_cpu_extensions(Object *obj) +{ +RISCVCPU *cpu = RISCV_CPU(obj); +CPURISCVState *env = >env; +Property *prop; + +/* Enable RVG, RVJ and RVV that are disabled by default */ +set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV); + +for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { +object_property_set_bool(obj, prop->name, true, NULL); +} + +/* set vector version */ +env->vext_ver = VEXT_VERSION_1_00_0; + +/* Zfinx is not compatible with F. Disable it */ +object_property_set_bool(obj, "zfinx", false, NULL); +object_property_set_bool(obj, "zdinx", false, NULL); +object_property_set_bool(obj, "zhinx", false, NULL); +object_property_set_bool(obj, "zhinxmin", false, NULL); + +object_property_set_bool(obj, "zce", false, NULL); +object_property_set_bool(obj, "zcmp", false, NULL); +object_property_set_bool(obj, "zcmt", false, NULL); + +if (env->misa_mxl != MXL_RV32) { +object_property_set_bool(obj, "zcf", false, NULL); +} +} + static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true), @@ -2365,6 +2420,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { .abstract = true, }, DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), +DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, riscv_max_cpu_init), #if defined(CONFIG_KVM) DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init),
[PATCH RESEND v8 05/20] target/riscv/cpu.c: split non-ratified exts from riscv_cpu_extensions[]
Create a new riscv_cpu_experimental_exts[] to store the non-ratified extensions properties. Once they are ratified we'll move them back to riscv_cpu_extensions[]. riscv_cpu_add_user_properties() and riscv_cpu_add_kvm_properties() are changed to keep adding non-ratified properties to users. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 14 +- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 272edaadf0..78eb2ac6bd 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1874,7 +1874,11 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false), DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false), -/* These are experimental so mark with 'x-' */ +DEFINE_PROP_END_OF_LIST(), +}; + +/* These are experimental so mark with 'x-' */ +static Property riscv_cpu_experimental_exts[] = { DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false), /* ePMP 0.9.3 */ @@ -1969,6 +1973,10 @@ static void riscv_cpu_add_kvm_properties(Object *obj) riscv_cpu_add_kvm_unavail_prop(obj, prop->name); } +for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) { +riscv_cpu_add_kvm_unavail_prop(obj, prop->name); +} + for (prop = riscv_cpu_options; prop && prop->name; prop++) { /* Check if KVM created the property already */ if (object_property_find(obj, prop->name)) { @@ -2008,6 +2016,10 @@ static void riscv_cpu_add_user_properties(Object *obj) for (prop = riscv_cpu_options; prop && prop->name; prop++) { qdev_property_add_static(dev, prop); } + +for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) { +qdev_property_add_static(dev, prop); +} } static Property riscv_cpu_properties[] = { -- 2.41.0
[PATCH RESEND v8 20/20] target/riscv/cpu.c: consider user option with RVG
Enabling RVG will enable a set of extensions that we're not checking if the user was okay enabling or not. And in this case we want to error out, instead of ignoring, otherwise we will be inconsistent enabling RVG without all its extensions. After this patch, disabling ifencei or icsr while enabling RVG will result in error: $ ./build/qemu-system-riscv64 -M virt -cpu rv64,g=true,Zifencei=false --nographic qemu-system-riscv64: warning: Setting G will also set IMAFD_Zicsr_Zifencei qemu-system-riscv64: RVG requires Zifencei but user set Zifencei to false Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 18 -- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index e07b2c73e7..21ebdbf084 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1155,8 +1155,22 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) riscv_has_ext(env, RVD) && cpu->cfg.ext_icsr && cpu->cfg.ext_ifencei)) { warn_report("Setting G will also set IMAFD_Zicsr_Zifencei"); -cpu->cfg.ext_icsr = true; -cpu->cfg.ext_ifencei = true; + +if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_icsr)) && +!cpu->cfg.ext_icsr) { +error_setg(errp, "RVG requires Zicsr but user set Zicsr to false"); +return; +} + +if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_ifencei)) && +!cpu->cfg.ext_ifencei) { +error_setg(errp, "RVG requires Zifencei but user set " + "Zifencei to false"); +return; +} + +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_icsr), true); +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_ifencei), true); env->misa_ext |= RVI | RVM | RVA | RVF | RVD; env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD; -- 2.41.0
[PATCH RESEND v8 15/20] target/riscv/cpu.c: introduce cpu_cfg_ext_auto_update()
During realize() time we're activating a lot of extensions based on some criteria, e.g.: if (cpu->cfg.ext_zk) { cpu->cfg.ext_zkn = true; cpu->cfg.ext_zkr = true; cpu->cfg.ext_zkt = true; } This practice resulted in at least one case where we ended up enabling something we shouldn't: RVC enabling zca/zcd/zcf when using a CPU that has priv_spec older than 1.12.0. We're also not considering user choice. There's no way of doing it now but this is about to change in the next few patches. cpu_cfg_ext_auto_update() will check for priv version mismatches before enabling extensions. If we have a mismatch between the current priv version and the extension we want to enable, do not enable it. In the near future, this same function will also consider user choice when deciding if we're going to enable/disable an extension or not. For now let's use it to handle zca/zcd/zcf enablement if RVC is enabled. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 44 +--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ddbf82f859..c56abf8395 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -177,6 +177,44 @@ static void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, *ext_enabled = en; } +static int cpu_cfg_ext_get_min_version(uint32_t ext_offset) +{ +int i; + +for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) { +if (isa_edata_arr[i].ext_enable_offset != ext_offset) { +continue; +} + +return isa_edata_arr[i].min_version; +} + +/* Default to oldest priv spec if no match found */ +return PRIV_VERSION_1_10_0; +} + +static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset, +bool value) +{ +CPURISCVState *env = >env; +bool prev_val = isa_ext_is_enabled(cpu, ext_offset); +int min_version; + +if (prev_val == value) { +return; +} + +if (value && env->priv_ver != PRIV_VERSION_LATEST) { +/* Do not enable it if priv_ver is older than min_version */ +min_version = cpu_cfg_ext_get_min_version(ext_offset); +if (env->priv_ver < min_version) { +return; +} +} + +isa_ext_update_enabled(cpu, ext_offset, value); +} + const char * const riscv_int_regnames[] = { "x0/zero", "x1/ra", "x2/sp", "x3/gp", "x4/tp", "x5/t0", "x6/t1", "x7/t2", "x8/s0", "x9/s1", "x10/a0", "x11/a1", "x12/a2", "x13/a3", @@ -1268,12 +1306,12 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) /* zca, zcd and zcf has a PRIV 1.12.0 restriction */ if (riscv_has_ext(env, RVC) && env->priv_ver >= PRIV_VERSION_1_12_0) { -cpu->cfg.ext_zca = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zca), true); if (riscv_has_ext(env, RVF) && env->misa_mxl_max == MXL_RV32) { -cpu->cfg.ext_zcf = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcf), true); } if (riscv_has_ext(env, RVD)) { -cpu->cfg.ext_zcd = true; +cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zcd), true); } } -- 2.41.0
[PATCH RESEND v8 03/20] target/riscv/cpu.c: split kvm prop handling to its own helper
Future patches will split the existing Property arrays even further, and the existing code in riscv_cpu_add_user_properties() will start to scale bad with it because it's dealing with KVM constraints mixed in with TCG constraints. We're going to pay a high price to share a couple of common lines of code between the two. Create a new riscv_cpu_add_kvm_properties() that will be forked from riscv_cpu_add_user_properties() if we're running KVM. The helper includes all properties that a KVM CPU will add. The rest of riscv_cpu_add_user_properties() body will then be relieved from having to deal with KVM constraints. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Weiwei Li Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 65 ++ 1 file changed, 42 insertions(+), 23 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6aac3ba1d1..a51b946804 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1937,6 +1937,46 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, } #endif +#ifndef CONFIG_USER_ONLY +static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) +{ +/* Check if KVM created the property already */ +if (object_property_find(obj, prop_name)) { +return; +} + +/* + * Set the default to disabled for every extension + * unknown to KVM and error out if the user attempts + * to enable any of them. + */ +object_property_add(obj, prop_name, "bool", +NULL, cpu_set_cfg_unavailable, +NULL, (void *)prop_name); +} + +static void riscv_cpu_add_kvm_properties(Object *obj) +{ +Property *prop; +DeviceState *dev = DEVICE(obj); + +kvm_riscv_init_user_properties(obj); +riscv_cpu_add_misa_properties(obj); + +for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { +riscv_cpu_add_kvm_unavail_prop(obj, prop->name); +} + +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { +/* Check if KVM created the property already */ +if (object_property_find(obj, riscv_cpu_options[i].name)) { +continue; +} +qdev_property_add_static(dev, _cpu_options[i]); +} +} +#endif + /* * Add CPU properties with user-facing flags. * @@ -1952,39 +1992,18 @@ static void riscv_cpu_add_user_properties(Object *obj) riscv_add_satp_mode_properties(obj); if (kvm_enabled()) { -kvm_riscv_init_user_properties(obj); +riscv_cpu_add_kvm_properties(obj); +return; } #endif riscv_cpu_add_misa_properties(obj); for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { -#ifndef CONFIG_USER_ONLY -if (kvm_enabled()) { -/* Check if KVM created the property already */ -if (object_property_find(obj, prop->name)) { -continue; -} - -/* - * Set the default to disabled for every extension - * unknown to KVM and error out if the user attempts - * to enable any of them. - */ -object_property_add(obj, prop->name, "bool", -NULL, cpu_set_cfg_unavailable, -NULL, (void *)prop->name); -continue; -} -#endif qdev_property_add_static(dev, prop); } for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { -/* Check if KVM created the property already */ -if (object_property_find(obj, riscv_cpu_options[i].name)) { -continue; -} qdev_property_add_static(dev, _cpu_options[i]); } } -- 2.41.0
[PATCH RESEND v8 09/20] target/riscv/cpu.c: limit cfg->vext_spec log message
Inside riscv_cpu_validate_v() we're always throwing a log message if the user didn't set a vector version via 'vext_spec'. We're going to include one case with the 'max' CPU where env->vext_ver will be set in the cpu_init(). But that alone will not stop the "vector version is not specified" message from appearing. The usefulness of this log message is debatable for the generic CPUs, but for a 'max' CPU type, where we are supposed to deliver a CPU model with all features possible, it's strange to force users to set 'vext_spec' to get rid of this message. Change riscv_cpu_validate_v() to not throw this log message if env->vext_ver is already set. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Reviewed-by: Weiwei Li --- target/riscv/cpu.c | 9 - 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d78c2c058f..5eb2d7f6da 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -959,8 +959,6 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg, Error **errp) { -int vext_version = VEXT_VERSION_1_00_0; - if (!is_power_of_2(cfg->vlen)) { error_setg(errp, "Vector extension VLEN must be power of 2"); return; @@ -983,17 +981,18 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg, } if (cfg->vext_spec) { if (!g_strcmp0(cfg->vext_spec, "v1.0")) { -vext_version = VEXT_VERSION_1_00_0; +env->vext_ver = VEXT_VERSION_1_00_0; } else { error_setg(errp, "Unsupported vector spec version '%s'", cfg->vext_spec); return; } -} else { +} else if (env->vext_ver == 0) { qemu_log("vector version is not specified, " "use the default value v1.0\n"); + +env->vext_ver = VEXT_VERSION_1_00_0; } -env->vext_ver = vext_version; } static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp) -- 2.41.0
[PATCH RESEND v8 17/20] target/riscv/cpu.c: introduce RISCVCPUMultiExtConfig
If we want to make better decisions when auto-enabling extensions during realize() we need a way to tell if an user set an extension manually. The RISC-V KVM driver has its own solution via a KVMCPUConfig struct that has an 'user_set' flag that is set during the Property set() callback. The set() callback also does init() time validations based on the current KVM driver capabilities. For TCG we would want a 'user_set' mechanic too, but we would look ad-hoc via cpu_cfg_ext_auto_update() if a certain extension was user set or not. If we copy what was made in the KVM side we would look for 'user_set' for one into 60+ extension structs spreaded in 3 arrays (riscv_cpu_extensions, riscv_cpu_experimental_exts, riscv_cpu_vendor_exts). We'll still need an extension struct but we won't be using the 'user_set' flag: - 'RISCVCPUMultiExtConfig' will be our specialized structure, similar to what we're already doing with the MISA extensions in 'RISCVCPUMisaExtConfig'. DEFINE_PROP_BOOL() for all 3 extensions arrays were replaced by MULTI_EXT_CFG_BOOL(), a macro that will init our specialized struct; - the 'multi_ext_user_opts' hash will be used to store the offset of each extension that the user set via the set() callback, cpu_set_multi_ext_cfg(). For now we're just initializing and populating it - next patch will use it to determine if a certain extension was user set; - cpu_add_multi_ext_prop() is a new helper that will replace the qdev_property_add_static() calls that our macros are doing to populate user properties. The macro was renamed to ADD_CPU_MULTIEXT_PROPS_ARRAY() for clarity. Note that the non-extension properties in riscv_cpu_options[] still need to be declared via qdev(). Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 257 - 1 file changed, 158 insertions(+), 99 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 0fe2ce0add..adfe671bd4 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -162,6 +162,9 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps), }; +/* Hash that stores user set extensions */ +static GHashTable *multi_ext_user_opts; + static bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset) { bool *ext_enabled = (void *)>cfg + ext_offset; @@ -1713,6 +1716,8 @@ static void riscv_cpu_init(Object *obj) qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq, IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX); #endif /* CONFIG_USER_ONLY */ + +multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); } typedef struct RISCVCPUMisaExtConfig { @@ -1864,109 +1869,118 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) } } -static Property riscv_cpu_extensions[] = { +typedef struct RISCVCPUMultiExtConfig { +const char *name; +uint32_t offset; +bool enabled; +} RISCVCPUMultiExtConfig; + +#define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \ +{.name = _name, .offset = CPU_CFG_OFFSET(_prop), \ + .enabled = _defval} + +static RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { /* Defaults for standard extensions */ -DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false), -DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), -DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), -DEFINE_PROP_BOOL("Zihintntl", RISCVCPU, cfg.ext_zihintntl, true), -DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true), -DEFINE_PROP_BOOL("Zawrs", RISCVCPU, cfg.ext_zawrs, true), -DEFINE_PROP_BOOL("Zfa", RISCVCPU, cfg.ext_zfa, true), -DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false), -DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false), -DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false), -DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false), -DEFINE_PROP_BOOL("Zve64d", RISCVCPU, cfg.ext_zve64d, false), -DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true), - -DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, false), -DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true), -DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false), -DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false), -DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false), - -DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true), -DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true), -DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true), -DEFINE_PROP_BOOL("zbkb", RISCVCPU, cfg.ext_zbkb, false), -DEFINE_PROP_BOOL("zbkc", RISCVCPU, cfg.ext_zbkc, false), -DEFINE_PROP_BOOL("zbkx", RISCVCPU, cfg.ext_zbkx, false), -DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true), -DEFINE_PROP_BOOL("zk", RISCVCPU, cfg.ext_zk, false), -DEFINE_PROP_BOOL("zkn", RISCVCPU, cfg.ext_zkn, false), -
[PATCH RESEND v8 01/20] target/riscv/cpu.c: split CPU options from riscv_cpu_extensions[]
We'll add a new CPU type that will enable a considerable amount of extensions. To make it easier for us we'll do a few cleanups in our existing riscv_cpu_extensions[] array. Start by splitting all CPU non-boolean options from it. Create a new riscv_cpu_options[] array for them. Add all these properties in riscv_cpu_add_user_properties() as it is already being done today. 'mmu' and 'pmp' aren't really extensions in the usual way we think about RISC-V extensions. These are closer to CPU features/options, so move both to riscv_cpu_options[] too. In the near future we'll need to match all extensions with all entries in isa_edata_arr[], and so it happens that both 'mmu' and 'pmp' do not have a riscv,isa string (thus, no priv spec version restriction). This further emphasizes the point that these are more a CPU option than an extension. No functional changes made. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Weiwei Li Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 33 +++-- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 34ac26e3ae..6a4f95991d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1804,7 +1804,6 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) static Property riscv_cpu_extensions[] = { /* Defaults for standard extensions */ -DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), @@ -1817,15 +1816,8 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false), DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false), DEFINE_PROP_BOOL("Zve64d", RISCVCPU, cfg.ext_zve64d, false), -DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), -DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true), -DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), -DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), -DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), -DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), - DEFINE_PROP_BOOL("smstateen", RISCVCPU, cfg.ext_smstateen, false), DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true), DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false), @@ -1856,9 +1848,7 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("zhinxmin", RISCVCPU, cfg.ext_zhinxmin, false), DEFINE_PROP_BOOL("zicbom", RISCVCPU, cfg.ext_icbom, true), -DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64), DEFINE_PROP_BOOL("zicboz", RISCVCPU, cfg.ext_icboz, true), -DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64), DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false), @@ -1912,6 +1902,21 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_END_OF_LIST(), }; +static Property riscv_cpu_options[] = { +DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), + +DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), +DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true), + +DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), +DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), + +DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), +DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), + +DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64), +DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64), +}; #ifndef CONFIG_USER_ONLY static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, @@ -1980,6 +1985,14 @@ static void riscv_cpu_add_user_properties(Object *obj) #endif qdev_property_add_static(dev, prop); } + +for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { +/* Check if KVM created the property already */ +if (object_property_find(obj, riscv_cpu_options[i].name)) { +continue; +} +qdev_property_add_static(dev, _cpu_options[i]); +} } static Property riscv_cpu_properties[] = { -- 2.41.0
[PATCH RESEND v8 00/20] riscv: 'max' CPU, detect user choice in TCG
Hi, This is a resend of these two patch sets because they no longer apply into Alistair's riscv-to-apply.next: [PATCH v8 00/12] riscv: add 'max' CPU, deprecate 'any' https://lore.kernel.org/qemu-riscv/20230815223741.433763-1-dbarb...@ventanamicro.com/ [PATCH v3 0/8] riscv: detecting user choice in TCG extensions https://lore.kernel.org/qemu-riscv/20230815224733.434682-1-dbarb...@ventanamicro.com/ They're being sent in a single package for convenience. No other changes made from their old versions aside from the rebase. Patches missing acks: 4,7,8 Changes from v7: - patch 7: - add riscv_cpu_add_qdev_prop_array() function instead of a macro - patch 8: - add riscv_cpu_add_kvm_unavail_prop_array() function instead of a macro - v7 link: https://lore.kernel.org/qemu-riscv/20230815201559.398643-1-dbarb...@ventanamicro.com/ Daniel Henrique Barboza (20): target/riscv/cpu.c: split CPU options from riscv_cpu_extensions[] target/riscv/cpu.c: skip 'bool' check when filtering KVM props target/riscv/cpu.c: split kvm prop handling to its own helper target/riscv: add DEFINE_PROP_END_OF_LIST() to riscv_cpu_options[] target/riscv/cpu.c: split non-ratified exts from riscv_cpu_extensions[] target/riscv/cpu.c: split vendor exts from riscv_cpu_extensions[] target/riscv/cpu.c: add riscv_cpu_add_qdev_prop_array() target/riscv/cpu.c: add riscv_cpu_add_kvm_unavail_prop_array() target/riscv/cpu.c: limit cfg->vext_spec log message target/riscv: add 'max' CPU type avocado, risc-v: add opensbi tests for 'max' CPU target/riscv: deprecate the 'any' CPU type target/riscv/cpu.c: use offset in isa_ext_is_enabled/update_enabled target/riscv: make CPUCFG() macro public target/riscv/cpu.c: introduce cpu_cfg_ext_auto_update() target/riscv/cpu.c: use cpu_cfg_ext_auto_update() during realize() target/riscv/cpu.c: introduce RISCVCPUMultiExtConfig target/riscv: use isa_ext_update_enabled() in init_max_cpu_extensions() target/riscv/cpu.c: honor user choice in cpu_cfg_ext_auto_update() target/riscv/cpu.c: consider user option with RVG docs/about/deprecated.rst | 12 + target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 555 +++-- target/riscv/cpu.h | 2 + target/riscv/kvm.c | 8 +- tests/avocado/riscv_opensbi.py | 16 + 6 files changed, 425 insertions(+), 169 deletions(-) -- 2.41.0
[PATCH RESEND v8 08/20] target/riscv/cpu.c: add riscv_cpu_add_kvm_unavail_prop_array()
Use a helper in riscv_cpu_add_kvm_properties() to eliminate some of its code repetition. Signed-off-by: Daniel Henrique Barboza --- target/riscv/cpu.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 4608fa2378..d78c2c058f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1971,6 +1971,14 @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) NULL, (void *)prop_name); } +static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj, + Property *array) +{ +for (Property *prop = array; prop && prop->name; prop++) { +riscv_cpu_add_kvm_unavail_prop(obj, prop->name); +} +} + static void riscv_cpu_add_kvm_properties(Object *obj) { Property *prop; @@ -1979,17 +1987,9 @@ static void riscv_cpu_add_kvm_properties(Object *obj) kvm_riscv_init_user_properties(obj); riscv_cpu_add_misa_properties(obj); -for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { -riscv_cpu_add_kvm_unavail_prop(obj, prop->name); -} - -for (prop = riscv_cpu_vendor_exts; prop && prop->name; prop++) { -riscv_cpu_add_kvm_unavail_prop(obj, prop->name); -} - -for (prop = riscv_cpu_experimental_exts; prop && prop->name; prop++) { -riscv_cpu_add_kvm_unavail_prop(obj, prop->name); -} +riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions); +riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_vendor_exts); +riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts); for (prop = riscv_cpu_options; prop && prop->name; prop++) { /* Check if KVM created the property already */ -- 2.41.0
[PATCH RESEND v8 04/20] target/riscv: add DEFINE_PROP_END_OF_LIST() to riscv_cpu_options[]
Add DEFINE_PROP_END_OF_LIST() and eliminate the ARRAY_SIZE() usage when iterating in the riscv_cpu_options[] array, making it similar to what we already do when working with riscv_cpu_extensions[]. We also have a more sophisticated motivation behind this change. In the future we might need to export riscv_cpu_options[] to other files, and ARRAY_LIST() doesn't work properly in that case because the array size isn't exposed to the header file. Here's a future sight of what we would deal with: ./target/riscv/kvm.c:1057:5: error: nested extern declaration of 'riscv_cpu_add_misa_properties' [-Werror=nested-externs] n file included from ../target/riscv/kvm.c:19: home/danielhb/work/qemu/include/qemu/osdep.h:473:31: error: invalid application of 'sizeof' to incomplete type 'const RISCVCPUMultiExtConfig[]' 473 | #define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \ | ^ ./target/riscv/kvm.c:1047:29: note: in expansion of macro 'ARRAY_SIZE' 1047 | for (int i = 0; i < ARRAY_SIZE(_array); i++) { \ | ^~ ./target/riscv/kvm.c:1059:5: note: in expansion of macro 'ADD_UNAVAIL_KVM_PROP_ARRAY' 1059 | ADD_UNAVAIL_KVM_PROP_ARRAY(obj, riscv_cpu_extensions); | ^~ home/danielhb/work/qemu/include/qemu/osdep.h:473:31: error: invalid application of 'sizeof' to incomplete type 'const RISCVCPUMultiExtConfig[]' 473 | #define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])) + \ | ^ ./target/riscv/kvm.c:1047:29: note: in expansion of macro 'ARRAY_SIZE' 1047 | for (int i = 0; i < ARRAY_SIZE(_array); i++) { \ Homogenize the present and change the future by using DEFINE_PROP_END_OF_LIST() in riscv_cpu_options[]. Signed-off-by: Daniel Henrique Barboza --- target/riscv/cpu.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index a51b946804..272edaadf0 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1916,6 +1916,8 @@ static Property riscv_cpu_options[] = { DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64), DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64), + +DEFINE_PROP_END_OF_LIST(), }; #ifndef CONFIG_USER_ONLY @@ -1967,12 +1969,12 @@ static void riscv_cpu_add_kvm_properties(Object *obj) riscv_cpu_add_kvm_unavail_prop(obj, prop->name); } -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { +for (prop = riscv_cpu_options; prop && prop->name; prop++) { /* Check if KVM created the property already */ -if (object_property_find(obj, riscv_cpu_options[i].name)) { +if (object_property_find(obj, prop->name)) { continue; } -qdev_property_add_static(dev, _cpu_options[i]); +qdev_property_add_static(dev, prop); } } #endif @@ -2003,8 +2005,8 @@ static void riscv_cpu_add_user_properties(Object *obj) qdev_property_add_static(dev, prop); } -for (int i = 0; i < ARRAY_SIZE(riscv_cpu_options); i++) { -qdev_property_add_static(dev, _cpu_options[i]); +for (prop = riscv_cpu_options; prop && prop->name; prop++) { +qdev_property_add_static(dev, prop); } } -- 2.41.0
Re: [PATCH V3 00/10] fix migration of suspended runstate
On 8/17/2023 2:23 PM, Peter Xu wrote: > On Mon, Aug 14, 2023 at 11:54:26AM -0700, Steve Sistare wrote: >> Migration of a guest in the suspended runstate is broken. The incoming >> migration code automatically tries to wake the guest, which is wrong; >> the guest should end migration in the same runstate it started. Further, >> for a restored snapshot, the automatic wakeup fails. The runstate is >> RUNNING, but the guest is not. See the commit messages for the details. > > Hi Steve, > > I drafted two small patches to show what I meant, on top of this series. > Before applying these two, one needs to revert patch 1 in this series. > > After applied, it should also pass all three new suspend tests. We can > continue the discussion here based on the patches. Your 2 patches look good. I suggest we keep patch 1, and I squash patch 2 into the other patches. There is one more fix needed: on the sending side, if the state is suspended, then ticks must be disabled so the tick globals are updated before they are written to vmstate. Otherwise, tick starts at 0 in the receiver when cpu_enable_ticks is called. --- diff --git a/migration/migration.c b/migration/migration.c index b004475..89d56a8 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -63,6 +63,7 @@ #include "sysemu/cpus.h" #include "yank_functions.h" #include "sysemu/qtest.h" +#include "sysemu/cpu-timers.h" #include "options.h" #include "sysemu/dirtylimit.h" @@ -2125,6 +2126,9 @@ static int postcopy_start(MigrationState *ms, Error **errp trace_postcopy_start_set_run(); global_state_store(); +if (runstate_check(RUN_STATE_SUSPENDED)) { +cpu_disable_ticks(); +} ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); if (ret < 0) { goto fail; @@ -2333,6 +2337,9 @@ static void migration_completion(MigrationState *s) s->vm_old_state = runstate_get(); global_state_store(); +if (runstate_check(RUN_STATE_SUSPENDED)) { +cpu_disable_ticks(); +} ret = vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); trace_migration_completion_vm_stop(ret); if (ret >= 0) { diff --git a/migration/savevm.c b/migration/savevm.c index 7b9c477..eff6976 100644 --- a/migration/savevm.c +++ b/migration/savevm.c @@ -58,6 +58,7 @@ #include "qemu/cutils.h" #include "io/channel-buffer.h" #include "io/channel-file.h" +#include "sysemu/cpu-timers.h" #include "sysemu/replay.h" #include "sysemu/runstate.h" #include "sysemu/sysemu.h" @@ -2969,6 +2970,9 @@ bool save_snapshot(const char *name, bool overwrite, const saved_vm_running = runstate_is_running(); global_state_store(); +if (runstate_check(RUN_STATE_SUSPENDED)) { +cpu_disable_ticks(); +} vm_stop(RUN_STATE_SAVE_VM); bdrv_drain_all_begin(); @@ -3037,6 +3041,8 @@ bool save_snapshot(const char *name, bool overwrite, const if (saved_vm_running) { vm_start(); +} else if (runstate_check(RUN_STATE_SUSPENDED)) { +cpu_enable_ticks(); } return ret == 0; } --- - Steve
Re: [PATCH V3 01/10] vl: start on wakeup request
On 8/17/2023 2:27 PM, Peter Xu wrote: > On Mon, Aug 14, 2023 at 11:54:27AM -0700, Steve Sistare wrote: >> +void vm_wakeup(void) >> +{ >> +if (!vm_started) { >> +vm_start(); > > (irrelevant of the global var that I wanted to remove..) > > Calling vm_start() is wrong here, IMHO. > > I think we need to notify everyone on the wakeup before really waking up > the vcpus: > > notifier_list_notify(_notifiers, _reason); > > There's resume_all_vcpus() after that. I don't know the side effect of > resuming vcpus without such notifications, at least some acpi fields do not > seem to be updated so the vcpu can see stale values (acpi_notify_wakeup()). Agreed, good catch. - Steve >> +} else { >> +runstate_set(RUN_STATE_RUNNING); >> } >> } >
Re: [PATCH V1 2/3] migration: fix suspended runstate
On 8/17/2023 2:19 PM, Peter Xu wrote: > On Wed, Aug 16, 2023 at 01:48:13PM -0400, Steven Sistare wrote: >> On 8/14/2023 3:37 PM, Peter Xu wrote: >>> On Mon, Aug 14, 2023 at 02:53:56PM -0400, Steven Sistare wrote: > Can we just call vm_state_notify() earlier? We cannot. The guest is not running yet, and will not be until later. We cannot call notifiers that perform actions that complete, or react to, the guest entering a running state. >>> >>> I tried to look at a few examples of the notifees and most of them I read >>> do not react to "vcpu running" but "vm running" (in which case I think >>> "suspended" mode falls into "vm running" case); most of them won't care on >>> the RunState parameter passed in, but only the bool "running". >>> >>> In reality, when running=true, it must be RUNNING so far. >>> >>> In that case does it mean we should notify right after the switchover, >>> since after migration the vm is indeed running only if the vcpus are not >>> during suspend? >> >> I cannot parse your question, but maybe this answers it. >> If the outgoing VM is running and not suspended, then the incoming side >> tests for autostart==true and calls vm_start, which calls the notifiers, >> right after the switchover. > > I meant IMHO SUSPENDED should be seen as "vm running" case to me, just like > RUNNING. Then, we should invoke vm_prepare_start(), just need some touch > ups. > >> >>> One example (of possible issue) is vfio_vmstate_change(), where iiuc if we >>> try to suspend a VM it should keep to be VFIO_DEVICE_STATE_RUNNING for that >>> device; this kind of prove to me that SUSPEND is actually one of >>> running=true states. >>> >>> If we postpone all notifiers here even after we switched over to dest qemu >>> to the next upcoming suspend wakeup, I think it means these devices will >>> not be in VFIO_DEVICE_STATE_RUNNING after switchover but perhaps >>> VFIO_DEVICE_STATE_STOP. >> >> or VFIO_DEVICE_STATE_RESUMING, which is set in vfio_load_setup. >> AFAIK it is OK to remain in that state until wakeup is called later. > > So let me provide another clue of why I think we should call > vm_prepare_start().. > > Firstly, I think RESUME event should always be there right after we > switched over, no matter suspeneded or not. I just noticed that your test > case would work because you put "wakeup" to be before RESUME. I'm not sure > whether that's correct. I'd bet people could rely on that RESUME to > identify the switchover. Yes, possibly. > More importantly, I'm wondering whether RTC should still be running during > the suspended mode? Sorry again if my knowledge over there is just > limited, so correct me otherwise - but my understanding is during suspend > mode (s1 or s3, frankly I can't tell which one this belongs..), rtc should > still be running along with the system clock. It means we _should_ at > least call cpu_enable_ticks() to enable rtc: Agreed. The comment above cpu_get_ticks says: * return the time elapsed in VM between vm_start and vm_stop Suspending a guest does not call vm_stop, so ticks keeps running. I also verified that experimentally. > /* > * enable cpu_get_ticks() > * Caller must hold BQL which serves as mutex for vm_clock_seqlock. > */ > void cpu_enable_ticks(void) > > I think that'll enable cpu_get_tsc() and make it start to work right. > >> >>> Ideally I think we should here call vm_state_notify() with running=true and >>> state=SUSPEND, but since I do see some hooks are not well prepared for >>> SUSPEND over running=true, I'd think we should on the safe side call >>> vm_state_notify(running=true, state=RUNNING) even for SUSPEND at switch >>> over phase. With that IIUC it'll naturally work (e.g. when wakeup again >>> later we just need to call no notifiers). >> >> Notifiers are just one piece, all the code in vm_prepare_start must be >> called. >> Is it correct to call all of that long before we actually resume the CPUs in >> wakeup? I don't know, but what is the point? > > The point is not only for cleaness (again, I really, really don't like that > new global.. sorry), but also now I think we should make the vm running. I do believe it is safe to call vm_prepare_start immediately, since the vcpus are never running when it is called. >> The wakeup code still needs >> modification to conditionally resume the vcpus. The scheme would be roughly: >> >> loadvm_postcopy_handle_run_bh() >> runstat = global_state_get_runstate(); >> if (runstate == RUN_STATE_RUNNING) { >> vm_start() >> } else if (runstate == RUN_STATE_SUSPENDED) >> vm_prepare_start(); // the start of vm_start() >> } >> >> qemu_system_wakeup_request() >> if (some condition) >> resume_all_vcpus(); // the remainder of vm_start() >> else >> runstate_set(RUN_STATE_RUNNING) > > No it doesn't. wakeup_reason is set there, main loop does the resuming. > See: > > if
Re: [Qemu PATCH v2 9/9] hw/mem/cxl_type3: Add dpa range validation for accesses to dc regions
On Mon, Aug 07, 2023 at 09:53:42AM +0100, Jonathan Cameron wrote: > On Tue, 25 Jul 2023 18:39:56 + > Fan Ni wrote: > > > From: Fan Ni > > > > Not all dpa range in the dc regions is valid to access until an extent > > covering the range has been added. Add a bitmap for each region to > > record whether a dc block in the region has been backed by dc extent. > > For the bitmap, a bit in the bitmap represents a dc block. When a dc > > extent is added, all the bits of the blocks in the extent will be set, > > which will be cleared when the extent is released. > > > > Signed-off-by: Fan Ni > Hi Fan, > > A few of the bits of feedback apply broadly across the series. Given I'm > rebasing this anyway to give myself something to test I'll tidy things up > (feel free to disagree with and revert any changes !) > and push a tree out in next day or two. I'll message when I've done so. > > Jonathan Hi Jonathan, I tried DCD with your branch "cxl-2023-08-07", and noticed the following, 1. You made some changes to the bitmap functionality, now it is only used to validate extents when adding/releasing dc extents. My original thought of adding the bitmap is to 1) validating extents for extent add/release as you do; 2) Add validating when doing read/write to the dc regions since some address region may not have valid extent added yet. Do you think 2) is not necessary? 2. Your change introduced a bug in the code. https://gitlab.com/jic23/qemu/-/blob/cxl-2023-08-07/hw/cxl/cxl-mailbox-utils.c?ref_type=heads#L1394 ct3d->dc.num_regions should be ct3d->dc.num_regions-1. Thanks, Fan > > > --- > > hw/mem/cxl_type3.c | 155 > > include/hw/cxl/cxl_device.h | 1 + > > 2 files changed, 156 insertions(+) > > > > diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c > > index 41a828598a..51943a36fc 100644 > > --- a/hw/mem/cxl_type3.c > > +++ b/hw/mem/cxl_type3.c > > @@ -787,13 +787,37 @@ static int cxl_create_dc_regions(CXLType3Dev *ct3d) > > /* dsmad_handle is set when creating cdat table entries */ > > region->flags = 0; > > > > +region->blk_bitmap = bitmap_new(region->len / region->block_size); > > In common with many allocators in qemu if this fails it calls abort() > internally so no need to handle potential errors. > > > +if (!region->blk_bitmap) { > > +break; > > +} > > + > > region_base += region->len; > > } > > + > > +if (i < ct3d->dc.num_regions) { > > +while (--i >= 0) { > > +g_free(ct3d->dc.regions[i].blk_bitmap); > > +} > > +return -1; > > +} > > + > > QTAILQ_INIT(>dc.extents); > > > > return 0; > > } > > > > +static void cxl_destroy_dc_regions(CXLType3Dev *ct3d) > > +{ > > +int i; > > +struct CXLDCD_Region *region; > > + > > +for (i = 0; i < ct3d->dc.num_regions; i++) { > > +region = >dc.regions[i]; > > +g_free(region->blk_bitmap); > > +} > > +} > > + > > static bool cxl_setup_memory(CXLType3Dev *ct3d, Error **errp) > > { > > DeviceState *ds = DEVICE(ct3d); > > @@ -1021,6 +1045,7 @@ err_free_special_ops: > > g_free(regs->special_ops); > > err_address_space_free: > > if (ct3d->dc.host_dc) { > > +cxl_destroy_dc_regions(ct3d); > > address_space_destroy(>dc.host_dc_as); > > } > > if (ct3d->hostpmem) { > > @@ -1043,6 +1068,7 @@ static void ct3_exit(PCIDevice *pci_dev) > > spdm_sock_fini(ct3d->doe_spdm.socket); > > g_free(regs->special_ops); > > if (ct3d->dc.host_dc) { > > +cxl_destroy_dc_regions(ct3d); > > address_space_destroy(>dc.host_dc_as); > > } > > if (ct3d->hostpmem) { > > @@ -1053,6 +1079,110 @@ static void ct3_exit(PCIDevice *pci_dev) > > } > > } > > > > +/* > > + * This function will marked the dpa range [dpa, dap + len) to be backed > > and > > + * accessible, this happens when a dc extent is added and accepted by the > > + * host. > > + */ > > +static void set_region_block_backed(CXLType3Dev *ct3d, uint64_t dpa, > > +uint64_t len) > > +{ > > +int i; > > +CXLDCD_Region *region = >dc.regions[0]; > > + > > +if (dpa < region->base > > +|| dpa >= region->base + ct3d->dc.total_capacity) > > +return; > > + > > +/* > > + * spec 3.0 9.13.3: Regions are used in increasing-DPA order, with > > + * Region 0 being used for the lowest DPA of Dynamic Capacity and > > + * Region 7 for the highest DPA. > > + * So we check from the last region to find where the dpa belongs. > > + * access across multiple regions is not allowed. > > + **/ > > +for (i = ct3d->dc.num_regions - 1; i >= 0; i--) { > > +region = >dc.regions[i]; > > +if (dpa >= region->base) { > > +break; > > +} > > +} > > + > > +bitmap_set(region->blk_bitmap, (dpa - region->base) / > > region->block_size, > > +len / region->block_size); > > +} > >
[PATCH] qemu-nbd: Restore "qemu-nbd -v --fork" output
Closing stderr earlier is good for daemonized qemu-nbd under ssh earlier, but breaks the case where -v is being used to track what is happening in the server, as in iotest 233. When we know we are verbose, we do NOT want qemu_daemon to close stderr. For management purposes, we still need to temporarily override the daemon child's stderr with the pipe to the parent until after the pid file is created; but since qemu_daemon would normally set stdout to /dev/null had we not been verbose, we can use stdout as a place to stash our original stderr. Thus, whether normal or vebose, when the management handoff is complete, copying stdout back to stderr does the right thing for the rest of the life of the daemon child. Note that while the error messages expected by iotest 233 are now restored, the change in file descriptors means they now show up earlier in the testsuite output. Reported-by: Kevin Wolf CC: Denis V. Lunev CC: qemu-sta...@nongnu.org Fixes: 5c56dd27a2 ("qemu-nbd: fix regression with qemu-nbd --fork run over ssh") Signed-off-by: Eric Blake --- qemu-nbd.c | 21 - tests/qemu-iotests/233.out | 20 ++-- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/qemu-nbd.c b/qemu-nbd.c index aaccaa33184..a105094fb17 100644 --- a/qemu-nbd.c +++ b/qemu-nbd.c @@ -944,9 +944,24 @@ int main(int argc, char **argv) close(stderr_fd[0]); -ret = qemu_daemon(1, 0); +ret = qemu_daemon(1, verbose); saved_errno = errno;/* dup2 will overwrite error below */ +if (verbose) { +/* We want stdin at /dev/null when qemu_daemon didn't do it */ +stdin = freopen("/dev/null", "r", stdin); +if (stdin == NULL) { +error_report("Failed to redirect stdin: %s", + strerror(errno)); +exit(EXIT_FAILURE); +} +/* To keep the parent's stderr alive, copy it to stdout */ +if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) { +error_report("Failed to redirect stdout: %s", + strerror(errno)); +exit(EXIT_FAILURE); +} +} /* Temporarily redirect stderr to the parent's pipe... */ if (dup2(stderr_fd[1], STDERR_FILENO) < 0) { char str[256]; @@ -1180,6 +1195,10 @@ int main(int argc, char **argv) } if (fork_process) { +/* + * See above. If verbose is false, stdout is /dev/null (thanks + * to qemu_daemon); otherwise, stdout is the parent's stderr. + */ if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0) { error_report("Could not set stderr to /dev/null: %s", strerror(errno)); diff --git a/tests/qemu-iotests/233.out b/tests/qemu-iotests/233.out index 237c82767ea..b09a197020a 100644 --- a/tests/qemu-iotests/233.out +++ b/tests/qemu-iotests/233.out @@ -41,8 +41,10 @@ exports available: 1 min block: 1 == check TLS fail over TCP with mismatched hostname == +qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort qemu-img: Could not open 'driver=nbd,host=localhost,port=PORT,tls-creds=tls0': Certificate does not match the hostname localhost qemu-nbd: Certificate does not match the hostname localhost +qemu-nbd: option negotiation failed: Failed to read opts magic: Cannot read from TLS channel: Software caused connection abort == check TLS works over TCP with mismatched hostname and override == image: nbd://localhost:PORT @@ -55,7 +57,9 @@ exports available: 1 min block: 1 == check TLS with different CA fails == +qemu-nbd: option negotiation failed: Verify failed: No certificate was found. qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': The certificate hasn't got a known issuer +qemu-nbd: option negotiation failed: Verify failed: No certificate was found. qemu-nbd: The certificate hasn't got a known issuer == perform I/O over TLS == @@ -67,11 +71,15 @@ read 1048576/1048576 bytes at offset 1048576 1 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) == check TLS with authorization == +qemu-nbd: option negotiation failed: TLS x509 authz check for C=South Pacific,L=R'lyeh,O=Cthulhu Dark Lord Enterprises client1,CN=localhost is denied qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Failed to read option reply: Cannot read from TLS channel: Software caused connection abort +qemu-nbd: option negotiation failed: TLS x509 authz check for C=South Pacific,L=R'lyeh,O=Cthulhu Dark Lord Enterprises client3,CN=localhost is denied qemu-img: Could not open 'driver=nbd,host=127.0.0.1,port=PORT,tls-creds=tls0': Failed to read option reply: Cannot read from TLS channel: Software caused connection abort
Re: [PATCH] util/iov: Avoid dynamic stack allocation
On Thu, Aug 24, 2023 at 05:47:06PM +0100, Peter Maydell wrote: > From: Philippe Mathieu-Daudé > > Use autofree heap allocation instead of variable-length array on the > stack. > > The codebase has very few VLAs, and if we can get rid of them all we > can make the compiler error on new additions. This is a defensive > measure against security bugs where an on-stack dynamic allocation > isn't correctly size-checked (e.g. CVE-2021-3527). > > Signed-off-by: Philippe Mathieu-Daudé > Signed-off-by: Peter Maydell > --- > Usual "only tested with make check/make check-avocado" caveat. > > util/iov.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) Reviewed-by: Eric Blake > > diff --git a/util/iov.c b/util/iov.c > index 866fb577f30..7e73948f5e3 100644 > --- a/util/iov.c > +++ b/util/iov.c > @@ -571,7 +571,7 @@ static int sortelem_cmp_src_index(const void *a, const > void *b) > */ > void qemu_iovec_clone(QEMUIOVector *dest, const QEMUIOVector *src, void *buf) > { > -IOVectorSortElem sortelems[src->niov]; > +g_autofree IOVectorSortElem *sortelems = g_new(IOVectorSortElem, > src->niov); > void *last_end; > int i; > > -- > 2.34.1 > -- Eric Blake, Principal Software Engineer Red Hat, Inc. Virtualization: qemu.org | libguestfs.org
Re: [PATCH v2 12/12] gdbstub: move comment for gdb_register_coprocessor
On 8/24/23 09:39, Alex Bennée wrote: Use proper kdoc style comments for this API function. Signed-off-by: Alex Bennée --- include/exec/gdbstub.h | 10 ++ gdbstub/gdbstub.c | 6 -- 2 files changed, 10 insertions(+), 6 deletions(-) Reviewed-by: Richard Henderson r~
Re: [PATCH v2 11/12] gdbstub: replace global gdb_has_xml with a function
On 8/24/23 09:39, Alex Bennée wrote: Try and make the self reported global hack a little less hackish by providing a query function instead. As gdb_has_xml was always set if we negotiated XML we can now use the presence of ->target_xml as the test instead. Signed-off-by: Alex Bennée --- gdbstub/internals.h| 1 + include/exec/gdbstub.h | 10 +- gdbstub/gdbstub.c | 12 +++- gdbstub/softmmu.c | 1 - gdbstub/user.c | 1 - target/arm/gdbstub.c | 8 target/ppc/gdbstub.c | 4 ++-- 7 files changed, 19 insertions(+), 18 deletions(-) Reviewed-by: Richard Henderson r~
Re: [PATCH v2 10/12] gdbstub: refactor get_feature_xml
On 8/24/23 09:39, Alex Bennée wrote: Try to bring up the code to more modern standards by: - use dynamic GString built xml over a fixed buffer - use autofree to save on explicit g_free() calls - don't hand hack strstr to find the delimiter Signed-off-by: Alex Bennée --- v2 - avoid needless g_strndup for copy of annex --- gdbstub/internals.h | 2 +- gdbstub/gdbstub.c | 63 + 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/gdbstub/internals.h b/gdbstub/internals.h index f2b46cce41..4876ebd74f 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -33,7 +33,7 @@ typedef struct GDBProcess { uint32_t pid; bool attached; -char target_xml[1024]; +char *target_xml; } GDBProcess; enum RSState { diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 8e9bc17e07..31a2451f27 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -354,54 +354,51 @@ static CPUState *gdb_get_cpu(uint32_t pid, uint32_t tid) static const char *get_feature_xml(const char *p, const char **newp, GDBProcess *process) { -size_t len; int i; const char *name; CPUState *cpu = gdb_get_first_cpu_in_process(process); CPUClass *cc = CPU_GET_CLASS(cpu); -len = 0; -while (p[len] && p[len] != ':') -len++; -*newp = p + len; +/* ‘qXfer:features:read:annex:offset,length' */ This is misleading, because "...:read:" has already been consumed. +char *term = g_strstr_len(p, -1, ":"); This is strchr(p, ':'). +g_autofree char *annex = g_strndup(p, len); +/* leave newp at offset,length for the rest of the params */ +*newp = term + 1; -name = NULL; -if (strncmp(p, "target.xml", len) == 0) { -char *buf = process->target_xml; -const size_t buf_sz = sizeof(process->target_xml); -/* Generate the XML description for this CPU. */ -if (!buf[0]) { +name = NULL; +if (g_strcmp0(annex, "target.xml") == 0) { Why the change to g_strcmp0? There's no null pointer to be handled. If you keep the strncmp, you don't have to allocate memory early. if (cc->gdb_get_dynamic_xml) { -char *xmlname = g_strndup(p, len); -const char *xml = cc->gdb_get_dynamic_xml(cpu, xmlname); - -g_free(xmlname); +const char *xml = cc->gdb_get_dynamic_xml(cpu, annex); You can leave the g_strndup (and autofree) to here. r~
[PULL v2 00/48] tcg patch queue
Dangit, missed the PULL tag for v2. The only change is fixing Anton's --author. r~ On 8/24/23 11:28, Richard Henderson wrote: The following changes since commit 50e7a40af372ee5931c99ef7390f5d3d6fbf6ec4: Merge tag 'pull-target-arm-20230824' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2023-08-24 10:08:33 -0400) are available in the Git repository at: https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230823-2 for you to fetch changes up to 4daad8d9d6b9d426beb8ce505d2164ba36ea3168: tcg: spelling fixes (2023-08-24 11:22:42 -0700) accel/*: Widen pc/saved_insn for *_sw_breakpoint accel/tcg: Replace remaining target_ulong in system-mode accel tcg: spelling fixes tcg: Document bswap, hswap, wswap byte patterns tcg: Introduce negsetcond opcodes tcg: Fold deposit with zero to and tcg: Unify TCG_TARGET_HAS_extr[lh]_i64_i32 tcg/i386: Drop BYTEH deposits for 64-bit tcg/i386: Allow immediate as input to deposit target/*: Use tcg_gen_negsetcond_* Anton Johansson (9): accel/kvm: Widen pc/saved_insn for kvm_sw_breakpoint accel/hvf: Widen pc/saved_insn for hvf_sw_breakpoint sysemu/kvm: Use vaddr for kvm_arch_[insert|remove]_hw_breakpoint sysemu/hvf: Use vaddr for hvf_arch_[insert|remove]_hw_breakpoint include/exec: Replace target_ulong with abi_ptr in cpu_[st|ld]*() include/exec: typedef abi_ptr to vaddr in softmmu include/exec: Widen tlb_hit/tlb_hit_page() accel/tcg: Widen address arg in tlb_compare_set() accel/tcg: Update run_on_cpu_data static assert Mark Cave-Ayland (1): docs/devel/tcg-ops: fix missing newlines in "Host vector operations" Michael Tokarev (1): tcg: spelling fixes Philippe Mathieu-Daudé (9): docs/devel/tcg-ops: Bury mentions of trunc_shr_i64_i32() tcg/tcg-op: Document bswap16_i32() byte pattern tcg/tcg-op: Document bswap16_i64() byte pattern tcg/tcg-op: Document bswap32_i32() byte pattern tcg/tcg-op: Document bswap32_i64() byte pattern tcg/tcg-op: Document bswap64_i64() byte pattern tcg/tcg-op: Document hswap_i32/64() byte pattern tcg/tcg-op: Document wswap_i64() byte pattern target/cris: Fix a typo in gen_swapr() Richard Henderson (28): target/m68k: Use tcg_gen_deposit_i32 in gen_partset_reg tcg/i386: Drop BYTEH deposits for 64-bit tcg: Fold deposit with zero to and tcg/i386: Allow immediate as input to deposit_* tcg: Unify TCG_TARGET_HAS_extr[lh]_i64_i32 tcg: Introduce negsetcond opcodes tcg: Use tcg_gen_negsetcond_* target/alpha: Use tcg_gen_movcond_i64 in gen_fold_mzero target/arm: Use tcg_gen_negsetcond_* target/m68k: Use tcg_gen_negsetcond_* target/openrisc: Use tcg_gen_negsetcond_* target/ppc: Use tcg_gen_negsetcond_* target/sparc: Use tcg_gen_movcond_i64 in gen_edge target/tricore: Replace gen_cond_w with tcg_gen_negsetcond_tl tcg/ppc: Implement negsetcond_* tcg/ppc: Use the Set Boolean Extension tcg/aarch64: Implement negsetcond_* tcg/arm: Implement negsetcond_i32 tcg/riscv: Implement negsetcond_* tcg/s390x: Implement negsetcond_* tcg/sparc64: Implement negsetcond_* tcg/i386: Merge tcg_out_brcond{32,64} tcg/i386: Merge tcg_out_setcond{32,64} tcg/i386: Merge tcg_out_movcond{32,64} tcg/i386: Use CMP+SBB in tcg_out_setcond tcg/i386: Clear dest first in tcg_out_setcond if possible tcg/i386: Use shift in tcg_out_setcond tcg/i386: Implement negsetcond_* docs/devel/tcg-ops.rst | 15 +- accel/tcg/atomic_template.h| 16 +- include/exec/cpu-all.h | 4 +- include/exec/cpu_ldst.h| 28 +-- include/sysemu/hvf.h | 12 +- include/sysemu/kvm.h | 12 +- include/tcg/tcg-op-common.h| 4 + include/tcg/tcg-op.h | 2 + include/tcg/tcg-opc.h | 6 +- include/tcg/tcg.h | 4 +- tcg/aarch64/tcg-target.h | 5 +- tcg/arm/tcg-target.h | 1 + tcg/i386/tcg-target-con-set.h | 2 +- tcg/i386/tcg-target-con-str.h | 1 - tcg/i386/tcg-target.h | 9 +- tcg/loongarch64/tcg-target.h | 6 +- tcg/mips/tcg-target.h | 5 +- tcg/ppc/tcg-target.h | 5 +- tcg/riscv/tcg-target.h | 5 +- tcg/s390x/tcg-target.h | 5 +- tcg/sparc64/tcg-target.h | 5 +- tcg/tci/tcg-target.h | 5 +- accel/hvf/hvf-accel-ops.c | 4 +- accel/hvf
Re: [PATCH v7 00/12] Add VIRTIO sound card
Emmanouil Pitsidianakis writes: > This patch series adds an audio device implementing the recent virtio > sound spec (1.2) and a corresponding PCI wrapper device. > > v7 can be found online at: > > https://github.com/epilys/qemu-virtio-snd/tree/virtio-snd-v7 > > Main differences with v6 patch series [^v6] > : > > - Removed minor stale/duplicate code. > - Addressed [^v6] review comments. > Notably, the audio driver name is now `virtio` instead of > `virtio-sound`. > - Fixed some invalid pointer logic. > - Fixed minor typos and updated documentation. I'm seeing a bunch of CI failures: https://gitlab.com/stsquad/qemu/-/pipelines/979444077 Most of them will probably clear up when you fix the missing parameter names. -- Alex Bennée Virtualisation Tech Lead @ Linaro
Re: [PATCH v7 03/12] virtio-sound: handle control messages and streams
Emmanouil Pitsidianakis writes: > Receive guest requests in the control (CTRL) queue of the virtio sound > device and reply with a NOT SUPPORTED error to all control commands. > > The receiving handler is virtio_snd_handle_ctrl(). It stores all control > messages in the queue in the device's command queue. Then it calls > virtio_snd_process_cmdq() to handle each message. > > The handler is process_cmd() which replies with VIRTIO_SND_S_NOT_SUPP. > > Signed-off-by: Emmanouil Pitsidianakis > --- > hw/virtio/trace-events | 4 + > hw/virtio/virtio-snd.c | 227 - > include/hw/virtio/virtio-snd.h | 70 +- > 3 files changed, 292 insertions(+), 9 deletions(-) > > diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events > index 3ed7da35f2..8a223e36e9 100644 > --- a/hw/virtio/trace-events > +++ b/hw/virtio/trace-events > @@ -163,3 +163,7 @@ virtio_snd_vm_state_running(void) "vm state running" > virtio_snd_vm_state_stopped(void) "vm state stopped" > virtio_snd_realize(void *snd) "snd %p: realize" > virtio_snd_unrealize(void *snd) "snd %p: unrealize" > +virtio_snd_handle_ctrl(void *vdev, void *vq) "snd %p: handle ctrl event for > queue %p" > +virtio_snd_handle_code(uint32_t val, const char *code) "ctrl code msg val = > %"PRIu32" == %s" > +virtio_snd_handle_chmap_info(void) "VIRTIO_SND_CHMAP_INFO called" > +virtio_snd_handle_event(void) "event queue callback called" > diff --git a/hw/virtio/virtio-snd.c b/hw/virtio/virtio-snd.c > index 0498e660a5..b23f8040e1 100644 > --- a/hw/virtio/virtio-snd.c > +++ b/hw/virtio/virtio-snd.c > @@ -30,6 +30,29 @@ > #define VIRTIO_SOUND_CHMAP_DEFAULT 0 > #define VIRTIO_SOUND_HDA_FN_NID 0 > > +static const char *print_code(uint32_t code) > +{ > +#define CASE(CODE)\ > +case VIRTIO_SND_R_##CODE: \ > +return "VIRTIO_SND_R_"#CODE > + > +switch (code) { > +CASE(JACK_INFO); > +CASE(JACK_REMAP); > +CASE(PCM_INFO); > +CASE(PCM_SET_PARAMS); > +CASE(PCM_PREPARE); > +CASE(PCM_RELEASE); > +CASE(PCM_START); > +CASE(PCM_STOP); > +CASE(CHMAP_INFO); > +default: > +return "invalid code"; > +} > + > +#undef CASE > +}; > + > static const VMStateDescription vmstate_virtio_snd_device = { > .name = TYPE_VIRTIO_SND, > .version_id = VIRTIO_SOUND_VM_VERSION, > @@ -88,12 +111,148 @@ virtio_snd_set_config(VirtIODevice *vdev, const uint8_t > *config) > } > > /* > - * Queue handler stub. > + * The actual processing done in virtio_snd_process_cmdq(). > + * > + * @s: VirtIOSound device > + * @cmd: control command request > + */ > +static inline void > +process_cmd(VirtIOSound *s, virtio_snd_ctrl_command *cmd) > +{ > +size_t sz = iov_to_buf(cmd->elem->out_sg, > + cmd->elem->out_num, > + 0, > + >ctrl, > + sizeof(cmd->ctrl)); > +if (sz != sizeof(cmd->ctrl)) { > +qemu_log_mask(LOG_GUEST_ERROR, > +"%s: virtio-snd command size incorrect %zu vs \ > +%zu\n", __func__, sz, sizeof(cmd->ctrl)); > +return; > +} > + > +trace_virtio_snd_handle_code(cmd->ctrl.code, > + print_code(cmd->ctrl.code)); > + > +switch (cmd->ctrl.code) { > +case VIRTIO_SND_R_JACK_INFO: > +case VIRTIO_SND_R_JACK_REMAP: > +qemu_log_mask(LOG_UNIMP, > + "virtio_snd: jack functionality is unimplemented."); > +cmd->resp.code = VIRTIO_SND_S_NOT_SUPP; > +break; > +case VIRTIO_SND_R_PCM_INFO: > +case VIRTIO_SND_R_PCM_SET_PARAMS: > +case VIRTIO_SND_R_PCM_PREPARE: > +case VIRTIO_SND_R_PCM_START: > +case VIRTIO_SND_R_PCM_STOP: > +case VIRTIO_SND_R_PCM_RELEASE: > +cmd->resp.code = VIRTIO_SND_S_NOT_SUPP; > +break; > +case VIRTIO_SND_R_CHMAP_INFO: > +qemu_log_mask(LOG_UNIMP, > + "virtio_snd: chmap info functionality is > unimplemented."); > +trace_virtio_snd_handle_chmap_info(); > +cmd->resp.code = VIRTIO_SND_S_NOT_SUPP; > +break; > +default: > +/* error */ > +error_report("virtio snd header not recognized: %"PRIu32, > + cmd->ctrl.code); > +cmd->resp.code = VIRTIO_SND_S_BAD_MSG; > +} > + > +iov_from_buf(cmd->elem->in_sg, > + cmd->elem->in_num, > + 0, > + >resp, > + sizeof(cmd->resp)); > +virtqueue_push(cmd->vq, cmd->elem, sizeof(cmd->elem)); > +virtio_notify(VIRTIO_DEVICE(s), cmd->vq); > +} > + > +/* > + * Consume all elements in command queue. > + * > + * @s: VirtIOSound device > + */ > +static void virtio_snd_process_cmdq(VirtIOSound *s) > +{ > +virtio_snd_ctrl_command *cmd; > + > +if (unlikely(qatomic_read(>processing_cmdq))) { > +return; > +} > + > +WITH_QEMU_LOCK_GUARD(>cmdq_mutex) { > +
[PATCH v3 4/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR
Introduce a model of Xilinx Versal's Configuration Frame Unit's Single Frame Read port (CFU_SFR). Signed-off-by: Francisco Iglesias Reviewed-by: Peter Maydell --- hw/misc/xlnx-versal-cfu.c | 87 +++ include/hw/misc/xlnx-versal-cfu.h | 15 ++ 2 files changed, 102 insertions(+) diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c index 255c1bf4b8..8e588ac1d8 100644 --- a/hw/misc/xlnx-versal-cfu.c +++ b/hw/misc/xlnx-versal-cfu.c @@ -264,6 +264,31 @@ static void cfu_stream_write(void *opaque, hwaddr addr, uint64_t value, } } +static uint64_t cfu_sfr_read(void *opaque, hwaddr addr, unsigned size) +{ +qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%" + HWADDR_PRIx "\n", __func__, addr); +return 0; +} + +static void cfu_sfr_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ +XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(opaque); +uint32_t wfifo[WFIFO_SZ]; + +if (update_wfifo(addr, value, s->wfifo, wfifo)) { +uint8_t row_addr = extract32(wfifo[0], 23, 5); +uint32_t frame_addr = extract32(wfifo[0], 0, 23); +XlnxCfiPacket pkt = { .reg_addr = CFRAME_SFR, + .data[0] = frame_addr }; + +if (s->cfg.cfu) { +cfu_transfer_cfi_packet(s->cfg.cfu, row_addr, ); +} +} +} + static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size) { XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque); @@ -293,6 +318,16 @@ static const MemoryRegionOps cfu_stream_ops = { }, }; +static const MemoryRegionOps cfu_sfr_ops = { +.read = cfu_sfr_read, +.write = cfu_sfr_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 4, +.max_access_size = 4, +}, +}; + static const MemoryRegionOps cfu_fdro_ops = { .read = cfu_fdro_read, .write = cfu_fdro_write, @@ -334,6 +369,23 @@ static void cfu_apb_init(Object *obj) sysbus_init_irq(sbd, >irq_cfu_imr); } +static void cfu_sfr_init(Object *obj) +{ +XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj); +SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + +memory_region_init_io(>iomem_sfr, obj, _sfr_ops, s, + TYPE_XLNX_VERSAL_CFU_SFR, KEYHOLE_STREAM_4K); +sysbus_init_mmio(sbd, >iomem_sfr); +} + +static void cfu_sfr_reset_enter(Object *obj, ResetType type) +{ +XlnxVersalCFUSFR *s = XLNX_VERSAL_CFU_SFR(obj); + +memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t)); +} + static void cfu_fdro_init(Object *obj) { XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj); @@ -401,6 +453,12 @@ static Property cfu_props[] = { DEFINE_PROP_END_OF_LIST(), }; +static Property cfu_sfr_props[] = { +DEFINE_PROP_LINK("cfu", XlnxVersalCFUSFR, cfg.cfu, + TYPE_XLNX_VERSAL_CFU_APB, XlnxVersalCFUAPB *), +DEFINE_PROP_END_OF_LIST(), +}; + static const VMStateDescription vmstate_cfu_apb = { .name = TYPE_XLNX_VERSAL_CFU_APB, .version_id = 1, @@ -423,6 +481,16 @@ static const VMStateDescription vmstate_cfu_fdro = { } }; +static const VMStateDescription vmstate_cfu_sfr = { +.name = TYPE_XLNX_VERSAL_CFU_SFR, +.version_id = 1, +.minimum_version_id = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFUSFR, 4), +VMSTATE_END_OF_LIST(), +} +}; + static void cfu_apb_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -443,6 +511,16 @@ static void cfu_fdro_class_init(ObjectClass *klass, void *data) rc->phases.enter = cfu_fdro_reset_enter; } +static void cfu_sfr_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +ResettableClass *rc = RESETTABLE_CLASS(klass); + +device_class_set_props(dc, cfu_sfr_props); +dc->vmsd = _cfu_sfr; +rc->phases.enter = cfu_sfr_reset_enter; +} + static const TypeInfo cfu_apb_info = { .name = TYPE_XLNX_VERSAL_CFU_APB, .parent= TYPE_SYS_BUS_DEVICE, @@ -467,10 +545,19 @@ static const TypeInfo cfu_fdro_info = { } }; +static const TypeInfo cfu_sfr_info = { +.name = TYPE_XLNX_VERSAL_CFU_SFR, +.parent= TYPE_SYS_BUS_DEVICE, +.instance_size = sizeof(XlnxVersalCFUSFR), +.class_init= cfu_sfr_class_init, +.instance_init = cfu_sfr_init, +}; + static void cfu_apb_register_types(void) { type_register_static(_apb_info); type_register_static(_fdro_info); +type_register_static(_sfr_info); } type_init(cfu_apb_register_types) diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h index 73e9a21af4..86fb841053 100644 --- a/include/hw/misc/xlnx-versal-cfu.h +++ b/include/hw/misc/xlnx-versal-cfu.h @@ -28,6 +28,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCFUAPB, XLNX_VERSAL_CFU_APB) #define TYPE_XLNX_VERSAL_CFU_FDRO
[PATCH v3 7/8] hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR
Connect the Configuration Frame Unit (CFU_APB, CFU_FDRO and CFU_SFR) to the Versal machine. Signed-off-by: Francisco Iglesias Acked-by: Edgar E. Iglesias Reviewed-by: Peter Maydell --- hw/arm/xlnx-versal.c | 42 include/hw/arm/xlnx-versal.h | 16 ++ 2 files changed, 58 insertions(+) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 60bf5fe657..3f4b4b1560 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -570,6 +570,47 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic) qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]); } +static void versal_create_cfu(Versal *s, qemu_irq *pic) +{ +SysBusDevice *sbd; + +/* CFU FDRO */ +object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro, +TYPE_XLNX_VERSAL_CFU_FDRO); +sbd = SYS_BUS_DEVICE(>pmc.cfu_fdro); + +sysbus_realize(sbd, _fatal); +memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO, +sysbus_mmio_get_region(sbd, 0)); + +/* CFU APB */ +object_initialize_child(OBJECT(s), "cfu-apb", >pmc.cfu_apb, +TYPE_XLNX_VERSAL_CFU_APB); +sbd = SYS_BUS_DEVICE(>pmc.cfu_apb); + +sysbus_realize(sbd, _fatal); +memory_region_add_subregion(>mr_ps, MM_PMC_CFU_APB, +sysbus_mmio_get_region(sbd, 0)); +memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM, +sysbus_mmio_get_region(sbd, 1)); +memory_region_add_subregion(>mr_ps, MM_PMC_CFU_STREAM_2, +sysbus_mmio_get_region(sbd, 2)); +sysbus_connect_irq(sbd, 0, pic[VERSAL_CFU_IRQ_0]); + +/* CFU SFR */ +object_initialize_child(OBJECT(s), "cfu-sfr", >pmc.cfu_sfr, +TYPE_XLNX_VERSAL_CFU_SFR); + +sbd = SYS_BUS_DEVICE(>pmc.cfu_sfr); + +object_property_set_link(OBJECT(>pmc.cfu_sfr), +"cfu", OBJECT(>pmc.cfu_apb), _abort); + +sysbus_realize(sbd, _fatal); +memory_region_add_subregion(>mr_ps, MM_PMC_CFU_SFR, +sysbus_mmio_get_region(sbd, 0)); +} + static void versal_create_crl(Versal *s, qemu_irq *pic) { SysBusDevice *sbd; @@ -763,6 +804,7 @@ static void versal_realize(DeviceState *dev, Error **errp) versal_create_pmc_iou_slcr(s, pic); versal_create_ospi(s, pic); versal_create_crl(s, pic); +versal_create_cfu(s, pic); versal_map_ddr(s); versal_unimp(s); diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h index 39ee31185c..29b9c60301 100644 --- a/include/hw/arm/xlnx-versal.h +++ b/include/hw/arm/xlnx-versal.h @@ -32,6 +32,7 @@ #include "hw/misc/xlnx-versal-crl.h" #include "hw/misc/xlnx-versal-pmc-iou-slcr.h" #include "hw/net/xlnx-versal-canfd.h" +#include "hw/misc/xlnx-versal-cfu.h" #define TYPE_XLNX_VERSAL "xlnx-versal" OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL) @@ -117,6 +118,9 @@ struct Versal { XlnxEFuse efuse; XlnxVersalEFuseCtrl efuse_ctrl; XlnxVersalEFuseCache efuse_cache; +XlnxVersalCFUAPB cfu_apb; +XlnxVersalCFUFDRO cfu_fdro; +XlnxVersalCFUSFR cfu_sfr; OrIRQState apb_irq_orgate; } pmc; @@ -147,6 +151,7 @@ struct Versal { #define VERSAL_GEM1_WAKE_IRQ_0 59 #define VERSAL_ADMA_IRQ_0 60 #define VERSAL_XRAM_IRQ_0 79 +#define VERSAL_CFU_IRQ_0 120 #define VERSAL_PMC_APB_IRQ 121 #define VERSAL_OSPI_IRQ124 #define VERSAL_SD0_IRQ_0 126 @@ -240,6 +245,17 @@ struct Versal { #define MM_PMC_EFUSE_CACHE 0xf125 #define MM_PMC_EFUSE_CACHE_SIZE 0x00C00 +#define MM_PMC_CFU_APB 0xf12b +#define MM_PMC_CFU_APB_SIZE 0x1 +#define MM_PMC_CFU_STREAM 0xf12c +#define MM_PMC_CFU_STREAM_SIZE 0x1000 +#define MM_PMC_CFU_SFR 0xf12c1000 +#define MM_PMC_CFU_SFR_SIZE 0x1000 +#define MM_PMC_CFU_FDRO 0xf12c2000 +#define MM_PMC_CFU_FDRO_SIZE0x1000 +#define MM_PMC_CFU_STREAM_2 0xf1f8 +#define MM_PMC_CFU_STREAM_2_SIZE0x4 + #define MM_PMC_CRP 0xf126U #define MM_PMC_CRP_SIZE 0x1 #define MM_PMC_RTC 0xf12a -- 2.34.1
[PATCH v3 1/8] hw/misc: Introduce the Xilinx CFI interface
Introduce the Xilinx Configuration Frame Interface (CFI) for transmitting CFI data packets between the Xilinx Configuration Frame Unit models (CFU_APB, CFU_FDRO and CFU_SFR), the Xilinx CFRAME controller (CFRAME_REG) and the Xilinx CFRAME broadcast controller (CFRAME_BCAST_REG) models (when emulating bitstream programming and readback). Signed-off-by: Francisco Iglesias Reviewed-by: Sai Pavan Boddu Acked-by: Edgar E. Iglesias --- MAINTAINERS | 6 hw/misc/meson.build | 1 + hw/misc/xlnx-cfi-if.c | 34 include/hw/misc/xlnx-cfi-if.h | 59 +++ 4 files changed, 100 insertions(+) create mode 100644 hw/misc/xlnx-cfi-if.c create mode 100644 include/hw/misc/xlnx-cfi-if.h diff --git a/MAINTAINERS b/MAINTAINERS index 6111b6b4d9..e0cd365462 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1034,6 +1034,12 @@ S: Maintained F: hw/ssi/xlnx-versal-ospi.c F: include/hw/ssi/xlnx-versal-ospi.h +Xilinx Versal CFI +M: Francisco Iglesias +S: Maintained +F: hw/misc/xlnx-cfi-if.c +F: include/hw/misc/xlnx-cfi-if.h + STM32F100 M: Alexandre Iooss L: qemu-...@nongnu.org diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 892f8b91c5..0c562f5e3e 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c')) system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-versal-xramc.c', 'xlnx-versal-pmc-iou-slcr.c', + 'xlnx-cfi-if.c', )) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) diff --git a/hw/misc/xlnx-cfi-if.c b/hw/misc/xlnx-cfi-if.c new file mode 100644 index 00..c45f05c4aa --- /dev/null +++ b/hw/misc/xlnx-cfi-if.c @@ -0,0 +1,34 @@ +/* + * Xilinx CFI interface + * + * Copyright (C) 2023, Advanced Micro Devices, Inc. + * + * Written by Francisco Iglesias + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include "qemu/osdep.h" +#include "hw/misc/xlnx-cfi-if.h" + +void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt) +{ +XlnxCfiIfClass *xcic = XLNX_CFI_IF_GET_CLASS(cfi_if); + +if (xcic->cfi_transfer_packet) { +xcic->cfi_transfer_packet(cfi_if, pkt); +} +} + +static const TypeInfo xlnx_cfi_if_info = { +.name = TYPE_XLNX_CFI_IF, +.parent= TYPE_INTERFACE, +.class_size = sizeof(XlnxCfiIfClass), +}; + +static void xlnx_cfi_if_register_types(void) +{ +type_register_static(_cfi_if_info); +} + +type_init(xlnx_cfi_if_register_types) + diff --git a/include/hw/misc/xlnx-cfi-if.h b/include/hw/misc/xlnx-cfi-if.h new file mode 100644 index 00..f9bd12292d --- /dev/null +++ b/include/hw/misc/xlnx-cfi-if.h @@ -0,0 +1,59 @@ +/* + * Xilinx CFI interface + * + * Copyright (C) 2023, Advanced Micro Devices, Inc. + * + * Written by Francisco Iglesias + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef XLNX_CFI_IF_H +#define XLNX_CFI_IF_H 1 + +#include "qemu/help-texts.h" +#include "hw/hw.h" +#include "qom/object.h" + +#define TYPE_XLNX_CFI_IF "xlnx-cfi-if" +typedef struct XlnxCfiIfClass XlnxCfiIfClass; +DECLARE_CLASS_CHECKERS(XlnxCfiIfClass, XLNX_CFI_IF, TYPE_XLNX_CFI_IF) + +#define XLNX_CFI_IF(obj) \ + INTERFACE_CHECK(XlnxCfiIf, (obj), TYPE_XLNX_CFI_IF) + +typedef enum { +PACKET_TYPE_CFU = 0x52, +PACKET_TYPE_CFRAME = 0xA1, +} xlnx_cfi_packet_type; + +typedef enum { +CFRAME_FAR = 1, +CFRAME_SFR = 2, +CFRAME_FDRI = 4, +CFRAME_CMD = 6, +} xlnx_cfi_reg_addr; + +typedef struct XlnxCfiPacket { +uint8_t reg_addr; +uint32_t data[4]; +} XlnxCfiPacket; + +typedef struct XlnxCfiIf { +Object Parent; +} XlnxCfiIf; + +typedef struct XlnxCfiIfClass { +InterfaceClass parent; + +void (*cfi_transfer_packet)(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt); +} XlnxCfiIfClass; + +/** + * Transfer a XlnxCfiPacket. + * + * @cfi_if: the object implementing this interface + * @XlnxCfiPacket: a pointer to the XlnxCfiPacket to transfer + */ +void xlnx_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt); + +#endif /* XLNX_CFI_IF_H */ -- 2.34.1
[PATCH v3 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG
Introduce a model of Xilinx Versal's Configuration Frame controller (CFRAME_REG). Signed-off-by: Francisco Iglesias --- MAINTAINERS | 2 + hw/misc/meson.build | 1 + hw/misc/xlnx-versal-cframe-reg.c | 685 +++ include/hw/misc/xlnx-versal-cframe-reg.h | 286 ++ 4 files changed, 974 insertions(+) create mode 100644 hw/misc/xlnx-versal-cframe-reg.c create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h diff --git a/MAINTAINERS b/MAINTAINERS index 847b997d73..645374c1d9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1041,6 +1041,8 @@ F: hw/misc/xlnx-cfi-if.c F: include/hw/misc/xlnx-cfi-if.h F: hw/misc/xlnx-versal-cfu.c F: include/hw/misc/xlnx-versal-cfu.h +F: hw/misc/xlnx-versal-cframe-reg.c +F: include/hw/misc/xlnx-versal-cframe-reg.h STM32F100 M: Alexandre Iooss diff --git a/hw/misc/meson.build b/hw/misc/meson.build index d95cc3fd87..1b425b03bd 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -99,6 +99,7 @@ system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-versal-pmc-iou-slcr.c', 'xlnx-versal-cfu.c', 'xlnx-cfi-if.c', + 'xlnx-versal-cframe-reg.c', )) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) system_ss.add(when: 'CONFIG_STM32F4XX_SYSCFG', if_true: files('stm32f4xx_syscfg.c')) diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c new file mode 100644 index 00..4c9afb184d --- /dev/null +++ b/hw/misc/xlnx-versal-cframe-reg.c @@ -0,0 +1,685 @@ +/* + * QEMU model of the Configuration Frame Control module + * + * Copyright (C) 2023, Advanced Micro Devices, Inc. + * + * Written by Francisco Iglesias + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/register.h" +#include "hw/registerfields.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/units.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" +#include "migration/vmstate.h" +#include "hw/irq.h" +#include "hw/misc/xlnx-versal-cframe-reg.h" + +#ifndef XLNX_VERSAL_CFRAME_REG_ERR_DEBUG +#define XLNX_VERSAL_CFRAME_REG_ERR_DEBUG 0 +#endif + +#define KEYHOLE_STREAM_4K (4 * KiB) +#define N_WORDS_128BIT 4 + +#define MAX_BLOCKTYPE 6 +#define MAX_BLOCKTYPE_FRAMES 0xF + +enum { +CFRAME_CMD_WCFG = 1, +CFRAME_CMD_ROWON = 2, +CFRAME_CMD_ROWOFF = 3, +CFRAME_CMD_RCFG = 4, +CFRAME_CMD_DLPARK = 5, +}; + +static gint int_cmp(gconstpointer a, gconstpointer b, gpointer user_data) +{ +guint ua = GPOINTER_TO_UINT(a); +guint ub = GPOINTER_TO_UINT(b); +return (ua > ub) - (ua < ub); +} + +static void cfrm_imr_update_irq(XlnxVersalCFrameReg *s) +{ +bool pending = s->regs[R_CFRM_ISR0] & ~s->regs[R_CFRM_IMR0]; +qemu_set_irq(s->irq_cfrm_imr, pending); +} + +static void cfrm_isr_postw(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque); +cfrm_imr_update_irq(s); +} + +static uint64_t cfrm_ier_prew(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque); + +s->regs[R_CFRM_IMR0] &= ~s->regs[R_CFRM_IER0]; +s->regs[R_CFRM_IER0] = 0; +cfrm_imr_update_irq(s); +return 0; +} + +static uint64_t cfrm_idr_prew(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque); + +s->regs[R_CFRM_IMR0] |= s->regs[R_CFRM_IDR0]; +s->regs[R_CFRM_IDR0] = 0; +cfrm_imr_update_irq(s); +return 0; +} + +static uint64_t cfrm_itr_prew(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque); + +s->regs[R_CFRM_ISR0] |= s->regs[R_CFRM_ITR0]; +s->regs[R_CFRM_ITR0] = 0; +cfrm_imr_update_irq(s); +return 0; +} + +static void cframe_incr_far(XlnxVersalCFrameReg *s) +{ +uint32_t faddr = ARRAY_FIELD_EX32(s->regs, FAR0, FRAME_ADDR); +uint32_t blktype = ARRAY_FIELD_EX32(s->regs, FAR0, BLOCKTYPE); + +assert(blktype <= MAX_BLOCKTYPE); + +faddr++; +if (faddr > s->cfg.blktype_num_frames[blktype]) { +/* Restart from 0 and increment block type */ +faddr = 0; +blktype++; + +assert(blktype <= MAX_BLOCKTYPE); + +ARRAY_FIELD_DP32(s->regs, FAR0, BLOCKTYPE, blktype); +} + +ARRAY_FIELD_DP32(s->regs, FAR0, FRAME_ADDR, faddr); +} + +static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val) +{ +XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque); + +if (s->row_configured && s->rowon && s->wcfg) { + +if (fifo32_num_free(>new_f_data) >= N_WORDS_128BIT) { +fifo32_push(>new_f_data, s->regs[R_FDRI0]); +fifo32_push(>new_f_data, s->regs[R_FDRI1]); +fifo32_push(>new_f_data, s->regs[R_FDRI2]); +fifo32_push(>new_f_data, s->regs[R_FDRI3]); +} + +if (fifo32_is_full(>new_f_data)) { +
Re: [PATCH v2 5/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG
Hi Peter, On 2023-08-21 15:34, Peter Maydell wrote: On Thu, 10 Aug 2023 at 20:16, Francisco Iglesias wrote: Introduce a model of Xilinx Versal's Configuration Frame controller (CFRAME_REG). Signed-off-by: Francisco Iglesias --- MAINTAINERS | 2 + hw/misc/meson.build | 1 + hw/misc/xlnx-versal-cframe-reg.c | 753 +++ include/hw/misc/xlnx-versal-cframe-reg.h | 289 + 4 files changed, 1045 insertions(+) create mode 100644 hw/misc/xlnx-versal-cframe-reg.c create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h +static XlnxCFrame *cframes_get_frame(XlnxVersalCFrameReg *s, uint32_t addr) +{ +for (int i = 0; i < s->cframes->len; i++) { +XlnxCFrame *f = _array_index(s->cframes, XlnxCFrame, i); + +if (f->addr == addr) { +return f; +} +} +return NULL; +} The handling of this and especially how it turns out in the migration support still feels quite awkward to me. The operations we want here seem to be: * find a cframe given the 'addr' * insert a new cframe for a given 'addr', overwriting any old data * iterate through n cframes starting at a given 'addr' You can do this with a GTree https://developer-old.gnome.org/glib/stable/glib-Balanced-Binary-Trees.html You can use GUINT_TO_POINTER(addr) as the keys, and use a Fifo32 as your data. Insert-with-overwrite is g_tree_replace_node(). Find-a-frame is g_tree_lookup(). Iterate through n cframes is for (node = g_tree_lookup(...), i = 0; i < n; node = g_tree_node_next(node), i++) { ... } GTrees are supported by the migration code, there is a VMSTATE_GTREE_DIRECT_KEY_V() macro, so you don't need to do any pre-save or post-load hooks. (This to me is one of the main benefits of using it rather than a GArray.) Is the data in each cframe fixed-size, or can it vary? The impression I get is that each cframe is always the same amount of data, and we use a fifo purely to handle the "guest writes the frame data a word at a time and when it's all arrived we put it into the cframe data structure". If so, it might be simpler to use a fifo32 for the new_f, but have the data in the gtree structure be a simple fixed-size block of memory. Thank you very much for the suggestionA I'll switch to a GTree in v3! (And it is correct above, both regarding required operations and that the cframes are fixed sized). + +static void cframe_alloc(XlnxCFrame *f) +{ +f->addr = 0; +fifo32_create(>data, FRAME_NUM_WORDS); +} + +static void cframe_move(XlnxCFrame *dst, XlnxCFrame *src) +{ +fifo32_destroy(>data); +dst[0] = src[0]; +} + +static void cfrm_fdri_post_write(RegisterInfo *reg, uint64_t val) +{ +XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque); + +if (s->row_configured && s->rowon && s->wcfg) { +XlnxCFrame *new_f = >new_f; + +if (fifo32_num_free(_f->data) >= N_WORDS_128BIT) { +fifo32_push(_f->data, s->regs[R_FDRI0]); +fifo32_push(_f->data, s->regs[R_FDRI1]); +fifo32_push(_f->data, s->regs[R_FDRI2]); +fifo32_push(_f->data, s->regs[R_FDRI3]); +} + +if (fifo32_is_full(_f->data)) { +XlnxCFrame *cur_f; + +/* Include block type and frame address */ +new_f->addr = extract32(s->regs[R_FAR0], 0, 23); + +cur_f = cframes_get_frame(s, new_f->addr); + +if (cur_f) { +cframe_move(cur_f, new_f); +} else { +g_array_append_val(s->cframes, new_f[0]); +} + +cframe_incr_far(s); + +/* Realloc new_f */ +cframe_alloc(new_f); +} +} +} + +static void cfrm_readout_frames(XlnxVersalCFrameReg *s, uint32_t start_addr, +uint32_t end_addr) +{ +for (uint32_t addr = start_addr; addr < end_addr; addr++) { +XlnxCFrame *f = cframes_get_frame(s, addr); + +/* Transmit the data if a frame was found */ +if (f) { +Fifo32 data = f->data; + +while (!fifo32_is_empty()) { +XlnxCfiPacket pkt = {}; + +g_assert(fifo32_num_used() >= N_WORDS_128BIT); + +pkt.data[0] = fifo32_pop(); +pkt.data[1] = fifo32_pop(); +pkt.data[2] = fifo32_pop(); +pkt.data[3] = fifo32_pop(); + +if (s->cfg.cfu_fdro) { +xlnx_cfi_transfer_packet(s->cfg.cfu_fdro, ); +} +} +} +} +} + +static void cfrm_frcnt_post_write(RegisterInfo *reg, uint64_t val) +{ +XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(reg->opaque); + +if (s->row_configured && s->rowon && s->rcfg) { +uint32_t start_addr = extract32(s->regs[R_FAR0], 0, 23); +uint32_t end_addr = start_addr + s->regs[R_FRCNT0] / FRAME_NUM_QWORDS; + +cfrm_readout_frames(s, start_addr,
[PATCH v3 6/8] hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG
Introduce a model of Xilinx Versal's Configuration Frame broadcast controller (CFRAME_BCAST_REG). Signed-off-by: Francisco Iglesias Reviewed-by: Peter Maydell --- hw/misc/xlnx-versal-cframe-reg.c | 161 +++ include/hw/misc/xlnx-versal-cframe-reg.h | 17 +++ 2 files changed, 178 insertions(+) diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c index 4c9afb184d..2ce62c1b2e 100644 --- a/hw/misc/xlnx-versal-cframe-reg.c +++ b/hw/misc/xlnx-versal-cframe-reg.c @@ -557,6 +557,83 @@ static const MemoryRegionOps cframe_reg_fdri_ops = { }, }; +static uint64_t cframes_bcast_reg_read(void *opaque, hwaddr addr, unsigned size) +{ +qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%" + HWADDR_PRIx "\n", __func__, addr); +return 0; +} + +static void cframes_bcast_write(XlnxVersalCFrameBcastReg *s, uint8_t reg_addr, +uint32_t *wfifo) +{ +XlnxCfiPacket pkt = { +.reg_addr = reg_addr, +.data[0] = wfifo[0], +.data[1] = wfifo[1], +.data[2] = wfifo[2], +.data[3] = wfifo[3] +}; + +for (int i = 0; i < ARRAY_SIZE(s->cfg.cframe); i++) { +if (s->cfg.cframe[i]) { +xlnx_cfi_transfer_packet(s->cfg.cframe[i], ); +} +} +} + +static void cframes_bcast_reg_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ +XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque); +uint32_t wfifo[WFIFO_SZ]; + +if (update_wfifo(addr, value, s->wfifo, wfifo)) { +uint8_t reg_addr = extract32(addr, 4, 6); + +cframes_bcast_write(s, reg_addr, wfifo); +} +} + +static uint64_t cframes_bcast_fdri_read(void *opaque, hwaddr addr, +unsigned size) +{ +qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported read from addr=%" + HWADDR_PRIx "\n", __func__, addr); +return 0; +} + +static void cframes_bcast_fdri_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ +XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(opaque); +uint32_t wfifo[WFIFO_SZ]; + +if (update_wfifo(addr, value, s->wfifo, wfifo)) { +cframes_bcast_write(s, CFRAME_FDRI, wfifo); +} +} + +static const MemoryRegionOps cframes_bcast_reg_reg_ops = { +.read = cframes_bcast_reg_read, +.write = cframes_bcast_reg_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 4, +.max_access_size = 4, +}, +}; + +static const MemoryRegionOps cframes_bcast_reg_fdri_ops = { +.read = cframes_bcast_fdri_read, +.write = cframes_bcast_fdri_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 4, +.max_access_size = 4, +}, +}; + static void cframe_reg_realize(DeviceState *dev, Error **errp) { XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(dev); @@ -651,6 +728,71 @@ static Property cframe_regs_props[] = { DEFINE_PROP_END_OF_LIST(), }; +static void cframe_bcast_reg_init(Object *obj) +{ +XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj); +SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + +memory_region_init_io(>iomem_reg, obj, _bcast_reg_reg_ops, s, + TYPE_XLNX_VERSAL_CFRAME_BCAST_REG, KEYHOLE_STREAM_4K); +memory_region_init_io(>iomem_fdri, obj, _bcast_reg_fdri_ops, s, + TYPE_XLNX_VERSAL_CFRAME_BCAST_REG "-fdri", + KEYHOLE_STREAM_4K); +sysbus_init_mmio(sbd, >iomem_reg); +sysbus_init_mmio(sbd, >iomem_fdri); +} + +static void cframe_bcast_reg_reset_enter(Object *obj, ResetType type) +{ +XlnxVersalCFrameBcastReg *s = XLNX_VERSAL_CFRAME_BCAST_REG(obj); + +memset(s->wfifo, 0, WFIFO_SZ * sizeof(uint32_t)); +} + +static const VMStateDescription vmstate_cframe_bcast_reg = { +.name = TYPE_XLNX_VERSAL_CFRAME_BCAST_REG, +.version_id = 1, +.minimum_version_id = 1, +.fields = (VMStateField[]) { +VMSTATE_UINT32_ARRAY(wfifo, XlnxVersalCFrameBcastReg, 4), +VMSTATE_END_OF_LIST(), +} +}; + +static Property cframe_bcast_regs_props[] = { +DEFINE_PROP_LINK("cframe0", XlnxVersalCFrameBcastReg, cfg.cframe[0], + TYPE_XLNX_CFI_IF, XlnxCfiIf *), +DEFINE_PROP_LINK("cframe1", XlnxVersalCFrameBcastReg, cfg.cframe[1], + TYPE_XLNX_CFI_IF, XlnxCfiIf *), +DEFINE_PROP_LINK("cframe2", XlnxVersalCFrameBcastReg, cfg.cframe[2], + TYPE_XLNX_CFI_IF, XlnxCfiIf *), +DEFINE_PROP_LINK("cframe3", XlnxVersalCFrameBcastReg, cfg.cframe[3], + TYPE_XLNX_CFI_IF, XlnxCfiIf *), +DEFINE_PROP_LINK("cframe4", XlnxVersalCFrameBcastReg, cfg.cframe[4], + TYPE_XLNX_CFI_IF, XlnxCfiIf *), +DEFINE_PROP_LINK("cframe5", XlnxVersalCFrameBcastReg, cfg.cframe[5], +
[PATCH v3 0/8] Xilinx Versal CFI support
Hi, This series adds support for the Configuration Frame Unit (CFU) and the Configuration Frame controllers (CFRAME) to the Xilinx Versal machine ([1], chapter 21) for emulaing bitstream loading and readback. The series starts by introducing the Xilinx CFI interface that is thereafter used by the Xilinx CFU components, the Xilinx CFRAME and Xilinx CFRAME broadcast models for transfering CFI packets between each other. Thereafter a model of the CFU_APB, CFU_FDRO and CFU_SFR are introduced and also models of the CFRAME controller and CFRAME broadcast controller. The series thereafter ends with connecting the models to Xilinx Versal machine. Best regards, Francisco Iglesias References: [1] https://docs.xilinx.com/r/en-US/am011-versal-acap-trm/PSM-Local-Registers Changelog: v2->v3: [PATCH 5] * Swap to store the CFrames in a GTree instead of GArray * Rename new_f to new_f_data and also add it to the vmstate * Removed unnecessary 'switch' braces in cframe_reg_cfi_transfer_packet * Correct the reset of new_f_data and the cframes GTree v1->v2: [PATCH 2] * Use KiB when defining KEYHOLE_STREAM_4K/KEYHOLE_STREAM_256K * Updated to be able to share wfifo code [PATCH 3] * Swap to use Fifo32 instead of GArray in the CFU_FDRO model * Add device reset to the CFU_FDRO model [PATCH 4] * Add device reset to the CFU_SFR model [PATCH 5] * Use KiB when defining KEYHOLE_STREAM_4K * Add comma after CFRAME_CMD_DLPARK * Remove backwards compatibility comment (and the 'cfu' alias propname for cfg.cfu_fdro) * Use Fifo32 inside the XlnxCFrame structure * Reworked cframes_reg_pre_save / cframes_reg_post_load [PATCH 6] * Add device reset to the CFrame broadcast reg model [PATCH 8] * Switch to use g_autofree instead of explicit g_free Francisco Iglesias (8): hw/misc: Introduce the Xilinx CFI interface hw/misc: Introduce a model of Xilinx Versal's CFU_APB hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal's CFU_SFR hw/misc: Introduce a model of Xilinx Versal's CFRAME_REG hw/misc: Introduce a model of Xilinx Versal's CFRAME_BCAST_REG hw/arm/xlnx-versal: Connect the CFU_APB, CFU_FDRO and CFU_SFR hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG MAINTAINERS | 10 + hw/arm/xlnx-versal.c | 155 - hw/misc/meson.build | 3 + hw/misc/xlnx-cfi-if.c| 34 + hw/misc/xlnx-versal-cframe-reg.c | 846 +++ hw/misc/xlnx-versal-cfu.c| 563 +++ include/hw/arm/xlnx-versal.h | 85 +++ include/hw/misc/xlnx-cfi-if.h| 59 ++ include/hw/misc/xlnx-versal-cframe-reg.h | 303 include/hw/misc/xlnx-versal-cfu.h| 258 +++ 10 files changed, 2315 insertions(+), 1 deletion(-) create mode 100644 hw/misc/xlnx-cfi-if.c create mode 100644 hw/misc/xlnx-versal-cframe-reg.c create mode 100644 hw/misc/xlnx-versal-cfu.c create mode 100644 include/hw/misc/xlnx-cfi-if.h create mode 100644 include/hw/misc/xlnx-versal-cframe-reg.h create mode 100644 include/hw/misc/xlnx-versal-cfu.h -- 2.34.1
[PATCH v3 2/8] hw/misc: Introduce a model of Xilinx Versal's CFU_APB
Introduce a model of the software programming interface (CFU_APB) of Xilinx Versal's Configuration Frame Unit. Signed-off-by: Francisco Iglesias Reviewed-by: Peter Maydell --- MAINTAINERS | 2 + hw/misc/meson.build | 1 + hw/misc/xlnx-versal-cfu.c | 380 ++ include/hw/misc/xlnx-versal-cfu.h | 231 ++ 4 files changed, 614 insertions(+) create mode 100644 hw/misc/xlnx-versal-cfu.c create mode 100644 include/hw/misc/xlnx-versal-cfu.h diff --git a/MAINTAINERS b/MAINTAINERS index e0cd365462..847b997d73 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1039,6 +1039,8 @@ M: Francisco Iglesias S: Maintained F: hw/misc/xlnx-cfi-if.c F: include/hw/misc/xlnx-cfi-if.h +F: hw/misc/xlnx-versal-cfu.c +F: include/hw/misc/xlnx-versal-cfu.h STM32F100 M: Alexandre Iooss diff --git a/hw/misc/meson.build b/hw/misc/meson.build index 0c562f5e3e..d95cc3fd87 100644 --- a/hw/misc/meson.build +++ b/hw/misc/meson.build @@ -97,6 +97,7 @@ specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c')) system_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files( 'xlnx-versal-xramc.c', 'xlnx-versal-pmc-iou-slcr.c', + 'xlnx-versal-cfu.c', 'xlnx-cfi-if.c', )) system_ss.add(when: 'CONFIG_STM32F2XX_SYSCFG', if_true: files('stm32f2xx_syscfg.c')) diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c new file mode 100644 index 00..b2dc6ab211 --- /dev/null +++ b/hw/misc/xlnx-versal-cfu.c @@ -0,0 +1,380 @@ +/* + * QEMU model of the CFU Configuration Unit. + * + * Copyright (C) 2023, Advanced Micro Devices, Inc. + * + * Written by Edgar E. Iglesias , + *Sai Pavan Boddu , + *Francisco Iglesias + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/sysbus.h" +#include "hw/register.h" +#include "hw/irq.h" +#include "qemu/bitops.h" +#include "qemu/log.h" +#include "qemu/units.h" +#include "migration/vmstate.h" +#include "hw/qdev-properties.h" +#include "hw/qdev-properties-system.h" +#include "hw/misc/xlnx-versal-cfu.h" + +#ifndef XLNX_VERSAL_CFU_APB_ERR_DEBUG +#define XLNX_VERSAL_CFU_APB_ERR_DEBUG 0 +#endif + +#define KEYHOLE_STREAM_4K (4 * KiB) +#define KEYHOLE_STREAM_256K (256 * KiB) +#define CFRAME_BROADCAST_ROW 0x1F + +bool update_wfifo(hwaddr addr, uint64_t value, + uint32_t *wfifo, uint32_t *wfifo_ret) +{ +unsigned int idx = extract32(addr, 2, 2); + +wfifo[idx] = value; + +if (idx == 3) { +memcpy(wfifo_ret, wfifo, WFIFO_SZ * sizeof(uint32_t)); +memset(wfifo, 0, WFIFO_SZ * sizeof(uint32_t)); +return true; +} + +return false; +} + +static void cfu_imr_update_irq(XlnxVersalCFUAPB *s) +{ +bool pending = s->regs[R_CFU_ISR] & ~s->regs[R_CFU_IMR]; +qemu_set_irq(s->irq_cfu_imr, pending); +} + +static void cfu_isr_postw(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque); +cfu_imr_update_irq(s); +} + +static uint64_t cfu_ier_prew(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque); +uint32_t val = val64; + +s->regs[R_CFU_IMR] &= ~val; +cfu_imr_update_irq(s); +return 0; +} + +static uint64_t cfu_idr_prew(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque); +uint32_t val = val64; + +s->regs[R_CFU_IMR] |= val; +cfu_imr_update_irq(s); +return 0; +} + +static uint64_t cfu_itr_prew(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque); +uint32_t val = val64; + +s->regs[R_CFU_ISR] |= val; +cfu_imr_update_irq(s); +return 0; +} + +static void cfu_fgcr_postw(RegisterInfo *reg, uint64_t val64) +{ +XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(reg->opaque); +uint32_t val = (uint32_t)val64; + +/* Do a scan. It always looks good. */ +if (FIELD_EX32(val, CFU_FGCR, SC_HBC_TRIGGER)) { +ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_PASS, 1); +ARRAY_FIELD_DP32(s->regs, CFU_STATUS, SCAN_CLEAR_DONE, 1); +} +} + +static const RegisterAccessInfo cfu_apb_regs_info[] = { +{ .name = "CFU_ISR", .addr = A_CFU_ISR, +.rsvd = 0xfc00, +.w1c = 0x3ff, +.post_write = cfu_isr_postw, +},{ .name = "CFU_IMR", .addr = A_CFU_IMR, +.reset = 0x3ff, +.rsvd = 0xfc00, +.ro = 0x3ff, +},{ .name = "CFU_IER", .addr = A_CFU_IER, +.rsvd = 0xfc00, +.pre_write = cfu_ier_prew, +},{ .name = "CFU_IDR", .addr = A_CFU_IDR, +.rsvd = 0xfc00, +.pre_write = cfu_idr_prew, +},{ .name = "CFU_ITR", .addr = A_CFU_ITR, +.rsvd = 0xfc00, +.pre_write = cfu_itr_prew, +},{ .name = "CFU_PROTECT", .addr = A_CFU_PROTECT, +.reset = 0x1, +},{ .name = "CFU_FGCR", .addr = A_CFU_FGCR, +.rsvd = 0x8000, +
[PATCH v3 3/8] hw/misc/xlnx-versal-cfu: Introduce a model of Xilinx Versal CFU_FDRO
Introduce a model of Xilinx Versal's Configuration Frame Unit's data out port (CFU_FDRO). Signed-off-by: Francisco Iglesias Reviewed-by: Peter Maydell --- hw/misc/xlnx-versal-cfu.c | 96 +++ include/hw/misc/xlnx-versal-cfu.h | 12 2 files changed, 108 insertions(+) diff --git a/hw/misc/xlnx-versal-cfu.c b/hw/misc/xlnx-versal-cfu.c index b2dc6ab211..255c1bf4b8 100644 --- a/hw/misc/xlnx-versal-cfu.c +++ b/hw/misc/xlnx-versal-cfu.c @@ -264,6 +264,25 @@ static void cfu_stream_write(void *opaque, hwaddr addr, uint64_t value, } } +static uint64_t cfu_fdro_read(void *opaque, hwaddr addr, unsigned size) +{ +XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(opaque); +uint64_t ret = 0; + +if (!fifo32_is_empty(>fdro_data)) { +ret = fifo32_pop(>fdro_data); +} + +return ret; +} + +static void cfu_fdro_write(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ +qemu_log_mask(LOG_GUEST_ERROR, "%s: Unsupported write from addr=%" + HWADDR_PRIx "\n", __func__, addr); +} + static const MemoryRegionOps cfu_stream_ops = { .read = cfu_stream_read, .write = cfu_stream_write, @@ -274,6 +293,16 @@ static const MemoryRegionOps cfu_stream_ops = { }, }; +static const MemoryRegionOps cfu_fdro_ops = { +.read = cfu_fdro_read, +.write = cfu_fdro_write, +.endianness = DEVICE_LITTLE_ENDIAN, +.valid = { +.min_access_size = 4, +.max_access_size = 4, +}, +}; + static void cfu_apb_init(Object *obj) { XlnxVersalCFUAPB *s = XLNX_VERSAL_CFU_APB(obj); @@ -305,6 +334,39 @@ static void cfu_apb_init(Object *obj) sysbus_init_irq(sbd, >irq_cfu_imr); } +static void cfu_fdro_init(Object *obj) +{ +XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj); +SysBusDevice *sbd = SYS_BUS_DEVICE(obj); + +memory_region_init_io(>iomem_fdro, obj, _fdro_ops, s, + TYPE_XLNX_VERSAL_CFU_FDRO, KEYHOLE_STREAM_4K); +sysbus_init_mmio(sbd, >iomem_fdro); +fifo32_create(>fdro_data, 8 * KiB / sizeof(uint32_t)); +} + +static void cfu_fdro_reset_enter(Object *obj, ResetType type) +{ +XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(obj); + +fifo32_reset(>fdro_data); +} + +static void cfu_fdro_cfi_transfer_packet(XlnxCfiIf *cfi_if, XlnxCfiPacket *pkt) +{ +XlnxVersalCFUFDRO *s = XLNX_VERSAL_CFU_FDRO(cfi_if); + +if (fifo32_num_free(>fdro_data) >= ARRAY_SIZE(pkt->data)) { +for (int i = 0; i < ARRAY_SIZE(pkt->data); i++) { +fifo32_push(>fdro_data, pkt->data[i]); +} +} else { +/* It is a programming error to fill the fifo. */ +qemu_log_mask(LOG_GUEST_ERROR, + "CFU_FDRO: CFI data dropped due to full read fifo\n"); +} +} + static Property cfu_props[] = { DEFINE_PROP_LINK("cframe0", XlnxVersalCFUAPB, cfg.cframe[0], TYPE_XLNX_CFI_IF, XlnxCfiIf *), @@ -351,6 +413,16 @@ static const VMStateDescription vmstate_cfu_apb = { } }; +static const VMStateDescription vmstate_cfu_fdro = { +.name = TYPE_XLNX_VERSAL_CFU_FDRO, +.version_id = 1, +.minimum_version_id = 1, +.fields = (VMStateField[]) { +VMSTATE_FIFO32(fdro_data, XlnxVersalCFUFDRO), +VMSTATE_END_OF_LIST(), +} +}; + static void cfu_apb_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -360,6 +432,17 @@ static void cfu_apb_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, cfu_props); } +static void cfu_fdro_class_init(ObjectClass *klass, void *data) +{ +DeviceClass *dc = DEVICE_CLASS(klass); +ResettableClass *rc = RESETTABLE_CLASS(klass); +XlnxCfiIfClass *xcic = XLNX_CFI_IF_CLASS(klass); + +dc->vmsd = _cfu_fdro; +xcic->cfi_transfer_packet = cfu_fdro_cfi_transfer_packet; +rc->phases.enter = cfu_fdro_reset_enter; +} + static const TypeInfo cfu_apb_info = { .name = TYPE_XLNX_VERSAL_CFU_APB, .parent= TYPE_SYS_BUS_DEVICE, @@ -372,9 +455,22 @@ static const TypeInfo cfu_apb_info = { } }; +static const TypeInfo cfu_fdro_info = { +.name = TYPE_XLNX_VERSAL_CFU_FDRO, +.parent= TYPE_SYS_BUS_DEVICE, +.instance_size = sizeof(XlnxVersalCFUFDRO), +.class_init= cfu_fdro_class_init, +.instance_init = cfu_fdro_init, +.interfaces = (InterfaceInfo[]) { +{ TYPE_XLNX_CFI_IF }, +{ } +} +}; + static void cfu_apb_register_types(void) { type_register_static(_apb_info); +type_register_static(_fdro_info); } type_init(cfu_apb_register_types) diff --git a/include/hw/misc/xlnx-versal-cfu.h b/include/hw/misc/xlnx-versal-cfu.h index 62d10caf27..73e9a21af4 100644 --- a/include/hw/misc/xlnx-versal-cfu.h +++ b/include/hw/misc/xlnx-versal-cfu.h @@ -20,10 +20,14 @@ #include "hw/sysbus.h" #include "hw/register.h" #include "hw/misc/xlnx-cfi-if.h" +#include
[PATCH v3 8/8] hw/arm/versal: Connect the CFRAME_REG and CFRAME_BCAST_REG
Connect the Configuration Frame controller (CFRAME_REG) and the Configuration Frame broadcast controller (CFRAME_BCAST_REG) to the Versal machine. Signed-off-by: Francisco Iglesias Reviewed-by: Peter Maydell --- hw/arm/xlnx-versal.c | 113 ++- include/hw/arm/xlnx-versal.h | 69 + 2 files changed, 181 insertions(+), 1 deletion(-) diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c index 3f4b4b1560..fa556d8764 100644 --- a/hw/arm/xlnx-versal.c +++ b/hw/arm/xlnx-versal.c @@ -27,7 +27,7 @@ #define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f") #define GEM_REVISION0x40070106 -#define VERSAL_NUM_PMC_APB_IRQS 3 +#define VERSAL_NUM_PMC_APB_IRQS 18 #define NUM_OSPI_IRQ_LINES 3 static void versal_create_apu_cpus(Versal *s) @@ -341,6 +341,7 @@ static void versal_create_pmc_apb_irq_orgate(Versal *s, qemu_irq *pic) * - RTC * - BBRAM * - PMC SLCR + * - CFRAME regs (input 3 - 17 to the orgate) */ object_initialize_child(OBJECT(s), "pmc-apb-irq-orgate", >pmc.apb_irq_orgate, TYPE_OR_IRQ); @@ -573,6 +574,42 @@ static void versal_create_ospi(Versal *s, qemu_irq *pic) static void versal_create_cfu(Versal *s, qemu_irq *pic) { SysBusDevice *sbd; +DeviceState *dev; +int i; +const struct { +uint64_t reg_base; +uint64_t fdri_base; +} cframe_addr[] = { +{ MM_PMC_CFRAME0_REG, MM_PMC_CFRAME0_FDRI }, +{ MM_PMC_CFRAME1_REG, MM_PMC_CFRAME1_FDRI }, +{ MM_PMC_CFRAME2_REG, MM_PMC_CFRAME2_FDRI }, +{ MM_PMC_CFRAME3_REG, MM_PMC_CFRAME3_FDRI }, +{ MM_PMC_CFRAME4_REG, MM_PMC_CFRAME4_FDRI }, +{ MM_PMC_CFRAME5_REG, MM_PMC_CFRAME5_FDRI }, +{ MM_PMC_CFRAME6_REG, MM_PMC_CFRAME6_FDRI }, +{ MM_PMC_CFRAME7_REG, MM_PMC_CFRAME7_FDRI }, +{ MM_PMC_CFRAME8_REG, MM_PMC_CFRAME8_FDRI }, +{ MM_PMC_CFRAME9_REG, MM_PMC_CFRAME9_FDRI }, +{ MM_PMC_CFRAME10_REG, MM_PMC_CFRAME10_FDRI }, +{ MM_PMC_CFRAME11_REG, MM_PMC_CFRAME11_FDRI }, +{ MM_PMC_CFRAME12_REG, MM_PMC_CFRAME12_FDRI }, +{ MM_PMC_CFRAME13_REG, MM_PMC_CFRAME13_FDRI }, +{ MM_PMC_CFRAME14_REG, MM_PMC_CFRAME14_FDRI }, +}; +const struct { +uint32_t blktype0_frames; +uint32_t blktype1_frames; +uint32_t blktype2_frames; +uint32_t blktype3_frames; +uint32_t blktype4_frames; +uint32_t blktype5_frames; +uint32_t blktype6_frames; +} cframe_cfg[] = { +[0] = { 34111, 3528, 12800, 11, 5, 1, 1 }, +[1] = { 38498, 3841, 15361, 13, 7, 3, 1 }, +[2] = { 38498, 3841, 15361, 13, 7, 3, 1 }, +[3] = { 38498, 3841, 15361, 13, 7, 3, 1 }, +}; /* CFU FDRO */ object_initialize_child(OBJECT(s), "cfu-fdro", >pmc.cfu_fdro, @@ -583,10 +620,84 @@ static void versal_create_cfu(Versal *s, qemu_irq *pic) memory_region_add_subregion(>mr_ps, MM_PMC_CFU_FDRO, sysbus_mmio_get_region(sbd, 0)); +/* CFRAME REG */ +for (i = 0; i < ARRAY_SIZE(s->pmc.cframe); i++) { +g_autofree char *name = g_strdup_printf("cframe%d", i); + +object_initialize_child(OBJECT(s), name, >pmc.cframe[i], +TYPE_XLNX_VERSAL_CFRAME_REG); + +sbd = SYS_BUS_DEVICE(>pmc.cframe[i]); +dev = DEVICE(>pmc.cframe[i]); + +if (i < ARRAY_SIZE(cframe_cfg)) { +object_property_set_int(OBJECT(dev), "blktype0-frames", +cframe_cfg[i].blktype0_frames, +_abort); +object_property_set_int(OBJECT(dev), "blktype1-frames", +cframe_cfg[i].blktype1_frames, +_abort); +object_property_set_int(OBJECT(dev), "blktype2-frames", +cframe_cfg[i].blktype2_frames, +_abort); +object_property_set_int(OBJECT(dev), "blktype3-frames", +cframe_cfg[i].blktype3_frames, +_abort); +object_property_set_int(OBJECT(dev), "blktype4-frames", +cframe_cfg[i].blktype4_frames, +_abort); +object_property_set_int(OBJECT(dev), "blktype5-frames", +cframe_cfg[i].blktype5_frames, +_abort); +object_property_set_int(OBJECT(dev), "blktype6-frames", +cframe_cfg[i].blktype6_frames, +_abort); +} +object_property_set_link(OBJECT(dev), "cfu-fdro", + OBJECT(>pmc.cfu_fdro), _fatal); + +sysbus_realize(SYS_BUS_DEVICE(dev), _fatal); + +memory_region_add_subregion(>mr_ps,
Re: Failing avocado tests in CI (was: Re: [PULL 00/24] tcg + linux-user queue for 8.1-rc3)
On 8/24/23 08:31, Alex Bennée wrote: It's some sort of timing issue, which sometimes goes away when re-run. I was re-running tests *a lot* in order to get them to go green while running the 8.1 release. There is a definite regression point for the test_pc_q35 case: Not exactly "definite" because it does vanish. which bisects to: commit f7eaf9d702efdd02481d5f1c25f7d8e0ffb64c6e (HEAD, refs/bisect/bad) Author: Richard Henderson Date: Tue Aug 1 10:46:03 2023 -0700 accel/tcg: Do not issue misaligned i/o Well, since you can reproduce it, would you please debug it. r~
[PATCH v2 00/48] tcg patch queue
The following changes since commit 50e7a40af372ee5931c99ef7390f5d3d6fbf6ec4: Merge tag 'pull-target-arm-20230824' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2023-08-24 10:08:33 -0400) are available in the Git repository at: https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230823-2 for you to fetch changes up to 4daad8d9d6b9d426beb8ce505d2164ba36ea3168: tcg: spelling fixes (2023-08-24 11:22:42 -0700) accel/*: Widen pc/saved_insn for *_sw_breakpoint accel/tcg: Replace remaining target_ulong in system-mode accel tcg: spelling fixes tcg: Document bswap, hswap, wswap byte patterns tcg: Introduce negsetcond opcodes tcg: Fold deposit with zero to and tcg: Unify TCG_TARGET_HAS_extr[lh]_i64_i32 tcg/i386: Drop BYTEH deposits for 64-bit tcg/i386: Allow immediate as input to deposit target/*: Use tcg_gen_negsetcond_* Anton Johansson (9): accel/kvm: Widen pc/saved_insn for kvm_sw_breakpoint accel/hvf: Widen pc/saved_insn for hvf_sw_breakpoint sysemu/kvm: Use vaddr for kvm_arch_[insert|remove]_hw_breakpoint sysemu/hvf: Use vaddr for hvf_arch_[insert|remove]_hw_breakpoint include/exec: Replace target_ulong with abi_ptr in cpu_[st|ld]*() include/exec: typedef abi_ptr to vaddr in softmmu include/exec: Widen tlb_hit/tlb_hit_page() accel/tcg: Widen address arg in tlb_compare_set() accel/tcg: Update run_on_cpu_data static assert Mark Cave-Ayland (1): docs/devel/tcg-ops: fix missing newlines in "Host vector operations" Michael Tokarev (1): tcg: spelling fixes Philippe Mathieu-Daudé (9): docs/devel/tcg-ops: Bury mentions of trunc_shr_i64_i32() tcg/tcg-op: Document bswap16_i32() byte pattern tcg/tcg-op: Document bswap16_i64() byte pattern tcg/tcg-op: Document bswap32_i32() byte pattern tcg/tcg-op: Document bswap32_i64() byte pattern tcg/tcg-op: Document bswap64_i64() byte pattern tcg/tcg-op: Document hswap_i32/64() byte pattern tcg/tcg-op: Document wswap_i64() byte pattern target/cris: Fix a typo in gen_swapr() Richard Henderson (28): target/m68k: Use tcg_gen_deposit_i32 in gen_partset_reg tcg/i386: Drop BYTEH deposits for 64-bit tcg: Fold deposit with zero to and tcg/i386: Allow immediate as input to deposit_* tcg: Unify TCG_TARGET_HAS_extr[lh]_i64_i32 tcg: Introduce negsetcond opcodes tcg: Use tcg_gen_negsetcond_* target/alpha: Use tcg_gen_movcond_i64 in gen_fold_mzero target/arm: Use tcg_gen_negsetcond_* target/m68k: Use tcg_gen_negsetcond_* target/openrisc: Use tcg_gen_negsetcond_* target/ppc: Use tcg_gen_negsetcond_* target/sparc: Use tcg_gen_movcond_i64 in gen_edge target/tricore: Replace gen_cond_w with tcg_gen_negsetcond_tl tcg/ppc: Implement negsetcond_* tcg/ppc: Use the Set Boolean Extension tcg/aarch64: Implement negsetcond_* tcg/arm: Implement negsetcond_i32 tcg/riscv: Implement negsetcond_* tcg/s390x: Implement negsetcond_* tcg/sparc64: Implement negsetcond_* tcg/i386: Merge tcg_out_brcond{32,64} tcg/i386: Merge tcg_out_setcond{32,64} tcg/i386: Merge tcg_out_movcond{32,64} tcg/i386: Use CMP+SBB in tcg_out_setcond tcg/i386: Clear dest first in tcg_out_setcond if possible tcg/i386: Use shift in tcg_out_setcond tcg/i386: Implement negsetcond_* docs/devel/tcg-ops.rst | 15 +- accel/tcg/atomic_template.h| 16 +- include/exec/cpu-all.h | 4 +- include/exec/cpu_ldst.h| 28 +-- include/sysemu/hvf.h | 12 +- include/sysemu/kvm.h | 12 +- include/tcg/tcg-op-common.h| 4 + include/tcg/tcg-op.h | 2 + include/tcg/tcg-opc.h | 6 +- include/tcg/tcg.h | 4 +- tcg/aarch64/tcg-target.h | 5 +- tcg/arm/tcg-target.h | 1 + tcg/i386/tcg-target-con-set.h | 2 +- tcg/i386/tcg-target-con-str.h | 1 - tcg/i386/tcg-target.h | 9 +- tcg/loongarch64/tcg-target.h | 6 +- tcg/mips/tcg-target.h | 5 +- tcg/ppc/tcg-target.h | 5 +- tcg/riscv/tcg-target.h | 5 +- tcg/s390x/tcg-target.h | 5 +- tcg/sparc64/tcg-target.h | 5 +- tcg/tci/tcg-target.h | 5 +- accel/hvf/hvf-accel-ops.c | 4 +- accel/hvf/hvf-all.c| 2 +- accel/kvm/kvm-all.c| 3 +- accel/tcg/cputlb.c | 17 +- target/alpha/translate.c | 7 +- targ
Re: [PATCH 2/2] io: follow coroutine AioContext in qio_channel_yield()
On Thu, Aug 24, 2023 at 12:26:05PM +0100, Daniel P. Berrangé wrote: > On Wed, Aug 23, 2023 at 07:45:04PM -0400, Stefan Hajnoczi wrote: > > The ongoing QEMU multi-queue block layer effort makes it possible for > > multiple > > threads to process I/O in parallel. The nbd block driver is not compatible > > with > > the multi-queue block layer yet because QIOChannel cannot be used easily > > from > > coroutines running in multiple threads. This series changes the QIOChannel > > API > > to make that possible. > > > > In the current API, calling qio_channel_attach_aio_context() sets the > > AioContext where qio_channel_yield() installs an fd handler prior to > > yielding: > > > > qio_channel_attach_aio_context(ioc, my_ctx); > > ... > > qio_channel_yield(ioc); // my_ctx is used here > > ... > > qio_channel_detach_aio_context(ioc); > > > > This API design has limitations: reading and writing must be done in the > > same > > AioContext and moving between AioContexts involves a cumbersome sequence of > > API > > calls that is not suitable for doing on a per-request basis. > > > > There is no fundamental reason why a QIOChannel needs to run within the > > same AioContext every time qio_channel_yield() is called. QIOChannel > > only uses the AioContext while inside qio_channel_yield(). The rest of > > the time, QIOChannel is independent of any AioContext. > > > > In the new API, qio_channel_yield() queries the AioContext from the current > > coroutine using qemu_coroutine_get_aio_context(). There is no need to > > explicitly attach/detach AioContexts anymore and > > qio_channel_attach_aio_context() and qio_channel_detach_aio_context() are > > gone. > > One coroutine can read from the QIOChannel while another coroutine writes > > from > > a different AioContext. > > > > This API change allows the nbd block driver to use QIOChannel from any > > thread. > > It's important to keep in mind that the block driver already synchronizes > > QIOChannel access and ensures that two coroutines never read simultaneously > > or > > write simultaneously. > > > > This patch updates all users of qio_channel_attach_aio_context() to the > > new API. Most conversions are simple, but vhost-user-server requires a > > new qemu_coroutine_yield() call to quiesce the vu_client_trip() > > coroutine when not attached to any AioContext. > > > > While the API is has become simpler, there is one wart: QIOChannel has a > > special case for the iohandler AioContext (used for handlers that must not > > run > > in nested event loops). I didn't find an elegant way preserve that > > behavior, so > > I added a new API called qio_channel_set_follow_coroutine_ctx(ioc, > > true|false) > > for opting in to the new AioContext model. By default QIOChannel uses the > > iohandler AioHandler. Code that formerly called > > qio_channel_attach_aio_context() now calls > > qio_channel_set_follow_coroutine_ctx(ioc, true) once after the QIOChannel is > > created. > > I wonder if it is better to just pass the AioContext object into > qio_channel_yield explicitly eg have > > qio_channel_yield(QIOChannel *ioc, > AioContext *ctx, > GIOCondition cond); > > With semantics that if 'ctx == NULL', then we assume the default > global iohandler context, and for non-default context it must > be non-NULL ? > > That could nicely de-couple the API from relying on global > coroutine/thread state for querying an AioContext, which > makes it easier to reason about IMHO. Hi Dan, I've done most of the audit necessary to understand which AioContext is used where. The call graph is large because qio_channel_yield() is used internally by qio_channel_readv_full_all_eof(), qio_channel_writev_full_all(), and their variants. They would all need a new AioContext argument. I think it's not worth passing AioContext explicitly everywhere since this involves a lot of code changes and more verbosity to achieve what we already have. However, If you think the QIOChannel API should pass AioContext explicitly then I'll go ahead and make the changes. Here is what I've explored so far: qio_channel_readv_full_all_eof mpqemu_read - should be doable qio_channel_readv_all_eof qio_channel_read_all_eof multifd_recv_thread - NULL non-coroutine vu_message_read - coroutine AioContext qio_channel_readv_full_all hw/virtio/vhost-user.c:backend_read() - NULL non-coroutine qio_channel_readv_all nbd_co_receive_offset_data_payload - coroutine AioContext nbd_co_do_receive_one_chunk - coroutine AioContext qio_channel_read_all hw/virtio/vhost-user.c:backend_read() - NULL non-coroutine tpm_emulator_unix_tx_bufs - NULL non-coroutine nbd_read - ? zlib_recv_pages - NULL non-coroutine zstd_recv_pages - NULL non-coroutine multifd_initial_recv_packet - NULL non-coroutine nbd_opt_read - iohandler pr_manager_helper_read - NULL non-coroutine
Re: [PATCH 1/2] io: check there are no qio_channel_yield() coroutines during ->finalize()
On Wed, Aug 23, 2023 at 07:45:03PM -0400, Stefan Hajnoczi wrote: > Callers must clean up their coroutines before calling > object_unref(OBJECT(ioc)) to prevent an fd handler leak. Add an > assertion to check this. > > This patch is preparation for the fd handler changes that follow. > > Signed-off-by: Stefan Hajnoczi > --- > io/channel.c | 4 > 1 file changed, 4 insertions(+) Reviewed-by: Eric Blake -- Eric Blake, Principal Software Engineer Red Hat, Inc. Virtualization: qemu.org | libguestfs.org
[RFC PATCH 0/2] target/sh4: Disable decode_gusa when plugins enabled
Alex, perhaps this will DTRT for your plugin test case. r~ Richard Henderson (2): accel/tcg: Add plugin_enabled to DisasContextBase target/sh4: Disable decode_gusa when plugins enabled include/exec/translator.h | 2 ++ accel/tcg/translator.c| 1 + target/sh4/translate.c| 41 +++ 3 files changed, 32 insertions(+), 12 deletions(-) -- 2.34.1