From 32226db011622fa7b791de3ac02ba67c21947f1d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 18 Jul 2022 15:23:09 +0100 Subject: [PATCH 0001/1020] scripts/coverity-scan/COMPONENTS.md: Add loongarch component Add the component regex for the new loongarch target. Signed-off-by: Peter Maydell Acked-by: Paolo Bonzini Message-id: 20220718142310.16013-2-peter.maydell@linaro.org --- scripts/coverity-scan/COMPONENTS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/coverity-scan/COMPONENTS.md b/scripts/coverity-scan/COMPONENTS.md index de2eb96241..a61d011d9a 100644 --- a/scripts/coverity-scan/COMPONENTS.md +++ b/scripts/coverity-scan/COMPONENTS.md @@ -143,3 +143,6 @@ testlibs tests ~ (/qemu)?(/tests/.*) + +loongarch + ~ (/qemu)?((/include)?/hw/(loongarch/.*|.*/loongarch.*)|/target/loongarch/.*) From 02b7035d15726b68bb94f12e2e0d92087da34708 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 18 Jul 2022 15:23:10 +0100 Subject: [PATCH 0002/1020] scripts/coverity-scan/COMPONENTS.md: Update slirp component info Update the regex for the slirp component now that it lives solely inside /slirp/, and note that it should be ignored in Coverity analysis (because it's a separate upstream project now, and they run Coverity on it themselves). Signed-off-by: Peter Maydell Acked-by: Paolo Bonzini Message-id: 20220718142310.16013-3-peter.maydell@linaro.org --- scripts/coverity-scan/COMPONENTS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/coverity-scan/COMPONENTS.md b/scripts/coverity-scan/COMPONENTS.md index a61d011d9a..3aad9cdfaf 100644 --- a/scripts/coverity-scan/COMPONENTS.md +++ b/scripts/coverity-scan/COMPONENTS.md @@ -108,8 +108,8 @@ qemu-ga scsi ~ (/qemu)?(/scsi/.*|/hw/scsi/.*|/include/hw/scsi/.*) -slirp - ~ (/qemu)?(/.*slirp.*) +slirp (component should be ignored in analysis) + ~ (/qemu)?(/slirp/.*) tcg ~ (/qemu)?(/accel/tcg/.*|/replay/.*|/(.*/)?softmmu.*) From fca75f60abbf2a7f88264977ff0bb3ff4285989c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 18 Jul 2022 11:01:44 +0100 Subject: [PATCH 0003/1020] target/arm: Add MO_128 entry to pred_esz_masks[] In commit 7390e0e9ab8475, we added support for SME loads and stores. Unlike SVE loads and stores, these include handling of 128-bit elements. The SME load/store functions call down into the existing sve_cont_ldst_elements() function, which uses the element size MO_* value as an index into the pred_esz_masks[] array. Because this code path now has to handle MO_128, we need to add an extra element to the array. This bug was spotted by Coverity because it meant we were reading off the end of the array. Resolves: Coverity CID 1490539, 1490541, 1490543, 1490544, 1490545, 1490546, 1490548, 1490549, 1490550, 1490551, 1490555, 1490557, 1490558, 1490560, 1490561, 1490563 Fixes: 7390e0e9ab8475 ("target/arm: Implement SME LD1, ST1") Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220718100144.3248052-1-peter.maydell@linaro.org --- target/arm/cpu.h | 2 +- target/arm/translate-sve.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index e890ee074d..5168e3d837 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3387,7 +3387,7 @@ static inline uint64_t *aa64_vfp_qreg(CPUARMState *env, unsigned regno) } /* Shared between translate-sve.c and sve_helper.c. */ -extern const uint64_t pred_esz_masks[4]; +extern const uint64_t pred_esz_masks[5]; /* Helper for the macros below, validating the argument type. */ static inline MemTxAttrs *typecheck_memtxattrs(MemTxAttrs *x) diff --git a/target/arm/translate-sve.c b/target/arm/translate-sve.c index 41f8b12259..621a2abb22 100644 --- a/target/arm/translate-sve.c +++ b/target/arm/translate-sve.c @@ -529,9 +529,10 @@ static void do_predtest(DisasContext *s, int dofs, int gofs, int words) } /* For each element size, the bits within a predicate word that are active. */ -const uint64_t pred_esz_masks[4] = { +const uint64_t pred_esz_masks[5] = { 0xffffffffffffffffull, 0x5555555555555555ull, - 0x1111111111111111ull, 0x0101010101010101ull + 0x1111111111111111ull, 0x0101010101010101ull, + 0x0001000100010001ull, }; static bool trans_INVALID(DisasContext *s, arg_INVALID *a) From 35a7a6fc5624b1df828d82f2dfa74d0e4188b3b2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 20 Jul 2022 16:26:27 +0100 Subject: [PATCH 0004/1020] configure: Add missing POSIX-required space In commit 7d7dbf9dc15be6e1 we added a line to the configure script which is not valid POSIX shell syntax, because it is missing a space after a '!' character. shellcheck diagnoses this: if !(GIT="$git" "$source_path/scripts/git-submodule.sh" "$git_submodules_action" "$git_submodules"); then ^-- SC1035: You are missing a required space after the !. and the OpenBSD shell will not correctly handle this without the space. Fixes: 7d7dbf9dc15be6e1 ("configure: replace --enable/disable-git-update with --with-git-submodules") Signed-off-by: Peter Maydell Reviewed-by: Thomas Huth Tested-by: Dr. David Alan Gilbert Message-id: 20220720152631.450903-2-peter.maydell@linaro.org --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 35e0b28198..dec6f03034 100755 --- a/configure +++ b/configure @@ -2425,7 +2425,7 @@ else cxx= fi -if !(GIT="$git" "$source_path/scripts/git-submodule.sh" "$git_submodules_action" "$git_submodules"); then +if ! (GIT="$git" "$source_path/scripts/git-submodule.sh" "$git_submodules_action" "$git_submodules"); then exit 1 fi From d466d416ed51aa72d2bfde2e2b44293bf6d73472 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 20 Jul 2022 16:26:28 +0100 Subject: [PATCH 0005/1020] configure: Add braces to clarify intent of $emu[[:space:]] In shell script syntax, $var[something] is not special for variable expansion: $var is expanded. However, as it can look as if it were intended to be an array element access (the correct syntax for which is ${var[something]}), shellcheck recommends using explicit braces around ${var} to clarify the intended expansion. This fixes the warning: In ./configure line 2346: if "$target_ld" -verbose 2>&1 | grep -q "^[[:space:]]*$emu[[:space:]]*$"; then ^-- SC1087: Use braces when expanding arrays, e.g. ${array[idx]} (or ${var}[.. to quiet). Signed-off-by: Peter Maydell Reviewed-by: Thomas Huth Message-id: 20220720152631.450903-3-peter.maydell@linaro.org --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index dec6f03034..a56c3d921b 100755 --- a/configure +++ b/configure @@ -2343,7 +2343,7 @@ if test -n "$target_cc" && # emulation. Linux and OpenBSD/amd64 use 'elf_i386'; FreeBSD uses the _fbsd # variant; OpenBSD/i386 uses the _obsd variant; and Windows uses i386pe. for emu in elf_i386 elf_i386_fbsd elf_i386_obsd i386pe; do - if "$target_ld" -verbose 2>&1 | grep -q "^[[:space:]]*$emu[[:space:]]*$"; then + if "$target_ld" -verbose 2>&1 | grep -q "^[[:space:]]*${emu}[[:space:]]*$"; then ld_i386_emulation="$emu" break fi From 65842b03d112070bbc3216841eb879c1fc42523a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 20 Jul 2022 16:26:29 +0100 Subject: [PATCH 0006/1020] configure: Don't use bash-specific string-replacement syntax The variable string-replacement syntax ${var/old/new} is a bashism (though it is also supported by some other shells), and for instance does not work with the NetBSD /bin/sh, which complains: ../src/configure: 687: Syntax error: Bad substitution Replace it with a more portable sed-based approach, similar to what we already do in quote_sh(). Note that shellcheck also diagnoses this: In ./configure line 687: e=${e/'\'/'\\'} ^-----------^ SC2039: In POSIX sh, string replacement is undefined. ^-- SC1003: Want to escape a single quote? echo 'This is how it'\''s done'. ^-- SC1003: Want to escape a single quote? echo 'This is how it'\''s done'. In ./configure line 688: e=${e/\"/'\"'} ^----------^ SC2039: In POSIX sh, string replacement is undefined. Fixes: 8154f5e64b0cf ("meson: Prefix each element of firmware path") Signed-off-by: Peter Maydell Tested-by: Thomas Huth Message-id: 20220720152631.450903-4-peter.maydell@linaro.org --- configure | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configure b/configure index a56c3d921b..c05205b608 100755 --- a/configure +++ b/configure @@ -684,9 +684,10 @@ meson_option_build_array() { IFS=: fi for e in $1; do - e=${e/'\'/'\\'} - e=${e/\"/'\"'} - printf '"""%s""",' "$e" + printf '"""' + # backslash escape any '\' and '"' characters + printf "%s" "$e" | sed -e 's/\([\"]\)/\\\1/g' + printf '""",' done) printf ']\n' } From aca5001dab50e8279826650e57abedd4f0d9765f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 20 Jul 2022 16:26:30 +0100 Subject: [PATCH 0007/1020] configure: Drop dead code attempting to use -msmall-data on alpha hosts In commit 823eb013452e93d we moved the setting of ARCH from configure to meson.build, but we accidentally left behind one attempt to use $ARCH in configure, which was trying to add -msmall-data to the compiler flags on Alpha hosts. Since ARCH is now never set, the test always fails and we never add the flag. There isn't actually any need to use this compiler flag on Alpha: the original intent was that it would allow us to simplify our TCG codegen on that platform, but we never actually made the TCG changes that would rely on -msmall-data. Drop the effectively-dead code from configure, as we don't need it. This was spotted by shellcheck: In ./configure line 2254: case "$ARCH" in ^---^ SC2153: Possible misspelling: ARCH may not be assigned, but arch is. Signed-off-by: Peter Maydell Reviewed-by: Thomas Huth Message-id: 20220720152631.450903-5-peter.maydell@linaro.org --- configure | 7 ------- 1 file changed, 7 deletions(-) diff --git a/configure b/configure index c05205b608..d0e9a51462 100755 --- a/configure +++ b/configure @@ -2251,13 +2251,6 @@ if test "$fortify_source" = "yes" ; then QEMU_CFLAGS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $QEMU_CFLAGS" fi -case "$ARCH" in -alpha) - # Ensure there's only a single GP - QEMU_CFLAGS="-msmall-data $QEMU_CFLAGS" -;; -esac - if test "$have_asan" = "yes"; then QEMU_CFLAGS="-fsanitize=address $QEMU_CFLAGS" QEMU_LDFLAGS="-fsanitize=address $QEMU_LDFLAGS" From c5cfdabaf5ba0963292d3f0e318170ae9fab3fcc Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Wed, 20 Jul 2022 16:26:31 +0100 Subject: [PATCH 0008/1020] configure: Avoid '==' bashism The '==' operator to test is a bashism; the standard way to copmare strings is '='. This causes dash to complain: ../../configure: 681: test: linux: unexpected operator Signed-off-by: Peter Maydell Reviewed-by: Thomas Huth Message-id: 20220720152631.450903-6-peter.maydell@linaro.org --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index d0e9a51462..2c19329d58 100755 --- a/configure +++ b/configure @@ -678,7 +678,7 @@ werror="" meson_option_build_array() { printf '[' - (if test "$targetos" == windows; then + (if test "$targetos" = windows; then IFS=\; else IFS=: From 5865d99fe88d8c8fa437c18c6b63fb2a8165634f Mon Sep 17 00:00:00 2001 From: Alan Jian Date: Mon, 25 Jul 2022 22:58:39 +0800 Subject: [PATCH 0009/1020] hw/display/bcm2835_fb: Fix framebuffer allocation address This patch fixes the dedicated framebuffer mailbox interface by removing an unneeded offset. This means that we pick the framebuffer address in the same way that we do if the guest code uses the buffer allocate mechanism of the bcm2835_property interface (case 0x00040001: /* Allocate buffer */ in bcm2835_property.c). The documentation of this mailbox interface doesn't say anything about using parts of the request buffer address to affect the chosen framebuffer address: https://github.com/raspberrypi/firmware/wiki/Mailbox-framebuffer-interface Some baremetal applications like the Screen01/Screen02 examples from Baking Pi tutorial[1] didn't work before this patch. [1] https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/screen01.html Signed-off-by: Alan Jian Message-id: 20220725145838.8412-1-alanjian85@outlook.com [PMM: tweaked commit message] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/display/bcm2835_fb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c index 088fc3d51c..a05277674f 100644 --- a/hw/display/bcm2835_fb.c +++ b/hw/display/bcm2835_fb.c @@ -279,8 +279,7 @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value) newconf.xoffset = ldl_le_phys(&s->dma_as, value + 24); newconf.yoffset = ldl_le_phys(&s->dma_as, value + 28); - newconf.base = s->vcram_base | (value & 0xc0000000); - newconf.base += BCM2835_FB_OFFSET; + newconf.base = s->vcram_base + BCM2835_FB_OFFSET; /* Copy fields which we don't want to change from the existing config */ newconf.pixo = s->config.pixo; From e4bcec0c3c8527a3f2be2791fa6a89387b9116c1 Mon Sep 17 00:00:00 2001 From: Robert Hoo Date: Mon, 4 Jul 2022 16:58:52 +0800 Subject: [PATCH 0010/1020] acpi/nvdimm: Define trace events for NVDIMM and substitute nvdimm_debug() Signed-off-by: Robert Hoo Reviewed-by: Jingqi Liu Message-Id: <20220704085852.330005-1-robert.hu@linux.intel.com> Reviewed-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/acpi/nvdimm.c | 35 ++++++++++++++++------------------- hw/acpi/trace-events | 13 +++++++++++++ include/hw/mem/nvdimm.h | 8 -------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c index 5f85b16327..31e46df0bd 100644 --- a/hw/acpi/nvdimm.c +++ b/hw/acpi/nvdimm.c @@ -35,6 +35,7 @@ #include "hw/nvram/fw_cfg.h" #include "hw/mem/nvdimm.h" #include "qemu/nvdimm-utils.h" +#include "trace.h" /* * define Byte Addressable Persistent Memory (PM) Region according to @@ -550,8 +551,8 @@ static void nvdimm_dsm_func_read_fit(NVDIMMState *state, NvdimmDsmIn *in, fit = fit_buf->fit; - nvdimm_debug("Read FIT: offset 0x%x FIT size 0x%x Dirty %s.\n", - read_fit->offset, fit->len, fit_buf->dirty ? "Yes" : "No"); + trace_acpi_nvdimm_read_fit(read_fit->offset, fit->len, + fit_buf->dirty ? "Yes" : "No"); if (read_fit->offset > fit->len) { func_ret_status = NVDIMM_DSM_RET_STATUS_INVALID; @@ -658,7 +659,7 @@ static void nvdimm_dsm_label_size(NVDIMMDevice *nvdimm, hwaddr dsm_mem_addr) label_size = nvdimm->label_size; mxfer = nvdimm_get_max_xfer_label_size(); - nvdimm_debug("label_size 0x%x, max_xfer 0x%x.\n", label_size, mxfer); + trace_acpi_nvdimm_label_info(label_size, mxfer); label_size_out.func_ret_status = cpu_to_le32(NVDIMM_DSM_RET_STATUS_SUCCESS); label_size_out.label_size = cpu_to_le32(label_size); @@ -674,20 +675,18 @@ static uint32_t nvdimm_rw_label_data_check(NVDIMMDevice *nvdimm, uint32_t ret = NVDIMM_DSM_RET_STATUS_INVALID; if (offset + length < offset) { - nvdimm_debug("offset 0x%x + length 0x%x is overflow.\n", offset, - length); + trace_acpi_nvdimm_label_overflow(offset, length); return ret; } if (nvdimm->label_size < offset + length) { - nvdimm_debug("position 0x%x is beyond label data (len = %" PRIx64 ").\n", - offset + length, nvdimm->label_size); + trace_acpi_nvdimm_label_oversize(offset + length, nvdimm->label_size); return ret; } if (length > nvdimm_get_max_xfer_label_size()) { - nvdimm_debug("length (0x%x) is larger than max_xfer (0x%x).\n", - length, nvdimm_get_max_xfer_label_size()); + trace_acpi_nvdimm_label_xfer_exceed(length, + nvdimm_get_max_xfer_label_size()); return ret; } @@ -710,8 +709,8 @@ static void nvdimm_dsm_get_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in, get_label_data->offset = le32_to_cpu(get_label_data->offset); get_label_data->length = le32_to_cpu(get_label_data->length); - nvdimm_debug("Read Label Data: offset 0x%x length 0x%x.\n", - get_label_data->offset, get_label_data->length); + trace_acpi_nvdimm_read_label(get_label_data->offset, + get_label_data->length); status = nvdimm_rw_label_data_check(nvdimm, get_label_data->offset, get_label_data->length); @@ -749,8 +748,8 @@ static void nvdimm_dsm_set_label_data(NVDIMMDevice *nvdimm, NvdimmDsmIn *in, set_label_data->offset = le32_to_cpu(set_label_data->offset); set_label_data->length = le32_to_cpu(set_label_data->length); - nvdimm_debug("Write Label Data: offset 0x%x length 0x%x.\n", - set_label_data->offset, set_label_data->length); + trace_acpi_nvdimm_write_label(set_label_data->offset, + set_label_data->length); status = nvdimm_rw_label_data_check(nvdimm, set_label_data->offset, set_label_data->length); @@ -821,7 +820,7 @@ static void nvdimm_dsm_device(NvdimmDsmIn *in, hwaddr dsm_mem_addr) static uint64_t nvdimm_dsm_read(void *opaque, hwaddr addr, unsigned size) { - nvdimm_debug("BUG: we never read _DSM IO Port.\n"); + trace_acpi_nvdimm_read_io_port(); return 0; } @@ -832,7 +831,7 @@ nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) NvdimmDsmIn *in; hwaddr dsm_mem_addr = val; - nvdimm_debug("dsm memory address 0x%" HWADDR_PRIx ".\n", dsm_mem_addr); + trace_acpi_nvdimm_dsm_mem_addr(dsm_mem_addr); /* * The DSM memory is mapped to guest address space so an evil guest @@ -846,12 +845,10 @@ nvdimm_dsm_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) in->function = le32_to_cpu(in->function); in->handle = le32_to_cpu(in->handle); - nvdimm_debug("Revision 0x%x Handler 0x%x Function 0x%x.\n", in->revision, - in->handle, in->function); + trace_acpi_nvdimm_dsm_info(in->revision, in->handle, in->function); if (in->revision != 0x1 /* Currently we only support DSM Spec Rev1. */) { - nvdimm_debug("Revision 0x%x is not supported, expect 0x%x.\n", - in->revision, 0x1); + trace_acpi_nvdimm_invalid_revision(in->revision); nvdimm_dsm_no_payload(NVDIMM_DSM_RET_STATUS_UNSUPPORT, dsm_mem_addr); goto exit; } diff --git a/hw/acpi/trace-events b/hw/acpi/trace-events index 2250126a22..eb60b04f9b 100644 --- a/hw/acpi/trace-events +++ b/hw/acpi/trace-events @@ -70,3 +70,16 @@ acpi_erst_reset_out(unsigned record_count) "record_count %u" acpi_erst_post_load(void *header, unsigned slot_size) "header: 0x%p slot_size %u" acpi_erst_class_init_in(void) acpi_erst_class_init_out(void) + +# nvdimm.c +acpi_nvdimm_read_fit(uint32_t offset, uint32_t len, const char *dirty) "Read FIT: offset 0x%" PRIx32 " FIT size 0x%" PRIx32 " Dirty %s" +acpi_nvdimm_label_info(uint32_t label_size, uint32_t mxfer) "label_size 0x%" PRIx32 ", max_xfer 0x%" PRIx32 +acpi_nvdimm_label_overflow(uint32_t offset, uint32_t length) "offset 0x%" PRIx32 " + length 0x%" PRIx32 " is overflow" +acpi_nvdimm_label_oversize(uint32_t pos, uint64_t size) "position 0x%" PRIx32 " is beyond label data (len = %" PRIu64 ")" +acpi_nvdimm_label_xfer_exceed(uint32_t length, uint32_t max_xfer) "length (0x%" PRIx32 ") is larger than max_xfer (0x%" PRIx32 ")" +acpi_nvdimm_read_label(uint32_t offset, uint32_t length) "Read Label Data: offset 0x%" PRIx32 " length 0x%" PRIx32 +acpi_nvdimm_write_label(uint32_t offset, uint32_t length) "Write Label Data: offset 0x%" PRIx32 " length 0x%" PRIx32 +acpi_nvdimm_read_io_port(void) "Alert: we never read _DSM IO Port" +acpi_nvdimm_dsm_mem_addr(uint64_t dsm_mem_addr) "dsm memory address 0x%" PRIx64 +acpi_nvdimm_dsm_info(uint32_t revision, uint32_t handle, uint32_t function) "Revision 0x%" PRIx32 " Handle 0x%" PRIx32 " Function 0x%" PRIx32 +acpi_nvdimm_invalid_revision(uint32_t revision) "Revision 0x%" PRIx32 " is not supported, expect 0x1" diff --git a/include/hw/mem/nvdimm.h b/include/hw/mem/nvdimm.h index cf8f59be44..acf887c83d 100644 --- a/include/hw/mem/nvdimm.h +++ b/include/hw/mem/nvdimm.h @@ -29,14 +29,6 @@ #include "hw/acpi/aml-build.h" #include "qom/object.h" -#define NVDIMM_DEBUG 0 -#define nvdimm_debug(fmt, ...) \ - do { \ - if (NVDIMM_DEBUG) { \ - fprintf(stderr, "nvdimm: " fmt, ## __VA_ARGS__); \ - } \ - } while (0) - /* * The minimum label data size is required by NVDIMM Namespace * specification, see the chapter 2 Namespaces: From 71a5f07e75ba34072a074181d37009abc28d7083 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 1 Jul 2022 14:22:58 +0100 Subject: [PATCH 0011/1020] hw/machine: Clear out left over CXL related pointer from move of state handling to machines. This got left behind in the move of the CXL setup code from core files to the machines that support it. Link: https://gitlab.com/qemu-project/qemu/-/commit/1ebf9001fb2701e3c00b401334c8f3900a46adaa Signed-off-by: Jonathan Cameron Message-Id: <20220701132300.2264-2-Jonathan.Cameron@huawei.com> Acked-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/boards.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index d94edcef28..7b416c9787 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -360,7 +360,6 @@ struct MachineState { CpuTopology smp; struct NVDIMMState *nvdimms_state; struct NumaState *numa_state; - CXLFixedMemoryWindowOptionsList *cfmws_list; }; #define DEFINE_MACHINE(namestr, machine_initfn) \ From 4a447a710c523392b09391232d5a3dfb156a9d75 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 1 Jul 2022 14:22:59 +0100 Subject: [PATCH 0012/1020] hw/i386/pc: Always place CXL Memory Regions after device_memory Previously broken_reserved_end was taken into account, but Igor Mammedov identified that this could lead to a clash between potential RAM being mapped in the region and CXL usage. Hence always add the size of the device_memory memory region. This only affects the case where the broken_reserved_end flag was set. Fixes: 6e4e3ae936e6 ("hw/cxl/component: Implement host bridge MMIO (8.2.5, table 142)") Reported-by: Igor Mammedov Signed-off-by: Jonathan Cameron Message-Id: <20220701132300.2264-3-Jonathan.Cameron@huawei.com> Acked-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index d2b5823ffb..46ab1dcb47 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -922,10 +922,8 @@ void pc_memory_init(PCMachineState *pcms, hwaddr cxl_size = MiB; if (pcmc->has_reserved_memory && machine->device_memory->base) { - cxl_base = machine->device_memory->base; - if (!pcmc->broken_reserved_end) { - cxl_base += memory_region_size(&machine->device_memory->mr); - } + cxl_base = machine->device_memory->base + + memory_region_size(&machine->device_memory->mr); } else if (pcms->sgx_epc.size != 0) { cxl_base = sgx_epc_above_4g_end(&pcms->sgx_epc); } else { From cb70b7e8712e17e5761a7447defdce5572cd4b80 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 1 Jul 2022 14:23:00 +0100 Subject: [PATCH 0013/1020] hw/cxl: Fix size of constant in interleave granularity function. Whilst the interleave granularity is always small enough that this isn't a real problem (much less than 4GiB) let's change the constant to ULL to fix the coverity warning. Reported-by: Peter Maydell Fixes: 829de299d1 ("hw/cxl/component: Add utils for interleave parameter encoding/decoding") Fixes: Coverity CID 1488868 Signed-off-by: Jonathan Cameron Message-Id: <20220701132300.2264-4-Jonathan.Cameron@huawei.com> Acked-by: Igor Mammedov Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/cxl/cxl_component.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h index 70b5018156..94ec2f07d7 100644 --- a/include/hw/cxl/cxl_component.h +++ b/include/hw/cxl/cxl_component.h @@ -215,7 +215,7 @@ uint8_t cxl_interleave_granularity_enc(uint64_t gran, Error **errp); static inline hwaddr cxl_decode_ig(int ig) { - return 1 << (ig + 8); + return 1ULL << (ig + 8); } CXLComponentState *cxl_get_hb_cstate(PCIHostState *hb); From 4ab4c33014b4876bc6d7888efecd6bfcca0d045a Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:04 +0100 Subject: [PATCH 0014/1020] hw/i386: add 4g boundary start to X86MachineState Rather than hardcoding the 4G boundary everywhere, introduce a X86MachineState field @above_4g_mem_start and use it accordingly. This is in preparation for relocating ram-above-4g to be dynamically start at 1T on AMD platforms. Signed-off-by: Joao Martins Reviewed-by: Igor Mammedov Message-Id: <20220719170014.27028-2-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 2 +- hw/i386/pc.c | 11 ++++++----- hw/i386/sgx.c | 2 +- hw/i386/x86.c | 1 + include/hw/i386/x86.h | 3 +++ 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index cad6f5ac41..0355bd3dda 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2024,7 +2024,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_srat_memory(table_data, mem_base, mem_len, i - 1, MEM_AFFINITY_ENABLED); } - mem_base = 1ULL << 32; + mem_base = x86ms->above_4g_mem_start; mem_len = next_base - x86ms->below_4g_mem_size; next_base = mem_base + mem_len; } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 46ab1dcb47..13b68307be 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -850,9 +850,10 @@ void pc_memory_init(PCMachineState *pcms, machine->ram, x86ms->below_4g_mem_size, x86ms->above_4g_mem_size); - memory_region_add_subregion(system_memory, 0x100000000ULL, + memory_region_add_subregion(system_memory, x86ms->above_4g_mem_start, ram_above_4g); - e820_add_entry(0x100000000ULL, x86ms->above_4g_mem_size, E820_RAM); + e820_add_entry(x86ms->above_4g_mem_start, x86ms->above_4g_mem_size, + E820_RAM); } if (pcms->sgx_epc.size != 0) { @@ -893,7 +894,7 @@ void pc_memory_init(PCMachineState *pcms, machine->device_memory->base = sgx_epc_above_4g_end(&pcms->sgx_epc); } else { machine->device_memory->base = - 0x100000000ULL + x86ms->above_4g_mem_size; + x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; } machine->device_memory->base = @@ -927,7 +928,7 @@ void pc_memory_init(PCMachineState *pcms, } else if (pcms->sgx_epc.size != 0) { cxl_base = sgx_epc_above_4g_end(&pcms->sgx_epc); } else { - cxl_base = 0x100000000ULL + x86ms->above_4g_mem_size; + cxl_base = x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; } e820_add_entry(cxl_base, cxl_size, E820_RESERVED); @@ -1035,7 +1036,7 @@ uint64_t pc_pci_hole64_start(void) } else if (pcms->sgx_epc.size != 0) { hole64_start = sgx_epc_above_4g_end(&pcms->sgx_epc); } else { - hole64_start = 0x100000000ULL + x86ms->above_4g_mem_size; + hole64_start = x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; } return ROUND_UP(hole64_start, 1 * GiB); diff --git a/hw/i386/sgx.c b/hw/i386/sgx.c index a44d66ba2a..09d9c7c73d 100644 --- a/hw/i386/sgx.c +++ b/hw/i386/sgx.c @@ -295,7 +295,7 @@ void pc_machine_init_sgx_epc(PCMachineState *pcms) return; } - sgx_epc->base = 0x100000000ULL + x86ms->above_4g_mem_size; + sgx_epc->base = x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; memory_region_init(&sgx_epc->mr, OBJECT(pcms), "sgx-epc", UINT64_MAX); memory_region_add_subregion(get_system_memory(), sgx_epc->base, diff --git a/hw/i386/x86.c b/hw/i386/x86.c index ecea25d249..050eedc0c8 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -1391,6 +1391,7 @@ static void x86_machine_initfn(Object *obj) x86ms->oem_id = g_strndup(ACPI_BUILD_APPNAME6, 6); x86ms->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); x86ms->bus_lock_ratelimit = 0; + x86ms->above_4g_mem_start = 4 * GiB; } static void x86_machine_class_init(ObjectClass *oc, void *data) diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index 6bdf1f6ab2..62fa5774f8 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -56,6 +56,9 @@ struct X86MachineState { /* RAM information (sizes, addresses, configuration): */ ram_addr_t below_4g_mem_size, above_4g_mem_size; + /* Start address of the initial RAM above 4G */ + uint64_t above_4g_mem_start; + /* CPU and apic information: */ bool apic_xrupt_override; unsigned pci_irq_mask; From 4876778749021a59a03dd3da3518dc861bc95ff8 Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:05 +0100 Subject: [PATCH 0015/1020] i386/pc: create pci-host qdev prior to pc_memory_init() At the start of pc_memory_init() we usually pass a range of 0..UINT64_MAX as pci_memory, when really its 2G (i440fx) or 32G (q35). To get the real user value, we need to get pci-host passed property for default pci_hole64_size. Thus to get that, create the qdev prior to memory init to better make estimations on max used/phys addr. This is in preparation to determine that host-phys-bits are enough and also for pci-hole64-size to be considered to relocate ram-above-4g to be at 1T (on AMD platforms). Signed-off-by: Joao Martins Reviewed-by: Igor Mammedov Message-Id: <20220719170014.27028-3-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc_piix.c | 7 +++++-- hw/i386/pc_q35.c | 6 +++--- hw/pci-host/i440fx.c | 5 ++--- include/hw/pci-host/i440fx.h | 3 ++- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index fbf9465318..b8b3ce3408 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -91,6 +91,7 @@ static void pc_init1(MachineState *machine, MemoryRegion *pci_memory; MemoryRegion *rom_memory; ram_addr_t lowmem; + DeviceState *i440fx_host; /* * Calculate ram split, for memory below and above 4G. It's a bit @@ -164,9 +165,11 @@ static void pc_init1(MachineState *machine, pci_memory = g_new(MemoryRegion, 1); memory_region_init(pci_memory, NULL, "pci", UINT64_MAX); rom_memory = pci_memory; + i440fx_host = qdev_new(host_type); } else { pci_memory = NULL; rom_memory = system_memory; + i440fx_host = NULL; } pc_guest_info_init(pcms); @@ -200,8 +203,8 @@ static void pc_init1(MachineState *machine, const char *type = xen_enabled() ? TYPE_PIIX3_XEN_DEVICE : TYPE_PIIX3_DEVICE; - pci_bus = i440fx_init(host_type, - pci_type, + pci_bus = i440fx_init(pci_type, + i440fx_host, system_memory, system_io, machine->ram_size, x86ms->below_4g_mem_size, x86ms->above_4g_mem_size, diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 12cc76aaf8..f4d23b1469 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -203,12 +203,12 @@ static void pc_q35_init(MachineState *machine) pcms->smbios_entry_point_type); } - /* allocate ram and load rom/bios */ - pc_memory_init(pcms, get_system_memory(), rom_memory, &ram_memory); - /* create pci host bus */ q35_host = Q35_HOST_DEVICE(qdev_new(TYPE_Q35_HOST_DEVICE)); + /* allocate ram and load rom/bios */ + pc_memory_init(pcms, get_system_memory(), rom_memory, &ram_memory); + object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host)); object_property_set_link(OBJECT(q35_host), MCH_HOST_PROP_RAM_MEM, OBJECT(ram_memory), NULL); diff --git a/hw/pci-host/i440fx.c b/hw/pci-host/i440fx.c index 1c5ad5f918..d5426ef4a5 100644 --- a/hw/pci-host/i440fx.c +++ b/hw/pci-host/i440fx.c @@ -237,7 +237,8 @@ static void i440fx_realize(PCIDevice *dev, Error **errp) } } -PCIBus *i440fx_init(const char *host_type, const char *pci_type, +PCIBus *i440fx_init(const char *pci_type, + DeviceState *dev, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, ram_addr_t ram_size, @@ -246,7 +247,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type, MemoryRegion *pci_address_space, MemoryRegion *ram_memory) { - DeviceState *dev; PCIBus *b; PCIDevice *d; PCIHostState *s; @@ -254,7 +254,6 @@ PCIBus *i440fx_init(const char *host_type, const char *pci_type, unsigned i; I440FXState *i440fx; - dev = qdev_new(host_type); s = PCI_HOST_BRIDGE(dev); b = pci_root_bus_new(dev, NULL, pci_address_space, address_space_io, 0, TYPE_PCI_BUS); diff --git a/include/hw/pci-host/i440fx.h b/include/hw/pci-host/i440fx.h index 52518dbf08..d02bf1ed6b 100644 --- a/include/hw/pci-host/i440fx.h +++ b/include/hw/pci-host/i440fx.h @@ -35,7 +35,8 @@ struct PCII440FXState { #define TYPE_IGD_PASSTHROUGH_I440FX_PCI_DEVICE "igd-passthrough-i440FX" -PCIBus *i440fx_init(const char *host_type, const char *pci_type, +PCIBus *i440fx_init(const char *pci_type, + DeviceState *dev, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, ram_addr_t ram_size, From c48eb7a4e869f338e5b3e233fed7c9dbb0520247 Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:06 +0100 Subject: [PATCH 0016/1020] i386/pc: pass pci_hole64_size to pc_memory_init() Use the pre-initialized pci-host qdev and fetch the pci-hole64-size into pc_memory_init() newly added argument. Use PCI_HOST_PROP_PCI_HOLE64_SIZE pci-host property for fetching pci-hole64-size. This is in preparation to determine that host-phys-bits are enough and for pci-hole64-size to be considered to relocate ram-above-4g to be at 1T (on AMD platforms). Signed-off-by: Joao Martins Reviewed-by: Igor Mammedov Message-Id: <20220719170014.27028-4-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 3 ++- hw/i386/pc_piix.c | 7 ++++++- hw/i386/pc_q35.c | 10 +++++++++- include/hw/i386/pc.h | 3 ++- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 13b68307be..f4d5b25fdd 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -817,7 +817,8 @@ void xen_load_linux(PCMachineState *pcms) void pc_memory_init(PCMachineState *pcms, MemoryRegion *system_memory, MemoryRegion *rom_memory, - MemoryRegion **ram_memory) + MemoryRegion **ram_memory, + uint64_t pci_hole64_size) { int linux_boot, i; MemoryRegion *option_rom_mr; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index b8b3ce3408..aa191d405a 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -91,6 +91,7 @@ static void pc_init1(MachineState *machine, MemoryRegion *pci_memory; MemoryRegion *rom_memory; ram_addr_t lowmem; + uint64_t hole64_size; DeviceState *i440fx_host; /* @@ -166,10 +167,14 @@ static void pc_init1(MachineState *machine, memory_region_init(pci_memory, NULL, "pci", UINT64_MAX); rom_memory = pci_memory; i440fx_host = qdev_new(host_type); + hole64_size = object_property_get_uint(OBJECT(i440fx_host), + PCI_HOST_PROP_PCI_HOLE64_SIZE, + &error_abort); } else { pci_memory = NULL; rom_memory = system_memory; i440fx_host = NULL; + hole64_size = 0; } pc_guest_info_init(pcms); @@ -186,7 +191,7 @@ static void pc_init1(MachineState *machine, /* allocate ram and load rom/bios */ if (!xen_enabled()) { pc_memory_init(pcms, system_memory, - rom_memory, &ram_memory); + rom_memory, &ram_memory, hole64_size); } else { pc_system_flash_cleanup_unused(pcms); if (machine->kernel_filename != NULL) { diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index f4d23b1469..307910b33c 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -138,6 +138,7 @@ static void pc_q35_init(MachineState *machine) MachineClass *mc = MACHINE_GET_CLASS(machine); bool acpi_pcihp; bool keep_pci_slot_hpc; + uint64_t pci_hole64_size = 0; /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping @@ -206,8 +207,15 @@ static void pc_q35_init(MachineState *machine) /* create pci host bus */ q35_host = Q35_HOST_DEVICE(qdev_new(TYPE_Q35_HOST_DEVICE)); + if (pcmc->pci_enabled) { + pci_hole64_size = object_property_get_uint(OBJECT(q35_host), + PCI_HOST_PROP_PCI_HOLE64_SIZE, + &error_abort); + } + /* allocate ram and load rom/bios */ - pc_memory_init(pcms, get_system_memory(), rom_memory, &ram_memory); + pc_memory_init(pcms, get_system_memory(), rom_memory, &ram_memory, + pci_hole64_size); object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host)); object_property_set_link(OBJECT(q35_host), MCH_HOST_PROP_RAM_MEM, diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 2a8ffbcfa8..01938fce4c 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -162,7 +162,8 @@ void xen_load_linux(PCMachineState *pcms); void pc_memory_init(PCMachineState *pcms, MemoryRegion *system_memory, MemoryRegion *rom_memory, - MemoryRegion **ram_memory); + MemoryRegion **ram_memory, + uint64_t pci_hole64_size); uint64_t pc_pci_hole64_start(void); DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus); void pc_basic_device_init(struct PCMachineState *pcms, From 5ff62e2afedf5c984048f90a881794622a9eb3e8 Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:07 +0100 Subject: [PATCH 0017/1020] i386/pc: factor out above-4g end to an helper There's a couple of places that seem to duplicate this calculation of RAM size above the 4G boundary. Move all those to a helper function. Signed-off-by: Joao Martins Reviewed-by: Igor Mammedov Message-Id: <20220719170014.27028-5-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index f4d5b25fdd..d1e20ccb27 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -814,6 +814,17 @@ void xen_load_linux(PCMachineState *pcms) #define PC_ROM_ALIGN 0x800 #define PC_ROM_SIZE (PC_ROM_MAX - PC_ROM_MIN_VGA) +static hwaddr pc_above_4g_end(PCMachineState *pcms) +{ + X86MachineState *x86ms = X86_MACHINE(pcms); + + if (pcms->sgx_epc.size != 0) { + return sgx_epc_above_4g_end(&pcms->sgx_epc); + } + + return x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; +} + void pc_memory_init(PCMachineState *pcms, MemoryRegion *system_memory, MemoryRegion *rom_memory, @@ -891,15 +902,8 @@ void pc_memory_init(PCMachineState *pcms, exit(EXIT_FAILURE); } - if (pcms->sgx_epc.size != 0) { - machine->device_memory->base = sgx_epc_above_4g_end(&pcms->sgx_epc); - } else { - machine->device_memory->base = - x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; - } - machine->device_memory->base = - ROUND_UP(machine->device_memory->base, 1 * GiB); + ROUND_UP(pc_above_4g_end(pcms), 1 * GiB); if (pcmc->enforce_aligned_dimm) { /* size device region assuming 1G page max alignment per slot */ @@ -926,10 +930,8 @@ void pc_memory_init(PCMachineState *pcms, if (pcmc->has_reserved_memory && machine->device_memory->base) { cxl_base = machine->device_memory->base + memory_region_size(&machine->device_memory->mr); - } else if (pcms->sgx_epc.size != 0) { - cxl_base = sgx_epc_above_4g_end(&pcms->sgx_epc); } else { - cxl_base = x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; + cxl_base = pc_above_4g_end(pcms); } e820_add_entry(cxl_base, cxl_size, E820_RESERVED); @@ -1016,7 +1018,6 @@ uint64_t pc_pci_hole64_start(void) PCMachineState *pcms = PC_MACHINE(qdev_get_machine()); PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); MachineState *ms = MACHINE(pcms); - X86MachineState *x86ms = X86_MACHINE(pcms); uint64_t hole64_start = 0; if (pcms->cxl_devices_state.host_mr.addr) { @@ -1034,10 +1035,8 @@ uint64_t pc_pci_hole64_start(void) if (!pcmc->broken_reserved_end) { hole64_start += memory_region_size(&ms->device_memory->mr); } - } else if (pcms->sgx_epc.size != 0) { - hole64_start = sgx_epc_above_4g_end(&pcms->sgx_epc); } else { - hole64_start = x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; + hole64_start = pc_above_4g_end(pcms); } return ROUND_UP(hole64_start, 1 * GiB); From 55668e409bcaf04e6af7acb44037d5f18c6b786e Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:08 +0100 Subject: [PATCH 0018/1020] i386/pc: factor out cxl range end to helper Move calculation of CXL memory region end to separate helper. This is in preparation to a future change that removes CXL range dependency on the CXL memory region, with the goal of allowing pc_pci_hole64_start() to be called before any memory region are initialized. Cc: Jonathan Cameron Signed-off-by: Joao Martins Acked-by: Igor Mammedov Message-Id: <20220719170014.27028-6-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index d1e20ccb27..cb27309e76 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -825,6 +825,25 @@ static hwaddr pc_above_4g_end(PCMachineState *pcms) return x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; } +static uint64_t pc_get_cxl_range_end(PCMachineState *pcms) +{ + uint64_t start = 0; + + if (pcms->cxl_devices_state.host_mr.addr) { + start = pcms->cxl_devices_state.host_mr.addr + + memory_region_size(&pcms->cxl_devices_state.host_mr); + if (pcms->cxl_devices_state.fixed_windows) { + GList *it; + for (it = pcms->cxl_devices_state.fixed_windows; it; it = it->next) { + CXLFixedWindow *fw = it->data; + start = fw->mr.addr + memory_region_size(&fw->mr); + } + } + } + + return start; +} + void pc_memory_init(PCMachineState *pcms, MemoryRegion *system_memory, MemoryRegion *rom_memory, @@ -1020,16 +1039,8 @@ uint64_t pc_pci_hole64_start(void) MachineState *ms = MACHINE(pcms); uint64_t hole64_start = 0; - if (pcms->cxl_devices_state.host_mr.addr) { - hole64_start = pcms->cxl_devices_state.host_mr.addr + - memory_region_size(&pcms->cxl_devices_state.host_mr); - if (pcms->cxl_devices_state.fixed_windows) { - GList *it; - for (it = pcms->cxl_devices_state.fixed_windows; it; it = it->next) { - CXLFixedWindow *fw = it->data; - hole64_start = fw->mr.addr + memory_region_size(&fw->mr); - } - } + if (pcms->cxl_devices_state.is_enabled) { + hole64_start = pc_get_cxl_range_end(pcms); } else if (pcmc->has_reserved_memory && ms->device_memory->base) { hole64_start = ms->device_memory->base; if (!pcmc->broken_reserved_end) { From 42bed0712725ce338fc1cad725c3d9cf5cf443dc Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:09 +0100 Subject: [PATCH 0019/1020] i386/pc: factor out cxl range start to helper Factor out the calculation of the base address of the memory region. It will be used later on for the cxl range end counterpart calculation and as well in pc_memory_init() CXL memory region initialization, thus avoiding duplication. Cc: Jonathan Cameron Signed-off-by: Joao Martins Acked-by: Igor Mammedov Message-Id: <20220719170014.27028-7-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index cb27309e76..9e1a067c41 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -825,6 +825,22 @@ static hwaddr pc_above_4g_end(PCMachineState *pcms) return x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; } +static uint64_t pc_get_cxl_range_start(PCMachineState *pcms) +{ + PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); + MachineState *machine = MACHINE(pcms); + hwaddr cxl_base; + + if (pcmc->has_reserved_memory && machine->device_memory->base) { + cxl_base = machine->device_memory->base + + memory_region_size(&machine->device_memory->mr); + } else { + cxl_base = pc_above_4g_end(pcms); + } + + return cxl_base; +} + static uint64_t pc_get_cxl_range_end(PCMachineState *pcms) { uint64_t start = 0; @@ -946,13 +962,7 @@ void pc_memory_init(PCMachineState *pcms, MemoryRegion *mr = &pcms->cxl_devices_state.host_mr; hwaddr cxl_size = MiB; - if (pcmc->has_reserved_memory && machine->device_memory->base) { - cxl_base = machine->device_memory->base - + memory_region_size(&machine->device_memory->mr); - } else { - cxl_base = pc_above_4g_end(pcms); - } - + cxl_base = pc_get_cxl_range_start(pcms); e820_add_entry(cxl_base, cxl_size, E820_RESERVED); memory_region_init(mr, OBJECT(machine), "cxl_host_reg", cxl_size); memory_region_add_subregion(system_memory, cxl_base, mr); From 1065b21993628a00066a2ab1439bfff5d186c12d Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:10 +0100 Subject: [PATCH 0020/1020] i386/pc: handle unitialized mr in pc_get_cxl_range_end() Remove pc_get_cxl_range_end() dependency on the CXL memory region, and replace with one that does not require the CXL host_mr to determine the start of CXL start. This in preparation to allow pc_pci_hole64_start() to be called early in pc_memory_init(), handle CXL memory region end when its underlying memory region isn't yet initialized. Cc: Jonathan Cameron Signed-off-by: Joao Martins Message-Id: <20220719170014.27028-8-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Acked-by: Igor Mammedov --- hw/i386/pc.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 9e1a067c41..611eb197da 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -843,17 +843,15 @@ static uint64_t pc_get_cxl_range_start(PCMachineState *pcms) static uint64_t pc_get_cxl_range_end(PCMachineState *pcms) { - uint64_t start = 0; + uint64_t start = pc_get_cxl_range_start(pcms) + MiB; - if (pcms->cxl_devices_state.host_mr.addr) { - start = pcms->cxl_devices_state.host_mr.addr + - memory_region_size(&pcms->cxl_devices_state.host_mr); - if (pcms->cxl_devices_state.fixed_windows) { - GList *it; - for (it = pcms->cxl_devices_state.fixed_windows; it; it = it->next) { - CXLFixedWindow *fw = it->data; - start = fw->mr.addr + memory_region_size(&fw->mr); - } + if (pcms->cxl_devices_state.fixed_windows) { + GList *it; + + start = ROUND_UP(start, 256 * MiB); + for (it = pcms->cxl_devices_state.fixed_windows; it; it = it->next) { + CXLFixedWindow *fw = it->data; + start += fw->size; } } From 8288a8286d00e074b765f1d47ee61159ed5291fd Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:11 +0100 Subject: [PATCH 0021/1020] i386/pc: factor out device_memory base/size to helper Move obtaining hole64_start from device_memory memory region base/size into an helper alongside correspondent getters in pc_memory_init() when the hotplug range is unitialized. While doing that remove the memory region based logic from this newly added helper. This is the final step that allows pc_pci_hole64_start() to be callable at the beginning of pc_memory_init() before any memory regions are initialized. Cc: Jonathan Cameron Signed-off-by: Joao Martins Acked-by: Igor Mammedov Message-Id: <20220719170014.27028-9-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 48 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 611eb197da..ebc27e4cb7 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -825,15 +825,36 @@ static hwaddr pc_above_4g_end(PCMachineState *pcms) return x86ms->above_4g_mem_start + x86ms->above_4g_mem_size; } -static uint64_t pc_get_cxl_range_start(PCMachineState *pcms) +static void pc_get_device_memory_range(PCMachineState *pcms, + hwaddr *base, + ram_addr_t *device_mem_size) { PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); MachineState *machine = MACHINE(pcms); - hwaddr cxl_base; + ram_addr_t size; + hwaddr addr; - if (pcmc->has_reserved_memory && machine->device_memory->base) { - cxl_base = machine->device_memory->base - + memory_region_size(&machine->device_memory->mr); + size = machine->maxram_size - machine->ram_size; + addr = ROUND_UP(pc_above_4g_end(pcms), 1 * GiB); + + if (pcmc->enforce_aligned_dimm) { + /* size device region assuming 1G page max alignment per slot */ + size += (1 * GiB) * machine->ram_slots; + } + + *base = addr; + *device_mem_size = size; +} + +static uint64_t pc_get_cxl_range_start(PCMachineState *pcms) +{ + PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); + hwaddr cxl_base; + ram_addr_t size; + + if (pcmc->has_reserved_memory) { + pc_get_device_memory_range(pcms, &cxl_base, &size); + cxl_base += size; } else { cxl_base = pc_above_4g_end(pcms); } @@ -920,7 +941,7 @@ void pc_memory_init(PCMachineState *pcms, /* initialize device memory address space */ if (pcmc->has_reserved_memory && (machine->ram_size < machine->maxram_size)) { - ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; + ram_addr_t device_mem_size; if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) { error_report("unsupported amount of memory slots: %"PRIu64, @@ -935,13 +956,7 @@ void pc_memory_init(PCMachineState *pcms, exit(EXIT_FAILURE); } - machine->device_memory->base = - ROUND_UP(pc_above_4g_end(pcms), 1 * GiB); - - if (pcmc->enforce_aligned_dimm) { - /* size device region assuming 1G page max alignment per slot */ - device_mem_size += (1 * GiB) * machine->ram_slots; - } + pc_get_device_memory_range(pcms, &machine->device_memory->base, &device_mem_size); if ((machine->device_memory->base + device_mem_size) < device_mem_size) { @@ -1046,13 +1061,14 @@ uint64_t pc_pci_hole64_start(void) PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); MachineState *ms = MACHINE(pcms); uint64_t hole64_start = 0; + ram_addr_t size = 0; if (pcms->cxl_devices_state.is_enabled) { hole64_start = pc_get_cxl_range_end(pcms); - } else if (pcmc->has_reserved_memory && ms->device_memory->base) { - hole64_start = ms->device_memory->base; + } else if (pcmc->has_reserved_memory && (ms->ram_size < ms->maxram_size)) { + pc_get_device_memory_range(pcms, &hole64_start, &size); if (!pcmc->broken_reserved_end) { - hole64_start += memory_region_size(&ms->device_memory->mr); + hole64_start += size; } } else { hole64_start = pc_above_4g_end(pcms); From 1caab5cf86bdf02fa71079c4ca4a3c0748f39eb5 Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:12 +0100 Subject: [PATCH 0022/1020] i386/pc: bounds check phys-bits against max used GPA Calculate max *used* GPA against the CPU maximum possible address and error out if the former surprasses the latter. This ensures max used GPA is reacheable by configured phys-bits. Default phys-bits on Qemu is TCG_PHYS_ADDR_BITS (40) which is enough for the CPU to address 1Tb (0xff ffff ffff) or 1010G (0xfc ffff ffff) in AMD hosts with IOMMU. This is preparation for AMD guests with >1010G, where it will want relocate ram-above-4g to be after 1Tb instead of 4G. Signed-off-by: Joao Martins Acked-by: Igor Mammedov Message-Id: <20220719170014.27028-10-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index ebc27e4cb7..56d8c179ea 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -879,6 +879,18 @@ static uint64_t pc_get_cxl_range_end(PCMachineState *pcms) return start; } +static hwaddr pc_max_used_gpa(PCMachineState *pcms, uint64_t pci_hole64_size) +{ + X86CPU *cpu = X86_CPU(first_cpu); + + /* 32-bit systems don't have hole64 thus return max CPU address */ + if (cpu->phys_bits <= 32) { + return ((hwaddr)1 << cpu->phys_bits) - 1; + } + + return pc_pci_hole64_start() + pci_hole64_size - 1; +} + void pc_memory_init(PCMachineState *pcms, MemoryRegion *system_memory, MemoryRegion *rom_memory, @@ -893,13 +905,28 @@ void pc_memory_init(PCMachineState *pcms, MachineClass *mc = MACHINE_GET_CLASS(machine); PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); X86MachineState *x86ms = X86_MACHINE(pcms); + hwaddr maxphysaddr, maxusedaddr; hwaddr cxl_base, cxl_resv_end = 0; + X86CPU *cpu = X86_CPU(first_cpu); assert(machine->ram_size == x86ms->below_4g_mem_size + x86ms->above_4g_mem_size); linux_boot = (machine->kernel_filename != NULL); + /* + * phys-bits is required to be appropriately configured + * to make sure max used GPA is reachable. + */ + maxusedaddr = pc_max_used_gpa(pcms, pci_hole64_size); + maxphysaddr = ((hwaddr)1 << cpu->phys_bits) - 1; + if (maxphysaddr < maxusedaddr) { + error_report("Address space limit 0x%"PRIx64" < 0x%"PRIx64 + " phys-bits too low (%u)", + maxphysaddr, maxusedaddr, cpu->phys_bits); + exit(EXIT_FAILURE); + } + /* * Split single memory region and use aliases to address portions of it, * done for backwards compatibility with older qemus. From 8504f129450b909c88e199ca44facd35d38ba4de Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:13 +0100 Subject: [PATCH 0023/1020] i386/pc: relocate 4g start to 1T where applicable It is assumed that the whole GPA space is available to be DMA addressable, within a given address space limit, except for a tiny region before the 4G. Since Linux v5.4, VFIO validates whether the selected GPA is indeed valid i.e. not reserved by IOMMU on behalf of some specific devices or platform-defined restrictions, and thus failing the ioctl(VFIO_DMA_MAP) with -EINVAL. AMD systems with an IOMMU are examples of such platforms and particularly may only have these ranges as allowed: 0000000000000000 - 00000000fedfffff (0 .. 3.982G) 00000000fef00000 - 000000fcffffffff (3.983G .. 1011.9G) 0000010000000000 - ffffffffffffffff (1Tb .. 16Pb[*]) We already account for the 4G hole, albeit if the guest is big enough we will fail to allocate a guest with >1010G due to the ~12G hole at the 1Tb boundary, reserved for HyperTransport (HT). [*] there is another reserved region unrelated to HT that exists in the 256T boundary in Fam 17h according to Errata #1286, documeted also in "Open-Source Register Reference for AMD Family 17h Processors (PUB)" When creating the region above 4G, take into account that on AMD platforms the HyperTransport range is reserved and hence it cannot be used either as GPAs. On those cases rather than establishing the start of ram-above-4g to be 4G, relocate instead to 1Tb. See AMD IOMMU spec, section 2.1.2 "IOMMU Logical Topology", for more information on the underlying restriction of IOVAs. After accounting for the 1Tb hole on AMD hosts, mtree should look like: 0000000000000000-000000007fffffff (prio 0, i/o): alias ram-below-4g @pc.ram 0000000000000000-000000007fffffff 0000010000000000-000001ff7fffffff (prio 0, i/o): alias ram-above-4g @pc.ram 0000000080000000-000000ffffffffff If the relocation is done or the address space covers it, we also add the the reserved HT e820 range as reserved. Default phys-bits on Qemu is TCG_PHYS_ADDR_BITS (40) which is enough to address 1Tb (0xff ffff ffff). On AMD platforms, if a ram-above-4g relocation is attempted and the CPU wasn't configured with a big enough phys-bits, an error message will be printed due to the maxphysaddr vs maxusedaddr check previously added. Suggested-by: Igor Mammedov Signed-off-by: Joao Martins Acked-by: Igor Mammedov Message-Id: <20220719170014.27028-11-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 56d8c179ea..1c5c9e17c6 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -891,6 +891,40 @@ static hwaddr pc_max_used_gpa(PCMachineState *pcms, uint64_t pci_hole64_size) return pc_pci_hole64_start() + pci_hole64_size - 1; } +/* + * AMD systems with an IOMMU have an additional hole close to the + * 1Tb, which are special GPAs that cannot be DMA mapped. Depending + * on kernel version, VFIO may or may not let you DMA map those ranges. + * Starting Linux v5.4 we validate it, and can't create guests on AMD machines + * with certain memory sizes. It's also wrong to use those IOVA ranges + * in detriment of leading to IOMMU INVALID_DEVICE_REQUEST or worse. + * The ranges reserved for Hyper-Transport are: + * + * FD_0000_0000h - FF_FFFF_FFFFh + * + * The ranges represent the following: + * + * Base Address Top Address Use + * + * FD_0000_0000h FD_F7FF_FFFFh Reserved interrupt address space + * FD_F800_0000h FD_F8FF_FFFFh Interrupt/EOI IntCtl + * FD_F900_0000h FD_F90F_FFFFh Legacy PIC IACK + * FD_F910_0000h FD_F91F_FFFFh System Management + * FD_F920_0000h FD_FAFF_FFFFh Reserved Page Tables + * FD_FB00_0000h FD_FBFF_FFFFh Address Translation + * FD_FC00_0000h FD_FDFF_FFFFh I/O Space + * FD_FE00_0000h FD_FFFF_FFFFh Configuration + * FE_0000_0000h FE_1FFF_FFFFh Extended Configuration/Device Messages + * FE_2000_0000h FF_FFFF_FFFFh Reserved + * + * See AMD IOMMU spec, section 2.1.2 "IOMMU Logical Topology", + * Table 3: Special Address Controls (GPA) for more information. + */ +#define AMD_HT_START 0xfd00000000UL +#define AMD_HT_END 0xffffffffffUL +#define AMD_ABOVE_1TB_START (AMD_HT_END + 1) +#define AMD_HT_SIZE (AMD_ABOVE_1TB_START - AMD_HT_START) + void pc_memory_init(PCMachineState *pcms, MemoryRegion *system_memory, MemoryRegion *rom_memory, @@ -914,6 +948,26 @@ void pc_memory_init(PCMachineState *pcms, linux_boot = (machine->kernel_filename != NULL); + /* + * The HyperTransport range close to the 1T boundary is unique to AMD + * hosts with IOMMUs enabled. Restrict the ram-above-4g relocation + * to above 1T to AMD vCPUs only. + */ + if (IS_AMD_CPU(&cpu->env)) { + /* Bail out if max possible address does not cross HT range */ + if (pc_max_used_gpa(pcms, pci_hole64_size) >= AMD_HT_START) { + x86ms->above_4g_mem_start = AMD_ABOVE_1TB_START; + } + + /* + * Advertise the HT region if address space covers the reserved + * region or if we relocate. + */ + if (cpu->phys_bits >= 40) { + e820_add_entry(AMD_HT_START, AMD_HT_SIZE, E820_RESERVED); + } + } + /* * phys-bits is required to be appropriately configured * to make sure max used GPA is reachable. From b3e6982b4154c1c0ab8b25f2e1ac7838a1809824 Mon Sep 17 00:00:00 2001 From: Joao Martins Date: Tue, 19 Jul 2022 18:00:14 +0100 Subject: [PATCH 0024/1020] i386/pc: restrict AMD only enforcing of 1Tb hole to new machine type The added enforcing is only relevant in the case of AMD where the range right before the 1TB is restricted and cannot be DMA mapped by the kernel consequently leading to IOMMU INVALID_DEVICE_REQUEST or possibly other kinds of IOMMU events in the AMD IOMMU. Although, there's a case where it may make sense to disable the IOVA relocation/validation when migrating from a non-amd-1tb-aware qemu to one that supports it. Relocating RAM regions to after the 1Tb hole has consequences for guest ABI because we are changing the memory mapping, so make sure that only new machine enforce but not older ones. Signed-off-by: Joao Martins Acked-by: Dr. David Alan Gilbert Acked-by: Igor Mammedov Message-Id: <20220719170014.27028-12-joao.m.martins@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/pc.c | 6 ++++-- hw/i386/pc_piix.c | 1 + hw/i386/pc_q35.c | 1 + include/hw/i386/pc.h | 1 + 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 1c5c9e17c6..7280c02ce3 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -951,9 +951,10 @@ void pc_memory_init(PCMachineState *pcms, /* * The HyperTransport range close to the 1T boundary is unique to AMD * hosts with IOMMUs enabled. Restrict the ram-above-4g relocation - * to above 1T to AMD vCPUs only. + * to above 1T to AMD vCPUs only. @enforce_amd_1tb_hole is only false in + * older machine types (<= 7.0) for compatibility purposes. */ - if (IS_AMD_CPU(&cpu->env)) { + if (IS_AMD_CPU(&cpu->env) && pcmc->enforce_amd_1tb_hole) { /* Bail out if max possible address does not cross HT range */ if (pc_max_used_gpa(pcms, pci_hole64_size) >= AMD_HT_START) { x86ms->above_4g_mem_start = AMD_ABOVE_1TB_START; @@ -1902,6 +1903,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) pcmc->has_reserved_memory = true; pcmc->kvmclock_enabled = true; pcmc->enforce_aligned_dimm = true; + pcmc->enforce_amd_1tb_hole = true; /* BIOS ACPI tables: 128K. Other BIOS datastructures: less than 4K reported * to be used at the moment, 32K should be enough for a while. */ pcmc->acpi_data_size = 0x20000 + 0x8000; diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index aa191d405a..a5c65c1c35 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -451,6 +451,7 @@ static void pc_i440fx_7_0_machine_options(MachineClass *m) m->alias = NULL; m->is_default = false; pcmc->legacy_no_rng_seed = true; + pcmc->enforce_amd_1tb_hole = false; compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len); compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 307910b33c..3a35193ff7 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -387,6 +387,7 @@ static void pc_q35_7_0_machine_options(MachineClass *m) pc_q35_7_1_machine_options(m); m->alias = NULL; pcmc->legacy_no_rng_seed = true; + pcmc->enforce_amd_1tb_hole = false; compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len); compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len); } diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 01938fce4c..8435733bd6 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -118,6 +118,7 @@ struct PCMachineClass { bool has_reserved_memory; bool enforce_aligned_dimm; bool broken_reserved_end; + bool enforce_amd_1tb_hole; /* generate legacy CPU hotplug AML */ bool legacy_cpu_hotplug; From eba088f91d21d9e42a81bef847173da30c5da961 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Thu, 14 Jul 2022 15:28:00 +0200 Subject: [PATCH 0025/1020] block/parallels: Fix buffer-based write call Commit a4072543ccdddbd241d5962d9237b8b41fd006bf has changed the I/O here from working on a local one-element I/O vector to just using the buffer directly (using the bdrv_co_pread()/bdrv_co_pwrite() helper functions introduced shortly before). However, it only changed the bdrv_co_preadv() call to bdrv_co_pread() - the subsequent bdrv_co_pwritev() call stayed this way, and so still expects a QEMUIOVector pointer instead of a plain buffer. We must change that to be a bdrv_co_pwrite() call. Fixes: a4072543ccdddbd241d5962d ("block/parallels: use buffer-based io") Signed-off-by: Hanna Reitz Reviewed-by: Denis V. Lunev Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220714132801.72464-2-hreitz@redhat.com> Signed-off-by: Vladimir Sementsov-Ogievskiy --- block/parallels.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/parallels.c b/block/parallels.c index 8b235b9505..a229c06f25 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -241,8 +241,8 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, return ret; } - ret = bdrv_co_pwritev(bs->file, s->data_end * BDRV_SECTOR_SIZE, - nb_cow_bytes, buf, 0); + ret = bdrv_co_pwrite(bs->file, s->data_end * BDRV_SECTOR_SIZE, + nb_cow_bytes, buf, 0); qemu_vfree(buf); if (ret < 0) { return ret; From 0c2cb3827e46dc30cd41eeb38f8e318eb665e6a4 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Thu, 14 Jul 2022 15:28:01 +0200 Subject: [PATCH 0026/1020] iotests/131: Add parallels regression test Test an allocating write to a parallels image that has a backing node. Before HEAD^, doing so used to give me a failed assertion (when the backing node contains only `42` bytes; the results varies with the value chosen, for `0` bytes, for example, all I get is EIO). Signed-off-by: Hanna Reitz Reviewed-by: Denis V. Lunev Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220714132801.72464-3-hreitz@redhat.com> Signed-off-by: Vladimir Sementsov-Ogievskiy --- tests/qemu-iotests/131 | 35 ++++++++++++++++++++++++++++++++++- tests/qemu-iotests/131.out | 13 +++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/tests/qemu-iotests/131 b/tests/qemu-iotests/131 index d7456cae5b..a847692b4c 100755 --- a/tests/qemu-iotests/131 +++ b/tests/qemu-iotests/131 @@ -43,7 +43,7 @@ _supported_os Linux inuse_offset=$((0x2c)) -size=64M +size=$((64 * 1024 * 1024)) CLUSTER_SIZE=64k IMGFMT=parallels _make_test_img $size @@ -70,6 +70,39 @@ _check_test_img _check_test_img -r all { $QEMU_IO -c "read -P 0x11 64k 64k" "$TEST_IMG"; } 2>&1 | _filter_qemu_io | _filter_testdir +echo "== allocate with backing ==" +# Verify that allocating clusters works fine even when there is a backing image. +# Regression test for a bug where we would pass a buffer read from the backing +# node as a QEMUIOVector object, which could cause anything from I/O errors over +# assertion failures to invalid reads from memory. + +# Clear image +_make_test_img $size +# Create base image +TEST_IMG="$TEST_IMG.base" _make_test_img $size + +# Write some data to the base image (which would trigger an assertion failure if +# interpreted as a QEMUIOVector) +$QEMU_IO -c 'write -P 42 0 64k' "$TEST_IMG.base" | _filter_qemu_io + +# Parallels does not seem to support storing a backing filename in the image +# itself, so we need to build our backing chain on the command line +imgopts="driver=$IMGFMT,file.driver=$IMGPROTO,file.filename=$TEST_IMG" +imgopts+=",backing.driver=$IMGFMT" +imgopts+=",backing.file.driver=$IMGPROTO,backing.file.filename=$TEST_IMG.base" + +# Cause allocation in the top image +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \ + $QEMU_IO --image-opts "$imgopts" -c 'write -P 1 0 64' | _filter_qemu_io + +# Verify +QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT \ + $QEMU_IO --image-opts "$imgopts" \ + -c 'read -P 1 0 64' \ + -c "read -P 42 64 $((64 * 1024 - 64))" \ + -c "read -P 0 64k $((size - 64 * 1024))" \ + | _filter_qemu_io + # success, all done echo "*** done" rm -f $seq.full diff --git a/tests/qemu-iotests/131.out b/tests/qemu-iotests/131.out index 70da03dee5..de5ef7a8f5 100644 --- a/tests/qemu-iotests/131.out +++ b/tests/qemu-iotests/131.out @@ -37,4 +37,17 @@ Double checking the fixed image now... No errors were found on the image. read 65536/65536 bytes at offset 65536 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +== allocate with backing == +Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=67108864 +Formatting 'TEST_DIR/t.IMGFMT.base', fmt=IMGFMT size=67108864 +wrote 65536/65536 bytes at offset 0 +64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +wrote 64/64 bytes at offset 0 +64 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 64/64 bytes at offset 0 +64 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 65472/65472 bytes at offset 64 +63.938 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +read 67043328/67043328 bytes at offset 65536 +63.938 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) *** done From 0522be9a0c0094088ccef7aab352c57f483ca250 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Mon, 18 Jul 2022 14:56:37 +0100 Subject: [PATCH 0027/1020] hw/virtio/virtio-iommu: Enforce power-of-two notify for both MAP and UNMAP Currently we only enforce power-of-two mappings (required by the QEMU notifier) for UNMAP requests. A MAP request not aligned on a power-of-two may be successfully handled by VFIO, and then the corresponding UNMAP notify will fail because it will attempt to split that mapping. Ensure MAP and UNMAP notifications are consistent. Fixes: dde3f08b5cab ("virtio-iommu: Handle non power of 2 range invalidations") Reported-by: Tina Zhang Signed-off-by: Jean-Philippe Brucker Message-Id: <20220718135636.338264-1-jean-philippe@linaro.org> Tested-by: Tina Zhang Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-iommu.c | 47 ++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/hw/virtio/virtio-iommu.c b/hw/virtio/virtio-iommu.c index 281152d338..62e07ec2e4 100644 --- a/hw/virtio/virtio-iommu.c +++ b/hw/virtio/virtio-iommu.c @@ -197,6 +197,32 @@ static gint interval_cmp(gconstpointer a, gconstpointer b, gpointer user_data) } } +static void virtio_iommu_notify_map_unmap(IOMMUMemoryRegion *mr, + IOMMUTLBEvent *event, + hwaddr virt_start, hwaddr virt_end) +{ + uint64_t delta = virt_end - virt_start; + + event->entry.iova = virt_start; + event->entry.addr_mask = delta; + + if (delta == UINT64_MAX) { + memory_region_notify_iommu(mr, 0, *event); + } + + while (virt_start != virt_end + 1) { + uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64); + + event->entry.addr_mask = mask; + event->entry.iova = virt_start; + memory_region_notify_iommu(mr, 0, *event); + virt_start += mask + 1; + if (event->entry.perm != IOMMU_NONE) { + event->entry.translated_addr += mask + 1; + } + } +} + static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, hwaddr virt_end, hwaddr paddr, uint32_t flags) @@ -215,19 +241,16 @@ static void virtio_iommu_notify_map(IOMMUMemoryRegion *mr, hwaddr virt_start, event.type = IOMMU_NOTIFIER_MAP; event.entry.target_as = &address_space_memory; - event.entry.addr_mask = virt_end - virt_start; - event.entry.iova = virt_start; event.entry.perm = perm; event.entry.translated_addr = paddr; - memory_region_notify_iommu(mr, 0, event); + virtio_iommu_notify_map_unmap(mr, &event, virt_start, virt_end); } static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start, hwaddr virt_end) { IOMMUTLBEvent event; - uint64_t delta = virt_end - virt_start; if (!(mr->iommu_notify_flags & IOMMU_NOTIFIER_UNMAP)) { return; @@ -239,22 +262,8 @@ static void virtio_iommu_notify_unmap(IOMMUMemoryRegion *mr, hwaddr virt_start, event.entry.target_as = &address_space_memory; event.entry.perm = IOMMU_NONE; event.entry.translated_addr = 0; - event.entry.addr_mask = delta; - event.entry.iova = virt_start; - if (delta == UINT64_MAX) { - memory_region_notify_iommu(mr, 0, event); - } - - - while (virt_start != virt_end + 1) { - uint64_t mask = dma_aligned_pow2_mask(virt_start, virt_end, 64); - - event.entry.addr_mask = mask; - event.entry.iova = virt_start; - memory_region_notify_iommu(mr, 0, event); - virt_start += mask + 1; - } + virtio_iommu_notify_map_unmap(mr, &event, virt_start, virt_end); } static gboolean virtio_iommu_notify_unmap_cb(gpointer key, gpointer value, From 7b17a1a841fc2336eba53afade9cadb14bd3dd9a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 26 Jul 2022 18:03:16 -0700 Subject: [PATCH 0028/1020] Update version for v7.1.0-rc0 release Signed-off-by: Richard Henderson --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 59f2fcbfc0..20780a61a3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0.50 +7.0.90 From 44602af8585fd2f331c69e2c071eff39227535ed Mon Sep 17 00:00:00 2001 From: Palmer Dabbelt Date: Thu, 14 Jul 2022 11:00:33 -0700 Subject: [PATCH 0029/1020] RISC-V: Allow both Zmmul and M We got to talking about how Zmmul and M interact with each other https://github.com/riscv/riscv-isa-manual/issues/869 , and it turns out that QEMU's behavior is slightly wrong: having Zmmul and M is a legal combination, it just means that the multiplication instructions are supported even when M is disabled at runtime via misa. This just stops overriding M from Zmmul, with that the other checks for the multiplication instructions work as per the ISA. Signed-off-by: Palmer Dabbelt Reviewed-by: Alistair Francis Message-Id: <20220714180033.22385-1-palmer@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 1bb3973806..ac6f82ebd0 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -619,11 +619,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) cpu->cfg.ext_ifencei = true; } - if (cpu->cfg.ext_m && cpu->cfg.ext_zmmul) { - warn_report("Zmmul will override M"); - cpu->cfg.ext_m = false; - } - if (cpu->cfg.ext_i && cpu->cfg.ext_e) { error_setg(errp, "I and E extensions are incompatible"); From 54f218363052be210e77d2ada8c0c1e51b3ad6cd Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Sat, 23 Jul 2022 02:03:35 -0700 Subject: [PATCH 0030/1020] hw/intc: sifive_plic: Fix multi-socket plic configuraiton Since commit 40244040a7ac, multi-socket configuration with plic is broken as the hartid for second socket is calculated incorrectly. The hartid stored in addr_config already includes the offset for the base hartid for that socket. Adding it again would lead to segfault while creating the plic device for the virt machine. qdev_connect_gpio_out was also invoked with incorrect number of gpio lines. Fixes: 40244040a7ac (hw/intc: sifive_plic: Avoid overflowing the addr_config buffer) Signed-off-by: Atish Patra Reviewed-by: Alistair Francis Message-Id: <20220723090335.671105-1-atishp@rivosinc.com> [ Changes by AF: - Change the qdev_connect_gpio_out() numbering ] Signed-off-by: Alistair Francis --- hw/intc/sifive_plic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c index 56d60e9ac9..af4ae3630e 100644 --- a/hw/intc/sifive_plic.c +++ b/hw/intc/sifive_plic.c @@ -454,10 +454,10 @@ DeviceState *sifive_plic_create(hwaddr addr, char *hart_config, for (i = 0; i < plic->num_addrs; i++) { int cpu_num = plic->addr_config[i].hartid; - CPUState *cpu = qemu_get_cpu(hartid_base + cpu_num); + CPUState *cpu = qemu_get_cpu(cpu_num); if (plic->addr_config[i].mode == PLICMode_M) { - qdev_connect_gpio_out(dev, num_harts + cpu_num, + qdev_connect_gpio_out(dev, num_harts - plic->hartid_base + cpu_num, qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT)); } if (plic->addr_config[i].mode == PLICMode_S) { From d82b11f69953cf15cee819bcf02dfd87325980a9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 28 Jul 2022 08:41:28 +0200 Subject: [PATCH 0031/1020] ui: dbus-display requires CONFIG_GBM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Without CONFIG_GBM, compiling dbus-display fails with ../ui/dbus.c: In function ‘dbus_create_context’: ../ui/dbus.c:47:20: error: ‘qemu_egl_rn_ctx’ undeclared (first use in this function); did you mean ‘qemu_egl_init_ctx’? 47 | qemu_egl_rn_ctx); | ^~~~~~~~~~~~~~~ | qemu_egl_init_ctx ../ui/dbus.c:47:20: note: each undeclared identifier is reported only once for each function it appears in and many other similar errors, because include/ui/egl-helpers.h only has these declaration if gbm is found on the system. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1108 Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Daniel P. BerrangĂ© Signed-off-by: Paolo Bonzini --- meson.build | 4 ++-- ui/meson.build | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/meson.build b/meson.build index 75aaca8462..294e9a8f32 100644 --- a/meson.build +++ b/meson.build @@ -1677,8 +1677,8 @@ dbus_display = get_option('dbus_display') \ error_message: '-display dbus requires --enable-modules') \ .require(gdbus_codegen.found(), error_message: '-display dbus requires gdbus-codegen') \ - .require(opengl.found(), - error_message: '-display dbus requires epoxy/egl') \ + .require(opengl.found() and gbm.found(), + error_message: '-display dbus requires epoxy/egl and gbm') \ .allowed() have_virtfs = get_option('virtfs') \ diff --git a/ui/meson.build b/ui/meson.build index e9f48c5315..ec13949776 100644 --- a/ui/meson.build +++ b/ui/meson.build @@ -81,7 +81,7 @@ if dbus_display '--interface-prefix', 'org.qemu.', '--c-namespace', 'QemuDBus', '--generate-c-code', '@BASENAME@']) - dbus_ss.add(when: [gio, pixman, opengl], + dbus_ss.add(when: [gio, pixman, opengl, gbm], if_true: [files( 'dbus-chardev.c', 'dbus-clipboard.c', From edccf661e6205d5ffff73860ab22eaf08a611ad9 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Sat, 9 Apr 2022 17:08:56 -0300 Subject: [PATCH 0032/1020] hw/ppc: check if spapr_drc_index() returns NULL in spapr_nvdimm.c spapr_nvdimm_flush_completion_cb() and flush_worker_cb() are using the DRC object returned by spapr_drc_index() without checking it for NULL. In this case we would be dereferencing a NULL pointer when doing SPAPR_NVDIMM(drc->dev) and PC_DIMM(drc->dev). This can happen if, during a scm_flush(), the DRC object is wrongly freed/released (e.g. a bug in another part of the code). spapr_drc_index() would then return NULL in the callbacks. Fixes: Coverity CID 1487108, 1487178 Reviewed-by: Greg Kurz Message-Id: <20220409200856.283076-2-danielhb413@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/spapr_nvdimm.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c index c4c97da5de..04a64cada3 100644 --- a/hw/ppc/spapr_nvdimm.c +++ b/hw/ppc/spapr_nvdimm.c @@ -447,9 +447,15 @@ static int flush_worker_cb(void *opaque) { SpaprNVDIMMDeviceFlushState *state = opaque; SpaprDrc *drc = spapr_drc_by_index(state->drcidx); - PCDIMMDevice *dimm = PC_DIMM(drc->dev); - HostMemoryBackend *backend = MEMORY_BACKEND(dimm->hostmem); - int backend_fd = memory_region_get_fd(&backend->mr); + PCDIMMDevice *dimm; + HostMemoryBackend *backend; + int backend_fd; + + g_assert(drc != NULL); + + dimm = PC_DIMM(drc->dev); + backend = MEMORY_BACKEND(dimm->hostmem); + backend_fd = memory_region_get_fd(&backend->mr); if (object_property_get_bool(OBJECT(backend), "pmem", NULL)) { MemoryRegion *mr = host_memory_backend_get_memory(dimm->hostmem); @@ -475,7 +481,11 @@ static void spapr_nvdimm_flush_completion_cb(void *opaque, int hcall_ret) { SpaprNVDIMMDeviceFlushState *state = opaque; SpaprDrc *drc = spapr_drc_by_index(state->drcidx); - SpaprNVDIMMDevice *s_nvdimm = SPAPR_NVDIMM(drc->dev); + SpaprNVDIMMDevice *s_nvdimm; + + g_assert(drc != NULL); + + s_nvdimm = SPAPR_NVDIMM(drc->dev); state->hcall_ret = hcall_ret; QLIST_REMOVE(state, node); From eda3f17bcd7b96cf43b1aead3c1c93a2dbbd21ae Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 26 Jul 2022 19:23:40 +0100 Subject: [PATCH 0033/1020] hw/ppc/ppc440_uc: Initialize length passed to cpu_physical_memory_map() In dcr_write_dma(), there is code that uses cpu_physical_memory_map() to implement a DMA transfer. That function takes a 'plen' argument, which points to a hwaddr which is used for both input and output: the caller must set it to the size of the range it wants to map, and on return it is updated to the actual length mapped. The dcr_write_dma() code fails to initialize rlen and wlen, so will end up mapping an unpredictable amount of memory. Initialize the length values correctly, and check that we managed to map the entire range before using the fast-path memmove(). This was spotted by Coverity, which points out that we never initialized the variables before using them. Fixes: Coverity CID 1487137, 1487150 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220726182341.1888115-2-peter.maydell@linaro.org> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc440_uc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index a1ecf6dd1c..11fdb88c22 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -904,14 +904,17 @@ static void dcr_write_dma(void *opaque, int dcrn, uint32_t val) int width, i, sidx, didx; uint8_t *rptr, *wptr; hwaddr rlen, wlen; + hwaddr xferlen; sidx = didx = 0; width = 1 << ((val & DMA0_CR_PW) >> 25); + xferlen = count * width; + wlen = rlen = xferlen; rptr = cpu_physical_memory_map(dma->ch[chnl].sa, &rlen, false); wptr = cpu_physical_memory_map(dma->ch[chnl].da, &wlen, true); - if (rptr && wptr) { + if (rptr && rlen == xferlen && wptr && wlen == xferlen) { if (!(val & DMA0_CR_DEC) && val & DMA0_CR_SAI && val & DMA0_CR_DAI) { /* optimise common case */ From 37e7b86766244b62a406747bb78e049390d0b528 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 28 Jul 2022 15:32:18 +0200 Subject: [PATCH 0034/1020] vga: fix incorrect line height in 640x200x2 mode When in CGA modes, QEMU wants to ignore the maximum scan field (bits 0..4) of the maximum scan length register in the CRTC. It is not clear why this is needed---for example, Bochs ignores bit 7 instead. The issue is that the CGA modes are not detected correctly, and in particular mode 6 results in multi_scan==3 according to how SeaBIOS programs it. The right way to check for CGA graphics modes is to check whether bit 13 of the address is special cased by the CRT controller to achieve line interleaving, i.e. whether bit 0 of the CRTC mode control register is clear. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1020 Reported-by: Korneliusz Osmenda Signed-off-by: Paolo Bonzini --- hw/display/vga.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/display/vga.c b/hw/display/vga.c index 5dca2d1528..50ecb1ad02 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -1514,9 +1514,10 @@ static void vga_draw_graphic(VGACommonState *s, int full_update) force_shadow = true; } + /* bits 5-6: 0 = 16-color mode, 1 = 4-color mode, 2 = 256-color mode. */ shift_control = (s->gr[VGA_GFX_MODE] >> 5) & 3; double_scan = (s->cr[VGA_CRTC_MAX_SCAN] >> 7); - if (shift_control != 1) { + if (s->cr[VGA_CRTC_MODE] & 1) { multi_scan = (((s->cr[VGA_CRTC_MAX_SCAN] & 0x1f) + 1) << double_scan) - 1; } else { From bb7e03cb5677b570c5966c7dd946f9ed7acd11bc Mon Sep 17 00:00:00 2001 From: Claudio Fontana Date: Mon, 4 Jul 2022 09:58:32 +0200 Subject: [PATCH 0035/1020] stubs: update replay-tools to match replay.h types detected with GCC 13 [-Werror=enum-int-mismatch] Solves Issue #1096. Signed-off-by: Claudio Fontana Cc: Pavel Dovgalyuk Reviewed-by: Thomas Huth Message-Id: <20220704075832.31537-1-cfontana@suse.de> Signed-off-by: Paolo Bonzini --- stubs/replay-tools.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stubs/replay-tools.c b/stubs/replay-tools.c index 43296b3d4e..f2e72bb225 100644 --- a/stubs/replay-tools.c +++ b/stubs/replay-tools.c @@ -7,13 +7,14 @@ bool replay_events_enabled(void) return false; } -int64_t replay_save_clock(unsigned int kind, int64_t clock, int64_t raw_icount) +int64_t replay_save_clock(ReplayClockKind kind, + int64_t clock, int64_t raw_icount) { abort(); return 0; } -int64_t replay_read_clock(unsigned int kind, int64_t raw_icount) +int64_t replay_read_clock(ReplayClockKind kind, int64_t raw_icount) { abort(); return 0; @@ -48,11 +49,11 @@ void replay_mutex_unlock(void) { } -void replay_register_char_driver(Chardev *chr) +void replay_register_char_driver(struct Chardev *chr) { } -void replay_chr_be_write(Chardev *s, uint8_t *buf, int len) +void replay_chr_be_write(struct Chardev *s, uint8_t *buf, int len) { abort(); } From 0c9717ff35d2fe46fa9cb91566fe2afbed9f4f2a Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 20 Jul 2022 23:33:52 +1000 Subject: [PATCH 0036/1020] target/ppc: Implement new wait variants MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ISA v2.06 adds new variations of wait, specified by the WC field. These are not all compatible with the prior wait implementation, because they add additional conditions that cause the processor to resume, which can cause software to hang or run very slowly. At this moment, with the current wait implementation and a pseries guest using mainline kernel with new wait upcodes [1], QEMU hangs during boot if more than one CPU is present: qemu-system-ppc64 -M pseries,x-vof=on -cpu POWER10 -smp 2 -nographic -kernel zImage.pseries -no-reboot QEMU will exit (as there's no filesystem) if the test "passes", or hang during boot if it hits the bug. ISA v3.0 changed the wait opcode and removed the new variants (retaining the WC field but making non-zero values reserved). ISA v3.1 added new WC values to the new wait opcode, and added a PL field. This patch implements the new wait encoding and supports WC variants with no-op implementations, which provides basic correctness as explained in comments. [1] https://lore.kernel.org/all/20220720132132.903462-1-npiggin@gmail.com/ Signed-off-by: Nicholas Piggin Reviewed-by: VĂ­ctor Colombo Tested-by: Joel Stanley Reviewed-by: Daniel Henrique Barboza Message-Id: <20220720133352.904263-1-npiggin@gmail.com> [danielhb: added information about the bug being fixed] Signed-off-by: Daniel Henrique Barboza --- target/ppc/internal.h | 3 ++ target/ppc/translate.c | 96 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 91 insertions(+), 8 deletions(-) diff --git a/target/ppc/internal.h b/target/ppc/internal.h index 467f3046c8..337a362205 100644 --- a/target/ppc/internal.h +++ b/target/ppc/internal.h @@ -165,6 +165,9 @@ EXTRACT_HELPER_SPLIT_3(DX, 10, 6, 6, 5, 16, 1, 1, 0, 0) /* darn */ EXTRACT_HELPER(L, 16, 2); #endif +/* wait */ +EXTRACT_HELPER(WC, 21, 2); +EXTRACT_HELPER(PL, 16, 2); /*** Jump target decoding ***/ /* Immediate address */ diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 5a18ee577f..388337f81b 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -4071,12 +4071,91 @@ static void gen_sync(DisasContext *ctx) /* wait */ static void gen_wait(DisasContext *ctx) { - TCGv_i32 t0 = tcg_const_i32(1); - tcg_gen_st_i32(t0, cpu_env, - -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted)); - tcg_temp_free_i32(t0); - /* Stop translation, as the CPU is supposed to sleep from now */ - gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next); + uint32_t wc; + + if (ctx->insns_flags & PPC_WAIT) { + /* v2.03-v2.07 define an older incompatible 'wait' encoding. */ + + if (ctx->insns_flags2 & PPC2_PM_ISA206) { + /* v2.06 introduced the WC field. WC > 0 may be treated as no-op. */ + wc = WC(ctx->opcode); + } else { + wc = 0; + } + + } else if (ctx->insns_flags2 & PPC2_ISA300) { + /* v3.0 defines a new 'wait' encoding. */ + wc = WC(ctx->opcode); + if (ctx->insns_flags2 & PPC2_ISA310) { + uint32_t pl = PL(ctx->opcode); + + /* WC 1,2 may be treated as no-op. WC 3 is reserved. */ + if (wc == 3) { + gen_invalid(ctx); + return; + } + + /* PL 1-3 are reserved. If WC=2 then the insn is treated as noop. */ + if (pl > 0 && wc != 2) { + gen_invalid(ctx); + return; + } + + } else { /* ISA300 */ + /* WC 1-3 are reserved */ + if (wc > 0) { + gen_invalid(ctx); + return; + } + } + + } else { + warn_report("wait instruction decoded with wrong ISA flags."); + gen_invalid(ctx); + return; + } + + /* + * wait without WC field or with WC=0 waits for an exception / interrupt + * to occur. + */ + if (wc == 0) { + TCGv_i32 t0 = tcg_const_i32(1); + tcg_gen_st_i32(t0, cpu_env, + -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted)); + tcg_temp_free_i32(t0); + /* Stop translation, as the CPU is supposed to sleep from now */ + gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next); + } + + /* + * Other wait types must not just wait until an exception occurs because + * ignoring their other wake-up conditions could cause a hang. + * + * For v2.06 and 2.07, wc=1,2,3 are architected but may be implemented as + * no-ops. + * + * wc=1 and wc=3 explicitly allow the instruction to be treated as a no-op. + * + * wc=2 waits for an implementation-specific condition, such could be + * always true, so it can be implemented as a no-op. + * + * For v3.1, wc=1,2 are architected but may be implemented as no-ops. + * + * wc=1 (waitrsv) waits for an exception or a reservation to be lost. + * Reservation-loss may have implementation-specific conditions, so it + * can be implemented as a no-op. + * + * wc=2 waits for an exception or an amount of time to pass. This + * amount is implementation-specific so it can be implemented as a + * no-op. + * + * ISA v3.1 allows for execution to resume "in the rare case of + * an implementation-dependent event", so in any case software must + * not depend on the architected resumption condition to become + * true, so no-op implementations should be architecturally correct + * (if suboptimal). + */ } #if defined(TARGET_PPC64) @@ -6691,8 +6770,9 @@ GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B), GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207), #endif GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC), -GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT), -GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039FF801, PPC_NONE, PPC2_ISA300), +/* ISA v3.0 changed the extended opcode from 62 to 30 */ +GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x039FF801, PPC_WAIT), +GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039CF801, PPC_NONE, PPC2_ISA300), GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW), GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW), GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW), From 734a659ad264ac080457167e845ffabbaaa66d0e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 28 Jul 2022 16:14:06 +0100 Subject: [PATCH 0037/1020] linux-user/flatload.c: Fix setting of image_info::end_code The flatload loader sets the end_code field in the image_info struct incorrectly, due to a typo. This is a very long-standing bug (dating all the way back to when the bFLT loader was added in 2006), but has gone unnoticed because (a) most people don't use bFLT binaries (b) we don't actually do anything with the end_code field, except print it in debugging traces and pass it to TCG plugins Fix the typo. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1119 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220728151406.2262862-1-peter.maydell@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/flatload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/flatload.c b/linux-user/flatload.c index e4c2f89a22..e99570ca18 100644 --- a/linux-user/flatload.c +++ b/linux-user/flatload.c @@ -808,7 +808,7 @@ int load_flt_binary(struct linux_binprm *bprm, struct image_info *info) /* Stash our initial stack pointer into the mm structure */ info->start_code = libinfo[0].start_code; - info->end_code = libinfo[0].start_code = libinfo[0].text_len; + info->end_code = libinfo[0].start_code + libinfo[0].text_len; info->start_data = libinfo[0].start_data; info->end_data = libinfo[0].end_data; info->start_brk = libinfo[0].start_brk; From 705c881f7d8573d7520de2566396feb6a1223d57 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 28 Jul 2022 11:39:01 -0700 Subject: [PATCH 0038/1020] configure: Fix ppc container_cross_cc substitution When moving this code out of probe_target_compiler(), we failed to adjust the variable in which the target is located, resulting in e.g. powerpc64-linux-user-linux-gnu-gcc-10 Fixes: cd362defbbd ("tests/tcg: merge configure.sh back into main configure script") Signed-off-by: Richard Henderson Message-Id: <20220728183901.1290113-1-richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 2c19329d58..c4c02b8438 100755 --- a/configure +++ b/configure @@ -2028,7 +2028,7 @@ probe_target_compiler() { ;; ppc64|ppc64le) container_image=debian-powerpc-test-cross - container_cross_prefix=powerpc${1#ppc}-linux-gnu- + container_cross_prefix=powerpc${target_arch#ppc}-linux-gnu- container_cross_cc=${container_cross_prefix}gcc-10 ;; riscv64) From 47c182fe8b03c0c40059fb95840923e65c9bdb4f Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 28 Jul 2022 16:24:46 +0200 Subject: [PATCH 0039/1020] kvm: don't use perror() without useful errno perror() is designed to append the decoded errno value to a string. This, however, only makes sense if we called something that actually sets errno prior to that. For the callers that check for split irqchip support that is not the case, and we end up with confusing error messages that end in "success". Use error_report() instead. Signed-off-by: Cornelia Huck Message-Id: <20220728142446.438177-1-cohuck@redhat.com> Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 2 +- target/arm/kvm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index f165074e99..645f0a249a 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -2265,7 +2265,7 @@ static void kvm_irqchip_create(KVMState *s) ret = kvm_arch_irqchip_create(s); if (ret == 0) { if (s->kernel_irqchip_split == ON_OFF_AUTO_ON) { - perror("Split IRQ chip mode not supported."); + error_report("Split IRQ chip mode not supported."); exit(1); } else { ret = kvm_vm_ioctl(s, KVM_CREATE_IRQCHIP); diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 4339e1cd6e..e5c1bd50d2 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -959,7 +959,7 @@ void kvm_arch_init_irq_routing(KVMState *s) int kvm_arch_irqchip_create(KVMState *s) { if (kvm_kernel_irqchip_split()) { - perror("-machine kernel_irqchip=split is not supported on ARM."); + error_report("-machine kernel_irqchip=split is not supported on ARM."); exit(1); } From ebc55f523c2f406e30ec8fad77bd3b9aad5d4579 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 29 Jul 2022 00:21:32 +0200 Subject: [PATCH 0040/1020] configure: pass correct cflags to container-based cross compilers probe_target_compiler returns nonempty $target_cc for installed toolchains and $container_cross_cc for container-based toolchains. In both cases however the flags (coming from $cross_cc_cflags_${target_arch}) must be in $target_cflags. Therefore, do not clear them prior to returning from probe_target_compiler. Reported-by: Taylor Simpson Fixes: 92e288fcfb ("build: try both native and cross compilers", 2022-07-08) Signed-off-by: Paolo Bonzini --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index c4c02b8438..72ab03f11a 100755 --- a/configure +++ b/configure @@ -2173,7 +2173,6 @@ probe_target_compiler() { build_static= target_cc= target_ccas= - target_cflags= target_ar= target_as= target_ld= From feb6cb936906ad049bdc77ef176b1d402e341c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Mon, 25 Jul 2022 15:05:08 +0100 Subject: [PATCH 0041/1020] tests: refresh to latest libvirt-ci module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Notable changes: - libvirt-ci source tree was re-arranged, so the script we run now lives in a bin/ sub-dir - opensuse 15.2 is replaced by opensuse 15.3 - libslirp is temporarily dropped on opensuse as the libslirp-version.h is broken https://bugzilla.opensuse.org/show_bug.cgi?id=1201551 - The incorrectly named python3-virtualenv module was changed to python3-venv, but most distros don't need any package as 'venv' is a standard part of python - glibc-static was renamed to libc-static, to reflect fact that it isn't going to be glibc on all distros - The cmocka/json-c deps that were manually added to the centos dockerfile and are now consistently added to all targets Acked-by: Thomas Huth Signed-off-by: Daniel P. BerrangĂ© Message-Id: <20220722130431.2319019-2-berrange@redhat.com> Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Acked-by: Richard Henderson Message-Id: <20220725140520.515340-2-alex.bennee@linaro.org> --- .gitlab-ci.d/cirrus/freebsd-12.vars | 3 +-- .gitlab-ci.d/cirrus/freebsd-13.vars | 3 +-- .gitlab-ci.d/cirrus/macos-11.vars | 4 ++-- tests/docker/dockerfiles/alpine.docker | 4 +++- tests/docker/dockerfiles/centos8.docker | 6 +++--- tests/docker/dockerfiles/debian-amd64.docker | 2 ++ tests/docker/dockerfiles/debian-arm64-cross.docker | 2 ++ tests/docker/dockerfiles/debian-armel-cross.docker | 2 ++ tests/docker/dockerfiles/debian-armhf-cross.docker | 2 ++ tests/docker/dockerfiles/debian-mips64el-cross.docker | 2 ++ tests/docker/dockerfiles/debian-mipsel-cross.docker | 2 ++ tests/docker/dockerfiles/debian-ppc64el-cross.docker | 2 ++ tests/docker/dockerfiles/debian-s390x-cross.docker | 2 ++ tests/docker/dockerfiles/fedora.docker | 3 ++- tests/docker/dockerfiles/opensuse-leap.docker | 7 ++++--- tests/docker/dockerfiles/ubuntu2004.docker | 2 ++ tests/lcitool/libvirt-ci | 2 +- tests/lcitool/projects/qemu.yml | 6 ++++-- tests/lcitool/refresh | 4 ++-- 19 files changed, 41 insertions(+), 19 deletions(-) diff --git a/.gitlab-ci.d/cirrus/freebsd-12.vars b/.gitlab-ci.d/cirrus/freebsd-12.vars index f59263731f..8fa5a320e9 100644 --- a/.gitlab-ci.d/cirrus/freebsd-12.vars +++ b/.gitlab-ci.d/cirrus/freebsd-12.vars @@ -1,5 +1,4 @@ # THIS FILE WAS AUTO-GENERATED -# ... and then edited to fix py39, pending proper lcitool update. # # $ lcitool variables freebsd-12 qemu # @@ -12,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-virtualenv py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' PYPI_PKGS='' PYTHON='/usr/local/bin/python3' diff --git a/.gitlab-ci.d/cirrus/freebsd-13.vars b/.gitlab-ci.d/cirrus/freebsd-13.vars index 40fc961398..8ed7e33a77 100644 --- a/.gitlab-ci.d/cirrus/freebsd-13.vars +++ b/.gitlab-ci.d/cirrus/freebsd-13.vars @@ -1,5 +1,4 @@ # THIS FILE WAS AUTO-GENERATED -# ... and then edited to fix py39, pending proper lcitool update. # # $ lcitool variables freebsd-13 qemu # @@ -12,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-virtualenv py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' PYPI_PKGS='' PYTHON='/usr/local/bin/python3' diff --git a/.gitlab-ci.d/cirrus/macos-11.vars b/.gitlab-ci.d/cirrus/macos-11.vars index cfe9181fd4..bec6e862d4 100644 --- a/.gitlab-ci.d/cirrus/macos-11.vars +++ b/.gitlab-ci.d/cirrus/macos-11.vars @@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='brew' PIP3='/usr/local/bin/pip3' -PKGS='bash bc bzip2 capstone ccache ctags curl dbus diffutils dtc gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd' -PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme virtualenv' +PKGS='bash bc bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd' +PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme' PYTHON='/usr/local/bin/python3' diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index 3f4c0f95cb..806cb19f17 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -21,6 +21,7 @@ RUN apk update && \ cdrkit \ ceph-dev \ clang \ + cmocka-dev \ ctags \ curl-dev \ cyrus-sasl-dev \ @@ -39,6 +40,7 @@ RUN apk update && \ glib-static \ gnutls-dev \ gtk+3.0-dev \ + json-c-dev \ libaio-dev \ libbpf-dev \ libcap-ng-dev \ @@ -64,6 +66,7 @@ RUN apk update && \ mesa-dev \ meson \ multipath-tools \ + musl-dev \ ncurses-dev \ ndctl-dev \ net-tools \ @@ -81,7 +84,6 @@ RUN apk update && \ py3-pip \ py3-sphinx \ py3-sphinx_rtd_theme \ - py3-virtualenv \ py3-yaml \ python3 \ rpm2cpio \ diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker index 10618bfa83..3c29883332 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -6,11 +6,12 @@ FROM quay.io/centos/centos:stream8 -RUN dnf update -y && \ +RUN dnf distro-sync -y && \ dnf install 'dnf-command(config-manager)' -y && \ dnf config-manager --set-enabled -y powertools && \ dnf install -y centos-release-advanced-virtualization && \ dnf install -y epel-release && \ + dnf install -y epel-next-release && \ dnf install -y \ SDL2-devel \ alsa-lib-devel \ @@ -45,6 +46,7 @@ RUN dnf update -y && \ gtk3-devel \ hostname \ jemalloc-devel \ + json-c-devel \ libaio-devel \ libasan \ libattr-devel \ @@ -60,7 +62,6 @@ RUN dnf update -y && \ libgcrypt-devel \ libiscsi-devel \ libjpeg-devel \ - json-c-devel \ libnfs-devel \ libpmem-devel \ libpng-devel \ @@ -99,7 +100,6 @@ RUN dnf update -y && \ python3-pip \ python3-sphinx \ python3-sphinx_rtd_theme \ - python3-virtualenv \ rdma-core-devel \ rpm \ sed \ diff --git a/tests/docker/dockerfiles/debian-amd64.docker b/tests/docker/dockerfiles/debian-amd64.docker index 503e282802..8d78ba2484 100644 --- a/tests/docker/dockerfiles/debian-amd64.docker +++ b/tests/docker/dockerfiles/debian-amd64.docker @@ -41,6 +41,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev \ libcap-ng-dev \ libcapstone-dev \ + libcmocka-dev \ libcurl4-gnutls-dev \ libdaxctl-dev \ libdrm-dev \ @@ -59,6 +60,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev \ libjemalloc-dev \ libjpeg62-turbo-dev \ + libjson-c-dev \ liblttng-ust-dev \ liblzo2-dev \ libncursesw5-dev \ diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker index b60426834c..b7ba2c527f 100644 --- a/tests/docker/dockerfiles/debian-arm64-cross.docker +++ b/tests/docker/dockerfiles/debian-arm64-cross.docker @@ -84,6 +84,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev:arm64 \ libcap-ng-dev:arm64 \ libcapstone-dev:arm64 \ + libcmocka-dev:arm64 \ libcurl4-gnutls-dev:arm64 \ libdaxctl-dev:arm64 \ libdrm-dev:arm64 \ @@ -102,6 +103,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev:arm64 \ libjemalloc-dev:arm64 \ libjpeg62-turbo-dev:arm64 \ + libjson-c-dev:arm64 \ liblttng-ust-dev:arm64 \ liblzo2-dev:arm64 \ libncursesw5-dev:arm64 \ diff --git a/tests/docker/dockerfiles/debian-armel-cross.docker b/tests/docker/dockerfiles/debian-armel-cross.docker index a6153e5a83..9b1778261e 100644 --- a/tests/docker/dockerfiles/debian-armel-cross.docker +++ b/tests/docker/dockerfiles/debian-armel-cross.docker @@ -84,6 +84,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev:armel \ libcap-ng-dev:armel \ libcapstone-dev:armel \ + libcmocka-dev:armel \ libcurl4-gnutls-dev:armel \ libdaxctl-dev:armel \ libdrm-dev:armel \ @@ -102,6 +103,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev:armel \ libjemalloc-dev:armel \ libjpeg62-turbo-dev:armel \ + libjson-c-dev:armel \ liblttng-ust-dev:armel \ liblzo2-dev:armel \ libncursesw5-dev:armel \ diff --git a/tests/docker/dockerfiles/debian-armhf-cross.docker b/tests/docker/dockerfiles/debian-armhf-cross.docker index a2ebce96f8..addbc9a793 100644 --- a/tests/docker/dockerfiles/debian-armhf-cross.docker +++ b/tests/docker/dockerfiles/debian-armhf-cross.docker @@ -84,6 +84,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev:armhf \ libcap-ng-dev:armhf \ libcapstone-dev:armhf \ + libcmocka-dev:armhf \ libcurl4-gnutls-dev:armhf \ libdaxctl-dev:armhf \ libdrm-dev:armhf \ @@ -102,6 +103,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev:armhf \ libjemalloc-dev:armhf \ libjpeg62-turbo-dev:armhf \ + libjson-c-dev:armhf \ liblttng-ust-dev:armhf \ liblzo2-dev:armhf \ libncursesw5-dev:armhf \ diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker index b02dcb7fd9..1bb7d8e184 100644 --- a/tests/docker/dockerfiles/debian-mips64el-cross.docker +++ b/tests/docker/dockerfiles/debian-mips64el-cross.docker @@ -83,6 +83,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev:mips64el \ libcap-ng-dev:mips64el \ libcapstone-dev:mips64el \ + libcmocka-dev:mips64el \ libcurl4-gnutls-dev:mips64el \ libdaxctl-dev:mips64el \ libdrm-dev:mips64el \ @@ -101,6 +102,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev:mips64el \ libjemalloc-dev:mips64el \ libjpeg62-turbo-dev:mips64el \ + libjson-c-dev:mips64el \ liblttng-ust-dev:mips64el \ liblzo2-dev:mips64el \ libncursesw5-dev:mips64el \ diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker index b6d99ae324..a94b459b23 100644 --- a/tests/docker/dockerfiles/debian-mipsel-cross.docker +++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker @@ -83,6 +83,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev:mipsel \ libcap-ng-dev:mipsel \ libcapstone-dev:mipsel \ + libcmocka-dev:mipsel \ libcurl4-gnutls-dev:mipsel \ libdaxctl-dev:mipsel \ libdrm-dev:mipsel \ @@ -101,6 +102,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev:mipsel \ libjemalloc-dev:mipsel \ libjpeg62-turbo-dev:mipsel \ + libjson-c-dev:mipsel \ liblttng-ust-dev:mipsel \ liblzo2-dev:mipsel \ libncursesw5-dev:mipsel \ diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker index bcf04bc90b..c641fd5d0e 100644 --- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker +++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker @@ -84,6 +84,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev:ppc64el \ libcap-ng-dev:ppc64el \ libcapstone-dev:ppc64el \ + libcmocka-dev:ppc64el \ libcurl4-gnutls-dev:ppc64el \ libdaxctl-dev:ppc64el \ libdrm-dev:ppc64el \ @@ -102,6 +103,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev:ppc64el \ libjemalloc-dev:ppc64el \ libjpeg62-turbo-dev:ppc64el \ + libjson-c-dev:ppc64el \ liblttng-ust-dev:ppc64el \ liblzo2-dev:ppc64el \ libncursesw5-dev:ppc64el \ diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker index ff79a2cc4f..c0cbe09e66 100644 --- a/tests/docker/dockerfiles/debian-s390x-cross.docker +++ b/tests/docker/dockerfiles/debian-s390x-cross.docker @@ -84,6 +84,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev:s390x \ libcap-ng-dev:s390x \ libcapstone-dev:s390x \ + libcmocka-dev:s390x \ libcurl4-gnutls-dev:s390x \ libdaxctl-dev:s390x \ libdrm-dev:s390x \ @@ -102,6 +103,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev:s390x \ libjemalloc-dev:s390x \ libjpeg62-turbo-dev:s390x \ + libjson-c-dev:s390x \ liblttng-ust-dev:s390x \ liblzo2-dev:s390x \ libncursesw5-dev:s390x \ diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index 2e6a84abfd..b39d311bbc 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -53,12 +53,14 @@ exec "$@"' > /usr/bin/nosync && \ gtk3-devel \ hostname \ jemalloc-devel \ + json-c-devel \ libaio-devel \ libasan \ libattr-devel \ libbpf-devel \ libcacard-devel \ libcap-ng-devel \ + libcmocka-devel \ libcurl-devel \ libdrm-devel \ libepoxy-devel \ @@ -106,7 +108,6 @@ exec "$@"' > /usr/bin/nosync && \ python3-pip \ python3-sphinx \ python3-sphinx_rtd_theme \ - python3-virtualenv \ rdma-core-devel \ rpm \ sed \ diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker index 6f5993d602..047a435ab5 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -1,10 +1,10 @@ # THIS FILE WAS AUTO-GENERATED # -# $ lcitool dockerfile --layers all opensuse-leap-152 qemu +# $ lcitool dockerfile --layers all opensuse-leap-153 qemu # # https://gitlab.com/libvirt/libvirt-ci -FROM registry.opensuse.org/opensuse/leap:15.2 +FROM registry.opensuse.org/opensuse/leap:15.3 RUN zypper update -y && \ zypper install -y \ @@ -44,6 +44,7 @@ RUN zypper update -y && \ libbz2-devel \ libcacard-devel \ libcap-ng-devel \ + libcmocka-devel \ libcurl-devel \ libdrm-devel \ libepoxy-devel \ @@ -53,6 +54,7 @@ RUN zypper update -y && \ libgnutls-devel \ libiscsi-devel \ libjpeg8-devel \ + libjson-c-devel \ libndctl-devel \ libnettle-devel \ libnfs-devel \ @@ -94,7 +96,6 @@ RUN zypper update -y && \ python3-pip \ python3-setuptools \ python3-sphinx_rtd_theme \ - python3-virtualenv \ python3-wheel \ rdma-core-devel \ rpm \ diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker index a3b38884e3..99803b343b 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -40,6 +40,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libcacard-dev \ libcap-ng-dev \ libcapstone-dev \ + libcmocka-dev \ libcurl4-gnutls-dev \ libdaxctl-dev \ libdrm-dev \ @@ -58,6 +59,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ libiscsi-dev \ libjemalloc-dev \ libjpeg-turbo8-dev \ + libjson-c-dev \ liblttng-ust-dev \ liblzo2-dev \ libncursesw5-dev \ diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci index f83b916d5e..324355cf62 160000 --- a/tests/lcitool/libvirt-ci +++ b/tests/lcitool/libvirt-ci @@ -1 +1 @@ -Subproject commit f83b916d5efa4bd33fbf4b7ea41bf6d535cc63fb +Subproject commit 324355cf62e86fb551408575afb123bac989ac37 diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml index d068a7a8de..d9f826f8eb 100644 --- a/tests/lcitool/projects/qemu.yml +++ b/tests/lcitool/projects/qemu.yml @@ -9,6 +9,7 @@ packages: - capstone - ccache - clang + - cmocka - column - ctags - cyrus-sasl @@ -26,15 +27,16 @@ packages: - genisoimage - glib2 - glib2-static - - glibc-static - glusterfs - gnutls - gtk3 - hostname + - json-c - libaio - libattr - libasan - libbpf + - libc-static - libcacard - libcap-ng - libcurl @@ -90,7 +92,7 @@ packages: - python3-pip - python3-sphinx - python3-sphinx-rtd-theme - - python3-virtualenv + - python3-venv - rpm2cpio - sdl2 - sdl2-image diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index 5e260f8cd6..2a59150322 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -25,7 +25,7 @@ self_dir = Path(__file__).parent src_dir = self_dir.parent.parent dockerfiles_dir = Path(src_dir, "tests", "docker", "dockerfiles") -lcitool_path = Path(self_dir, "libvirt-ci", "lcitool") +lcitool_path = Path(self_dir, "libvirt-ci", "bin", "lcitool") lcitool_cmd = [lcitool_path, "--data-dir", self_dir] @@ -112,7 +112,7 @@ try: generate_dockerfile("debian-amd64", "debian-11", trailer="".join(debian11_extras)) generate_dockerfile("fedora", "fedora-35") - generate_dockerfile("opensuse-leap", "opensuse-leap-152") + generate_dockerfile("opensuse-leap", "opensuse-leap-153") generate_dockerfile("ubuntu2004", "ubuntu-2004", trailer="".join(ubuntu2004_tsanhack)) From 998f3347223234eeb2f47235eaa222cf0ee7f8ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Mon, 25 Jul 2022 15:05:09 +0100 Subject: [PATCH 0042/1020] gitlab: show testlog.txt contents when cirrus/custom-runner jobs fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When tests fail meson just displays a summary and tells you to look at the testlog.txt file for details. The native jobs on shared runners publish testlog.txt as an artifact. For the Cirrus jobs and custom runner jobs this is not currently possible. The best we can do is cat the log contents on failure, to give maintainers a fighting chance of diagnosing the problem. Reviewed-by: Thomas Huth Signed-off-by: Daniel P. BerrangĂ© Message-Id: <20220722130431.2319019-3-berrange@redhat.com> Signed-off-by: Alex BennĂ©e Message-Id: <20220725140520.515340-3-alex.bennee@linaro.org> --- .gitlab-ci.d/cirrus/build.yml | 3 ++- .../custom-runners/centos-stream-8-x86_64.yml | 2 ++ .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml | 2 ++ .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml | 12 ++++++++++++ .gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml | 12 ++++++++++++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.d/cirrus/build.yml b/.gitlab-ci.d/cirrus/build.yml index c555f5d36e..7ef6af8d33 100644 --- a/.gitlab-ci.d/cirrus/build.yml +++ b/.gitlab-ci.d/cirrus/build.yml @@ -32,5 +32,6 @@ build_task: - $MAKE -j$(sysctl -n hw.ncpu) - for TARGET in $TEST_TARGETS ; do - $MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1 ; + $MAKE -j$(sysctl -n hw.ncpu) $TARGET V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; done diff --git a/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml b/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml index 49aa703f55..068b0c4335 100644 --- a/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml +++ b/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml @@ -23,6 +23,8 @@ centos-stream-8-x86_64: - mkdir build - cd build - ../scripts/ci/org.centos/stream/8/x86_64/configure + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make -j"$JOBS" - make NINJA=":" check + || { cat meson-logs/testlog.txt; exit 1; } ; - ../scripts/ci/org.centos/stream/8/x86_64/test-avocado diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml index 1998460d06..cbfa9cc164 100644 --- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml +++ b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml @@ -19,5 +19,7 @@ ubuntu-20.04-aarch32-all: - mkdir build - cd build - ../configure --cross-prefix=arm-linux-gnueabihf- + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml index 65718a188a..3d878914e7 100644 --- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml +++ b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml @@ -17,9 +17,12 @@ ubuntu-20.04-aarch64-all-linux-static: - mkdir build - cd build - ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; - make --output-sync -j`nproc --ignore=40` check-tcg V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; ubuntu-20.04-aarch64-all: needs: [] @@ -38,8 +41,10 @@ ubuntu-20.04-aarch64-all: - mkdir build - cd build - ../configure --disable-libssh + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; ubuntu-20.04-aarch64-alldbg: needs: [] @@ -54,9 +59,11 @@ ubuntu-20.04-aarch64-alldbg: - mkdir build - cd build - ../configure --enable-debug --disable-libssh + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make clean - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; ubuntu-20.04-aarch64-clang: needs: [] @@ -75,8 +82,10 @@ ubuntu-20.04-aarch64-clang: - mkdir build - cd build - ../configure --disable-libssh --cc=clang-10 --cxx=clang++-10 --enable-sanitizers + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; ubuntu-20.04-aarch64-tci: needs: [] @@ -95,6 +104,7 @@ ubuntu-20.04-aarch64-tci: - mkdir build - cd build - ../configure --disable-libssh --enable-tcg-interpreter + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` ubuntu-20.04-aarch64-notcg: @@ -114,5 +124,7 @@ ubuntu-20.04-aarch64-notcg: - mkdir build - cd build - ../configure --disable-libssh --disable-tcg + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml b/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml index 03e74c97db..0c835939db 100644 --- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml +++ b/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml @@ -17,9 +17,12 @@ ubuntu-20.04-s390x-all-linux-static: - mkdir build - cd build - ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc` - make --output-sync -j`nproc` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; - make --output-sync -j`nproc` check-tcg V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; ubuntu-20.04-s390x-all: needs: [] @@ -35,8 +38,10 @@ ubuntu-20.04-s390x-all: - mkdir build - cd build - ../configure --disable-libssh + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc` - make --output-sync -j`nproc` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; ubuntu-20.04-s390x-alldbg: needs: [] @@ -55,9 +60,11 @@ ubuntu-20.04-s390x-alldbg: - mkdir build - cd build - ../configure --enable-debug --disable-libssh + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make clean - make --output-sync -j`nproc` - make --output-sync -j`nproc` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; ubuntu-20.04-s390x-clang: needs: [] @@ -76,8 +83,10 @@ ubuntu-20.04-s390x-clang: - mkdir build - cd build - ../configure --disable-libssh --cc=clang --cxx=clang++ --enable-sanitizers + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc` - make --output-sync -j`nproc` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; ubuntu-20.04-s390x-tci: needs: [] @@ -96,6 +105,7 @@ ubuntu-20.04-s390x-tci: - mkdir build - cd build - ../configure --disable-libssh --enable-tcg-interpreter + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc` ubuntu-20.04-s390x-notcg: @@ -115,5 +125,7 @@ ubuntu-20.04-s390x-notcg: - mkdir build - cd build - ../configure --disable-libssh --disable-tcg + || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc` - make --output-sync -j`nproc` check V=1 + || { cat meson-logs/testlog.txt; exit 1; } ; From ca58b4931ec2599eb8a2564bef231b32247348bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Mon, 25 Jul 2022 15:05:10 +0100 Subject: [PATCH 0043/1020] gitlab: drop 'containers-layer2' stage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we express dependencies via a 'needs' clause, we don't need to split container builds into separate stages. GitLab happily lets jobs depend on other jobs in the same stage and will run them when possible. Acked-by: Thomas Huth Signed-off-by: Daniel P. BerrangĂ© Message-Id: <20220722130431.2319019-4-berrange@redhat.com> [AJB: fix typo] Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220725140520.515340-4-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 24 ++++++++++++------------ .gitlab-ci.d/stages.yml | 1 - 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index b7963498a3..505b267542 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -1,20 +1,20 @@ alpha-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-alpha-cross amd64-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-amd64-cross amd64-debian-user-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-all-test-cross @@ -65,21 +65,21 @@ hexagon-cross-container: hppa-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-hppa-cross m68k-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-m68k-cross mips64-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-mips64-cross @@ -92,7 +92,7 @@ mips64el-debian-cross-container: mips-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-mips-cross @@ -105,7 +105,7 @@ mipsel-debian-cross-container: powerpc-test-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian11-container'] variables: NAME: debian-powerpc-test-cross @@ -127,7 +127,7 @@ riscv64-debian-cross-container: # we can however build TCG tests using a non-sid base riscv64-debian-test-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian11-container'] variables: NAME: debian-riscv64-test-cross @@ -140,21 +140,21 @@ s390x-debian-cross-container: sh4-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-sh4-cross sparc64-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-sparc64-cross tricore-debian-cross-container: extends: .container_job_template - stage: containers-layer2 + stage: containers needs: ['amd64-debian10-container'] variables: NAME: debian-tricore-cross diff --git a/.gitlab-ci.d/stages.yml b/.gitlab-ci.d/stages.yml index f50826018d..f92f57a27d 100644 --- a/.gitlab-ci.d/stages.yml +++ b/.gitlab-ci.d/stages.yml @@ -3,6 +3,5 @@ # - test (for test stages, using build artefacts from a build stage) stages: - containers - - containers-layer2 - build - test From 6ad5208661643aad31328433aaaa2045805b12b8 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 25 Jul 2022 15:05:11 +0100 Subject: [PATCH 0044/1020] .cirrus.yml: Change winsymlinks to 'native' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At present winsymlinks is set to 'nativestrict', and its behavior is: a) if native symlinks are enabled and exists, creates as a native Windows symlink; b) else if native symlinks are not enabled or if does not exist, 'ln -s' fails. This causes the following error message was seen during the configure: "ln: failed to create symbolic link 'x86_64-softmmu/qemu-system-x86_64.exe': No such file or directory" Change winsymlinks to 'native' whose behavior is most similar to the behavior of 'ln -s' on *nix, that is: a) if native symlinks are enabled, and whether exists or not, creates as a native Windows symlink; b) else if native symlinks are not enabled, and whether exists or not, 'ln -s' creates as a Windows shortcut file. Signed-off-by: Bin Meng Acked-by: Thomas Huth Reviewed-by: Yonggang Luo Message-Id: <20220719161230.766063-1-bmeng.cn@gmail.com> Signed-off-by: Alex BennĂ©e Message-Id: <20220725140520.515340-5-alex.bennee@linaro.org> --- .cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 20843a420c..eac39024f2 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -10,7 +10,7 @@ windows_msys2_task: memory: 8G env: CIRRUS_SHELL: powershell - MSYS: winsymlinks:nativestrict + MSYS: winsymlinks:native MSYSTEM: MINGW64 MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2022-05-03/msys2-base-x86_64-20220503.sfx.exe MSYS2_FINGERPRINT: 0 From 93a02e822fc65d8f16eb98f64af88d69ba3c9fd6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Mon, 25 Jul 2022 15:05:12 +0100 Subject: [PATCH 0045/1020] .gitlab-ci.d/windows.yml: Enable native Windows symlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following error message was seen during the configure: "ln: failed to create symbolic link 'x86_64-softmmu/qemu-system-x86_64.exe': No such file or directory" By default the MSYS environment variable is not defined, so the runtime behavior of winsymlinks is: if does not exist, 'ln -s' fails. At the configure phase, the qemu-system-x86_64.exe has not been built so creation of the symbolic link fails hence the error message. Set winsymlinks to 'native' whose behavior is most similar to the behavior of 'ln -s' on *nix, that is: a) if native symlinks are enabled, and whether exists or not, creates as a native Windows symlink; b) else if native symlinks are not enabled, and whether exists or not, 'ln -s' creates as a Windows shortcut file. Signed-off-by: Bin Meng Signed-off-by: Alex BennĂ©e Message-Id: <20220725123000.807608-1-bmeng.cn@gmail.com> Message-Id: <20220725140520.515340-6-alex.bennee@linaro.org> --- .gitlab-ci.d/windows.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index 1b2ede49e1..0b9572a8a3 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -57,6 +57,7 @@ msys2-64bit: mingw-w64-x86_64-zstd " - $env:CHERE_INVOKING = 'yes' # Preserve the current working directory - $env:MSYSTEM = 'MINGW64' # Start a 64 bit Mingw environment + - $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink - .\msys64\usr\bin\bash -lc './configure --target-list=x86_64-softmmu --enable-capstone --without-default-devices' - .\msys64\usr\bin\bash -lc "sed -i '/^ROMS=/d' build/config-host.mak" @@ -89,6 +90,7 @@ msys2-32bit: mingw-w64-i686-usbredir " - $env:CHERE_INVOKING = 'yes' # Preserve the current working directory - $env:MSYSTEM = 'MINGW32' # Start a 32-bit MinG environment + - $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink - mkdir output - cd output - ..\msys64\usr\bin\bash -lc "../configure --target-list=ppc64-softmmu" From aed04e6357fa10735c43574ea67a9551580d6e82 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 25 Jul 2022 15:05:13 +0100 Subject: [PATCH 0046/1020] semihosting: Don't return negative values on qemu_semihosting_console_write() failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The documentation comment for qemu_semihosting_console_write() says * Returns: number of bytes written -- this should only ever be short * on some sort of i/o error. and the callsites rely on this. However, the implementation code path which sends console output to a chardev doesn't honour this, and will return negative values on error. Bring it into line with the other implementation codepaths and the documentation, so that it returns 0 on error. Spotted by Coverity, because console_write() passes the return value to unlock_user(), which doesn't accept a negative length. Resolves: Coverity CID 1490288 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220719121110.225657-2-peter.maydell@linaro.org> Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220725140520.515340-7-alex.bennee@linaro.org> --- semihosting/console.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/semihosting/console.c b/semihosting/console.c index 5b1ec0a1c3..0f976fe8cb 100644 --- a/semihosting/console.c +++ b/semihosting/console.c @@ -111,7 +111,8 @@ int qemu_semihosting_console_read(CPUState *cs, void *buf, int len) int qemu_semihosting_console_write(void *buf, int len) { if (console.chr) { - return qemu_chr_write_all(console.chr, (uint8_t *)buf, len); + int r = qemu_chr_write_all(console.chr, (uint8_t *)buf, len); + return r < 0 ? 0 : r; } else { return fwrite(buf, 1, len, stderr); } From 45704e89047fc0a151c5909f006d8757140f23d6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 25 Jul 2022 15:05:14 +0100 Subject: [PATCH 0047/1020] semihosting: Don't copy buffer after console_write() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The console_write() semihosting function outputs guest data from a buffer; it doesn't update that buffer. It therefore doesn't need to pass a length value to unlock_user(), but can pass 0, meaning "do not copy any data back to the guest memory". Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220719121110.225657-3-peter.maydell@linaro.org> Signed-off-by: Alex BennĂ©e Message-Id: <20220725140520.515340-8-alex.bennee@linaro.org> --- semihosting/syscalls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semihosting/syscalls.c b/semihosting/syscalls.c index 4847f66c02..508a0ad88c 100644 --- a/semihosting/syscalls.c +++ b/semihosting/syscalls.c @@ -627,7 +627,7 @@ static void console_write(CPUState *cs, gdb_syscall_complete_cb complete, } ret = qemu_semihosting_console_write(ptr, len); complete(cs, ret ? ret : -1, ret ? 0 : EIO); - unlock_user(ptr, buf, ret); + unlock_user(ptr, buf, 0); } static void console_fstat(CPUState *cs, gdb_syscall_complete_cb complete, From fed49cdf6a721d76f9ac1cf76fd05b3fbd8b4892 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 25 Jul 2022 15:05:15 +0100 Subject: [PATCH 0048/1020] semihosting: Check for errors on SET_ARG() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SET_ARG() macro returns an error indication; we check this in the TARGET_SYS_GET_CMDLINE case but not when we use it in implementing TARGET_SYS_ELAPSED. Check for and handle the errors via the do_fault codepath, and update the comment documenting the SET_ARG() and GET_ARG() macros to note how they handle memory access errors. Resolves: Coverity CID 1490287 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220719121110.225657-4-peter.maydell@linaro.org> Signed-off-by: Alex BennĂ©e Message-Id: <20220725140520.515340-9-alex.bennee@linaro.org> --- semihosting/arm-compat-semi.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c index 1a1e2a6960..d12288fc80 100644 --- a/semihosting/arm-compat-semi.c +++ b/semihosting/arm-compat-semi.c @@ -171,6 +171,12 @@ static LayoutInfo common_semi_find_bases(CPUState *cs) * Read the input value from the argument block; fail the semihosting * call if the memory read fails. Eventually we could use a generic * CPUState helper function here. + * Note that GET_ARG() handles memory access errors by jumping to + * do_fault, so must be used as the first thing done in handling a + * semihosting call, to avoid accidentally leaking allocated resources. + * SET_ARG(), since it unavoidably happens late, instead returns an + * error indication (0 on success, non-0 for error) which the caller + * should check. */ #define GET_ARG(n) do { \ @@ -739,10 +745,14 @@ void do_common_semihosting(CPUState *cs) case TARGET_SYS_ELAPSED: elapsed = get_clock() - clock_start; if (sizeof(target_ulong) == 8) { - SET_ARG(0, elapsed); + if (SET_ARG(0, elapsed)) { + goto do_fault; + } } else { - SET_ARG(0, (uint32_t) elapsed); - SET_ARG(1, (uint32_t) (elapsed >> 32)); + if (SET_ARG(0, (uint32_t) elapsed) || + SET_ARG(1, (uint32_t) (elapsed >> 32))) { + goto do_fault; + } } common_semi_set_ret(cs, 0); break; From 9b1268f55ceb0d9390a051cad299b3021dfa9896 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 25 Jul 2022 15:05:16 +0100 Subject: [PATCH 0049/1020] semihosting: Fix handling of buffer in TARGET_SYS_TMPNAM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The TARGET_SYS_TMPNAM implementation has two bugs spotted by Coverity: * confusion about whether 'len' has the length of the string including or excluding the terminating NUL means we lock_user() len bytes of memory but memcpy() len + 1 bytes * In the error-exit cases we forget to free() the buffer that asprintf() returned to us Resolves: Coverity CID 1490285, 1490289 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220719121110.225657-5-peter.maydell@linaro.org> Signed-off-by: Alex BennĂ©e Message-Id: <20220725140520.515340-10-alex.bennee@linaro.org> --- semihosting/arm-compat-semi.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c index d12288fc80..e741674238 100644 --- a/semihosting/arm-compat-semi.c +++ b/semihosting/arm-compat-semi.c @@ -504,16 +504,25 @@ void do_common_semihosting(CPUState *cs) GET_ARG(1); GET_ARG(2); len = asprintf(&s, "/tmp/qemu-%x%02x", getpid(), (int)arg1 & 0xff); + if (len < 0) { + common_semi_set_ret(cs, -1); + break; + } + + /* Allow for trailing NUL */ + len++; /* Make sure there's enough space in the buffer */ - if (len < 0 || len >= arg2) { + if (len > arg2) { + free(s); common_semi_set_ret(cs, -1); break; } p = lock_user(VERIFY_WRITE, arg0, len, 0); if (!p) { + free(s); goto do_fault; } - memcpy(p, s, len + 1); + memcpy(p, s, len); unlock_user(p, arg0, len); free(s); common_semi_set_ret(cs, 0); From 0882caf4d607bcfb1efa99034f5f045f30eb43d7 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 26 Jul 2022 00:37:45 +0200 Subject: [PATCH 0050/1020] qapi: Add exit-failure PanicAction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently QEMU exits with code 0 on both panic an shutdown. For tests it is useful to return 1 on panic, so that it counts as a test failure. Introduce a new exit-failure PanicAction that makes main() return EXIT_FAILURE. Tests can use -action panic=exit-failure option to activate this behavior. Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Reviewed-by: David Hildenbrand Message-Id: <20220725223746.227063-2-iii@linux.ibm.com> Signed-off-by: Alex BennĂ©e --- include/sysemu/sysemu.h | 2 +- qapi/run-state.json | 5 ++++- qemu-options.hx | 2 +- softmmu/main.c | 6 ++++-- softmmu/runstate.c | 17 +++++++++++++---- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 812f66a31a..31aa45160b 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -103,7 +103,7 @@ void qemu_boot_set(const char *boot_order, Error **errp); bool defaults_enabled(void); void qemu_init(int argc, char **argv, char **envp); -void qemu_main_loop(void); +int qemu_main_loop(void); void qemu_cleanup(void); extern QemuOptsList qemu_legacy_drive_opts; diff --git a/qapi/run-state.json b/qapi/run-state.json index 6e2162d7b3..9273ea6516 100644 --- a/qapi/run-state.json +++ b/qapi/run-state.json @@ -364,10 +364,13 @@ # # @shutdown: Shutdown the VM and exit, according to the shutdown action # +# @exit-failure: Shutdown the VM and exit with nonzero status +# (since 7.1) +# # Since: 6.0 ## { 'enum': 'PanicAction', - 'data': [ 'pause', 'shutdown', 'none' ] } + 'data': [ 'pause', 'shutdown', 'exit-failure', 'none' ] } ## # @watchdog-set-action: diff --git a/qemu-options.hx b/qemu-options.hx index 79e00916a1..8e17c5064a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4239,7 +4239,7 @@ DEF("action", HAS_ARG, QEMU_OPTION_action, " action when guest reboots [default=reset]\n" "-action shutdown=poweroff|pause\n" " action when guest shuts down [default=poweroff]\n" - "-action panic=pause|shutdown|none\n" + "-action panic=pause|shutdown|exit-failure|none\n" " action when guest panics [default=shutdown]\n" "-action watchdog=reset|shutdown|poweroff|inject-nmi|pause|debug|none\n" " action when watchdog fires [default=reset]\n", diff --git a/softmmu/main.c b/softmmu/main.c index c00432ff09..1b675a8c03 100644 --- a/softmmu/main.c +++ b/softmmu/main.c @@ -32,11 +32,13 @@ int qemu_main(int argc, char **argv, char **envp) { + int status; + qemu_init(argc, argv, envp); - qemu_main_loop(); + status = qemu_main_loop(); qemu_cleanup(); - return 0; + return status; } #ifndef CONFIG_COCOA diff --git a/softmmu/runstate.c b/softmmu/runstate.c index 168e1b78a0..1e68680b9d 100644 --- a/softmmu/runstate.c +++ b/softmmu/runstate.c @@ -482,7 +482,8 @@ void qemu_system_guest_panicked(GuestPanicInformation *info) qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, !!info, info); vm_stop(RUN_STATE_GUEST_PANICKED); - } else if (panic_action == PANIC_ACTION_SHUTDOWN) { + } else if (panic_action == PANIC_ACTION_SHUTDOWN || + panic_action == PANIC_ACTION_EXIT_FAILURE) { qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF, !!info, info); vm_stop(RUN_STATE_GUEST_PANICKED); @@ -662,7 +663,7 @@ void qemu_system_debug_request(void) qemu_notify_event(); } -static bool main_loop_should_exit(void) +static bool main_loop_should_exit(int *status) { RunState r; ShutdownCause request; @@ -680,6 +681,10 @@ static bool main_loop_should_exit(void) if (shutdown_action == SHUTDOWN_ACTION_PAUSE) { vm_stop(RUN_STATE_SHUTDOWN); } else { + if (request == SHUTDOWN_CAUSE_GUEST_PANIC && + panic_action == PANIC_ACTION_EXIT_FAILURE) { + *status = EXIT_FAILURE; + } return true; } } @@ -715,12 +720,14 @@ static bool main_loop_should_exit(void) return false; } -void qemu_main_loop(void) +int qemu_main_loop(void) { + int status = EXIT_SUCCESS; #ifdef CONFIG_PROFILER int64_t ti; #endif - while (!main_loop_should_exit()) { + + while (!main_loop_should_exit(&status)) { #ifdef CONFIG_PROFILER ti = profile_getclock(); #endif @@ -729,6 +736,8 @@ void qemu_main_loop(void) dev_time += profile_getclock() - ti; #endif } + + return status; } void qemu_add_exit_notifier(Notifier *notify) From 503e549e441e6f28eaf8a5ffd0edd3e1eba9cfec Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 26 Jul 2022 00:37:46 +0200 Subject: [PATCH 0051/1020] tests/tcg/s390x: Test unaligned accesses to lowcore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a small test to avoid regressions. Signed-off-by: Ilya Leoshkevich Acked-by: Richard Henderson Acked-by: Thomas Huth Message-Id: <20220725223746.227063-3-iii@linux.ibm.com> Signed-off-by: Alex BennĂ©e --- tests/tcg/s390x/Makefile.softmmu-target | 9 +++++++++ tests/tcg/s390x/unaligned-lowcore.S | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 tests/tcg/s390x/Makefile.softmmu-target create mode 100644 tests/tcg/s390x/unaligned-lowcore.S diff --git a/tests/tcg/s390x/Makefile.softmmu-target b/tests/tcg/s390x/Makefile.softmmu-target new file mode 100644 index 0000000000..a34fa68473 --- /dev/null +++ b/tests/tcg/s390x/Makefile.softmmu-target @@ -0,0 +1,9 @@ +S390X_SRC=$(SRC_PATH)/tests/tcg/s390x +VPATH+=$(S390X_SRC) +QEMU_OPTS=-action panic=exit-failure -kernel + +%: %.S + $(CC) -march=z13 -m64 -nostartfiles -static -Wl,-Ttext=0 \ + -Wl,--build-id=none $< -o $@ + +TESTS += unaligned-lowcore diff --git a/tests/tcg/s390x/unaligned-lowcore.S b/tests/tcg/s390x/unaligned-lowcore.S new file mode 100644 index 0000000000..f5da2ae64c --- /dev/null +++ b/tests/tcg/s390x/unaligned-lowcore.S @@ -0,0 +1,19 @@ + .org 0x1D0 /* program new PSW */ + .quad 0x2000000000000,0 /* disabled wait */ + .org 0x200 /* lowcore padding */ + + .globl _start +_start: + lctlg %c0,%c0,_c0 + vst %v0,_unaligned + lpswe quiesce_psw + + .align 8 +quiesce_psw: + .quad 0x2000000000000,0xfff /* see is_special_wait_psw() */ +_c0: + .quad 0x10060000 /* lowcore protection, AFP, VX */ + + .byte 0 +_unaligned: + .octa 0 From 28053143ab865d5a5fae7d486cf68181d37dde72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 25 Jul 2022 15:05:19 +0100 Subject: [PATCH 0052/1020] docs/devel: fix description of OBJECT_DECLARE_SIMPLE_TYPE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since 30b5707c26 (qom: Remove module_obj_name parameter from OBJECT_DECLARE* macros) we don't need the additional two parameters. Fix the documentation. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220725140520.515340-13-alex.bennee@linaro.org> --- docs/devel/qom.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/devel/qom.rst b/docs/devel/qom.rst index e5fe3597cd..0cf9a714f0 100644 --- a/docs/devel/qom.rst +++ b/docs/devel/qom.rst @@ -292,8 +292,7 @@ in the header file: .. code-block:: c :caption: Declaring a simple type - OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, my_device, - MY_DEVICE, DEVICE) + OBJECT_DECLARE_SIMPLE_TYPE(MyDevice, MY_DEVICE) This is equivalent to the following: From 1235cf7d315b415fc2e4aa81815fda6ce96518c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 25 Jul 2022 15:05:20 +0100 Subject: [PATCH 0053/1020] qemu-options: bring the kernel and image options together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit How to control the booting of QEMU is often a source of confusion for users. Bring the options that control this together in the manual pages and add some verbiage to describe when each option is appropriate. This attempts to codify some of the knowledge expressed in: https://stackoverflow.com/questions/58420670/qemu-bios-vs-kernel-vs-device-loader-file/58434837#58434837 Signed-off-by: Alex BennĂ©e Reviewed-by: Peter Maydell Reviewed-by: CĂ©dric Le Goater Message-Id: <20220725140520.515340-14-alex.bennee@linaro.org> --- qemu-options.hx | 96 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 78 insertions(+), 18 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 8e17c5064a..3f23a42fa8 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1585,13 +1585,6 @@ SRST Use file as SecureDigital card image. ERST -DEF("pflash", HAS_ARG, QEMU_OPTION_pflash, - "-pflash file use 'file' as a parallel flash image\n", QEMU_ARCH_ALL) -SRST -``-pflash file`` - Use file as a parallel flash image. -ERST - DEF("snapshot", 0, QEMU_OPTION_snapshot, "-snapshot write to temporary files instead of disk image files\n", QEMU_ARCH_ALL) @@ -3684,12 +3677,67 @@ DEFHEADING() #endif -DEFHEADING(Linux/Multiboot boot specific:) +DEFHEADING(Boot Image or Kernel specific:) SRST -When using these options, you can use a given Linux or Multiboot kernel -without installing it in the disk image. It can be useful for easier -testing of various kernels. +There are broadly 4 ways you can boot a system with QEMU. + - specify a firmware and let it control finding a kernel + - specify a firmware and pass a hint to the kernel to boot + - direct kernel image boot + - manually load files into the guest's address space + +The third method is useful for quickly testing kernels but as there is +no firmware to pass configuration information to the kernel the +hardware must either be probeable, the kernel built for the exact +configuration or passed some configuration data (e.g. a DTB blob) +which tells the kernel what drivers it needs. This exact details are +often hardware specific. + +The final method is the most generic way of loading images into the +guest address space and used mostly for ``bare metal`` type +development where the reset vectors of the processor are taken into +account. + +ERST + +SRST + +For x86 machines and some other architectures ``-bios`` will generally +do the right thing with whatever it is given. For other machines the +more strict ``-pflash`` option needs an image that is sized for the +flash device for the given machine type. + +Please see the :ref:`system-targets-ref` section of the manual for +more detailed documentation. + +ERST + +DEF("bios", HAS_ARG, QEMU_OPTION_bios, \ + "-bios file set the filename for the BIOS\n", QEMU_ARCH_ALL) +SRST +``-bios file`` + Set the filename for the BIOS. +ERST + +DEF("pflash", HAS_ARG, QEMU_OPTION_pflash, + "-pflash file use 'file' as a parallel flash image\n", QEMU_ARCH_ALL) +SRST +``-pflash file`` + Use file as a parallel flash image. +ERST + +SRST + +The kernel options were designed to work with Linux kernels although +other things (like hypervisors) can be packaged up as a kernel +executable image. The exact format of a executable image is usually +architecture specific. + +The way in which the kernel is started (what address it is loaded at, +what if any information is passed to it via CPU registers, the state +of the hardware when it is started, and so on) is also architecture +specific. Typically it follows the specification laid down by the +Linux kernel for how kernels for that architecture must be started. ERST @@ -3729,6 +3777,25 @@ SRST kernel on boot. ERST +SRST + +Finally you can also manually load images directly into the address +space of the guest. This is most useful for developers who already +know the layout of their guest and take care to ensure something sane +will happen when the reset vector executes. + +The generic loader can be invoked by using the loader device: + +``-device loader,addr=,data=,data-len=[,data-be=][,cpu-num=]`` + +there is also the guest loader which operates in a similar way but +tweaks the DTB so a hypervisor loaded via ``-kernel`` can find where +the guest image is: + +``-device guest-loader,addr=[,kernel=,[bootargs=]][,initrd=]`` + +ERST + DEFHEADING() DEFHEADING(Debug/Expert options:) @@ -4179,13 +4246,6 @@ SRST To list all the data directories, use ``-L help``. ERST -DEF("bios", HAS_ARG, QEMU_OPTION_bios, \ - "-bios file set the filename for the BIOS\n", QEMU_ARCH_ALL) -SRST -``-bios file`` - Set the filename for the BIOS. -ERST - DEF("enable-kvm", 0, QEMU_OPTION_enable_kvm, \ "-enable-kvm enable KVM full virtualization support\n", QEMU_ARCH_ARM | QEMU_ARCH_I386 | QEMU_ARCH_MIPS | QEMU_ARCH_PPC | From f71fa4e3bb22f534ee668e7f4bdf64e59c193afd Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 25 Jul 2022 15:41:00 +0200 Subject: [PATCH 0054/1020] linux-user: Do not treat madvise()'s advice as a bitmask Advice is enum, not flags. Doing (advice & MADV_DONTNEED) also matches e.g. MADV_MERGEABLE. Signed-off-by: Ilya Leoshkevich Reviewed-by: Laurent Vivier Message-Id: <20220725134100.128035-1-iii@linux.ibm.com> Fixes: 892a4f6a750a ("linux-user: Add partial support for MADV_DONTNEED") Signed-off-by: Laurent Vivier --- linux-user/mmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 4e7a6be6ee..edceaca4a8 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -891,7 +891,7 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice) * anonymous mappings. In this case passthrough is safe, so do it. */ mmap_lock(); - if ((advice & MADV_DONTNEED) && + if (advice == MADV_DONTNEED && can_passthrough_madv_dontneed(start, end)) { ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED)); } From fc2cc19ffa02c86ec1471ec8fdbc39d33fcec626 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Fri, 29 Jul 2022 04:04:22 +0800 Subject: [PATCH 0055/1020] ci: Upgrade msys2 release to 20220603 Signed-off-by: Yonggang Luo Reviewed-by: Bin Meng Message-Id: <20220728200422.1502-1-luoyonggang@gmail.com> Signed-off-by: Richard Henderson --- .cirrus.yml | 2 +- .gitlab-ci.d/windows.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index eac39024f2..4895987da4 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -12,7 +12,7 @@ windows_msys2_task: CIRRUS_SHELL: powershell MSYS: winsymlinks:native MSYSTEM: MINGW64 - MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2022-05-03/msys2-base-x86_64-20220503.sfx.exe + MSYS2_URL: https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe MSYS2_FINGERPRINT: 0 MSYS2_PACKAGES: " diffutils git grep make pkg-config sed diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index 0b9572a8a3..c4bde758be 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -17,7 +17,7 @@ } - If ( !(Test-Path -Path msys64\var\cache\msys2.exe ) ) { Invoke-WebRequest - "https://github.com/msys2/msys2-installer/releases/download/2022-05-03/msys2-base-x86_64-20220503.sfx.exe" + "https://github.com/msys2/msys2-installer/releases/download/2022-06-03/msys2-base-x86_64-20220603.sfx.exe" -outfile "msys64\var\cache\msys2.exe" } - msys64\var\cache\msys2.exe -y From 587858ed0dd4833eadb3894d03d687fa461c6915 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Fri, 29 Jul 2022 15:30:17 +0800 Subject: [PATCH 0056/1020] hw/loongarch: Rename file 'loongson3.XXX' to 'virt.XXX' 1. Rename 'loongson3.c' to 'virt.c' and change the meson.build file. 2. Rename 'loongson3.rst' to 'virt.rst'. Signed-off-by: Xiaojuan Yang Message-Id: <20220729073018.27037-2-yangxiaojuan@loongson.cn> Signed-off-by: Richard Henderson --- MAINTAINERS | 2 +- hw/loongarch/meson.build | 2 +- hw/loongarch/{loongson3.c => virt.c} | 0 target/loongarch/README | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename hw/loongarch/{loongson3.c => virt.c} (100%) diff --git a/MAINTAINERS b/MAINTAINERS index 6af9cd985c..5ce4227ff6 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1129,7 +1129,7 @@ Virt M: Xiaojuan Yang M: Song Gao S: Maintained -F: docs/system/loongarch/loongson3.rst +F: docs/system/loongarch/virt.rst F: configs/targets/loongarch64-softmmu.mak F: configs/devices/loongarch64-softmmu/default.mak F: hw/loongarch/ diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build index 6a2a1b18e5..c0421502ab 100644 --- a/hw/loongarch/meson.build +++ b/hw/loongarch/meson.build @@ -2,7 +2,7 @@ loongarch_ss = ss.source_set() loongarch_ss.add(files( 'fw_cfg.c', )) -loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: [files('loongson3.c'), fdt]) +loongarch_ss.add(when: 'CONFIG_LOONGARCH_VIRT', if_true: [files('virt.c'), fdt]) loongarch_ss.add(when: 'CONFIG_ACPI', if_true: files('acpi-build.c')) hw_arch += {'loongarch': loongarch_ss} diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/virt.c similarity index 100% rename from hw/loongarch/loongson3.c rename to hw/loongarch/virt.c diff --git a/target/loongarch/README b/target/loongarch/README index 9f5edd10c8..1823375d04 100644 --- a/target/loongarch/README +++ b/target/loongarch/README @@ -15,7 +15,7 @@ 3A5000 support multiple interrupt cascading while here we just emulate the extioi interrupt cascading. LS7A1000 host bridge support multiple devices, such as sata, gmac, uart, rtc and so on. But we just realize the rtc. Others use the qemu common devices. It does not affect - the general use. We also introduced the emulation of devices at docs/system/loongarch/loongson3.rst. + the general use. We also introduced the emulation of devices at docs/system/loongarch/virt.rst. This version only supports running binary files in ELF format, and does not depend on BIOS and kernel file. You can compile the test program with 'make & make check-tcg' and run the test case with the following command: From 74725231d6fd1605d8b60c5afc2c0aec2f0b1e67 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Fri, 29 Jul 2022 15:30:18 +0800 Subject: [PATCH 0057/1020] hw/loongarch: Change macro name 'LS7A_XXX' to 'VIRT_XXX' Change macro name 'LS7A_XXX' to 'VIRT_XXX', as the loongarch virt machinue use the GPEX bridge instead of LS7A bridge. So the macro name should keep consistency. Signed-off-by: Xiaojuan Yang Message-Id: <20220729073018.27037-3-yangxiaojuan@loongson.cn> Signed-off-by: Richard Henderson --- hw/loongarch/acpi-build.c | 18 ++++++------ hw/loongarch/virt.c | 56 ++++++++++++++++++------------------- include/hw/loongarch/virt.h | 8 +++--- include/hw/pci-host/ls7a.h | 43 +++++++++++++--------------- 4 files changed, 61 insertions(+), 64 deletions(-) diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index b95b83b079..4b4529a3fb 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -135,7 +135,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, LoongArchMachineState *lams) build_append_int_noprefix(table_data, 21, 1); /* Type */ build_append_int_noprefix(table_data, 19, 1); /* Length */ build_append_int_noprefix(table_data, 1, 1); /* Version */ - build_append_int_noprefix(table_data, LS7A_PCH_MSI_ADDR_LOW, 8);/* Address */ + build_append_int_noprefix(table_data, VIRT_PCH_MSI_ADDR_LOW, 8);/* Address */ build_append_int_noprefix(table_data, 0x40, 4); /* Start */ build_append_int_noprefix(table_data, 0xc0, 4); /* Count */ @@ -143,7 +143,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, LoongArchMachineState *lams) build_append_int_noprefix(table_data, 22, 1); /* Type */ build_append_int_noprefix(table_data, 17, 1); /* Length */ build_append_int_noprefix(table_data, 1, 1); /* Version */ - build_append_int_noprefix(table_data, LS7A_PCH_REG_BASE, 8);/* Address */ + build_append_int_noprefix(table_data, VIRT_PCH_REG_BASE, 8);/* Address */ build_append_int_noprefix(table_data, 0x1000, 2); /* Size */ build_append_int_noprefix(table_data, 0, 2); /* Id */ build_append_int_noprefix(table_data, 0x40, 2); /* Base */ @@ -307,7 +307,7 @@ static void build_uart_device_aml(Aml *table) Aml *dev; Aml *crs; Aml *pkg0, *pkg1, *pkg2; - uint32_t uart_irq = LS7A_UART_IRQ; + uint32_t uart_irq = VIRT_UART_IRQ; Aml *scope = aml_scope("_SB"); dev = aml_device("COMA"); @@ -367,7 +367,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) if (lams->acpi_ged) { build_ged_aml(dsdt, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(lams->acpi_ged), - LS7A_SCI_IRQ - PCH_PIC_IRQ_OFFSET, AML_SYSTEM_MEMORY, + VIRT_SCI_IRQ - PCH_PIC_IRQ_OFFSET, AML_SYSTEM_MEMORY, VIRT_GED_EVT_ADDR); } @@ -385,9 +385,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) aml_append(crs, aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, AML_CACHEABLE, AML_READ_WRITE, - 0, LS7A_PCI_MEM_BASE, - LS7A_PCI_MEM_BASE + LS7A_PCI_MEM_SIZE - 1, - 0, LS7A_PCI_MEM_BASE)); + 0, VIRT_PCI_MEM_BASE, + VIRT_PCI_MEM_BASE + VIRT_PCI_MEM_SIZE - 1, + 0, VIRT_PCI_MEM_BASE)); aml_append(scope, aml_name_decl("_CRS", crs)); aml_append(dsdt, scope); @@ -462,8 +462,8 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine) acpi_add_table(table_offsets, tables_blob); { AcpiMcfgInfo mcfg = { - .base = cpu_to_le64(LS_PCIECFG_BASE), - .size = cpu_to_le64(LS_PCIECFG_SIZE), + .base = cpu_to_le64(VIRT_PCI_CFG_BASE), + .size = cpu_to_le64(VIRT_PCI_CFG_SIZE), }; build_mcfg(tables_blob, tables->linker, &mcfg, lams->oem_id, lams->oem_table_id); diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index a08dc9d299..5cc0b05538 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -126,12 +126,12 @@ static void fdt_add_fw_cfg_node(const LoongArchMachineState *lams) static void fdt_add_pcie_node(const LoongArchMachineState *lams) { char *nodename; - hwaddr base_mmio = LS7A_PCI_MEM_BASE; - hwaddr size_mmio = LS7A_PCI_MEM_SIZE; - hwaddr base_pio = LS7A_PCI_IO_BASE; - hwaddr size_pio = LS7A_PCI_IO_SIZE; - hwaddr base_pcie = LS_PCIECFG_BASE; - hwaddr size_pcie = LS_PCIECFG_SIZE; + hwaddr base_mmio = VIRT_PCI_MEM_BASE; + hwaddr size_mmio = VIRT_PCI_MEM_SIZE; + hwaddr base_pio = VIRT_PCI_IO_BASE; + hwaddr size_pio = VIRT_PCI_IO_SIZE; + hwaddr base_pcie = VIRT_PCI_CFG_BASE; + hwaddr size_pcie = VIRT_PCI_CFG_SIZE; hwaddr base = base_pcie; const MachineState *ms = MACHINE(lams); @@ -145,12 +145,12 @@ static void fdt_add_pcie_node(const LoongArchMachineState *lams) qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 2); qemu_fdt_setprop_cell(ms->fdt, nodename, "linux,pci-domain", 0); qemu_fdt_setprop_cells(ms->fdt, nodename, "bus-range", 0, - PCIE_MMCFG_BUS(LS_PCIECFG_SIZE - 1)); + PCIE_MMCFG_BUS(VIRT_PCI_CFG_SIZE - 1)); qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0); qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, base_pcie, 2, size_pcie); qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "ranges", - 1, FDT_PCI_RANGE_IOPORT, 2, LS7A_PCI_IO_OFFSET, + 1, FDT_PCI_RANGE_IOPORT, 2, VIRT_PCI_IO_OFFSET, 2, base_pio, 2, size_pio, 1, FDT_PCI_RANGE_MMIO, 2, base_mmio, 2, base_mmio, 2, size_mmio); @@ -313,7 +313,7 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, LoongArchMachineState sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_GED_REG_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, - qdev_get_gpio_in(pch_pic, LS7A_SCI_IRQ - PCH_PIC_IRQ_OFFSET)); + qdev_get_gpio_in(pch_pic, VIRT_SCI_IRQ - PCH_PIC_IRQ_OFFSET)); sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); return dev; } @@ -336,24 +336,24 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * ecam_alias = g_new0(MemoryRegion, 1); ecam_reg = sysbus_mmio_get_region(d, 0); memory_region_init_alias(ecam_alias, OBJECT(gpex_dev), "pcie-ecam", - ecam_reg, 0, LS_PCIECFG_SIZE); - memory_region_add_subregion(get_system_memory(), LS_PCIECFG_BASE, + ecam_reg, 0, VIRT_PCI_CFG_SIZE); + memory_region_add_subregion(get_system_memory(), VIRT_PCI_CFG_BASE, ecam_alias); /* Map PCI mem space */ mmio_alias = g_new0(MemoryRegion, 1); mmio_reg = sysbus_mmio_get_region(d, 1); memory_region_init_alias(mmio_alias, OBJECT(gpex_dev), "pcie-mmio", - mmio_reg, LS7A_PCI_MEM_BASE, LS7A_PCI_MEM_SIZE); - memory_region_add_subregion(get_system_memory(), LS7A_PCI_MEM_BASE, + mmio_reg, VIRT_PCI_MEM_BASE, VIRT_PCI_MEM_SIZE); + memory_region_add_subregion(get_system_memory(), VIRT_PCI_MEM_BASE, mmio_alias); /* Map PCI IO port space. */ pio_alias = g_new0(MemoryRegion, 1); pio_reg = sysbus_mmio_get_region(d, 2); memory_region_init_alias(pio_alias, OBJECT(gpex_dev), "pcie-io", pio_reg, - LS7A_PCI_IO_OFFSET, LS7A_PCI_IO_SIZE); - memory_region_add_subregion(get_system_memory(), LS7A_PCI_IO_BASE, + VIRT_PCI_IO_OFFSET, VIRT_PCI_IO_SIZE); + memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE, pio_alias); for (i = 0; i < GPEX_NUM_IRQS; i++) { @@ -362,9 +362,9 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i); } - serial_mm_init(get_system_memory(), LS7A_UART_BASE, 0, + serial_mm_init(get_system_memory(), VIRT_UART_BASE, 0, qdev_get_gpio_in(pch_pic, - LS7A_UART_IRQ - PCH_PIC_IRQ_OFFSET), + VIRT_UART_IRQ - PCH_PIC_IRQ_OFFSET), 115200, serial_hd(0), DEVICE_LITTLE_ENDIAN); /* Network init */ @@ -386,9 +386,9 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * * Create some unimplemented devices to emulate this. */ create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4); - sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE, + sysbus_create_simple("ls7a_rtc", VIRT_RTC_REG_BASE, qdev_get_gpio_in(pch_pic, - LS7A_RTC_IRQ - PCH_PIC_IRQ_OFFSET)); + VIRT_RTC_IRQ - PCH_PIC_IRQ_OFFSET)); pm_mem = g_new(MemoryRegion, 1); memory_region_init_io(pm_mem, NULL, &loongarch_virt_pm_ops, @@ -472,13 +472,13 @@ static void loongarch_irq_init(LoongArchMachineState *lams) pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC); d = SYS_BUS_DEVICE(pch_pic); sysbus_realize_and_unref(d, &error_fatal); - memory_region_add_subregion(get_system_memory(), LS7A_IOAPIC_REG_BASE, + memory_region_add_subregion(get_system_memory(), VIRT_IOAPIC_REG_BASE, sysbus_mmio_get_region(d, 0)); memory_region_add_subregion(get_system_memory(), - LS7A_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET, + VIRT_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET, sysbus_mmio_get_region(d, 1)); memory_region_add_subregion(get_system_memory(), - LS7A_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO, + VIRT_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO, sysbus_mmio_get_region(d, 2)); /* Connect 64 pch_pic irqs to extioi */ @@ -490,7 +490,7 @@ static void loongarch_irq_init(LoongArchMachineState *lams) qdev_prop_set_uint32(pch_msi, "msi_irq_base", PCH_MSI_IRQ_START); d = SYS_BUS_DEVICE(pch_msi); sysbus_realize_and_unref(d, &error_fatal); - sysbus_mmio_map(d, 0, LS7A_PCH_MSI_ADDR_LOW); + sysbus_mmio_map(d, 0, VIRT_PCH_MSI_ADDR_LOW); for (i = 0; i < PCH_MSI_IRQ_NUM; i++) { /* Connect 192 pch_msi irqs to extioi */ qdev_connect_gpio_out(DEVICE(d), i, @@ -666,8 +666,8 @@ static void loongarch_init(MachineState *machine) memmap_add_entry(0x90000000, highram_size, 1); /* Add isa io region */ memory_region_init_alias(&lams->isa_io, NULL, "isa-io", - get_system_io(), 0, LOONGARCH_ISA_IO_SIZE); - memory_region_add_subregion(address_space_mem, LOONGARCH_ISA_IO_BASE, + get_system_io(), 0, VIRT_ISA_IO_SIZE); + memory_region_add_subregion(address_space_mem, VIRT_ISA_IO_BASE, &lams->isa_io); /* load the BIOS image. */ loongarch_firmware_init(lams); @@ -706,9 +706,9 @@ static void loongarch_init(MachineState *machine) /* load fdt */ MemoryRegion *fdt_rom = g_new(MemoryRegion, 1); - memory_region_init_rom(fdt_rom, NULL, "fdt", LA_FDT_SIZE, &error_fatal); - memory_region_add_subregion(get_system_memory(), LA_FDT_BASE, fdt_rom); - rom_add_blob_fixed("fdt", machine->fdt, lams->fdt_size, LA_FDT_BASE); + memory_region_init_rom(fdt_rom, NULL, "fdt", VIRT_FDT_SIZE, &error_fatal); + memory_region_add_subregion(get_system_memory(), VIRT_FDT_BASE, fdt_rom); + rom_add_blob_fixed("fdt", machine->fdt, lams->fdt_size, VIRT_FDT_BASE); } bool loongarch_is_acpi_enabled(LoongArchMachineState *lams) diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index f4f24df428..92b84de1c5 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -15,8 +15,8 @@ #define LOONGARCH_MAX_VCPUS 4 -#define LOONGARCH_ISA_IO_BASE 0x18000000UL -#define LOONGARCH_ISA_IO_SIZE 0x0004000 +#define VIRT_ISA_IO_BASE 0x18000000UL +#define VIRT_ISA_IO_SIZE 0x0004000 #define VIRT_FWCFG_BASE 0x1e020000UL #define VIRT_BIOS_BASE 0x1c000000UL #define VIRT_BIOS_SIZE (4 * MiB) @@ -28,8 +28,8 @@ #define VIRT_GED_MEM_ADDR (VIRT_GED_EVT_ADDR + ACPI_GED_EVT_SEL_LEN) #define VIRT_GED_REG_ADDR (VIRT_GED_MEM_ADDR + MEMORY_HOTPLUG_IO_LEN) -#define LA_FDT_BASE 0x1c400000 -#define LA_FDT_SIZE 0x100000 +#define VIRT_FDT_BASE 0x1c400000 +#define VIRT_FDT_SIZE 0x100000 struct LoongArchMachineState { /*< private >*/ diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h index 0fdc86b973..cdde0af1f8 100644 --- a/include/hw/pci-host/ls7a.h +++ b/include/hw/pci-host/ls7a.h @@ -15,34 +15,31 @@ #include "qemu/range.h" #include "qom/object.h" -#define LS7A_PCI_MEM_BASE 0x40000000UL -#define LS7A_PCI_MEM_SIZE 0x40000000UL -#define LS7A_PCI_IO_OFFSET 0x4000 -#define LS_PCIECFG_BASE 0x20000000 -#define LS_PCIECFG_SIZE 0x08000000 -#define LS7A_PCI_IO_BASE 0x18004000UL -#define LS7A_PCI_IO_SIZE 0xC000 +#define VIRT_PCI_MEM_BASE 0x40000000UL +#define VIRT_PCI_MEM_SIZE 0x40000000UL +#define VIRT_PCI_IO_OFFSET 0x4000 +#define VIRT_PCI_CFG_BASE 0x20000000 +#define VIRT_PCI_CFG_SIZE 0x08000000 +#define VIRT_PCI_IO_BASE 0x18004000UL +#define VIRT_PCI_IO_SIZE 0xC000 -#define LS7A_PCI_MEM_BASE 0x40000000UL -#define LS7A_PCI_MEM_SIZE 0x40000000UL - -#define LS7A_PCH_REG_BASE 0x10000000UL -#define LS7A_IOAPIC_REG_BASE (LS7A_PCH_REG_BASE) -#define LS7A_PCH_MSI_ADDR_LOW 0x2FF00000UL +#define VIRT_PCH_REG_BASE 0x10000000UL +#define VIRT_IOAPIC_REG_BASE (VIRT_PCH_REG_BASE) +#define VIRT_PCH_MSI_ADDR_LOW 0x2FF00000UL /* * According to the kernel pch irq start from 64 offset * 0 ~ 16 irqs used for non-pci device while 16 ~ 64 irqs * used for pci device. */ -#define PCH_PIC_IRQ_OFFSET 64 -#define LS7A_DEVICE_IRQS 16 -#define LS7A_PCI_IRQS 48 -#define LS7A_UART_IRQ (PCH_PIC_IRQ_OFFSET + 2) -#define LS7A_UART_BASE 0x1fe001e0 -#define LS7A_RTC_IRQ (PCH_PIC_IRQ_OFFSET + 3) -#define LS7A_MISC_REG_BASE (LS7A_PCH_REG_BASE + 0x00080000) -#define LS7A_RTC_REG_BASE (LS7A_MISC_REG_BASE + 0x00050100) -#define LS7A_RTC_LEN 0x100 -#define LS7A_SCI_IRQ (PCH_PIC_IRQ_OFFSET + 4) +#define PCH_PIC_IRQ_OFFSET 64 +#define VIRT_DEVICE_IRQS 16 +#define VIRT_PCI_IRQS 48 +#define VIRT_UART_IRQ (PCH_PIC_IRQ_OFFSET + 2) +#define VIRT_UART_BASE 0x1fe001e0 +#define VIRT_RTC_IRQ (PCH_PIC_IRQ_OFFSET + 3) +#define VIRT_MISC_REG_BASE (VIRT_PCH_REG_BASE + 0x00080000) +#define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100) +#define VIRT_RTC_LEN 0x100 +#define VIRT_SCI_IRQ (PCH_PIC_IRQ_OFFSET + 4) #endif From 1e814a0dc4b255a58f2cdab54aee50b25af2a006 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Mon, 18 Jul 2022 16:03:18 -0700 Subject: [PATCH 0058/1020] Hexagon (target/hexagon) make VyV operands use a unique temp VyV operand is only used in the vshuff and vdeal instructions. These instructions write to both VyV and VxV operands. In the case where both operands are the same register, we need a separate location for VyV. We use the existing vtmp field in CPUHexagonState. Test case added in tests/tcg/hexagon/hvx_misc.c Signed-off-by: Taylor Simpson Reviewed-by: Richard Henderson Message-Id: <20220718230320.24444-2-tsimpson@quicinc.com> --- target/hexagon/gen_tcg_funcs.py | 9 +++---- tests/tcg/hexagon/hvx_misc.c | 45 +++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py index 1fd9de95d5..d72c689ad7 100755 --- a/target/hexagon/gen_tcg_funcs.py +++ b/target/hexagon/gen_tcg_funcs.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -164,7 +164,9 @@ def genptr_decl(f, tag, regtype, regid, regno): (regtype, regid, regno)) f.write(" const intptr_t %s%sV_off =\n" % \ (regtype, regid)) - if (hex_common.is_tmp_result(tag)): + if (regid == "y"): + f.write(" offsetof(CPUHexagonState, vtmp);\n") + elif (hex_common.is_tmp_result(tag)): f.write(" ctx_tmp_vreg_off(ctx, %s%sN, 1, true);\n" % \ (regtype, regid)) else: @@ -379,9 +381,6 @@ def genptr_src_read(f, tag, regtype, regid): f.write(" vreg_src_off(ctx, %s%sN),\n" % \ (regtype, regid)) f.write(" sizeof(MMVector), sizeof(MMVector));\n") - if (not hex_common.skip_qemu_helper(tag)): - f.write(" tcg_gen_addi_ptr(%s%sV, cpu_env, %s%sV_off);\n" % \ - (regtype, regid, regtype, regid)) else: print("Bad register parse: ", regtype, regid) elif (regtype == "Q"): diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c index b896f5897e..6e2c9ab3cd 100644 --- a/tests/tcg/hexagon/hvx_misc.c +++ b/tests/tcg/hexagon/hvx_misc.c @@ -498,6 +498,49 @@ static void test_vsubuwsat_dv(void) check_output_w(__LINE__, 2); } +static void test_vshuff(void) +{ + /* Test that vshuff works when the two operands are the same register */ + const uint32_t splat = 0x089be55c; + const uint32_t shuff = 0x454fa926; + MMVector v0, v1; + + memset(expect, 0x12, sizeof(MMVector)); + memset(output, 0x34, sizeof(MMVector)); + + asm volatile("v25 = vsplat(%0)\n\t" + "vshuff(v25, v25, %1)\n\t" + "vmem(%2 + #0) = v25\n\t" + : /* no outputs */ + : "r"(splat), "r"(shuff), "r"(output) + : "v25", "memory"); + + /* + * The semantics of Hexagon are the operands are pass-by-value, so create + * two copies of the vsplat result. + */ + for (int i = 0; i < MAX_VEC_SIZE_BYTES / 4; i++) { + v0.uw[i] = splat; + v1.uw[i] = splat; + } + /* Do the vshuff operation */ + for (int offset = 1; offset < MAX_VEC_SIZE_BYTES; offset <<= 1) { + if (shuff & offset) { + for (int k = 0; k < MAX_VEC_SIZE_BYTES; k++) { + if (!(k & offset)) { + uint8_t tmp = v0.ub[k]; + v0.ub[k] = v1.ub[k + offset]; + v1.ub[k + offset] = tmp; + } + } + } + } + /* Put the result in the expect buffer for verification */ + expect[0] = v1; + + check_output_b(__LINE__, 1); +} + int main() { init_buffers(); @@ -533,6 +576,8 @@ int main() test_vadduwsat(); test_vsubuwsat_dv(); + test_vshuff(); + puts(err ? "FAIL" : "PASS"); return err ? 1 : 0; } From a1ad040dbaa7528d4d47a98f2b068015d2da0fcc Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Mon, 18 Jul 2022 16:03:19 -0700 Subject: [PATCH 0059/1020] Hexagon (tests/tcg/hexagon) Fix alignment in load_unpack.c The increment used in :brev tests was causing unaligned addresses Change the increment and the relevant expected values Signed-off-by: Taylor Simpson Acked-by: Richard Henderson Message-Id: <20220718230320.24444-3-tsimpson@quicinc.com> --- tests/tcg/hexagon/load_unpack.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/tcg/hexagon/load_unpack.c b/tests/tcg/hexagon/load_unpack.c index 3575a37a28..4aa26fc388 100644 --- a/tests/tcg/hexagon/load_unpack.c +++ b/tests/tcg/hexagon/load_unpack.c @@ -245,7 +245,7 @@ TEST_pr(loadbsw4_pr, long long, S, 4, 0x0000ff000000ff00LL, */ #define BxW_LOAD_pbr(SZ, RES, PTR) \ __asm__( \ - "r4 = #(1 << (16 - 3))\n\t" \ + "r4 = #(1 << (16 - 4))\n\t" \ "m0 = r4\n\t" \ "%0 = mem" #SZ "(%1++m0:brev)\n\t" \ : "=r"(RES), "+r"(PTR) \ @@ -273,15 +273,15 @@ void test_##NAME(void) \ } TEST_pbr(loadbzw2_pbr, int, Z, 0x00000000, - 0x00020081, 0x00060085, 0x00040083, 0x00080087) + 0x00020081, 0x000a0089, 0x00060085, 0x000e008d) TEST_pbr(loadbsw2_pbr, int, S, 0x0000ff00, - 0x00020081, 0x00060085, 0x00040083, 0x00080087) + 0x00020081, 0x000aff89, 0x0006ff85, 0x000eff8d) TEST_pbr(loadbzw4_pbr, long long, Z, 0x0000000000000000LL, - 0x0004008300020081LL, 0x0008008700060085LL, - 0x0006008500040083LL, 0x000a008900080087LL) + 0x0004008300020081LL, 0x000c008b000a0089LL, + 0x0008008700060085LL, 0x0010008f000e008dLL) TEST_pbr(loadbsw4_pbr, long long, S, 0x0000ff000000ff00LL, - 0x0004008300020081LL, 0x0008008700060085LL, - 0x0006008500040083LL, 0x000a008900080087LL) + 0x0004008300020081LL, 0x000cff8b000aff89LL, + 0x0008ff870006ff85LL, 0x0010ff8f000eff8dLL) /* **************************************************************************** From 7eabb050ea77e529f549ea1ddaaa18e91ae01e34 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Mon, 18 Jul 2022 16:03:20 -0700 Subject: [PATCH 0060/1020] Hexagon (tests/tcg/hexagon) reference file for float_convd The test is in tests/tcg/multiarch/float_convd.c Signed-off-by: Taylor Simpson Acked-by: Richard Henderson Message-Id: <20220718230320.24444-4-tsimpson@quicinc.com> --- tests/tcg/hexagon/float_convd.ref | 988 ++++++++++++++++++++++++++++++ 1 file changed, 988 insertions(+) create mode 100644 tests/tcg/hexagon/float_convd.ref diff --git a/tests/tcg/hexagon/float_convd.ref b/tests/tcg/hexagon/float_convd.ref new file mode 100644 index 0000000000..aba1e13e35 --- /dev/null +++ b/tests/tcg/hexagon/float_convd.ref @@ -0,0 +1,988 @@ +### Rounding to nearest +from double: f64(nan:0x007ff4000000000000) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(-nan:0x00fff8000000000000) + to single: f32(-nan:0xffffffff) (OK) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(-inf:0x00fff0000000000000) + to single: f32(-inf:0xff800000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffffffffff0000000p+1023:0x00ffefffffffffffff) + to single: f32(-inf:0xff800000) (OVERFLOW INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.1874b135ff6540000000p+103:0x00c661874b135ff654) + to single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) (INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.c0bab523323b90000000p+99:0x00c62c0bab523323b9) + to single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) (INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p+1:0x00c000000000000000) + to single: f32(-0x1.00000000000000000000p+1:0xc0000000) (OK) + to int32: -2 (OK) + to int64: -2 (OK) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p+0:0x00bff0000000000000) + to single: f32(-0x1.00000000000000000000p+0:0xbf800000) (OK) + to int32: -1 (OK) + to int64: -1 (OK) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p-1022:0x008010000000000000) + to single: f32(-0x0.00000000000000000000p+0:0x80000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) + to single: f32(-0x1.00000000000000000000p-126:0x80800000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(0x0.00000000000000000000p+0:00000000000000000000) + to single: f32(0x0.00000000000000000000p+0:0000000000) (OK) + to int32: 0 (OK) + to int64: 0 (OK) + to uint32: 0 (OK) + to uint64: 0 (OK) +from double: f64(0x1.00000000000000000000p-126:0x003810000000000000) + to single: f32(0x1.00000000000000000000p-126:0x00800000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000001c5f680000000p-25:0x003e600000001c5f68) + to single: f32(0x1.00000000000000000000p-25:0x33000000) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.ffffe6cb2fa820000000p-25:0x003e6ffffe6cb2fa82) + to single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.ff801a9af58a10000000p-15:0x003f0ff801a9af58a1) + to single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000c06a1ef50000000p-14:0x003f100000c06a1ef5) + to single: f32(0x1.00000c00000000000000p-14:0x38800006) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) + to single: f32(0x1.00000000000000000000p+0:0x3f800000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) + to single: f32(0x1.00400000000000000000p+0:0x3f802000) (OK) + to int32: 1 (INEXACT ) + to int64: 1 (INEXACT ) + to uint32: 1 (INEXACT ) + to uint64: 1 (INEXACT ) +from double: f64(0x1.00000000000000000000p-1022:0x000010000000000000) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.3d5054450ed000000000p-1023:0x000009ea82a2287680) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.5731f750864200000000p-1023:0x00000ab98fba843210) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) + to single: f32(0x1.00000000000000000000p+0:0x3f800000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from double: f64(0x1.00000000000000000000p+1:0x004000000000000000) + to single: f32(0x1.00000000000000000000p+1:0x40000000) (OK) + to int32: 2 (OK) + to int64: 2 (OK) + to uint32: 2 (OK) + to uint64: 2 (OK) +from double: f64(0x1.5bf0a8b1457690000000p+1:0x004005bf0a8b145769) + to single: f32(0x1.5bf0a800000000000000p+1:0x402df854) (INEXACT ) + to int32: 2 (INEXACT ) + to int64: 2 (INEXACT ) + to uint32: 2 (INEXACT ) + to uint64: 2 (INEXACT ) +from double: f64(0x1.921fb54442d180000000p+1:0x00400921fb54442d18) + to single: f32(0x1.921fb600000000000000p+1:0x40490fdb) (INEXACT ) + to int32: 3 (INEXACT ) + to int64: 3 (INEXACT ) + to uint32: 3 (INEXACT ) + to uint64: 3 (INEXACT ) +from double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) + to single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) (OK) + to int32: 65503 (OK) + to int64: 65503 (OK) + to uint32: 65503 (OK) + to uint64: 65503 (OK) +from double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) + to single: f32(0x1.ffc00000000000000000p+15:0x477fe000) (OK) + to int32: 65504 (OK) + to int64: 65504 (OK) + to uint32: 65504 (OK) + to uint64: 65504 (OK) +from double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) + to single: f32(0x1.ffc20000000000000000p+15:0x477fe100) (OK) + to int32: 65505 (OK) + to int64: 65505 (OK) + to uint32: 65505 (OK) + to uint64: 65505 (OK) +from double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) + to single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) (OK) + to int32: 131007 (OK) + to int64: 131007 (OK) + to uint32: 131007 (OK) + to uint64: 131007 (OK) +from double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) + to single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) (OK) + to int32: 131008 (OK) + to int64: 131008 (OK) + to uint32: 131008 (OK) + to uint64: 131008 (OK) +from double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) + to single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) (OK) + to int32: 131009 (OK) + to int64: 131009 (OK) + to uint32: 131009 (OK) + to uint64: 131009 (OK) +from double: f64(0x1.fffffffc000000000000p+30:0x0041dfffffffc00000) + to single: f32(0x1.00000000000000000000p+31:0x4f000000) (INEXACT ) + to int32: 2147483647 (OK) + to int64: 2147483647 (OK) + to uint32: 2147483647 (OK) + to uint64: 2147483647 (OK) +from double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(0x1.fffffffffffff0000000p+1023:0x007fefffffffffffff) + to single: f32(inf:0x7f800000) (OVERFLOW INEXACT ) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(inf:0x007ff0000000000000) + to single: f32(inf:0x7f800000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff8000000000000) + to single: f32(-nan:0xffffffff) (OK) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff0000000000001) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff4000000000000) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +### Rounding upwards +from double: f64(nan:0x007ff4000000000000) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(-nan:0x00fff8000000000000) + to single: f32(-nan:0xffffffff) (OK) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(-inf:0x00fff0000000000000) + to single: f32(-inf:0xff800000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffffffffff0000000p+1023:0x00ffefffffffffffff) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OVERFLOW INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.1874b135ff6540000000p+103:0x00c661874b135ff654) + to single: f32(-0x1.1874b000000000000000p+103:0xf30c3a58) (INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.c0bab523323b90000000p+99:0x00c62c0bab523323b9) + to single: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) (INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p+1:0x00c000000000000000) + to single: f32(-0x1.00000000000000000000p+1:0xc0000000) (OK) + to int32: -2 (OK) + to int64: -2 (OK) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p+0:0x00bff0000000000000) + to single: f32(-0x1.00000000000000000000p+0:0xbf800000) (OK) + to int32: -1 (OK) + to int64: -1 (OK) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p-1022:0x008010000000000000) + to single: f32(-0x0.00000000000000000000p+0:0x80000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) + to single: f32(-0x1.00000000000000000000p-126:0x80800000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(0x0.00000000000000000000p+0:00000000000000000000) + to single: f32(0x0.00000000000000000000p+0:0000000000) (OK) + to int32: 0 (OK) + to int64: 0 (OK) + to uint32: 0 (OK) + to uint64: 0 (OK) +from double: f64(0x1.00000000000000000000p-126:0x003810000000000000) + to single: f32(0x1.00000000000000000000p-126:0x00800000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000001c5f680000000p-25:0x003e600000001c5f68) + to single: f32(0x1.00000200000000000000p-25:0x33000001) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.ffffe6cb2fa820000000p-25:0x003e6ffffe6cb2fa82) + to single: f32(0x1.ffffe800000000000000p-25:0x337ffff4) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.ff801a9af58a10000000p-15:0x003f0ff801a9af58a1) + to single: f32(0x1.ff801c00000000000000p-15:0x387fc00e) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000c06a1ef50000000p-14:0x003f100000c06a1ef5) + to single: f32(0x1.00000e00000000000000p-14:0x38800007) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) + to single: f32(0x1.00000000000000000000p+0:0x3f800000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) + to single: f32(0x1.00400000000000000000p+0:0x3f802000) (OK) + to int32: 1 (INEXACT ) + to int64: 1 (INEXACT ) + to uint32: 1 (INEXACT ) + to uint64: 1 (INEXACT ) +from double: f64(0x1.00000000000000000000p-1022:0x000010000000000000) + to single: f32(0x1.00000000000000000000p-149:0x00000001) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.3d5054450ed000000000p-1023:0x000009ea82a2287680) + to single: f32(0x1.00000000000000000000p-149:0x00000001) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.5731f750864200000000p-1023:0x00000ab98fba843210) + to single: f32(0x1.00000000000000000000p-149:0x00000001) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) + to single: f32(0x1.00000000000000000000p+0:0x3f800000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from double: f64(0x1.00000000000000000000p+1:0x004000000000000000) + to single: f32(0x1.00000000000000000000p+1:0x40000000) (OK) + to int32: 2 (OK) + to int64: 2 (OK) + to uint32: 2 (OK) + to uint64: 2 (OK) +from double: f64(0x1.5bf0a8b1457690000000p+1:0x004005bf0a8b145769) + to single: f32(0x1.5bf0aa00000000000000p+1:0x402df855) (INEXACT ) + to int32: 2 (INEXACT ) + to int64: 2 (INEXACT ) + to uint32: 2 (INEXACT ) + to uint64: 2 (INEXACT ) +from double: f64(0x1.921fb54442d180000000p+1:0x00400921fb54442d18) + to single: f32(0x1.921fb600000000000000p+1:0x40490fdb) (INEXACT ) + to int32: 3 (INEXACT ) + to int64: 3 (INEXACT ) + to uint32: 3 (INEXACT ) + to uint64: 3 (INEXACT ) +from double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) + to single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) (OK) + to int32: 65503 (OK) + to int64: 65503 (OK) + to uint32: 65503 (OK) + to uint64: 65503 (OK) +from double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) + to single: f32(0x1.ffc00000000000000000p+15:0x477fe000) (OK) + to int32: 65504 (OK) + to int64: 65504 (OK) + to uint32: 65504 (OK) + to uint64: 65504 (OK) +from double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) + to single: f32(0x1.ffc20000000000000000p+15:0x477fe100) (OK) + to int32: 65505 (OK) + to int64: 65505 (OK) + to uint32: 65505 (OK) + to uint64: 65505 (OK) +from double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) + to single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) (OK) + to int32: 131007 (OK) + to int64: 131007 (OK) + to uint32: 131007 (OK) + to uint64: 131007 (OK) +from double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) + to single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) (OK) + to int32: 131008 (OK) + to int64: 131008 (OK) + to uint32: 131008 (OK) + to uint64: 131008 (OK) +from double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) + to single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) (OK) + to int32: 131009 (OK) + to int64: 131009 (OK) + to uint32: 131009 (OK) + to uint64: 131009 (OK) +from double: f64(0x1.fffffffc000000000000p+30:0x0041dfffffffc00000) + to single: f32(0x1.00000000000000000000p+31:0x4f000000) (INEXACT ) + to int32: 2147483647 (OK) + to int64: 2147483647 (OK) + to uint32: 2147483647 (OK) + to uint64: 2147483647 (OK) +from double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(0x1.fffffffffffff0000000p+1023:0x007fefffffffffffff) + to single: f32(inf:0x7f800000) (OVERFLOW INEXACT ) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(inf:0x007ff0000000000000) + to single: f32(inf:0x7f800000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff8000000000000) + to single: f32(-nan:0xffffffff) (OK) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff0000000000001) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff4000000000000) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +### Rounding downwards +from double: f64(nan:0x007ff4000000000000) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(-nan:0x00fff8000000000000) + to single: f32(-nan:0xffffffff) (OK) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(-inf:0x00fff0000000000000) + to single: f32(-inf:0xff800000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffffffffff0000000p+1023:0x00ffefffffffffffff) + to single: f32(-inf:0xff800000) (OVERFLOW INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.1874b135ff6540000000p+103:0x00c661874b135ff654) + to single: f32(-0x1.1874b200000000000000p+103:0xf30c3a59) (INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.c0bab523323b90000000p+99:0x00c62c0bab523323b9) + to single: f32(-0x1.c0bab600000000000000p+99:0xf1605d5b) (INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p+1:0x00c000000000000000) + to single: f32(-0x1.00000000000000000000p+1:0xc0000000) (OK) + to int32: -2 (OK) + to int64: -2 (OK) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p+0:0x00bff0000000000000) + to single: f32(-0x1.00000000000000000000p+0:0xbf800000) (OK) + to int32: -1 (OK) + to int64: -1 (OK) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p-1022:0x008010000000000000) + to single: f32(-0x1.00000000000000000000p-149:0x80000001) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) + to single: f32(-0x1.00000000000000000000p-126:0x80800000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(0x0.00000000000000000000p+0:00000000000000000000) + to single: f32(0x0.00000000000000000000p+0:0000000000) (OK) + to int32: 0 (OK) + to int64: 0 (OK) + to uint32: 0 (OK) + to uint64: 0 (OK) +from double: f64(0x1.00000000000000000000p-126:0x003810000000000000) + to single: f32(0x1.00000000000000000000p-126:0x00800000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000001c5f680000000p-25:0x003e600000001c5f68) + to single: f32(0x1.00000000000000000000p-25:0x33000000) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.ffffe6cb2fa820000000p-25:0x003e6ffffe6cb2fa82) + to single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.ff801a9af58a10000000p-15:0x003f0ff801a9af58a1) + to single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000c06a1ef50000000p-14:0x003f100000c06a1ef5) + to single: f32(0x1.00000c00000000000000p-14:0x38800006) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) + to single: f32(0x1.00000000000000000000p+0:0x3f800000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) + to single: f32(0x1.00400000000000000000p+0:0x3f802000) (OK) + to int32: 1 (INEXACT ) + to int64: 1 (INEXACT ) + to uint32: 1 (INEXACT ) + to uint64: 1 (INEXACT ) +from double: f64(0x1.00000000000000000000p-1022:0x000010000000000000) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.3d5054450ed000000000p-1023:0x000009ea82a2287680) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.5731f750864200000000p-1023:0x00000ab98fba843210) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) + to single: f32(0x1.00000000000000000000p+0:0x3f800000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from double: f64(0x1.00000000000000000000p+1:0x004000000000000000) + to single: f32(0x1.00000000000000000000p+1:0x40000000) (OK) + to int32: 2 (OK) + to int64: 2 (OK) + to uint32: 2 (OK) + to uint64: 2 (OK) +from double: f64(0x1.5bf0a8b1457690000000p+1:0x004005bf0a8b145769) + to single: f32(0x1.5bf0a800000000000000p+1:0x402df854) (INEXACT ) + to int32: 2 (INEXACT ) + to int64: 2 (INEXACT ) + to uint32: 2 (INEXACT ) + to uint64: 2 (INEXACT ) +from double: f64(0x1.921fb54442d180000000p+1:0x00400921fb54442d18) + to single: f32(0x1.921fb400000000000000p+1:0x40490fda) (INEXACT ) + to int32: 3 (INEXACT ) + to int64: 3 (INEXACT ) + to uint32: 3 (INEXACT ) + to uint64: 3 (INEXACT ) +from double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) + to single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) (OK) + to int32: 65503 (OK) + to int64: 65503 (OK) + to uint32: 65503 (OK) + to uint64: 65503 (OK) +from double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) + to single: f32(0x1.ffc00000000000000000p+15:0x477fe000) (OK) + to int32: 65504 (OK) + to int64: 65504 (OK) + to uint32: 65504 (OK) + to uint64: 65504 (OK) +from double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) + to single: f32(0x1.ffc20000000000000000p+15:0x477fe100) (OK) + to int32: 65505 (OK) + to int64: 65505 (OK) + to uint32: 65505 (OK) + to uint64: 65505 (OK) +from double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) + to single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) (OK) + to int32: 131007 (OK) + to int64: 131007 (OK) + to uint32: 131007 (OK) + to uint64: 131007 (OK) +from double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) + to single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) (OK) + to int32: 131008 (OK) + to int64: 131008 (OK) + to uint32: 131008 (OK) + to uint64: 131008 (OK) +from double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) + to single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) (OK) + to int32: 131009 (OK) + to int64: 131009 (OK) + to uint32: 131009 (OK) + to uint64: 131009 (OK) +from double: f64(0x1.fffffffc000000000000p+30:0x0041dfffffffc00000) + to single: f32(0x1.fffffe00000000000000p+30:0x4effffff) (INEXACT ) + to int32: 2147483647 (OK) + to int64: 2147483647 (OK) + to uint32: 2147483647 (OK) + to uint64: 2147483647 (OK) +from double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(0x1.fffffffffffff0000000p+1023:0x007fefffffffffffff) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OVERFLOW INEXACT ) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(inf:0x007ff0000000000000) + to single: f32(inf:0x7f800000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff8000000000000) + to single: f32(-nan:0xffffffff) (OK) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff0000000000001) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff4000000000000) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +### Rounding to zero +from double: f64(nan:0x007ff4000000000000) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(-nan:0x00fff8000000000000) + to single: f32(-nan:0xffffffff) (OK) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(-inf:0x00fff0000000000000) + to single: f32(-inf:0xff800000) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffffffffff0000000p+1023:0x00ffefffffffffffff) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OVERFLOW INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.fffffe00000000000000p+127:0x00c7efffffe0000000) + to single: f32(-0x1.fffffe00000000000000p+127:0xff7fffff) (OK) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.1874b135ff6540000000p+103:0x00c661874b135ff654) + to single: f32(-0x1.1874b000000000000000p+103:0xf30c3a58) (INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.c0bab523323b90000000p+99:0x00c62c0bab523323b9) + to single: f32(-0x1.c0bab400000000000000p+99:0xf1605d5a) (INEXACT ) + to int32: -2147483648 (INVALID) + to int64: -9223372036854775808 (INVALID) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p+1:0x00c000000000000000) + to single: f32(-0x1.00000000000000000000p+1:0xc0000000) (OK) + to int32: -2 (OK) + to int64: -2 (OK) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p+0:0x00bff0000000000000) + to single: f32(-0x1.00000000000000000000p+0:0xbf800000) (OK) + to int32: -1 (OK) + to int64: -1 (OK) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p-1022:0x008010000000000000) + to single: f32(-0x0.00000000000000000000p+0:0x80000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(-0x1.00000000000000000000p-126:0x00b810000000000000) + to single: f32(-0x1.00000000000000000000p-126:0x80800000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INVALID) + to uint64: 0 (INVALID) +from double: f64(0x0.00000000000000000000p+0:00000000000000000000) + to single: f32(0x0.00000000000000000000p+0:0000000000) (OK) + to int32: 0 (OK) + to int64: 0 (OK) + to uint32: 0 (OK) + to uint64: 0 (OK) +from double: f64(0x1.00000000000000000000p-126:0x003810000000000000) + to single: f32(0x1.00000000000000000000p-126:0x00800000) (OK) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000001c5f680000000p-25:0x003e600000001c5f68) + to single: f32(0x1.00000000000000000000p-25:0x33000000) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.ffffe6cb2fa820000000p-25:0x003e6ffffe6cb2fa82) + to single: f32(0x1.ffffe600000000000000p-25:0x337ffff3) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.ff801a9af58a10000000p-15:0x003f0ff801a9af58a1) + to single: f32(0x1.ff801a00000000000000p-15:0x387fc00d) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000c06a1ef50000000p-14:0x003f100000c06a1ef5) + to single: f32(0x1.00000c00000000000000p-14:0x38800006) (INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) + to single: f32(0x1.00000000000000000000p+0:0x3f800000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from double: f64(0x1.00400000000000000000p+0:0x003ff0040000000000) + to single: f32(0x1.00400000000000000000p+0:0x3f802000) (OK) + to int32: 1 (INEXACT ) + to int64: 1 (INEXACT ) + to uint32: 1 (INEXACT ) + to uint64: 1 (INEXACT ) +from double: f64(0x1.00000000000000000000p-1022:0x000010000000000000) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.3d5054450ed000000000p-1023:0x000009ea82a2287680) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.5731f750864200000000p-1023:0x00000ab98fba843210) + to single: f32(0x0.00000000000000000000p+0:0000000000) (UNDERFLOW INEXACT ) + to int32: 0 (INEXACT ) + to int64: 0 (INEXACT ) + to uint32: 0 (INEXACT ) + to uint64: 0 (INEXACT ) +from double: f64(0x1.00000000000000000000p+0:0x003ff0000000000000) + to single: f32(0x1.00000000000000000000p+0:0x3f800000) (OK) + to int32: 1 (OK) + to int64: 1 (OK) + to uint32: 1 (OK) + to uint64: 1 (OK) +from double: f64(0x1.00000000000000000000p+1:0x004000000000000000) + to single: f32(0x1.00000000000000000000p+1:0x40000000) (OK) + to int32: 2 (OK) + to int64: 2 (OK) + to uint32: 2 (OK) + to uint64: 2 (OK) +from double: f64(0x1.5bf0a8b1457690000000p+1:0x004005bf0a8b145769) + to single: f32(0x1.5bf0a800000000000000p+1:0x402df854) (INEXACT ) + to int32: 2 (INEXACT ) + to int64: 2 (INEXACT ) + to uint32: 2 (INEXACT ) + to uint64: 2 (INEXACT ) +from double: f64(0x1.921fb54442d180000000p+1:0x00400921fb54442d18) + to single: f32(0x1.921fb400000000000000p+1:0x40490fda) (INEXACT ) + to int32: 3 (INEXACT ) + to int64: 3 (INEXACT ) + to uint32: 3 (INEXACT ) + to uint64: 3 (INEXACT ) +from double: f64(0x1.ffbe0000000000000000p+15:0x0040effbe000000000) + to single: f32(0x1.ffbe0000000000000000p+15:0x477fdf00) (OK) + to int32: 65503 (OK) + to int64: 65503 (OK) + to uint32: 65503 (OK) + to uint64: 65503 (OK) +from double: f64(0x1.ffc00000000000000000p+15:0x0040effc0000000000) + to single: f32(0x1.ffc00000000000000000p+15:0x477fe000) (OK) + to int32: 65504 (OK) + to int64: 65504 (OK) + to uint32: 65504 (OK) + to uint64: 65504 (OK) +from double: f64(0x1.ffc20000000000000000p+15:0x0040effc2000000000) + to single: f32(0x1.ffc20000000000000000p+15:0x477fe100) (OK) + to int32: 65505 (OK) + to int64: 65505 (OK) + to uint32: 65505 (OK) + to uint64: 65505 (OK) +from double: f64(0x1.ffbf0000000000000000p+16:0x0040fffbf000000000) + to single: f32(0x1.ffbf0000000000000000p+16:0x47ffdf80) (OK) + to int32: 131007 (OK) + to int64: 131007 (OK) + to uint32: 131007 (OK) + to uint64: 131007 (OK) +from double: f64(0x1.ffc00000000000000000p+16:0x0040fffc0000000000) + to single: f32(0x1.ffc00000000000000000p+16:0x47ffe000) (OK) + to int32: 131008 (OK) + to int64: 131008 (OK) + to uint32: 131008 (OK) + to uint64: 131008 (OK) +from double: f64(0x1.ffc10000000000000000p+16:0x0040fffc1000000000) + to single: f32(0x1.ffc10000000000000000p+16:0x47ffe080) (OK) + to int32: 131009 (OK) + to int64: 131009 (OK) + to uint32: 131009 (OK) + to uint64: 131009 (OK) +from double: f64(0x1.fffffffc000000000000p+30:0x0041dfffffffc00000) + to single: f32(0x1.fffffe00000000000000p+30:0x4effffff) (INEXACT ) + to int32: 2147483647 (OK) + to int64: 2147483647 (OK) + to uint32: 2147483647 (OK) + to uint64: 2147483647 (OK) +from double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(0x1.fffffe00000000000000p+127:0x0047efffffe0000000) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(0x1.fffffffffffff0000000p+1023:0x007fefffffffffffff) + to single: f32(0x1.fffffe00000000000000p+127:0x7f7fffff) (OVERFLOW INEXACT ) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(inf:0x007ff0000000000000) + to single: f32(inf:0x7f800000) (OK) + to int32: 2147483647 (INVALID) + to int64: 9223372036854775807 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff8000000000000) + to single: f32(-nan:0xffffffff) (OK) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff0000000000001) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) +from double: f64(nan:0x007ff4000000000000) + to single: f32(-nan:0xffffffff) (INVALID) + to int32: -1 (INVALID) + to int64: -1 (INVALID) + to uint32: -1 (INVALID) + to uint64: -1 (INVALID) From b9e6074fc5b429b1e956e9c60db7e284a91e0f3d Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Mon, 25 Jul 2022 16:42:51 +0200 Subject: [PATCH 0061/1020] tests/tcg/linux-test: Fix random hangs in test_socket test_socket hangs randomly in connect(), especially when run without qemu. Apparently the reason is that linux started treating backlog value of 0 literally instead of rounding it up since v4.4 (commit ef547f2ac16b). So set it to 1 instead. Signed-off-by: Ilya Leoshkevich Message-Id: <20220725144251.192720-1-iii@linux.ibm.com> Signed-off-by: Thomas Huth --- tests/tcg/multiarch/linux/linux-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tcg/multiarch/linux/linux-test.c b/tests/tcg/multiarch/linux/linux-test.c index 019d8175ca..5a2a4f2258 100644 --- a/tests/tcg/multiarch/linux/linux-test.c +++ b/tests/tcg/multiarch/linux/linux-test.c @@ -263,7 +263,7 @@ static int server_socket(void) sockaddr.sin_port = htons(0); /* choose random ephemeral port) */ sockaddr.sin_addr.s_addr = 0; chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr))); - chk_error(listen(fd, 0)); + chk_error(listen(fd, 1)); return fd; } From 219044b8e63994fedd3ba9d88a33ebcd04c5a029 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Thu, 28 Jul 2022 09:35:15 -0400 Subject: [PATCH 0062/1020] migration-test: Use migrate_ensure_converge() for auto-converge Thomas reported that auto-converge test will timeout on MacOS CI gatings. Use the migrate_ensure_converge() helper too in the auto-converge as when Daniel reworked the other test cases. Since both max_bandwidth / downtime_limit will not be used for converge calculations, make it simple by removing the remaining check, then we can completely remove both variables altogether, since migrate_ensure_converge is used the remaining check won't make much sense anyway. Reported-by: Thomas Huth Suggested-by: Daniel P. Berrange Signed-off-by: Peter Xu Message-Id: <20220728133516.92061-2-peterx@redhat.com> Tested-by: Thomas Huth Reviewed-by: Daniel P. Berrange Signed-off-by: Thomas Huth --- tests/qtest/migration-test.c | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 71595a74fd..c1e002087d 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -1768,7 +1768,7 @@ static void test_migrate_auto_converge(void) g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); MigrateStart args = {}; QTestState *from, *to; - int64_t remaining, percentage; + int64_t percentage; /* * We want the test to be stable and as fast as possible. @@ -1776,14 +1776,6 @@ static void test_migrate_auto_converge(void) * so we need to decrease a bandwidth. */ const int64_t init_pct = 5, inc_pct = 50, max_pct = 95; - const int64_t max_bandwidth = 400000000; /* ~400Mb/s */ - const int64_t downtime_limit = 250; /* 250ms */ - /* - * We migrate through unix-socket (> 500Mb/s). - * Thus, expected migration speed ~= bandwidth limit (< 500Mb/s). - * So, we can predict expected_threshold - */ - const int64_t expected_threshold = max_bandwidth * downtime_limit / 1000; if (test_migrate_start(&from, &to, uri, &args)) { return; @@ -1818,8 +1810,7 @@ static void test_migrate_auto_converge(void) /* The first percentage of throttling should be equal to init_pct */ g_assert_cmpint(percentage, ==, init_pct); /* Now, when we tested that throttling works, let it converge */ - migrate_set_parameter_int(from, "downtime-limit", downtime_limit); - migrate_set_parameter_int(from, "max-bandwidth", max_bandwidth); + migrate_ensure_converge(from); /* * Wait for pre-switchover status to check last throttle percentage @@ -1830,11 +1821,6 @@ static void test_migrate_auto_converge(void) /* The final percentage of throttling shouldn't be greater than max_pct */ percentage = read_migrate_property_int(from, "cpu-throttle-percentage"); g_assert_cmpint(percentage, <=, max_pct); - - remaining = read_ram_property_int(from, "remaining"); - g_assert_cmpint(remaining, <, - (expected_threshold + expected_threshold / 100)); - migrate_continue(from, "pre-switchover"); qtest_qmp_eventwait(to, "RESUME"); @@ -1842,7 +1828,6 @@ static void test_migrate_auto_converge(void) wait_for_serial("dest_serial"); wait_for_migration_complete(from); - test_migrate_end(from, to, true); } From 2649a72555e72df56562777ca0c6a46897838eca Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Thu, 28 Jul 2022 09:35:16 -0400 Subject: [PATCH 0063/1020] migration-test: Allow test to run without uffd We used to stop running all tests if uffd is not detected. However logically that's only needed for postcopy not the rest of tests. Keep running the rest when still possible. Signed-off-by: Peter Xu Tested-by: Thomas Huth Message-Id: <20220728133516.92061-3-peterx@redhat.com> Reviewed-by: Daniel P. Berrange Signed-off-by: Thomas Huth --- tests/qtest/migration-test.c | 48 +++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index c1e002087d..10ab7a708c 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -2424,14 +2424,11 @@ int main(int argc, char **argv) { char template[] = "/tmp/migration-test-XXXXXX"; const bool has_kvm = qtest_has_accel("kvm"); + const bool has_uffd = ufd_version_check(); int ret; g_test_init(&argc, &argv, NULL); - if (!ufd_version_check()) { - return g_test_run(); - } - /* * On ppc64, the test only works with kvm-hv, but not with kvm-pr and TCG * is touchy due to race conditions on dirty bits (especially on PPC for @@ -2460,13 +2457,15 @@ int main(int argc, char **argv) module_call_init(MODULE_INIT_QOM); - qtest_add_func("/migration/postcopy/unix", test_postcopy); - qtest_add_func("/migration/postcopy/plain", test_postcopy); - qtest_add_func("/migration/postcopy/recovery/plain", - test_postcopy_recovery); - qtest_add_func("/migration/postcopy/preempt/plain", test_postcopy_preempt); - qtest_add_func("/migration/postcopy/preempt/recovery/plain", - test_postcopy_preempt_recovery); + if (has_uffd) { + qtest_add_func("/migration/postcopy/unix", test_postcopy); + qtest_add_func("/migration/postcopy/plain", test_postcopy); + qtest_add_func("/migration/postcopy/recovery/plain", + test_postcopy_recovery); + qtest_add_func("/migration/postcopy/preempt/plain", test_postcopy_preempt); + qtest_add_func("/migration/postcopy/preempt/recovery/plain", + test_postcopy_preempt_recovery); + } qtest_add_func("/migration/bad_dest", test_baddest); qtest_add_func("/migration/precopy/unix/plain", test_precopy_unix_plain); @@ -2474,18 +2473,21 @@ int main(int argc, char **argv) #ifdef CONFIG_GNUTLS qtest_add_func("/migration/precopy/unix/tls/psk", test_precopy_unix_tls_psk); - /* - * NOTE: psk test is enough for postcopy, as other types of TLS - * channels are tested under precopy. Here what we want to test is the - * general postcopy path that has TLS channel enabled. - */ - qtest_add_func("/migration/postcopy/tls/psk", test_postcopy_tls_psk); - qtest_add_func("/migration/postcopy/recovery/tls/psk", - test_postcopy_recovery_tls_psk); - qtest_add_func("/migration/postcopy/preempt/tls/psk", - test_postcopy_preempt_tls_psk); - qtest_add_func("/migration/postcopy/preempt/recovery/tls/psk", - test_postcopy_preempt_all); + + if (has_uffd) { + /* + * NOTE: psk test is enough for postcopy, as other types of TLS + * channels are tested under precopy. Here what we want to test is the + * general postcopy path that has TLS channel enabled. + */ + qtest_add_func("/migration/postcopy/tls/psk", test_postcopy_tls_psk); + qtest_add_func("/migration/postcopy/recovery/tls/psk", + test_postcopy_recovery_tls_psk); + qtest_add_func("/migration/postcopy/preempt/tls/psk", + test_postcopy_preempt_tls_psk); + qtest_add_func("/migration/postcopy/preempt/recovery/tls/psk", + test_postcopy_preempt_all); + } #ifdef CONFIG_TASN1 qtest_add_func("/migration/precopy/unix/tls/x509/default-host", test_precopy_unix_tls_x509_default_host); From ebf705541c03ba90cb93eef605abd18728e0a25b Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 27 Jul 2022 10:39:13 +0200 Subject: [PATCH 0064/1020] tests/unit/test-qga: Replace the word 'blacklist' in the guest agent unit test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's use better, more inclusive wording here. Message-Id: <20220727092135.302915-4-thuth@redhat.com> Reviewed-by: Konstantin Kostiuk Reviewed-by: Daniel P. BerrangĂ© Signed-off-by: Thomas Huth --- tests/unit/test-qga.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c index 530317044b..b27c77a695 100644 --- a/tests/unit/test-qga.c +++ b/tests/unit/test-qga.c @@ -629,7 +629,7 @@ static void test_qga_get_time(gconstpointer fix) g_assert_cmpint(time, >, 0); } -static void test_qga_blacklist(gconstpointer data) +static void test_qga_blockedrpcs(gconstpointer data) { TestFixture fix; QDict *ret, *error; @@ -637,7 +637,7 @@ static void test_qga_blacklist(gconstpointer data) fixture_setup(&fix, "-b guest-ping,guest-get-time", NULL); - /* check blacklist */ + /* check blocked RPCs */ ret = qmp_fd(fix.fd, "{'execute': 'guest-ping'}"); g_assert_nonnull(ret); error = qdict_get_qdict(ret, "error"); @@ -968,7 +968,7 @@ int main(int argc, char **argv) g_test_add_data_func("/qga/fsfreeze-status", &fix, test_qga_fsfreeze_status); - g_test_add_data_func("/qga/blacklist", NULL, test_qga_blacklist); + g_test_add_data_func("/qga/blockedrpcs", NULL, test_qga_blockedrpcs); g_test_add_data_func("/qga/config", NULL, test_qga_config); g_test_add_data_func("/qga/guest-exec", &fix, test_qga_guest_exec); g_test_add_data_func("/qga/guest-exec-invalid", &fix, From 7a21bee2aa52fc95b25e38372678986ee94f05f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Thu, 7 Jul 2022 17:37:15 +0100 Subject: [PATCH 0065/1020] misc: fix commonly doubled up words MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Daniel P. BerrangĂ© Message-Id: <20220707163720.1421716-5-berrange@redhat.com> Reviewed-by: Peter Maydell Signed-off-by: Thomas Huth --- block/linux-aio.c | 2 +- block/qcow2-bitmap.c | 8 ++++---- contrib/plugins/cache.c | 2 +- docs/devel/qom.rst | 4 ++-- docs/interop/live-block-operations.rst | 4 ++-- docs/system/arm/cpu-features.rst | 2 +- docs/system/devices/cxl.rst | 2 +- docs/system/s390x/bootdevices.rst | 2 +- docs/system/tls.rst | 2 +- docs/tools/qemu-pr-helper.rst | 4 ++-- hw/core/clock.c | 2 +- hw/intc/arm_gicv3_redist.c | 2 +- hw/misc/iotkit-secctl.c | 2 +- hw/misc/iotkit-sysctl.c | 4 ++-- hw/s390x/s390-ccw.c | 2 +- hw/usb/u2f.h | 2 +- include/hw/qdev-core.h | 2 +- include/user/safe-syscall.h | 2 +- linux-user/i386/cpu_loop.c | 2 +- pc-bios/s390-ccw/virtio-scsi.c | 2 +- python/Makefile | 2 +- python/qemu/utils/__init__.py | 2 +- target/arm/translate.c | 2 +- target/i386/cpu.c | 2 +- tcg/i386/tcg-target.c.inc | 2 +- tests/qtest/microbit-test.c | 6 +++--- tools/virtiofsd/fuse_virtio.c | 2 +- 27 files changed, 36 insertions(+), 36 deletions(-) diff --git a/block/linux-aio.c b/block/linux-aio.c index 9c2393a2f7..d2cfb7f523 100644 --- a/block/linux-aio.c +++ b/block/linux-aio.c @@ -461,7 +461,7 @@ LinuxAioState *laio_init(Error **errp) s = g_malloc0(sizeof(*s)); rc = event_notifier_init(&s->e, false); if (rc < 0) { - error_setg_errno(errp, -rc, "failed to to initialize event notifier"); + error_setg_errno(errp, -rc, "failed to initialize event notifier"); goto out_free_state; } diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index e98bafe0f4..ff3309846c 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -787,10 +787,10 @@ static int bitmap_list_store(BlockDriverState *bs, Qcow2BitmapList *bm_list, } } - /* Actually, even in in-place case ignoring QCOW2_OL_BITMAP_DIRECTORY is not - * necessary, because we drop QCOW2_AUTOCLEAR_BITMAPS when updating bitmap - * directory in-place (actually, turn-off the extension), which is checked - * in qcow2_check_metadata_overlap() */ + /* Actually, even in the in-place case ignoring QCOW2_OL_BITMAP_DIRECTORY + * is not necessary, because we drop QCOW2_AUTOCLEAR_BITMAPS when updating + * bitmap directory in-place (actually, turn-off the extension), which is + * checked in qcow2_check_metadata_overlap() */ ret = qcow2_pre_write_overlap_check( bs, in_place ? QCOW2_OL_BITMAP_DIRECTORY : 0, dir_offset, dir_size, false); diff --git a/contrib/plugins/cache.c b/contrib/plugins/cache.c index b9226e7c40..ac1510aaa1 100644 --- a/contrib/plugins/cache.c +++ b/contrib/plugins/cache.c @@ -38,7 +38,7 @@ enum EvictionPolicy policy; * put in any of the blocks inside the set. The number of block per set is * called the associativity (assoc). * - * Each block contains the the stored tag and a valid bit. Since this is not + * Each block contains the stored tag and a valid bit. Since this is not * a functional simulator, the data itself is not stored. We only identify * whether a block is in the cache or not by searching for its tag. * diff --git a/docs/devel/qom.rst b/docs/devel/qom.rst index 0cf9a714f0..3e34b07c98 100644 --- a/docs/devel/qom.rst +++ b/docs/devel/qom.rst @@ -371,8 +371,8 @@ This accepts an array of interface type names. { TYPE_USER_CREATABLE }, { NULL }) -If the type is not intended to be instantiated, then then -the OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead: +If the type is not intended to be instantiated, then the +OBJECT_DEFINE_ABSTRACT_TYPE() macro can be used instead: .. code-block:: c :caption: Defining a simple abstract type diff --git a/docs/interop/live-block-operations.rst b/docs/interop/live-block-operations.rst index 39e62c9915..135784ab33 100644 --- a/docs/interop/live-block-operations.rst +++ b/docs/interop/live-block-operations.rst @@ -53,7 +53,7 @@ files in a disk image backing chain: (1) Directional: 'base' and 'top'. Given the simple disk image chain above, image [A] can be referred to as 'base', and image [B] as - 'top'. (This terminology can be seen in in QAPI schema file, + 'top'. (This terminology can be seen in the QAPI schema file, block-core.json.) (2) Relational: 'backing file' and 'overlay'. Again, taking the same @@ -825,7 +825,7 @@ entire disk image chain, to a target, using ``blockdev-mirror`` would be: job ready to be completed (5) Gracefully complete the 'mirror' block device job, and notice the - the event ``BLOCK_JOB_COMPLETED`` + event ``BLOCK_JOB_COMPLETED`` (6) Shutdown the guest by issuing the QMP ``quit`` command so that caches are flushed diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index 3fd76fa0b4..c2c01ec7d2 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -284,7 +284,7 @@ SVE CPU Property Parsing Semantics CPU Property Dependencies and Constraints"). 4) If one or more vector lengths have been explicitly enabled and at - at least one of the dependency lengths of the maximum enabled length + least one of the dependency lengths of the maximum enabled length has been explicitly disabled, then an error is generated (see constraint (2) of "SVE CPU Property Dependencies and Constraints"). diff --git a/docs/system/devices/cxl.rst b/docs/system/devices/cxl.rst index a57e4c4e5c..36031325cc 100644 --- a/docs/system/devices/cxl.rst +++ b/docs/system/devices/cxl.rst @@ -15,7 +15,7 @@ with CXL Host Bridges, which have CXL Root Ports which may be directly attached to CXL or PCI End Points. Alternatively there may be CXL Switches with CXL and PCI Endpoints attached below them. In many cases additional control and capabilities are exposed via PCI Express interfaces. -This sharing of interfaces and hence emulation code is is reflected +This sharing of interfaces and hence emulation code is reflected in how the devices are emulated in QEMU. In most cases the various CXL elements are built upon an equivalent PCIe devices. diff --git a/docs/system/s390x/bootdevices.rst b/docs/system/s390x/bootdevices.rst index 9e591cb9dc..b5950133e8 100644 --- a/docs/system/s390x/bootdevices.rst +++ b/docs/system/s390x/bootdevices.rst @@ -65,7 +65,7 @@ you can specify it via the ``-global s390-ipl.netboot_fw=filename`` command line option. The ``bootindex`` property is especially important for booting via the network. -If you don't specify the the ``bootindex`` property here, the network bootloader +If you don't specify the ``bootindex`` property here, the network bootloader firmware code won't get loaded into the guest memory so that the network boot will fail. For a successful network boot, try something like this:: diff --git a/docs/system/tls.rst b/docs/system/tls.rst index 1a04674362..e284c82801 100644 --- a/docs/system/tls.rst +++ b/docs/system/tls.rst @@ -182,7 +182,7 @@ certificates. --template client-hostNNN.info \ --outfile client-hostNNN-cert.pem -The subject alt name extension data is not required for clients, so the +The subject alt name extension data is not required for clients, so the ``dns_name`` and ``ip_address`` fields are not included. The ``tls_www_client`` keyword is the key purpose extension to indicate this certificate is intended for usage in a web client. Although QEMU network diff --git a/docs/tools/qemu-pr-helper.rst b/docs/tools/qemu-pr-helper.rst index eaebe40da0..c32867cfc6 100644 --- a/docs/tools/qemu-pr-helper.rst +++ b/docs/tools/qemu-pr-helper.rst @@ -21,8 +21,8 @@ programs because incorrect usage can disrupt regular operation of the storage fabric. QEMU's SCSI passthrough devices ``scsi-block`` and ``scsi-generic`` support passing guest persistent reservation requests to a privileged external helper program. :program:`qemu-pr-helper` -is that external helper; it creates a socket which QEMU can -connect to to communicate with it. +is that external helper; it creates a listener socket which will +accept incoming connections for communication with QEMU. If you want to run VMs in a setup like this, this helper should be started as a system service, and you should read the QEMU manual diff --git a/hw/core/clock.c b/hw/core/clock.c index 916875e07a..d82e44cd1a 100644 --- a/hw/core/clock.c +++ b/hw/core/clock.c @@ -68,7 +68,7 @@ static uint64_t clock_get_child_period(Clock *clk) { /* * Return the period to be used for child clocks, which is the parent - * clock period adjusted for for multiplier and divider effects. + * clock period adjusted for multiplier and divider effects. */ return muldiv64(clk->period, clk->multiplier, clk->divider); } diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index f1ecb2502b..c92ceecc16 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -492,7 +492,7 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset, return MEMTX_OK; case GICR_WAKER: /* Only the ProcessorSleep bit is writable. When the guest sets - * it it requests that we transition the channel between the + * it, it requests that we transition the channel between the * redistributor and the cpu interface to quiescent, and that * we set the ChildrenAsleep bit once the inteface has reached the * quiescent state. diff --git a/hw/misc/iotkit-secctl.c b/hw/misc/iotkit-secctl.c index 7b41cfa8fc..b5a9e30a2c 100644 --- a/hw/misc/iotkit-secctl.c +++ b/hw/misc/iotkit-secctl.c @@ -114,7 +114,7 @@ static const uint8_t iotkit_secctl_ns_sse300_idregs[] = { * AHB expansion, APB expansion) are all set up so that they are * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs * 0, 1, 2, 3 of that type, so we can convert a register address offset - * into an an index into a PPC array easily. + * into an index into a PPC array easily. */ static inline int offset_to_ppc_idx(uint32_t offset) { diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c index 9ee8fe8495..7147e2f84e 100644 --- a/hw/misc/iotkit-sysctl.c +++ b/hw/misc/iotkit-sysctl.c @@ -237,7 +237,7 @@ static uint64_t iotkit_sysctl_read(void *opaque, hwaddr offset, r = s->ewctrl; break; case ARMSSE_SSE300: - /* In SSE300 this offset is is NMI_ENABLE */ + /* In SSE300 this offset is NMI_ENABLE */ r = s->nmi_enable; break; default: @@ -555,7 +555,7 @@ static void iotkit_sysctl_write(void *opaque, hwaddr offset, s->ewctrl = value; break; case ARMSSE_SSE300: - /* In SSE300 this offset is is NMI_ENABLE */ + /* In SSE300 this offset is NMI_ENABLE */ qemu_log_mask(LOG_UNIMP, "IoTKit SysCtl NMI_ENABLE unimplemented\n"); s->nmi_enable = value; break; diff --git a/hw/s390x/s390-ccw.c b/hw/s390x/s390-ccw.c index 2fc8bb9c23..e2d86d96e7 100644 --- a/hw/s390x/s390-ccw.c +++ b/hw/s390x/s390-ccw.c @@ -57,7 +57,7 @@ IOInstEnding s390_ccw_store(SubchDev *sch) /* * This code is called for both virtual and passthrough devices, - * but only applies to to the latter. This ugly check makes that + * but only applies to the latter. This ugly check makes that * distinction for us. */ if (object_dynamic_cast(OBJECT(sch->driver_data), TYPE_S390_CCW)) { diff --git a/hw/usb/u2f.h b/hw/usb/u2f.h index db30f3586b..a408a82927 100644 --- a/hw/usb/u2f.h +++ b/hw/usb/u2f.h @@ -74,7 +74,7 @@ typedef struct U2FKeyState { /* * API to be used by the U2F key device variants (i.e. hw/u2f-*.c) - * to interact with the the U2F key base device (i.e. hw/u2f.c) + * to interact with the U2F key base device (i.e. hw/u2f.c) */ void u2f_send_to_guest(U2FKeyState *key, const uint8_t packet[U2FHID_PACKET_SIZE]); diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 98774e2835..785dd5a56e 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -386,7 +386,7 @@ bool qdev_realize_and_unref(DeviceState *dev, BusState *bus, Error **errp); * * - unrealize any child buses by calling qbus_unrealize() * (this will recursively unrealize any devices on those buses) - * - call the the unrealize method of @dev + * - call the unrealize method of @dev * * The device can then be freed by causing its reference count to go * to zero. diff --git a/include/user/safe-syscall.h b/include/user/safe-syscall.h index 61a04e2b5a..ddceef12e2 100644 --- a/include/user/safe-syscall.h +++ b/include/user/safe-syscall.h @@ -70,7 +70,7 @@ * If the host libc is used then the implementation will appear to work * most of the time, but there will be a race condition where a * signal could arrive just before we make the host syscall inside libc, - * and then then guest syscall will not correctly be interrupted. + * and then the guest syscall will not correctly be interrupted. * Instead the implementation of the guest syscall can use the safe_syscall * function but otherwise just return the result or errno in the usual * way; the main loop code will take care of restarting the syscall diff --git a/linux-user/i386/cpu_loop.c b/linux-user/i386/cpu_loop.c index 492701dd9a..42837399bc 100644 --- a/linux-user/i386/cpu_loop.c +++ b/linux-user/i386/cpu_loop.c @@ -137,7 +137,7 @@ static void emulate_vsyscall(CPUX86State *env) } /* - * Validate the the pointer arguments. + * Validate the pointer arguments. */ switch (syscall) { case TARGET_NR_gettimeofday: diff --git a/pc-bios/s390-ccw/virtio-scsi.c b/pc-bios/s390-ccw/virtio-scsi.c index 3b7069270c..dcce696a33 100644 --- a/pc-bios/s390-ccw/virtio-scsi.c +++ b/pc-bios/s390-ccw/virtio-scsi.c @@ -195,7 +195,7 @@ static bool scsi_read_capacity(VDev *vdev, /* virtio-scsi routines */ /* - * Tries to locate a SCSI device and and adds the information for the found + * Tries to locate a SCSI device and adds the information for the found * device to the vdev->scsi_device structure. * Returns 0 if SCSI device could be located, or a error code < 0 otherwise */ diff --git a/python/Makefile b/python/Makefile index 3334311362..b170708398 100644 --- a/python/Makefile +++ b/python/Makefile @@ -29,7 +29,7 @@ help: @echo " Performs no environment setup of any kind." @echo "" @echo "make develop:" - @echo " Install deps needed for for 'make check'," + @echo " Install deps needed for 'make check'," @echo " and install the qemu package in editable mode." @echo " (Can be used in or outside of a venv.)" @echo "" diff --git a/python/qemu/utils/__init__.py b/python/qemu/utils/__init__.py index 9fb273b13d..017cfdcda7 100644 --- a/python/qemu/utils/__init__.py +++ b/python/qemu/utils/__init__.py @@ -79,7 +79,7 @@ def add_visual_margin( :param content: The text to wrap and decorate. :param width: The number of columns to use, including for the decoration - itself. The default (None) uses the the available width of the + itself. The default (None) uses the available width of the current terminal, or a fallback of 72 lines. A negative number subtracts a fixed-width from the default size. The default obeys the COLUMNS environment variable, if set. diff --git a/target/arm/translate.c b/target/arm/translate.c index 4ffb095c73..ad617b9948 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -8056,7 +8056,7 @@ static TCGv_i32 op_addr_block_pre(DisasContext *s, arg_ldst_block *a, int n) * If the writeback is incrementing SP rather than * decrementing it, and the initial SP is below the * stack limit but the final written-back SP would - * be above, then then we must not perform any memory + * be above, then we must not perform any memory * accesses, but it is IMPDEF whether we generate * an exception. We choose to do so in this case. * At this point 'addr' is the lowest address, so diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 6a57ef13af..194b5a31af 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -3632,7 +3632,7 @@ static const X86CPUDefinition builtin_x86_defs[] = { CPUID_7_0_EDX_CORE_CAPABILITY, .features[FEAT_CORE_CAPABILITY] = MSR_CORE_CAP_SPLIT_LOCK_DETECT, - /* XSAVES is is added in version 3 */ + /* XSAVES is added in version 3 */ .features[FEAT_XSAVE] = CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | CPUID_XSAVE_XGETBV1, diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc index d52206ba4d..cb04e4b3ad 100644 --- a/tcg/i386/tcg-target.c.inc +++ b/tcg/i386/tcg-target.c.inc @@ -1652,7 +1652,7 @@ static void tcg_out_branch(TCGContext *s, int call, const tcg_insn_unit *dest) } else { /* rip-relative addressing into the constant pool. This is 6 + 8 = 14 bytes, as compared to using an - an immediate load 10 + 6 = 16 bytes, plus we may + immediate load 10 + 6 = 16 bytes, plus we may be able to re-use the pool constant for more calls. */ tcg_out_opc(s, OPC_GRP5, 0, 0, 0); tcg_out8(s, (call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev) << 3 | 5); diff --git a/tests/qtest/microbit-test.c b/tests/qtest/microbit-test.c index 04e199ec33..b71daae9a9 100644 --- a/tests/qtest/microbit-test.c +++ b/tests/qtest/microbit-test.c @@ -447,11 +447,11 @@ static void test_nrf51_timer(void) timer_set_bitmode(qts, NRF51_TIMER_WIDTH_16); /* 16 MHz Timer */ timer_set_prescaler(qts, 0); - /* Swept over in first step */ + /* Swept over, during the first step */ timer_set_cc(qts, 0, 2); - /* Barely miss on first step */ + /* Barely miss, after the second step */ timer_set_cc(qts, 1, 162); - /* Spot on on third step */ + /* Spot on, after the third step */ timer_set_cc(qts, 2, 480); timer_assert_events(qts, 0, 0, 0, 0); diff --git a/tools/virtiofsd/fuse_virtio.c b/tools/virtiofsd/fuse_virtio.c index a52eacf82e..9368e292e4 100644 --- a/tools/virtiofsd/fuse_virtio.c +++ b/tools/virtiofsd/fuse_virtio.c @@ -379,7 +379,7 @@ int virtio_send_data_iov(struct fuse_session *se, struct fuse_chan *ch, copy_iov(iov, count, in_sg, in_num, iov_len); /* - * Build a copy of the the in_sg iov so we can skip bits in it, + * Build a copy of the in_sg iov so we can skip bits in it, * including changing the offsets */ in_sg_cpy = g_new(struct iovec, in_num); From a07d9df0fd9d449c0271e2fe358e472bc7efefc2 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 22 Jul 2022 16:35:21 +0200 Subject: [PATCH 0066/1020] trivial: Fix duplicated words Some files wrongly contain the same word twice in a row. One of them should be removed or replaced. Message-Id: <20220722145859.1952732-1-thuth@redhat.com> Signed-off-by: Thomas Huth --- hw/arm/omap2.c | 2 +- hw/misc/mac_via.c | 2 +- target/arm/helper.c | 2 +- tests/docker/dockerfiles/debian-native.docker | 2 +- ui/vdagent.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index 02b1aa8c97..8571eedd73 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -274,7 +274,7 @@ static void omap_eac_format_update(struct omap_eac_s *s) fmt.freq = s->codec.rate; /* TODO: signedness possibly depends on the CODEC hardware - or * does I2S specify it? */ - /* All register writes are 16 bits so we we store 16-bit samples + /* All register writes are 16 bits so we store 16-bit samples * in the buffers regardless of AGCFR[B8_16] value. */ fmt.fmt = AUDIO_FORMAT_U16; diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c index fba85a53d7..f42c12755a 100644 --- a/hw/misc/mac_via.c +++ b/hw/misc/mac_via.c @@ -587,7 +587,7 @@ static void adb_via_poll(void *opaque) /* * For older Linux kernels that switch to IDLE mode after sending the * ADB command, detect if there is an existing response and return that - * as a a "fake" autopoll reply or bus timeout accordingly + * as a "fake" autopoll reply or bus timeout accordingly */ *data = v1s->adb_data_out[0]; olen = v1s->adb_data_in_size; diff --git a/target/arm/helper.c b/target/arm/helper.c index 1a8b06410e..e1bdc80c35 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3898,7 +3898,7 @@ static const ARMCPRegInfo cache_dirty_status_cp_reginfo[] = { }; static const ARMCPRegInfo cache_block_ops_cp_reginfo[] = { - /* We never have a a block transfer operation in progress */ + /* We never have a block transfer operation in progress */ { .name = "BXSR", .cp = 15, .crn = 7, .crm = 12, .opc1 = 0, .opc2 = 4, .access = PL0_R, .type = ARM_CP_CONST | ARM_CP_NO_RAW, .resetvalue = 0 }, diff --git a/tests/docker/dockerfiles/debian-native.docker b/tests/docker/dockerfiles/debian-native.docker index efd55cb6e0..8dd033097c 100644 --- a/tests/docker/dockerfiles/debian-native.docker +++ b/tests/docker/dockerfiles/debian-native.docker @@ -1,7 +1,7 @@ # # Docker Debian Native # -# This this intended to build QEMU on native host systems. Debian is +# This is intended to build QEMU on native host systems. Debian is # chosen due to the broadest range on supported host systems for QEMU. # # This docker target is based on the docker.io Debian Bullseye base diff --git a/ui/vdagent.c b/ui/vdagent.c index aa6167f0b4..a899eed195 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -544,7 +544,7 @@ static void vdagent_clipboard_recv_grab(VDAgentChardev *vd, uint8_t s, uint32_t if (size > sizeof(uint32_t) * 10) { /* * spice has 6 types as of 2021. Limiting to 10 entries - * so we we have some wiggle room. + * so we have some wiggle room. */ return; } From a2da737729efbd9e35eded30a5b8966423bde62d Mon Sep 17 00:00:00 2001 From: Klaus Jensen Date: Thu, 28 Jul 2022 08:36:07 +0200 Subject: [PATCH 0067/1020] hw/nvme: skip queue processing if notifier is cleared While it is safe to process the queues when they are empty, skip it if the event notifier callback was invoked spuriously. Reviewed-by: Keith Busch Reviewed-by: Jinhao Fan Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 533ad14e7a..8aa73b048d 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -4238,7 +4238,9 @@ static void nvme_cq_notifier(EventNotifier *e) NvmeCQueue *cq = container_of(e, NvmeCQueue, notifier); NvmeCtrl *n = cq->ctrl; - event_notifier_test_and_clear(&cq->notifier); + if (!event_notifier_test_and_clear(e)) { + return; + } nvme_update_cq_head(cq); @@ -4275,7 +4277,9 @@ static void nvme_sq_notifier(EventNotifier *e) { NvmeSQueue *sq = container_of(e, NvmeSQueue, notifier); - event_notifier_test_and_clear(&sq->notifier); + if (!event_notifier_test_and_clear(e)) { + return; + } nvme_process_sq(sq); } From 04e8da889016e77a3b9fea7e11569f61aadafbcb Mon Sep 17 00:00:00 2001 From: Klaus Jensen Date: Thu, 28 Jul 2022 08:48:51 +0200 Subject: [PATCH 0068/1020] hw/nvme: unregister the event notifier handler on the main loop Make sure the notifier handler is unregistered in the main loop prior to cleaning it up. Fixes: 2e53b0b45024 ("hw/nvme: Use ioeventfd to handle doorbell updates") Reviewed-by: Keith Busch Reviewed-by: Jinhao Fan Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 8aa73b048d..70b454eedb 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -4311,6 +4311,7 @@ static void nvme_free_sq(NvmeSQueue *sq, NvmeCtrl *n) if (sq->ioeventfd_enabled) { memory_region_del_eventfd(&n->iomem, 0x1000 + offset, 4, false, 0, &sq->notifier); + event_notifier_set_handler(&sq->notifier, NULL); event_notifier_cleanup(&sq->notifier); } g_free(sq->io_req); @@ -4701,6 +4702,7 @@ static void nvme_free_cq(NvmeCQueue *cq, NvmeCtrl *n) if (cq->ioeventfd_enabled) { memory_region_del_eventfd(&n->iomem, 0x1000 + offset, 4, false, 0, &cq->notifier); + event_notifier_set_handler(&cq->notifier, NULL); event_notifier_cleanup(&cq->notifier); } if (msix_enabled(&n->parent_obj)) { From e2e137f64282a2ee2f359b6df4cd93c83a308e7b Mon Sep 17 00:00:00 2001 From: Klaus Jensen Date: Thu, 28 Jul 2022 08:34:21 +0200 Subject: [PATCH 0069/1020] hw/nvme: do not enable ioeventfd by default Do not enable ioeventfd by default. Let the feature mature a bit before we consider enabling it by default. Fixes: 2e53b0b45024 ("hw/nvme: Use ioeventfd to handle doorbell updates") Reviewed-by: Keith Busch Reviewed-by: Jinhao Fan Signed-off-by: Klaus Jensen --- hw/nvme/ctrl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/nvme/ctrl.c b/hw/nvme/ctrl.c index 70b454eedb..87aeba0564 100644 --- a/hw/nvme/ctrl.c +++ b/hw/nvme/ctrl.c @@ -7670,7 +7670,7 @@ static Property nvme_props[] = { DEFINE_PROP_UINT8("vsl", NvmeCtrl, params.vsl, 7), DEFINE_PROP_BOOL("use-intel-id", NvmeCtrl, params.use_intel_id, false), DEFINE_PROP_BOOL("legacy-cmb", NvmeCtrl, params.legacy_cmb, false), - DEFINE_PROP_BOOL("ioeventfd", NvmeCtrl, params.ioeventfd, true), + DEFINE_PROP_BOOL("ioeventfd", NvmeCtrl, params.ioeventfd, false), DEFINE_PROP_UINT8("zoned.zasl", NvmeCtrl, params.zasl, 0), DEFINE_PROP_BOOL("zoned.auto_transition", NvmeCtrl, params.auto_transition_zones, true), From 3fde641e7286f9b968bdb3b4b922c6465f2a9abc Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Sun, 31 Jul 2022 17:58:09 -0500 Subject: [PATCH 0070/1020] ipmi:smbus: Add a check around a memcpy In one case: memcpy(sid->inmsg + sid->inlen, buf, len); if len == 0 then sid->inmsg + sig->inlen can point to one past the inmsg array if the array is full. We have to allow len == 0 due to some vagueness in the spec, but we don't have to call memcpy. Found by Coverity. This is not a problem in practice, but the results are technically (maybe) undefined. So make Coverity happy. Reported-by: Peter Maydell Signed-off-by: Corey Minyard Acked-by: Michael S. Tsirkin Reviewed-by: Peter Maydell --- hw/ipmi/smbus_ipmi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/ipmi/smbus_ipmi.c b/hw/ipmi/smbus_ipmi.c index 9ef9112dd5..d0991ab7f9 100644 --- a/hw/ipmi/smbus_ipmi.c +++ b/hw/ipmi/smbus_ipmi.c @@ -281,7 +281,9 @@ static int ipmi_write_data(SMBusDevice *dev, uint8_t *buf, uint8_t len) */ send = true; } - memcpy(sid->inmsg + sid->inlen, buf, len); + if (len > 0) { + memcpy(sid->inmsg + sid->inlen, buf, len); + } sid->inlen += len; break; } From 54a53a006ed9c1fe027fd89045d6de1e9128d7f4 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 30 Jul 2022 13:26:55 +0100 Subject: [PATCH 0071/1020] scsi-disk: fix overflow when block size is not a multiple of BDRV_SECTOR_SIZE In scsi_disk_emulate_write_same() the number of host sectors to transfer is calculated as (s->qdev.blocksize / BDRV_SECTOR_SIZE) which is then used to copy data in block size chunks to the iov buffer. Since the loop copying the data to the iov buffer uses a fixed increment of s->qdev.blocksize then using a block size that isn't a multiple of BDRV_SECTOR_SIZE introduces a rounding error in the iov buffer size calculation such that the iov buffer copy overflows the space allocated. Update the iov buffer copy for() loop so that it will use the smallest of either the current block size or the remaining transfer count to prevent the overflow. Signed-off-by: Mark Cave-Ayland Message-Id: <20220730122656.253448-2-mark.cave-ayland@ilande.co.uk> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index f5cdb9ad4b..3027ac3b1e 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1849,7 +1849,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) uint32_t nb_sectors = scsi_data_cdb_xfer(r->req.cmd.buf); WriteSameCBData *data; uint8_t *buf; - int i; + int i, l; /* Fail if PBDATA=1 or LBDATA=1 or ANCHOR=1. */ if (nb_sectors == 0 || (req->cmd.buf[1] & 0x16)) { @@ -1891,8 +1891,9 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf) data->iov.iov_len); qemu_iovec_init_external(&data->qiov, &data->iov, 1); - for (i = 0; i < data->iov.iov_len; i += s->qdev.blocksize) { - memcpy(&buf[i], inbuf, s->qdev.blocksize); + for (i = 0; i < data->iov.iov_len; i += l) { + l = MIN(s->qdev.blocksize, data->iov.iov_len - i); + memcpy(&buf[i], inbuf, l); } scsi_req_ref(&r->req); From 55794c904df723109b228da28b5db778e0df3110 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 30 Jul 2022 13:26:56 +0100 Subject: [PATCH 0072/1020] scsi-disk: ensure block size is non-zero and changes limited to bits 8-15 The existing code assumes that the block size can be generated from p[1] << 8 in multiple places which ignores the top and bottom 8 bits. If the block size is allowed to be set to an arbitrary value then this causes a mismatch between the value written by the guest in the block descriptor and the value subsequently read back using READ CAPACITY causing the guest to generate requests that can crash QEMU. For now restrict block size changes to bits 8-15 and also ignore requests to set the block size to 0 which causes the SCSI emulation to crash in at least one place with a divide by zero error. Fixes: 356c4c441e ("scsi-disk: allow MODE SELECT block descriptor to set the block size") Closes: https://gitlab.com/qemu-project/qemu/-/issues/1112 Signed-off-by: Mark Cave-Ayland Message-Id: <20220730122656.253448-3-mark.cave-ayland@ilande.co.uk> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-disk.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 3027ac3b1e..efee6739f9 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -1591,7 +1591,7 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf) int cmd = r->req.cmd.buf[0]; int len = r->req.cmd.xfer; int hdr_len = (cmd == MODE_SELECT ? 4 : 8); - int bd_len; + int bd_len, bs; int pass; if ((r->req.cmd.buf[1] & 0x11) != 0x10) { @@ -1617,9 +1617,19 @@ static void scsi_disk_emulate_mode_select(SCSIDiskReq *r, uint8_t *inbuf) } /* Allow changing the block size */ - if (bd_len && p[6] != (s->qdev.blocksize >> 8)) { - s->qdev.blocksize = p[6] << 8; - trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize); + if (bd_len) { + bs = p[5] << 16 | p[6] << 8 | p[7]; + + /* + * Since the existing code only checks/updates bits 8-15 of the block + * size, restrict ourselves to the same requirement for now to ensure + * that a block size set by a block descriptor and then read back by + * a subsequent SCSI command will be the same + */ + if (bs && !(bs & ~0xff00) && bs != s->qdev.blocksize) { + s->qdev.blocksize = bs; + trace_scsi_disk_mode_select_set_blocksize(s->qdev.blocksize); + } } len -= bd_len; From 3867c1c5fd8f509bd1deada6119cd0f28edeb9af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Thu, 28 Jul 2022 08:15:52 +0200 Subject: [PATCH 0073/1020] aspeed: Remove unused fields from AspeedMachineState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: 346160cbf2af ("aspeed: Set the dram container at the SoC level") Message-Id: <20220727102714.803041-2-clg@kaod.org> Signed-off-by: CĂ©dric Le Goater --- hw/arm/aspeed.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 4193a3d23d..b3bbe06f8f 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -38,8 +38,6 @@ struct AspeedMachineState { /* Public */ AspeedSoCState soc; - MemoryRegion ram_container; - MemoryRegion max_ram; bool mmio_exec; char *fmc_model; char *spi_model; From 398c01da9c8c8af5db0b2b4b4888c2bd27218230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Thu, 28 Jul 2022 08:15:52 +0200 Subject: [PATCH 0074/1020] aspeed/fby35: Fix owner of the BMC RAM memory region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A MachineState object is used as a owner of the RAM region and this asserts in memory_region_init_ram() when QEMU is built with CONFIG_QOM_CAST_DEBUG : /* This will assert if owner is neither NULL nor a DeviceState. * We only want the owner here for the purposes of defining a * unique name for migration. TODO: Ideally we should implement * a naming scheme for Objects which are not DeviceStates, in * which case we can relax this restriction. */ owner_dev = DEVICE(owner); Use the BMC and BIC objects as the owners of their memory regions. Cc: Peter Delevoryas Fixes: 778e14cc5cd5 ("aspeed: Add AST2600 (BMC) to fby35") Reviewed-by: Peter Delevoryas Message-Id: <20220727102714.803041-3-clg@kaod.org> Signed-off-by: CĂ©dric Le Goater --- hw/arm/fby35.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/hw/arm/fby35.c b/hw/arm/fby35.c index 79605f3064..90c04bbc33 100644 --- a/hw/arm/fby35.c +++ b/hw/arm/fby35.c @@ -72,11 +72,13 @@ static void fby35_bmc_init(Fby35State *s) { DriveInfo *drive0 = drive_get(IF_MTD, 0, 0); - memory_region_init(&s->bmc_memory, OBJECT(s), "bmc-memory", UINT64_MAX); - memory_region_init_ram(&s->bmc_dram, OBJECT(s), "bmc-dram", + object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3"); + + memory_region_init(&s->bmc_memory, OBJECT(&s->bmc), "bmc-memory", + UINT64_MAX); + memory_region_init_ram(&s->bmc_dram, OBJECT(&s->bmc), "bmc-dram", FBY35_BMC_RAM_SIZE, &error_abort); - object_initialize_child(OBJECT(s), "bmc", &s->bmc, "ast2600-a3"); object_property_set_int(OBJECT(&s->bmc), "ram-size", FBY35_BMC_RAM_SIZE, &error_abort); object_property_set_link(OBJECT(&s->bmc), "memory", OBJECT(&s->bmc_memory), @@ -120,9 +122,11 @@ static void fby35_bic_init(Fby35State *s) s->bic_sysclk = clock_new(OBJECT(s), "SYSCLK"); clock_set_hz(s->bic_sysclk, 200000000ULL); - memory_region_init(&s->bic_memory, OBJECT(s), "bic-memory", UINT64_MAX); - object_initialize_child(OBJECT(s), "bic", &s->bic, "ast1030-a1"); + + memory_region_init(&s->bic_memory, OBJECT(&s->bic), "bic-memory", + UINT64_MAX); + qdev_connect_clock_in(DEVICE(&s->bic), "sysclk", s->bic_sysclk); object_property_set_link(OBJECT(&s->bic), "memory", OBJECT(&s->bic_memory), &error_abort); From 1bca64a3f0490861c03ceb849821ebf42c926f82 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 1 Aug 2022 13:17:46 +0200 Subject: [PATCH 0075/1020] tests/qtest/migration-test: Run the dirty ring tests only with the x86 target kvm_dirty_ring_supported() only checks whether the dirty ring support is available on the x86 host, but it ignores whether the target QEMU architecture is x86 or not. Thus the test_vcpu_dirty_limit() test currently fails with the assert((strcmp(arch, "x86_64") == 0)) statement in dirtylimit_start_vm() if the users run e.g. "make check-qtest-aarch64" on their x86 host. Fix it by only executing the tests when we're running with a x86_64 target QEMU binary with KVM. Message-Id: <20220801114644.208197-1-thuth@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Thomas Huth --- tests/qtest/migration-test.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 10ab7a708c..520a5f917c 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -2425,6 +2425,7 @@ int main(int argc, char **argv) char template[] = "/tmp/migration-test-XXXXXX"; const bool has_kvm = qtest_has_accel("kvm"); const bool has_uffd = ufd_version_check(); + const char *arch = qtest_get_arch(); int ret; g_test_init(&argc, &argv, NULL); @@ -2434,7 +2435,7 @@ int main(int argc, char **argv) * is touchy due to race conditions on dirty bits (especially on PPC for * some reason) */ - if (g_str_equal(qtest_get_arch(), "ppc64") && + if (g_str_equal(arch, "ppc64") && (!has_kvm || access("/sys/module/kvm_hv", F_OK))) { g_test_message("Skipping test: kvm_hv not available"); return g_test_run(); @@ -2444,7 +2445,7 @@ int main(int argc, char **argv) * Similar to ppc64, s390x seems to be touchy with TCG, so disable it * there until the problems are resolved */ - if (g_str_equal(qtest_get_arch(), "s390x") && !has_kvm) { + if (g_str_equal(arch, "s390x") && !has_kvm) { g_test_message("Skipping test: s390x host with KVM is required"); return g_test_run(); } @@ -2559,7 +2560,7 @@ int main(int argc, char **argv) #endif /* CONFIG_TASN1 */ #endif /* CONFIG_GNUTLS */ - if (kvm_dirty_ring_supported()) { + if (g_str_equal(arch, "x86_64") && has_kvm && kvm_dirty_ring_supported()) { qtest_add_func("/migration/dirty_ring", test_precopy_unix_dirty_ring); qtest_add_func("/migration/vcpu_dirty_limit", From 0dd14e9555225a2b1f56ccdab5eb99d1684869b9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 1 Aug 2022 16:21:17 +0100 Subject: [PATCH 0076/1020] target/arm: Use kvm_arm_sve_supported in kvm_arm_get_host_cpu_features Indication for support for SVE will not depend on whether we perform the query on the main kvm_state or the temp vcpu. Signed-off-by: Richard Henderson Message-id: 20220726045828.53697-2-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/kvm64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index d16d4ea250..bb1516b3d5 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -675,7 +675,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) } } - sve_supported = ioctl(fdarray[0], KVM_CHECK_EXTENSION, KVM_CAP_ARM_SVE) > 0; + sve_supported = kvm_arm_sve_supported(); /* Add feature bits that can't appear until after VCPU init. */ if (sve_supported) { From b9e8d68a3982a470b1d42abda90fcd46c01b52bc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 1 Aug 2022 16:21:18 +0100 Subject: [PATCH 0077/1020] target/arm: Set KVM_ARM_VCPU_SVE while probing the host Because we weren't setting this flag, our probe of ID_AA64ZFR0 was always returning zero. This also obviates the adjustment of ID_AA64PFR0, which had sanitized the SVE field. The effects of the bug are not visible, because the only thing that ID_AA64ZFR0 is used for within qemu at present is tcg translation. The other tests for SVE within KVM are via ID_AA64PFR0.SVE. Reported-by: Zenghui Yu Signed-off-by: Richard Henderson Message-id: 20220726045828.53697-3-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/kvm64.c | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index bb1516b3d5..43cd7eb890 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -507,7 +507,6 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) bool sve_supported; bool pmu_supported = false; uint64_t features = 0; - uint64_t t; int err; /* Old kernels may not know about the PREFERRED_TARGET ioctl: however @@ -528,10 +527,17 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) struct kvm_vcpu_init init = { .target = -1, }; /* - * Ask for Pointer Authentication if supported. We can't play the - * SVE trick of synthesising the ID reg as KVM won't tell us - * whether we have the architected or IMPDEF version of PAuth, so - * we have to use the actual ID regs. + * Ask for SVE if supported, so that we can query ID_AA64ZFR0, + * which is otherwise RAZ. + */ + sve_supported = kvm_arm_sve_supported(); + if (sve_supported) { + init.features[0] |= 1 << KVM_ARM_VCPU_SVE; + } + + /* + * Ask for Pointer Authentication if supported, so that we get + * the unsanitized field values for AA64ISAR1_EL1. */ if (kvm_arm_pauth_supported()) { init.features[0] |= (1 << KVM_ARM_VCPU_PTRAUTH_ADDRESS | @@ -675,20 +681,13 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) } } - sve_supported = kvm_arm_sve_supported(); - - /* Add feature bits that can't appear until after VCPU init. */ if (sve_supported) { - t = ahcf->isar.id_aa64pfr0; - t = FIELD_DP64(t, ID_AA64PFR0, SVE, 1); - ahcf->isar.id_aa64pfr0 = t; - /* * There is a range of kernels between kernel commit 73433762fcae * and f81cb2c3ad41 which have a bug where the kernel doesn't expose * SYS_ID_AA64ZFR0_EL1 via the ONE_REG API unless the VM has enabled - * SVE support, so we only read it here, rather than together with all - * the other ID registers earlier. + * SVE support, which resulted in an error rather than RAZ. + * So only read the register if we set KVM_ARM_VCPU_SVE above. */ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, ARM64_SYS_REG(3, 0, 0, 4, 4)); From 5265d24c981dfdda8d29b44f7e84a514da75eedc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 1 Aug 2022 16:21:18 +0100 Subject: [PATCH 0078/1020] target/arm: Move sve probe inside kvm >= 4.15 branch The test for the IF block indicates no ID registers are exposed, much less host support for SVE. Move the SVE probe into the ELSE block. Signed-off-by: Richard Henderson Message-id: 20220726045828.53697-4-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/kvm64.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 43cd7eb890..9b9dd46d78 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -679,18 +679,18 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) err |= read_sys_reg64(fdarray[2], &ahcf->isar.reset_pmcr_el0, ARM64_SYS_REG(3, 3, 9, 12, 0)); } - } - if (sve_supported) { - /* - * There is a range of kernels between kernel commit 73433762fcae - * and f81cb2c3ad41 which have a bug where the kernel doesn't expose - * SYS_ID_AA64ZFR0_EL1 via the ONE_REG API unless the VM has enabled - * SVE support, which resulted in an error rather than RAZ. - * So only read the register if we set KVM_ARM_VCPU_SVE above. - */ - err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, - ARM64_SYS_REG(3, 0, 0, 4, 4)); + if (sve_supported) { + /* + * There is a range of kernels between kernel commit 73433762fcae + * and f81cb2c3ad41 which have a bug where the kernel doesn't + * expose SYS_ID_AA64ZFR0_EL1 via the ONE_REG API unless the VM has + * enabled SVE support, which resulted in an error rather than RAZ. + * So only read the register if we set KVM_ARM_VCPU_SVE above. + */ + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64zfr0, + ARM64_SYS_REG(3, 0, 0, 4, 4)); + } } kvm_arm_destroy_scratch_host_vcpu(fdarray); From 1eaa63429a9944265c92efdb94c02fabb231f564 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 29 Jul 2022 13:19:42 -0700 Subject: [PATCH 0079/1020] linux-user/riscv: Align signal frame to 16 bytes Follow the kernel's alignment, as we already noted. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1093 Signed-off-by: Richard Henderson Reviewed-by: Alistair Francis Message-Id: <20220729201942.30738-1-richard.henderson@linaro.org> Signed-off-by: Alistair Francis --- linux-user/riscv/signal.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c index 296e39fbf0..eaa168199a 100644 --- a/linux-user/riscv/signal.c +++ b/linux-user/riscv/signal.c @@ -64,9 +64,7 @@ static abi_ulong get_sigframe(struct target_sigaction *ka, /* This is the X/Open sanctioned signal stack switching. */ sp = target_sigsp(sp, ka) - framesize; - - /* XXX: kernel aligns with 0xf ? */ - sp &= ~3UL; /* align sp on 4-byte boundary */ + sp &= ~0xf; return sp; } From 77e3f038af1764983087e3551a0fde9951952c4d Mon Sep 17 00:00:00 2001 From: Jinhao Fan Date: Thu, 21 Jul 2022 14:56:45 +0800 Subject: [PATCH 0080/1020] block/io_uring: add missing include file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The commit "Use io_uring_register_ring_fd() to skip fd operations" uses warn_report but did not include the header file "qemu/error-report.h". This causes "error: implicit declaration of function ‘warn_report’". Include this header file. Fixes: e2848bc574 ("Use io_uring_register_ring_fd() to skip fd operations") Signed-off-by: Jinhao Fan Message-Id: <20220721065645.577404-1-fanjinhao21s@ict.ac.cn> Reviewed-by: Stefano Garzarella Signed-off-by: Kevin Wolf --- block/io_uring.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/io_uring.c b/block/io_uring.c index f8a19fd97f..a1760152e0 100644 --- a/block/io_uring.c +++ b/block/io_uring.c @@ -11,6 +11,7 @@ #include "qemu/osdep.h" #include #include "block/aio.h" +#include "qemu/error-report.h" #include "qemu/queue.h" #include "block/block.h" #include "block/raw-aio.h" From e7156ff7cb3ea79c5c859168484a216c431bdd5a Mon Sep 17 00:00:00 2001 From: Xie Yongji Date: Wed, 6 Jul 2022 17:56:22 +0800 Subject: [PATCH 0081/1020] libvduse: Fix the incorrect function name In vduse_name_is_valid(), we actually check whether the name is invalid or not. So let's change the function name to vduse_name_is_invalid() to match the behavior. Signed-off-by: Xie Yongji Reviewed-by: Markus Armbruster Message-Id: <20220706095624.328-2-xieyongji@bytedance.com> Signed-off-by: Kevin Wolf --- subprojects/libvduse/libvduse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c index 9a2bcec282..6374933881 100644 --- a/subprojects/libvduse/libvduse.c +++ b/subprojects/libvduse/libvduse.c @@ -1193,7 +1193,7 @@ static int vduse_dev_init(VduseDev *dev, const char *name, return 0; } -static inline bool vduse_name_is_valid(const char *name) +static inline bool vduse_name_is_invalid(const char *name) { return strlen(name) >= VDUSE_NAME_MAX || strstr(name, ".."); } @@ -1242,7 +1242,7 @@ VduseDev *vduse_dev_create_by_name(const char *name, uint16_t num_queues, VduseDev *dev; int ret; - if (!name || vduse_name_is_valid(name) || !ops || + if (!name || vduse_name_is_invalid(name) || !ops || !ops->enable_queue || !ops->disable_queue) { fprintf(stderr, "Invalid parameter for vduse\n"); return NULL; @@ -1276,7 +1276,7 @@ VduseDev *vduse_dev_create(const char *name, uint32_t device_id, struct vduse_dev_config *dev_config; size_t size = offsetof(struct vduse_dev_config, config); - if (!name || vduse_name_is_valid(name) || + if (!name || vduse_name_is_invalid(name) || !has_feature(features, VIRTIO_F_VERSION_1) || !config || !config_size || !ops || !ops->enable_queue || !ops->disable_queue) { fprintf(stderr, "Invalid parameter for vduse\n"); From d9cf16c0bee5b97fb76e0e1ad915a22bec0031b9 Mon Sep 17 00:00:00 2001 From: Xie Yongji Date: Wed, 6 Jul 2022 17:56:23 +0800 Subject: [PATCH 0082/1020] libvduse: Replace strcpy() with strncpy() Coverity reported a string overflow issue since we copied "name" to "dev_config->name" without checking the length. This should be a false positive since we already checked the length of "name" in vduse_name_is_invalid(). But anyway, let's replace strcpy() with strncpy() (as a general library, we'd like to minimize dependencies on other libraries, so we didn't use g_strlcpy() here) to fix the coverity complaint. Fixes: Coverity CID 1490224 Signed-off-by: Xie Yongji Reviewed-by: Markus Armbruster Message-Id: <20220706095624.328-3-xieyongji@bytedance.com> Signed-off-by: Kevin Wolf --- subprojects/libvduse/libvduse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c index 6374933881..1e36227388 100644 --- a/subprojects/libvduse/libvduse.c +++ b/subprojects/libvduse/libvduse.c @@ -1309,7 +1309,8 @@ VduseDev *vduse_dev_create(const char *name, uint32_t device_id, goto err_dev; } - strcpy(dev_config->name, name); + strncpy(dev_config->name, name, VDUSE_NAME_MAX); + dev_config->name[VDUSE_NAME_MAX - 1] = '\0'; dev_config->device_id = device_id; dev_config->vendor_id = vendor_id; dev_config->features = features; From 630179b7f7d147ee0f7d396e71775b60a16f46a1 Mon Sep 17 00:00:00 2001 From: Xie Yongji Date: Wed, 6 Jul 2022 17:56:24 +0800 Subject: [PATCH 0083/1020] libvduse: Pass positive value to strerror() The value passed to strerror() should be positive. So let's fix it. Fixes: Coverity CID 1490226, 1490223 Signed-off-by: Xie Yongji Reviewed-by: Richard Henderson Reviewed-by: Markus Armbruster Message-Id: <20220706095624.328-4-xieyongji@bytedance.com> Signed-off-by: Kevin Wolf --- subprojects/libvduse/libvduse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/subprojects/libvduse/libvduse.c b/subprojects/libvduse/libvduse.c index 1e36227388..1a5981445c 100644 --- a/subprojects/libvduse/libvduse.c +++ b/subprojects/libvduse/libvduse.c @@ -1257,7 +1257,7 @@ VduseDev *vduse_dev_create_by_name(const char *name, uint16_t num_queues, ret = vduse_dev_init(dev, name, num_queues, ops, priv); if (ret < 0) { fprintf(stderr, "Failed to init vduse device %s: %s\n", - name, strerror(ret)); + name, strerror(-ret)); free(dev); return NULL; } @@ -1331,7 +1331,7 @@ VduseDev *vduse_dev_create(const char *name, uint32_t device_id, ret = vduse_dev_init(dev, name, num_queues, ops, priv); if (ret < 0) { fprintf(stderr, "Failed to init vduse device %s: %s\n", - name, strerror(ret)); + name, strerror(-ret)); goto err; } From fd8a68ad6823d33bedeba20a22857867a1c3890e Mon Sep 17 00:00:00 2001 From: Lev Kujawski Date: Thu, 7 Jul 2022 20:40:45 +0000 Subject: [PATCH 0084/1020] hw/block/hd-geometry: Do not override specified bios-chs-trans For small disk images (<4 GiB), QEMU and SeaBIOS default to the LARGE/ECHS disk translation method, but it is not uncommon for other BIOS software to use LBA in these cases as well. Some operating system boot loaders (e.g., NT 4) do not handle LARGE translations outside of fixed configurations. See, e.g., Q154052: "When starting an x86 based computer, Ntdetect.com retrieves and stores Interrupt 13 information. . . If the disk controller is using a 32 sector/64 head translation scheme, this boundary will be 1 GB. If the controller uses 63 sector/255 head translation [AUTHOR: i.e., LBA], the limit will be 4 GB." To accommodate these situations, hd_geometry_guess() now follows the disk translation specified by the user even when the ATA disk geometry is guessed. hd_geometry_guess(): * Only set the disk translation when translation is AUTO. * Show the soon-to-be active translation (*ptrans) in the trace rather than what was guessed. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/56 Buglink: https://bugs.launchpad.net/qemu/+bug/1745312 Signed-off-by: Lev Kujawski Message-Id: <20220707204045.999544-1-lkujaw@member.fsf.org> Signed-off-by: Kevin Wolf --- hw/block/hd-geometry.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/block/hd-geometry.c b/hw/block/hd-geometry.c index 112094358e..dae13ab14d 100644 --- a/hw/block/hd-geometry.c +++ b/hw/block/hd-geometry.c @@ -150,7 +150,12 @@ void hd_geometry_guess(BlockBackend *blk, translation = BIOS_ATA_TRANSLATION_NONE; } if (ptrans) { - *ptrans = translation; + if (*ptrans == BIOS_ATA_TRANSLATION_AUTO) { + *ptrans = translation; + } else { + /* Defer to the translation specified by the user. */ + translation = *ptrans; + } } trace_hd_geometry_guess(blk, *pcyls, *pheads, *psecs, translation); } From e13fe274bfbc4c5b338854a3519a64b84c2d5517 Mon Sep 17 00:00:00 2001 From: Cole Robinson Date: Sun, 5 Jun 2022 10:57:17 -0400 Subject: [PATCH 0085/1020] qemu-iotests: Discard stderr when probing devices qemu-iotests fails in the following setup: ./configure --enable-modules --enable-smartcard \ --target-list=x86_64-softmmu,s390x-softmmu make cd build QEMU_PROG=`pwd`/s390x-softmmu/qemu-system-s390x \ ../tests/check-block.sh qcow2 ... --- /home/crobinso/src/qemu/tests/qemu-iotests/127.out +++ /home/crobinso/src/qemu/build/tests/qemu-iotests/scratch/127.out.bad @@ -1,4 +1,18 @@ QA output created by 127 +Failed to open module: /home/crobinso/src/qemu/build/hw-usb-smartcard.so: undefined symbol: ccid_card_ccid_attach ... --- /home/crobinso/src/qemu/tests/qemu-iotests/267.out +++ /home/crobinso/src/qemu/build/tests/qemu-iotests/scratch/267.out.bad @@ -1,4 +1,11 @@ QA output created by 267 +Failed to open module: /home/crobinso/src/qemu/build/hw-usb-smartcard.so: undefined symbol: ccid_card_ccid_attach The stderr spew is its own known issue, but seems like iotests should be discarding stderr in this case. Signed-off-by: Cole Robinson Reviewed-by: Thomas Huth Signed-off-by: Kevin Wolf --- tests/qemu-iotests/common.rc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc index 165b54a61e..db757025cb 100644 --- a/tests/qemu-iotests/common.rc +++ b/tests/qemu-iotests/common.rc @@ -982,7 +982,7 @@ _require_large_file() # _require_devices() { - available=$($QEMU -M none -device help | \ + available=$($QEMU -M none -device help 2> /dev/null | \ grep ^name | sed -e 's/^name "//' -e 's/".*$//') for device do @@ -994,7 +994,7 @@ _require_devices() _require_one_device_of() { - available=$($QEMU -M none -device help | \ + available=$($QEMU -M none -device help 2> /dev/null | \ grep ^name | sed -e 's/^name "//' -e 's/".*$//') for device do From 21b1d974595b3986c68fe80a1f7e9b87886d4bae Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Thu, 9 Jun 2022 08:22:06 -0400 Subject: [PATCH 0086/1020] main loop: add missing documentation links to GS/IO macros If we go directly to GLOBAL_STATE_CODE, IO_CODE or IO_OR_GS_CODE definition, we just find that they "mark and check that the function is part of the {category} API". However, ther is no definition on what {category} API is, they are in include/block/block-*.h Therefore, add a comment that refers to such documentation. Signed-off-by: Emanuele Giuseppe Esposito Message-Id: <20220609122206.1016936-1-eesposit@redhat.com> Reviewed-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- include/qemu/main-loop.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 5518845299..c50d1b7e3a 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -279,7 +279,11 @@ bool qemu_mutex_iothread_locked(void); */ bool qemu_in_main_thread(void); -/* Mark and check that the function is part of the global state API. */ +/* + * Mark and check that the function is part of the Global State API. + * Please refer to include/block/block-global-state.h for more + * information about GS API. + */ #ifdef CONFIG_COCOA /* * When using the Cocoa UI, addRemovableDevicesMenuItems() is called from @@ -298,13 +302,21 @@ bool qemu_in_main_thread(void); } while (0) #endif /* CONFIG_COCOA */ -/* Mark and check that the function is part of the I/O API. */ +/* + * Mark and check that the function is part of the I/O API. + * Please refer to include/block/block-io.h for more + * information about IO API. + */ #define IO_CODE() \ do { \ /* nop */ \ } while (0) -/* Mark and check that the function is part of the "I/O OR GS" API. */ +/* + * Mark and check that the function is part of the "I/O OR GS" API. + * Please refer to include/block/block-io.h for more + * information about "IO or GS" API. + */ #define IO_OR_GS_CODE() \ do { \ /* nop */ \ From 5b63de6b54add51822db3c89325c6fc05534a54c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rainer=20M=C3=BCller?= Date: Fri, 29 Jul 2022 17:49:51 +0200 Subject: [PATCH 0087/1020] linux-user: Use memfd for open syscall emulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For certain paths in /proc, the open syscall is intercepted and the returned file descriptor points to a temporary file with emulated contents. If TMPDIR is not accessible or writable for the current user (for example in a read-only mounted chroot or container) tools such as ps from procps may fail unexpectedly. Trying to read one of these paths such as /proc/self/stat would return an error such as ENOENT or EROFS. To relax the requirement on a writable TMPDIR, use memfd_create() instead to create an anonymous file and return its file descriptor. Signed-off-by: Rainer MĂ¼ller Reviewed-by: Richard Henderson Message-Id: <20220729154951.76268-1-raimue@codingfarm.de> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b27a6552aa..ef53feb5ab 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8260,16 +8260,22 @@ static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int char filename[PATH_MAX]; int fd, r; - /* create temporary file to map stat to */ - tmpdir = getenv("TMPDIR"); - if (!tmpdir) - tmpdir = "/tmp"; - snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir); - fd = mkstemp(filename); + fd = memfd_create("qemu-open", 0); if (fd < 0) { - return fd; + if (errno != ENOSYS) { + return fd; + } + /* create temporary file to map stat to */ + tmpdir = getenv("TMPDIR"); + if (!tmpdir) + tmpdir = "/tmp"; + snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir); + fd = mkstemp(filename); + if (fd < 0) { + return fd; + } + unlink(filename); } - unlink(filename); if ((r = fake_open->fill(cpu_env, fd))) { int e = errno; From df67aa3e61e2c83459da7d815962d9706f1528fc Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Mon, 25 Jul 2022 22:02:35 -0300 Subject: [PATCH 0088/1020] migration: add remaining params->has_* = true in migration_instance_init() Some of params->has_* = true are missing in migration_instance_init, this causes migrate_params_check() to skip some tests, allowing some unsupported scenarios. Fix this by adding all missing params->has_* = true in migration_instance_init(). Fixes: 69ef1f36b0 ("migration: define 'tls-creds' and 'tls-hostname' migration parameters") Fixes: 1d58872a91 ("migration: do not wait for free thread") Fixes: d2f1d29b95 ("migration: add support for a "tls-authz" migration parameter") Signed-off-by: Leonardo Bras Message-Id: <20220726010235.342927-1-leobras@redhat.com> Reviewed-by: Peter Xu Signed-off-by: Dr. David Alan Gilbert --- migration/migration.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/migration/migration.c b/migration/migration.c index e03f698a3c..82fbe0cf55 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -4451,6 +4451,7 @@ static void migration_instance_init(Object *obj) /* Set has_* up only for parameter checks */ params->has_compress_level = true; params->has_compress_threads = true; + params->has_compress_wait_thread = true; params->has_decompress_threads = true; params->has_throttle_trigger_threshold = true; params->has_cpu_throttle_initial = true; @@ -4471,6 +4472,9 @@ static void migration_instance_init(Object *obj) params->has_announce_max = true; params->has_announce_rounds = true; params->has_announce_step = true; + params->has_tls_creds = true; + params->has_tls_hostname = true; + params->has_tls_authz = true; qemu_sem_init(&ms->postcopy_pause_sem, 0); qemu_sem_init(&ms->postcopy_pause_rp_sem, 0); From 777f53c75983dd10756f5dbfc8af50fe11da81c1 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 2 Aug 2022 08:19:49 +0200 Subject: [PATCH 0089/1020] Revert "migration: Simplify unqueue_page()" This reverts commit cfd66f30fb0f735df06ff4220e5000290a43dad3. The simplification of unqueue_page() introduced a bug that sometimes breaks migration on s390x hosts. The problem is not fully understood yet, but since we are already in the freeze for QEMU 7.1 and we need something working there, let's revert this patch for the upcoming release. The optimization can be redone later again in a proper way if necessary. Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2099934 Signed-off-by: Thomas Huth Message-Id: <20220802061949.331576-1-thuth@redhat.com> Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- migration/ram.c | 37 ++++++++++++++++++++++++++----------- migration/trace-events | 3 ++- 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/migration/ram.c b/migration/ram.c index b94669ba5d..dc1de9ddbc 100644 --- a/migration/ram.c +++ b/migration/ram.c @@ -1612,7 +1612,6 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset) { struct RAMSrcPageRequest *entry; RAMBlock *block = NULL; - size_t page_size; if (!postcopy_has_request(rs)) { return NULL; @@ -1629,13 +1628,10 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset) entry = QSIMPLEQ_FIRST(&rs->src_page_requests); block = entry->rb; *offset = entry->offset; - page_size = qemu_ram_pagesize(block); - /* Each page request should only be multiple page size of the ramblock */ - assert((entry->len % page_size) == 0); - if (entry->len > page_size) { - entry->len -= page_size; - entry->offset += page_size; + if (entry->len > TARGET_PAGE_SIZE) { + entry->len -= TARGET_PAGE_SIZE; + entry->offset += TARGET_PAGE_SIZE; } else { memory_region_unref(block->mr); QSIMPLEQ_REMOVE_HEAD(&rs->src_page_requests, next_req); @@ -1643,9 +1639,6 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset) migration_consume_urgent_request(); } - trace_unqueue_page(block->idstr, *offset, - test_bit((*offset >> TARGET_PAGE_BITS), block->bmap)); - return block; } @@ -2069,8 +2062,30 @@ static bool get_queued_page(RAMState *rs, PageSearchStatus *pss) { RAMBlock *block; ram_addr_t offset; + bool dirty; - block = unqueue_page(rs, &offset); + do { + block = unqueue_page(rs, &offset); + /* + * We're sending this page, and since it's postcopy nothing else + * will dirty it, and we must make sure it doesn't get sent again + * even if this queue request was received after the background + * search already sent it. + */ + if (block) { + unsigned long page; + + page = offset >> TARGET_PAGE_BITS; + dirty = test_bit(page, block->bmap); + if (!dirty) { + trace_get_queued_page_not_dirty(block->idstr, (uint64_t)offset, + page); + } else { + trace_get_queued_page(block->idstr, (uint64_t)offset, page); + } + } + + } while (block && !dirty); if (block) { /* See comment above postcopy_preempted_contains() */ diff --git a/migration/trace-events b/migration/trace-events index a34afe7b85..57003edcbd 100644 --- a/migration/trace-events +++ b/migration/trace-events @@ -85,6 +85,8 @@ put_qlist_end(const char *field_name, const char *vmsd_name) "%s(%s)" qemu_file_fclose(void) "" # ram.c +get_queued_page(const char *block_name, uint64_t tmp_offset, unsigned long page_abs) "%s/0x%" PRIx64 " page_abs=0x%lx" +get_queued_page_not_dirty(const char *block_name, uint64_t tmp_offset, unsigned long page_abs) "%s/0x%" PRIx64 " page_abs=0x%lx" migration_bitmap_sync_start(void) "" migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64 migration_bitmap_clear_dirty(char *str, uint64_t start, uint64_t size, unsigned long page) "rb %s start 0x%"PRIx64" size 0x%"PRIx64" page 0x%lx" @@ -110,7 +112,6 @@ ram_save_iterate_big_wait(uint64_t milliconds, int iterations) "big wait: %" PRI ram_load_complete(int ret, uint64_t seq_iter) "exit_code %d seq iteration %" PRIu64 ram_write_tracking_ramblock_start(const char *block_id, size_t page_size, void *addr, size_t length) "%s: page_size: %zu addr: %p length: %zu" ram_write_tracking_ramblock_stop(const char *block_id, size_t page_size, void *addr, size_t length) "%s: page_size: %zu addr: %p length: %zu" -unqueue_page(char *block, uint64_t offset, bool dirty) "ramblock '%s' offset 0x%"PRIx64" dirty %d" postcopy_preempt_triggered(char *str, unsigned long page) "during sending ramblock %s offset 0x%lx" postcopy_preempt_restored(char *str, unsigned long page) "ramblock %s offset 0x%lx" postcopy_preempt_hit(char *str, uint64_t offset) "ramblock %s offset 0x%"PRIx64 From ead34f64f97d11626774a57863ca285a7ddc0d18 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 21 Jul 2022 12:52:06 +0100 Subject: [PATCH 0090/1020] migration: Assert that migrate_multifd_compression() returns an in-range value Coverity complains that when we use the return value from migrate_multifd_compression() as an array index: multifd_recv_state->ops = multifd_ops[migrate_multifd_compression()]; that this might overrun the array (which is declared to have size MULTIFD_COMPRESSION__MAX). This is because the function return type is MultiFDCompression, which is an autogenerated enum. The code generator includes the "one greater than the maximum possible value" MULTIFD_COMPRESSION__MAX in the enum, even though this is not actually a valid value for the enum, and this makes Coverity think that migrate_multifd_compression() could return that __MAX value and index off the end of the array. Suppress the Coverity error by asserting that the value we're going to return is within range. Resolves: Coverity CID 1487239, 1487254 Signed-off-by: Peter Maydell Message-Id: <20220721115207.729615-2-peter.maydell@linaro.org> Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Juan Quintela Signed-off-by: Dr. David Alan Gilbert --- migration/migration.c | 1 + 1 file changed, 1 insertion(+) diff --git a/migration/migration.c b/migration/migration.c index 82fbe0cf55..bb8bbddfe4 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -2617,6 +2617,7 @@ MultiFDCompression migrate_multifd_compression(void) s = migrate_get_current(); + assert(s->parameters.multifd_compression < MULTIFD_COMPRESSION__MAX); return s->parameters.multifd_compression; } From 4bcb7de072fd8ab9de40b24aac00c7b6659f7f7d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 21 Jul 2022 12:52:07 +0100 Subject: [PATCH 0091/1020] migration: Define BLK_MIG_BLOCK_SIZE as unsigned long long When we use BLK_MIG_BLOCK_SIZE in expressions like block_mig_state.submitted * BLK_MIG_BLOCK_SIZE, this multiplication is done as 32 bits, because both operands are 32 bits. Coverity complains about possible overflows because we then accumulate that into a 64 bit variable. Define BLK_MIG_BLOCK_SIZE as unsigned long long using the ULL suffix. The only two current uses of it with this problem are both in block_save_pending(), so we could just cast to uint64_t there, but using the ULL suffix is simpler and ensures that we don't accidentally introduce new variants of the same issue in future. Resolves: Coverity CID 1487136, 1487175 Signed-off-by: Peter Maydell Message-Id: <20220721115207.729615-3-peter.maydell@linaro.org> Reviewed-by: Dr. David Alan Gilbert Reviewed-by: Juan Quintela Signed-off-by: Dr. David Alan Gilbert --- migration/block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migration/block.c b/migration/block.c index 9e5aae5898..3577c815a9 100644 --- a/migration/block.c +++ b/migration/block.c @@ -28,7 +28,7 @@ #include "sysemu/block-backend.h" #include "trace.h" -#define BLK_MIG_BLOCK_SIZE (1 << 20) +#define BLK_MIG_BLOCK_SIZE (1ULL << 20) #define BDRV_SECTORS_PER_DIRTY_CHUNK (BLK_MIG_BLOCK_SIZE >> BDRV_SECTOR_BITS) #define BLK_MIG_FLAG_DEVICE_BLOCK 0x01 From a21ba54dd5ca38cd05da9035fc65374d7af54f13 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Fri, 29 Jul 2022 09:17:06 -0400 Subject: [PATCH 0092/1020] virtiofsd: Disable killpriv_v2 by default We are having bunch of issues with killpriv_v2 enabled by default. First of all it relies on clearing suid/sgid bits as needed by dropping capability CAP_FSETID. This does not work for remote filesystems like NFS (and possibly others). Secondly, we are noticing other issues related to clearing of SGID which leads to failures for xfstests generic/355 and generic/193. Thirdly, there are other issues w.r.t caching of metadata (suid/sgid) bits in fuse client with killpriv_v2 enabled. Guest can cache that data for sometime even if cleared on server. Second and Third issue are fixable. Just that it might take a little while to get it fixed in kernel. First one will probably not see any movement for a long time. Given these issues, killpriv_v2 does not seem to be a good candidate for enabling by default. We have already disabled it by default in rust version of virtiofsd. Hence this patch disabled killpriv_v2 by default. User can choose to enable it by passing option "-o killpriv_v2". Signed-off-by: Vivek Goyal Message-Id: Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Dr. David Alan Gilbert --- tools/virtiofsd/passthrough_ll.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 7a73dfcce9..371a7bead6 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -767,19 +767,10 @@ static void lo_init(void *userdata, struct fuse_conn_info *conn) fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling killpriv_v2\n"); conn->want |= FUSE_CAP_HANDLE_KILLPRIV_V2; lo->killpriv_v2 = 1; - } else if (lo->user_killpriv_v2 == -1 && - conn->capable & FUSE_CAP_HANDLE_KILLPRIV_V2) { - /* - * User did not specify a value for killpriv_v2. By default enable it - * if connection offers this capability - */ - fuse_log(FUSE_LOG_DEBUG, "lo_init: enabling killpriv_v2\n"); - conn->want |= FUSE_CAP_HANDLE_KILLPRIV_V2; - lo->killpriv_v2 = 1; } else { /* - * Either user specified to disable killpriv_v2, or connection does - * not offer this capability. Disable killpriv_v2 in both the cases + * Either user specified to disable killpriv_v2, or did not + * specify anything. Disable killpriv_v2 in both the cases. */ fuse_log(FUSE_LOG_DEBUG, "lo_init: disabling killpriv_v2\n"); conn->want &= ~FUSE_CAP_HANDLE_KILLPRIV_V2; From d44971e725c02e0656d2f53d4fb564f92e06aef7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 29 Jul 2022 19:17:02 -0700 Subject: [PATCH 0093/1020] target/mips: Advance pc after semihosting exception MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Delay generating the exception until after we know the insn length, and record that length in env->error_code. Fixes: 8ec7e3c53d4 ("target/mips: Use an exception for semihosting") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1126 Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Richard Henderson --- target/mips/tcg/micromips_translate.c.inc | 6 +++--- target/mips/tcg/mips16e_translate.c.inc | 2 +- target/mips/tcg/nanomips_translate.c.inc | 4 ++-- target/mips/tcg/sysemu/tlb_helper.c | 1 + target/mips/tcg/translate.c | 10 +++++----- target/mips/tcg/translate.h | 4 ++++ 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc index 274caf2c3c..b2c696f891 100644 --- a/target/mips/tcg/micromips_translate.c.inc +++ b/target/mips/tcg/micromips_translate.c.inc @@ -826,7 +826,7 @@ static void gen_pool16c_insn(DisasContext *ctx) break; case SDBBP16: if (is_uhi(extract32(ctx->opcode, 0, 4))) { - generate_exception_end(ctx, EXCP_SEMIHOST); + ctx->base.is_jmp = DISAS_SEMIHOST; } else { /* * XXX: not clear which exception should be raised @@ -942,7 +942,7 @@ static void gen_pool16c_r6_insn(DisasContext *ctx) case R6_SDBBP16: /* SDBBP16 */ if (is_uhi(extract32(ctx->opcode, 6, 4))) { - generate_exception_end(ctx, EXCP_SEMIHOST); + ctx->base.is_jmp = DISAS_SEMIHOST; } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { generate_exception(ctx, EXCP_RI); @@ -1311,7 +1311,7 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs) break; case SDBBP: if (is_uhi(extract32(ctx->opcode, 16, 10))) { - generate_exception_end(ctx, EXCP_SEMIHOST); + ctx->base.is_jmp = DISAS_SEMIHOST; } else { check_insn(ctx, ISA_MIPS_R1); if (ctx->hflags & MIPS_HFLAG_SBRI) { diff --git a/target/mips/tcg/mips16e_translate.c.inc b/target/mips/tcg/mips16e_translate.c.inc index 0a3ba252e4..7568933e23 100644 --- a/target/mips/tcg/mips16e_translate.c.inc +++ b/target/mips/tcg/mips16e_translate.c.inc @@ -952,7 +952,7 @@ static int decode_ase_mips16e(CPUMIPSState *env, DisasContext *ctx) break; case RR_SDBBP: if (is_uhi(extract32(ctx->opcode, 5, 6))) { - generate_exception_end(ctx, EXCP_SEMIHOST); + ctx->base.is_jmp = DISAS_SEMIHOST; } else { /* * XXX: not clear which exception should be raised diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index ecb0ebed57..b3aff22c18 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -3695,7 +3695,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) break; case NM_SDBBP: if (is_uhi(extract32(ctx->opcode, 0, 19))) { - generate_exception_end(ctx, EXCP_SEMIHOST); + ctx->base.is_jmp = DISAS_SEMIHOST; } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { gen_reserved_instruction(ctx); @@ -4634,7 +4634,7 @@ static int decode_isa_nanomips(CPUMIPSState *env, DisasContext *ctx) break; case NM_SDBBP16: if (is_uhi(extract32(ctx->opcode, 0, 3))) { - generate_exception_end(ctx, EXCP_SEMIHOST); + ctx->base.is_jmp = DISAS_SEMIHOST; } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { gen_reserved_instruction(ctx); diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/tlb_helper.c index 57ffad2902..9d16859c0a 100644 --- a/target/mips/tcg/sysemu/tlb_helper.c +++ b/target/mips/tcg/sysemu/tlb_helper.c @@ -1056,6 +1056,7 @@ void mips_cpu_do_interrupt(CPUState *cs) case EXCP_SEMIHOST: cs->exception_index = EXCP_NONE; mips_semihosting(env); + env->active_tc.PC += env->error_code; return; case EXCP_DSS: env->CP0_Debug |= 1 << CP0DB_DSS; diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 1f6a779808..de1511baaf 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -1213,9 +1213,6 @@ TCGv_i64 fpu_f64[32]; #include "exec/gen-icount.h" -#define DISAS_STOP DISAS_TARGET_0 -#define DISAS_EXIT DISAS_TARGET_1 - static const char regnames_HI[][4] = { "HI0", "HI1", "HI2", "HI3", }; @@ -13902,7 +13899,7 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) break; case R6_OPC_SDBBP: if (is_uhi(extract32(ctx->opcode, 6, 20))) { - generate_exception_end(ctx, EXCP_SEMIHOST); + ctx->base.is_jmp = DISAS_SEMIHOST; } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { gen_reserved_instruction(ctx); @@ -14314,7 +14311,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) break; case OPC_SDBBP: if (is_uhi(extract32(ctx->opcode, 6, 20))) { - generate_exception_end(ctx, EXCP_SEMIHOST); + ctx->base.is_jmp = DISAS_SEMIHOST; } else { /* * XXX: not clear which exception should be raised @@ -16098,6 +16095,9 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (is_slot) { gen_branch(ctx, insn_bytes); } + if (ctx->base.is_jmp == DISAS_SEMIHOST) { + generate_exception_err(ctx, EXCP_SEMIHOST, insn_bytes); + } ctx->base.pc_next += insn_bytes; if (ctx->base.is_jmp != DISAS_NEXT) { diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h index 55053226ae..69f85841d2 100644 --- a/target/mips/tcg/translate.h +++ b/target/mips/tcg/translate.h @@ -51,6 +51,10 @@ typedef struct DisasContext { int gi; } DisasContext; +#define DISAS_STOP DISAS_TARGET_0 +#define DISAS_EXIT DISAS_TARGET_1 +#define DISAS_SEMIHOST DISAS_TARGET_2 + /* MIPS major opcodes */ #define MASK_OP_MAJOR(op) (op & (0x3F << 26)) From d2656dd577754129f86328f95e6ee4a241913d6f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Aug 2022 20:12:42 -0700 Subject: [PATCH 0094/1020] Update version for v7.1.0-rc1 release Signed-off-by: Richard Henderson --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 20780a61a3..38bd418901 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0.90 +7.0.91 From 9567fc1665b6649d2aff0184f68377a9e7c30dd9 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 3 Aug 2022 11:02:50 +0200 Subject: [PATCH 0095/1020] README.rst: fix link formatting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the links render correctly. Signed-off-by: Cornelia Huck Reviewed-by: Daniel P. BerrangĂ© Message-Id: <20220803090250.136556-1-cohuck@redhat.com> Signed-off-by: Laurent Vivier --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 23795b8377..21df79ef43 100644 --- a/README.rst +++ b/README.rst @@ -39,7 +39,7 @@ Documentation can be found hosted online at current development version that is available at ``_ is generated from the ``docs/`` folder in the source tree, and is built by `Sphinx -_`. +`_. Building @@ -78,7 +78,7 @@ format-patch' and/or 'git send-email' to format & send the mail to the qemu-devel@nongnu.org mailing list. All patches submitted must contain a 'Signed-off-by' line from the author. Patches should follow the guidelines set out in the `style section -` of +`_ of the Developers Guide. Additional information on submitting patches can be found online via From aed5da45daf734ddc543c0791e877dac75e16f61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 2 Aug 2022 13:24:46 +0200 Subject: [PATCH 0096/1020] vdpa: Fix file descriptor leak on get features error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit File descriptor vdpa_device_fd is not free in the case of returning error from vhost_vdpa_get_features. Fixing it by making all errors go to the same error path. Resolves: Coverity CID 1490785 Fixes: 8170ab3f43 ("vdpa: Extract get features part from vhost_vdpa_get_max_queue_pairs") Signed-off-by: Eugenio PĂ©rez Reviewed-by: Laurent Vivier Reviewed-by: Michael S. Tsirkin Message-Id: <20220802112447.249436-2-eperezma@redhat.com> Signed-off-by: Laurent Vivier --- net/vhost-vdpa.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 6abad276a6..303447a68e 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -566,7 +566,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, g_autofree NetClientState **ncs = NULL; g_autoptr(VhostIOVATree) iova_tree = NULL; NetClientState *nc; - int queue_pairs, r, i, has_cvq = 0; + int queue_pairs, r, i = 0, has_cvq = 0; assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA); opts = &netdev->u.vhost_vdpa; @@ -582,7 +582,7 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name, r = vhost_vdpa_get_features(vdpa_device_fd, &features, errp); if (unlikely(r < 0)) { - return r; + goto err; } queue_pairs = vhost_vdpa_get_max_queue_pairs(vdpa_device_fd, features, From 9878fbf3424015da93e0a8e8cec40a2d45323fad Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 2 Aug 2022 09:56:11 +0200 Subject: [PATCH 0097/1020] docs/about/removed-features: Move the -soundhw into the right section MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The note about the removal of '-soundhw' has been accidentally added to the section of removed "linux-user mode CPUs" ... it should reside in the section about removed "System emulator command line arguments" instead. Fixes: 039a68373c ("introduce -audio as a replacement for -soundhw") Signed-off-by: Thomas Huth Reviewed-by: Daniel P. BerrangĂ© Reviewed-by: Christian Schoenebeck Message-Id: <20220802075611.346835-1-thuth@redhat.com> Signed-off-by: Laurent Vivier --- docs/about/removed-features.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index c7b9dadd5d..925e22016f 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -396,6 +396,13 @@ Use ``-display sdl`` instead. Use ``-display curses`` instead. +Creating sound card devices using ``-soundhw`` (removed in 7.1) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Sound card devices should be created using ``-device`` or ``-audio``. +The exception is ``pcspk`` which can be activated using ``-machine +pcspk-audiodev=``. + QEMU Machine Protocol (QMP) commands ------------------------------------ @@ -681,13 +688,6 @@ tripped up the CI testing and was suspected to be quite broken. For that reason the maintainers strongly suspected no one actually used it. -Creating sound card devices using ``-soundhw`` (removed in 7.1) -''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - -Sound card devices should be created using ``-device`` or ``-audio``. -The exception is ``pcspk`` which can be activated using ``-machine -pcspk-audiodev=``. - TCG introspection features -------------------------- From 1e2dd311491565a58b30f29e71c6e429fc8e7e84 Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Fri, 29 Jul 2022 04:11:35 +0800 Subject: [PATCH 0098/1020] ppc: Remove redundant macro MSR_BOOK3S_MASK. Signed-off-by: Yonggang Luo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220728201135.223-1-luoyonggang@gmail.com> Signed-off-by: Laurent Vivier --- target/ppc/excp_helper.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index cb752b184a..7550aafed6 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2015,7 +2015,6 @@ void helper_rfi(CPUPPCState *env) do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful); } -#define MSR_BOOK3S_MASK #if defined(TARGET_PPC64) void helper_rfid(CPUPPCState *env) { From 21d4e557e2fd0cb7f10b632b35f51146a1b6d892 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 21 Jul 2022 09:48:09 +0200 Subject: [PATCH 0099/1020] include/qemu/host-utils.h: Simplify the compiler check in mulu128() We currently require at least GCC 7.4 or Clang 6.0 for compiling QEMU. GCC has __builtin_mul_overflow since version 5 already, and Clang 6.0 also provides this built-in function (see its documentation on this page: https://releases.llvm.org/6.0.0/tools/clang/docs/LanguageExtensions.html ). So we can simplify the #if statement here. Signed-off-by: Thomas Huth Reviewed-by: Richard Henderson Message-Id: <20220721074809.1513357-1-thuth@redhat.com> Signed-off-by: Laurent Vivier --- include/qemu/host-utils.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/include/qemu/host-utils.h b/include/qemu/host-utils.h index 29f3a99878..88d476161c 100644 --- a/include/qemu/host-utils.h +++ b/include/qemu/host-utils.h @@ -533,8 +533,7 @@ static inline bool umul64_overflow(uint64_t x, uint64_t y, uint64_t *ret) */ static inline bool mulu128(uint64_t *plow, uint64_t *phigh, uint64_t factor) { -#if defined(CONFIG_INT128) && \ - (__has_builtin(__builtin_mul_overflow) || __GNUC__ >= 5) +#if defined(CONFIG_INT128) bool res; __uint128_t r; __uint128_t f = ((__uint128_t)*phigh << 64) | *plow; From ed021daf2d6c19499ae406055156dc19c073228f Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Wed, 3 Aug 2022 20:32:04 -0300 Subject: [PATCH 0100/1020] hw/ppc: sam460ex.c: store all GPIO lines in mal_irqs[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We're not storing all GPIO lines we're retrieving with qdev_get_gpio_in() in mal_irqs[]. We're storing just the last one in the first index: for (i = 0; i < ARRAY_SIZE(mal_irqs); i++) { mal_irqs[0] = qdev_get_gpio_in(uic[2], 3 + i); } ppc4xx_mal_init(env, 4, 16, mal_irqs); mal_irqs is used in ppc4xx_mal_init() to assign the IRQs to MAL: for (i = 0; i < 4; i++) { mal->irqs[i] = irqs[i]; } Since only irqs[0] has been initialized, mal->irqs[1,2,3] are being zeroed. This doesn´t seem to trigger any apparent issues at this moment, but Cedric's QOMification of the MAL device [1] is executing a sysbus_connect_irq() that will fail if we do not store all GPIO lines properly. [1] https://lists.gnu.org/archive/html/qemu-devel/2022-08/msg00497.html Cc: Peter Maydell Cc: BALATON Zoltan Fixes: 706e944206d7 ("hw/ppc/sam460ex: Drop use of ppcuic_init()") Acked-by: BALATON Zoltan Reviewed-by: CĂ©dric Le Goater Message-Id: <20220803233204.2724202-1-danielhb413@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/sam460ex.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 7e8da657c2..0357ee077f 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -384,7 +384,7 @@ static void sam460ex_init(MachineState *machine) /* MAL */ for (i = 0; i < ARRAY_SIZE(mal_irqs); i++) { - mal_irqs[0] = qdev_get_gpio_in(uic[2], 3 + i); + mal_irqs[i] = qdev_get_gpio_in(uic[2], 3 + i); } ppc4xx_mal_init(env, 4, 16, mal_irqs); From 7b0ca313647532a2c7007379ff800c9a2415c95d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Thu, 4 Aug 2022 09:48:33 +0200 Subject: [PATCH 0101/1020] virtiofsd: Fix format strings Signed-off-by: Stefan Weil Message-Id: <20220804074833.892604-1-sw@weilnetz.de> Signed-off-by: Stefan Hajnoczi --- tools/virtiofsd/fuse_lowlevel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/virtiofsd/fuse_lowlevel.c b/tools/virtiofsd/fuse_lowlevel.c index 752928741d..2f08471627 100644 --- a/tools/virtiofsd/fuse_lowlevel.c +++ b/tools/virtiofsd/fuse_lowlevel.c @@ -2025,7 +2025,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, fuse_log(FUSE_LOG_DEBUG, "INIT: %u.%u\n", arg->major, arg->minor); if (arg->major == 7 && arg->minor >= 6) { - fuse_log(FUSE_LOG_DEBUG, "flags=0x%016llx\n", flags); + fuse_log(FUSE_LOG_DEBUG, "flags=0x%016" PRIx64 "\n", flags); fuse_log(FUSE_LOG_DEBUG, "max_readahead=0x%08x\n", arg->max_readahead); } se->conn.proto_major = arg->major; @@ -2174,7 +2174,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, if (se->conn.want & (~se->conn.capable)) { fuse_log(FUSE_LOG_ERR, "fuse: error: filesystem requested capabilities " - "0x%llx that are not supported by kernel, aborting.\n", + "0x%" PRIx64 " that are not supported by kernel, aborting.\n", se->conn.want & (~se->conn.capable)); fuse_reply_err(req, EPROTO); se->error = -EPROTO; From fbf8c96be3eff5f4d9fa7e7f5d989c54e62dd294 Mon Sep 17 00:00:00 2001 From: Andrea Bolognani Date: Wed, 20 Apr 2022 18:03:11 +0200 Subject: [PATCH 0102/1020] docs: build-platforms: Clarify stance on minor releases and backports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These changes match those made in the following libvirt commits: 2ac78307af docs: Clarify our stance on backported packages 78cffd450a docs: Spell out our policy concerning minor releases Since QEMU's platform support policy is based on libvirt's, it makes sense to mirror these recent changes made to the latter. The policy is not altered significantly - we're simply spelling out some rules that were likely already being implicitly enforced. Signed-off-by: Andrea Bolognani Signed-off-by: Daniel P. BerrangĂ© --- docs/about/build-platforms.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/about/build-platforms.rst b/docs/about/build-platforms.rst index 6b8496c430..26028756d0 100644 --- a/docs/about/build-platforms.rst +++ b/docs/about/build-platforms.rst @@ -71,7 +71,10 @@ The project aims to support the most recent major version at all times. Support for the previous major version will be dropped 2 years after the new major version is released or when the vendor itself drops support, whichever comes first. In this context, third-party efforts to extend the lifetime of a distro -are not considered, even when they are endorsed by the vendor (eg. Debian LTS). +are not considered, even when they are endorsed by the vendor (eg. Debian LTS); +the same is true of repositories that contain packages backported from later +releases (e.g. Debian backports). Within each major release, only the most +recent minor release is considered. For the purposes of identifying supported software versions available on Linux, the project will look at CentOS, Debian, Fedora, openSUSE, RHEL, SLES and From 5258a7e2c0677d16e9e1d06845f60171adf0b290 Mon Sep 17 00:00:00 2001 From: Leonardo Bras Date: Thu, 4 Aug 2022 04:10:43 -0300 Subject: [PATCH 0103/1020] QIOChannelSocket: Add support for MSG_ZEROCOPY + IPV6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For using MSG_ZEROCOPY, there are two steps: 1 - io_writev() the packet, which enqueues the packet for sending, and 2 - io_flush(), which gets confirmation that all packets got correctly sent Currently, if MSG_ZEROCOPY is used to send packets over IPV6, no error will be reported in (1), but it will fail in the first time (2) happens. This happens because (2) currently checks for cmsg_level & cmsg_type associated with IPV4 only, before reporting any error. Add checks for cmsg_level & cmsg_type associated with IPV6, and thus enable support for MSG_ZEROCOPY + IPV6 Fixes: 2bc58ffc29 ("QIOChannelSocket: Implement io_writev zero copy flag & io_flush for CONFIG_LINUX") Signed-off-by: Leonardo Bras Signed-off-by: Daniel P. BerrangĂ© --- io/channel-socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/io/channel-socket.c b/io/channel-socket.c index 74a936cc1f..b76dca9cc1 100644 --- a/io/channel-socket.c +++ b/io/channel-socket.c @@ -746,8 +746,8 @@ static int qio_channel_socket_flush(QIOChannel *ioc, } cm = CMSG_FIRSTHDR(&msg); - if (cm->cmsg_level != SOL_IP && - cm->cmsg_type != IP_RECVERR) { + if (cm->cmsg_level != SOL_IP && cm->cmsg_type != IP_RECVERR && + cm->cmsg_level != SOL_IPV6 && cm->cmsg_type != IPV6_RECVERR) { error_setg_errno(errp, EPROTOTYPE, "Wrong cmsg in errqueue"); return -1; From 5dfa9e8689d08c529bf772fc199597efa947fa27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 24 May 2022 15:44:55 +0100 Subject: [PATCH 0104/1020] target/i386: display deprecation status in '-cpu help' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the user queries CPU models via QMP there is a 'deprecated' flag present, however, this is not done for the CLI '-cpu help' command. Reviewed-by: Cornelia Huck Signed-off-by: Daniel P. BerrangĂ© --- target/i386/cpu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 194b5a31af..1db1278a59 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -4837,6 +4837,11 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data) desc = g_strdup_printf("%s", model_id); } + if (cc->model && cc->model->cpudef->deprecation_note) { + g_autofree char *olddesc = desc; + desc = g_strdup_printf("%s (deprecated)", olddesc); + } + qemu_printf("x86 %-20s %s\n", name, desc); } From 738cdc2f6ea1ce22bb3f2a4e0fc84fc8121896fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 24 May 2022 15:44:55 +0100 Subject: [PATCH 0105/1020] target/s390x: display deprecation status in '-cpu help' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the user queries CPU models via QMP there is a 'deprecated' flag present, however, this is not done for the CLI '-cpu help' command. Reviewed-by: Cornelia Huck Signed-off-by: Daniel P. BerrangĂ© --- target/s390x/cpu_models.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c index 1a562d2801..c3a4f80633 100644 --- a/target/s390x/cpu_models.c +++ b/target/s390x/cpu_models.c @@ -334,18 +334,31 @@ const S390CPUDef *s390_find_cpu_def(uint16_t type, uint8_t gen, uint8_t ec_ga, static void s390_print_cpu_model_list_entry(gpointer data, gpointer user_data) { const S390CPUClass *scc = S390_CPU_CLASS((ObjectClass *)data); + CPUClass *cc = CPU_CLASS(scc); char *name = g_strdup(object_class_get_name((ObjectClass *)data)); - const char *details = ""; + g_autoptr(GString) details = g_string_new(""); if (scc->is_static) { - details = "(static, migration-safe)"; - } else if (scc->is_migration_safe) { - details = "(migration-safe)"; + g_string_append(details, "static, "); + } + if (scc->is_migration_safe) { + g_string_append(details, "migration-safe, "); + } + if (cc->deprecation_note) { + g_string_append(details, "deprecated, "); + } + if (details->len) { + /* cull trailing ', ' */ + g_string_truncate(details, details->len - 2); } /* strip off the -s390x-cpu */ g_strrstr(name, "-" TYPE_S390_CPU)[0] = 0; - qemu_printf("s390 %-15s %-35s %s\n", name, scc->desc, details); + if (details->len) { + qemu_printf("s390 %-15s %-35s (%s)\n", name, scc->desc, details->str); + } else { + qemu_printf("s390 %-15s %-35s\n", name, scc->desc); + } g_free(name); } From 977c33ba5de58c9c5c857979516cb896db2c0969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 24 May 2022 15:44:55 +0100 Subject: [PATCH 0106/1020] target/arm: display deprecation status in '-cpu help' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the user queries CPU models via QMP there is a 'deprecated' flag present, however, this is not done for the CLI '-cpu help' command. Reviewed-by: Cornelia Huck Signed-off-by: Daniel P. BerrangĂ© --- target/arm/helper.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index e1bdc80c35..d7bc467a2a 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -8185,12 +8185,17 @@ static gint arm_cpu_list_compare(gconstpointer a, gconstpointer b) static void arm_cpu_list_entry(gpointer data, gpointer user_data) { ObjectClass *oc = data; + CPUClass *cc = CPU_CLASS(oc); const char *typename; char *name; typename = object_class_get_name(oc); name = g_strndup(typename, strlen(typename) - strlen("-" TYPE_ARM_CPU)); - qemu_printf(" %s\n", name); + if (cc->deprecation_note) { + qemu_printf(" %s (deprecated)\n", name); + } else { + qemu_printf(" %s\n", name); + } g_free(name); } From e3fdb13e8851be570db41a50589ce82d11d61c12 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 2 Aug 2022 15:51:57 +0800 Subject: [PATCH 0107/1020] util/qemu-sockets: Replace the call to close a socket with closesocket() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close() is a *nix function. It works on any file descriptor, and sockets in *nix are an example of a file descriptor. closesocket() is a Windows-specific function, which works only specifically with sockets. Sockets on Windows do not use *nix-style file descriptors, and socket() returns a handle to a kernel object instead, so it must be closed with closesocket(). In QEMU there is already a logic to handle such platform difference in os-posix.h and os-win32.h, that: * closesocket maps to close on POSIX * closesocket maps to a wrapper that calls the real closesocket() on Windows Replace the call to close a socket with closesocket() instead. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Daniel P. BerrangĂ© --- util/qemu-sockets.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 13b5b197f9..0e2298278f 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -487,7 +487,7 @@ int inet_connect_saddr(InetSocketAddress *saddr, Error **errp) if (ret < 0) { error_setg_errno(errp, errno, "Unable to set KEEPALIVE"); - close(sock); + closesocket(sock); return -1; } } @@ -1050,7 +1050,7 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) return sock; err: - close(sock); + closesocket(sock); return -1; } From 00952d93e0ad3aaba3886803c812549626ac214a Mon Sep 17 00:00:00 2001 From: Qi Hu Date: Thu, 4 Aug 2022 21:24:50 +0800 Subject: [PATCH 0108/1020] target/loongarch: Fix macros SET_FPU_* in cpu.h The macros SET_FPU_* are used to set corresponding bits of fcsr. Unfortunately it forgets to set the result and it causes fcsr's "CAUSE" never being updated. This patch is to fix this bug. Signed-off-by: Qi Hu Reviewed-by: Song Gao Message-Id: <20220804132450.314329-1-huqi@loongson.cn> Signed-off-by: Richard Henderson --- target/loongarch/cpu.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index a36349df83..dce999aaac 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -47,11 +47,23 @@ FIELD(FCSR0, FLAGS, 16, 5) FIELD(FCSR0, CAUSE, 24, 5) #define GET_FP_CAUSE(REG) FIELD_EX32(REG, FCSR0, CAUSE) -#define SET_FP_CAUSE(REG, V) FIELD_DP32(REG, FCSR0, CAUSE, V) +#define SET_FP_CAUSE(REG, V) \ + do { \ + (REG) = FIELD_DP32(REG, FCSR0, CAUSE, V); \ + } while (0) + #define GET_FP_ENABLES(REG) FIELD_EX32(REG, FCSR0, ENABLES) -#define SET_FP_ENABLES(REG, V) FIELD_DP32(REG, FCSR0, ENABLES, V) +#define SET_FP_ENABLES(REG, V) \ + do { \ + (REG) = FIELD_DP32(REG, FCSR0, ENABLES, V); \ + } while (0) + #define GET_FP_FLAGS(REG) FIELD_EX32(REG, FCSR0, FLAGS) -#define SET_FP_FLAGS(REG, V) FIELD_DP32(REG, FCSR0, FLAGS, V) +#define SET_FP_FLAGS(REG, V) \ + do { \ + (REG) = FIELD_DP32(REG, FCSR0, FLAGS, V); \ + } while (0) + #define UPDATE_FP_FLAGS(REG, V) \ do { \ (REG) |= FIELD_DP32(0, FCSR0, FLAGS, V); \ From 4cbadc40b99801488bf8d5153d56ae751af15ab9 Mon Sep 17 00:00:00 2001 From: Song Gao Date: Thu, 21 Jul 2022 12:00:46 +0800 Subject: [PATCH 0109/1020] hw/loongarch: remove acpi-build.c unused variable 'aml_len' Fix a compiler warning on openbsd: ../src/hw/loongarch/acpi-build.c:416:12: warning: variable 'aml_len' set but not used [-Wunused-but-set-variable] size_t aml_len = 0; ^ Reported-by: Peter Maydell Signed-off-by: Song Gao Reviewed-by: Richard Henderson Message-Id: <20220721040046.3985609-1-gaosong@loongson.cn> [rth: Removing aml_len in turn makes fadt set but not used.] Signed-off-by: Richard Henderson --- hw/loongarch/acpi-build.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index 4b4529a3fb..d0f01a6485 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -411,9 +411,8 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine) LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); GArray *table_offsets; AcpiFadtData fadt_data; - unsigned facs, rsdt, fadt, dsdt; + unsigned facs, rsdt, dsdt; uint8_t *u; - size_t aml_len = 0; GArray *tables_blob = tables->table_data; init_common_fadt_data(&fadt_data); @@ -437,21 +436,13 @@ static void acpi_build(AcpiBuildTables *tables, MachineState *machine) dsdt = tables_blob->len; build_dsdt(tables_blob, tables->linker, machine); - /* - * Count the size of the DSDT, we will need it for - * legacy sizing of ACPI tables. - */ - aml_len += tables_blob->len - dsdt; - /* ACPI tables pointed to by RSDT */ - fadt = tables_blob->len; acpi_add_table(table_offsets, tables_blob); fadt_data.facs_tbl_offset = &facs; fadt_data.dsdt_tbl_offset = &dsdt; fadt_data.xdsdt_tbl_offset = &dsdt; build_fadt(tables_blob, tables->linker, &fadt_data, lams->oem_id, lams->oem_table_id); - aml_len += tables_blob->len - fadt; acpi_add_table(table_offsets, tables_blob); build_madt(tables_blob, tables->linker, lams); From 1fe8ac3511fc771376019c6bfe77f317c5e56cd6 Mon Sep 17 00:00:00 2001 From: Song Gao Date: Fri, 5 Aug 2022 11:35:19 +0800 Subject: [PATCH 0110/1020] target/loongarch: Fix GDB get the wrong pc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GDB LoongArch add a register orig_a0, see the base64.xml [1]. We should add the orig_a0 to match the upstream GDB. [1]: https://github.com/bminor/binutils-gdb/blob/master/gdb/features/loongarch/base64.xml Signed-off-by: Song Gao Reviewed-by: Richard Henderson Acked-by: Alex BennĂ©e Message-Id: <20220805033523.1416837-2-gaosong@loongson.cn> --- gdb-xml/loongarch-base64.xml | 1 + target/loongarch/cpu.c | 2 +- target/loongarch/gdbstub.c | 7 +++++-- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/gdb-xml/loongarch-base64.xml b/gdb-xml/loongarch-base64.xml index 4962bdbd28..a1dd4f2208 100644 --- a/gdb-xml/loongarch-base64.xml +++ b/gdb-xml/loongarch-base64.xml @@ -39,6 +39,7 @@ + diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 1c69a76f2b..d84ec38cf7 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -683,7 +683,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data) cc->gdb_read_register = loongarch_cpu_gdb_read_register; cc->gdb_write_register = loongarch_cpu_gdb_write_register; cc->disas_set_info = loongarch_cpu_disas_set_info; - cc->gdb_num_core_regs = 34; + cc->gdb_num_core_regs = 35; cc->gdb_core_xml_file = "loongarch-base64.xml"; cc->gdb_stop_before_watchpoint = true; diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c index 24e126fb2d..5feb43445f 100644 --- a/target/loongarch/gdbstub.c +++ b/target/loongarch/gdbstub.c @@ -19,8 +19,11 @@ int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) if (0 <= n && n < 32) { return gdb_get_regl(mem_buf, env->gpr[n]); } else if (n == 32) { - return gdb_get_regl(mem_buf, env->pc); + /* orig_a0 */ + return gdb_get_regl(mem_buf, 0); } else if (n == 33) { + return gdb_get_regl(mem_buf, env->pc); + } else if (n == 34) { return gdb_get_regl(mem_buf, env->CSR_BADV); } return 0; @@ -36,7 +39,7 @@ int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) if (0 <= n && n < 32) { env->gpr[n] = tmp; length = sizeof(target_ulong); - } else if (n == 32) { + } else if (n == 33) { env->pc = tmp; length = sizeof(target_ulong); } From cd8ef0ed3b20068ed170b6c30999ce8f948fec35 Mon Sep 17 00:00:00 2001 From: Song Gao Date: Fri, 5 Aug 2022 11:35:20 +0800 Subject: [PATCH 0111/1020] target/loongarch: add gdb_arch_name() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Matches bfd/cpu-loongarch.c, bfd_loongarch_arch. Reviewed-by: Richard Henderson Signed-off-by: Song Gao Acked-by: Alex BennĂ©e Message-Id: <20220805033523.1416837-3-gaosong@loongson.cn> --- target/loongarch/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index d84ec38cf7..941e2772bc 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -661,6 +661,11 @@ static const struct SysemuCPUOps loongarch_sysemu_ops = { }; #endif +static gchar *loongarch_gdb_arch_name(CPUState *cs) +{ + return g_strdup("loongarch64"); +} + static void loongarch_cpu_class_init(ObjectClass *c, void *data) { LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c); @@ -686,6 +691,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data) cc->gdb_num_core_regs = 35; cc->gdb_core_xml_file = "loongarch-base64.xml"; cc->gdb_stop_before_watchpoint = true; + cc->gdb_arch_name = loongarch_gdb_arch_name; #ifdef CONFIG_TCG cc->tcg_ops = &loongarch_tcg_ops; From 96c3298c0ad11a51c34b253e15abe9f4275e9c57 Mon Sep 17 00:00:00 2001 From: Song Gao Date: Fri, 5 Aug 2022 11:35:21 +0800 Subject: [PATCH 0112/1020] target/loongarch: update loongarch-base64.xml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update loongarch-base64.xml to match the upstream GDB [1]. [1]:https://github.com/bminor/binutils-gdb/blob/master/gdb/features/loongarch/base64.xml Reviewed-by: Richard Henderson Signed-off-by: Song Gao Acked-by: Alex BennĂ©e Message-Id: <20220805033523.1416837-4-gaosong@loongson.cn> --- gdb-xml/loongarch-base64.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gdb-xml/loongarch-base64.xml b/gdb-xml/loongarch-base64.xml index a1dd4f2208..2d8a1f6b73 100644 --- a/gdb-xml/loongarch-base64.xml +++ b/gdb-xml/loongarch-base64.xml @@ -1,5 +1,5 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb-xml/loongarch-fpu64.xml b/gdb-xml/loongarch-fpu64.xml deleted file mode 100644 index e52cf89fbc..0000000000 --- a/gdb-xml/loongarch-fpu64.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c index 5feb43445f..d3a5e404b0 100644 --- a/target/loongarch/gdbstub.c +++ b/target/loongarch/gdbstub.c @@ -80,5 +80,5 @@ static int loongarch_gdb_set_fpu(CPULoongArchState *env, void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs) { gdb_register_coprocessor(cs, loongarch_gdb_get_fpu, loongarch_gdb_set_fpu, - 41, "loongarch-fpu64.xml", 0); + 41, "loongarch-fpu.xml", 0); } From 2f149c759ff352399e7a0eca25a62388822d7d13 Mon Sep 17 00:00:00 2001 From: Song Gao Date: Fri, 5 Aug 2022 11:35:23 +0800 Subject: [PATCH 0114/1020] target/loongarch: Update gdb_set_fpu() and gdb_get_fpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GDB LoongArch fpu use fcc register, update gdb_set_fpu() and gdb_get_fpu() to match it. Signed-off-by: Song Gao Reviewed-by: Richard Henderson Acked-by: Alex BennĂ©e Message-Id: <20220805033523.1416837-6-gaosong@loongson.cn> --- linux-user/loongarch64/signal.c | 24 ++--------------------- target/loongarch/gdbstub.c | 34 ++++++++++++++++++++++++++------- target/loongarch/internals.h | 3 +++ 3 files changed, 32 insertions(+), 29 deletions(-) diff --git a/linux-user/loongarch64/signal.c b/linux-user/loongarch64/signal.c index 65fd5f3857..7c7afb652e 100644 --- a/linux-user/loongarch64/signal.c +++ b/linux-user/loongarch64/signal.c @@ -71,26 +71,6 @@ struct extctx_layout { struct ctx_layout end; }; -/* The kernel's sc_save_fcc macro is a sequence of MOVCF2GR+BSTRINS. */ -static uint64_t read_all_fcc(CPULoongArchState *env) -{ - uint64_t ret = 0; - - for (int i = 0; i < 8; ++i) { - ret |= (uint64_t)env->cf[i] << (i * 8); - } - - return ret; -} - -/* The kernel's sc_restore_fcc macro is a sequence of BSTRPICK+MOVGR2CF. */ -static void write_all_fcc(CPULoongArchState *env, uint64_t val) -{ - for (int i = 0; i < 8; ++i) { - env->cf[i] = (val >> (i * 8)) & 1; - } -} - static abi_ptr extframe_alloc(struct extctx_layout *extctx, struct ctx_layout *sctx, unsigned size, unsigned align, abi_ptr orig_sp) @@ -150,7 +130,7 @@ static void setup_sigframe(CPULoongArchState *env, for (i = 0; i < 32; ++i) { __put_user(env->fpr[i], &fpu_ctx->regs[i]); } - __put_user(read_all_fcc(env), &fpu_ctx->fcc); + __put_user(read_fcc(env), &fpu_ctx->fcc); __put_user(env->fcsr0, &fpu_ctx->fcsr); /* @@ -216,7 +196,7 @@ static void restore_sigframe(CPULoongArchState *env, __get_user(env->fpr[i], &fpu_ctx->regs[i]); } __get_user(fcc, &fpu_ctx->fcc); - write_all_fcc(env, fcc); + write_fcc(env, fcc); __get_user(env->fcsr0, &fpu_ctx->fcsr); restore_fp_status(env); } diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c index d3a5e404b0..a4d1e28e36 100644 --- a/target/loongarch/gdbstub.c +++ b/target/loongarch/gdbstub.c @@ -11,6 +11,24 @@ #include "internals.h" #include "exec/gdbstub.h" +uint64_t read_fcc(CPULoongArchState *env) +{ + uint64_t ret = 0; + + for (int i = 0; i < 8; ++i) { + ret |= (uint64_t)env->cf[i] << (i * 8); + } + + return ret; +} + +void write_fcc(CPULoongArchState *env, uint64_t val) +{ + for (int i = 0; i < 8; ++i) { + env->cf[i] = (val >> (i * 8)) & 1; + } +} + int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) { LoongArchCPU *cpu = LOONGARCH_CPU(cs); @@ -51,9 +69,10 @@ static int loongarch_gdb_get_fpu(CPULoongArchState *env, { if (0 <= n && n < 32) { return gdb_get_reg64(mem_buf, env->fpr[n]); - } else if (32 <= n && n < 40) { - return gdb_get_reg8(mem_buf, env->cf[n - 32]); - } else if (n == 40) { + } else if (n == 32) { + uint64_t val = read_fcc(env); + return gdb_get_reg64(mem_buf, val); + } else if (n == 33) { return gdb_get_reg32(mem_buf, env->fcsr0); } return 0; @@ -67,10 +86,11 @@ static int loongarch_gdb_set_fpu(CPULoongArchState *env, if (0 <= n && n < 32) { env->fpr[n] = ldq_p(mem_buf); length = 8; - } else if (32 <= n && n < 40) { - env->cf[n - 32] = ldub_p(mem_buf); - length = 1; - } else if (n == 40) { + } else if (n == 32) { + uint64_t val = ldq_p(mem_buf); + write_fcc(env, val); + length = 8; + } else if (n == 33) { env->fcsr0 = ldl_p(mem_buf); length = 4; } diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h index ea227362b6..f01635aed6 100644 --- a/target/loongarch/internals.h +++ b/target/loongarch/internals.h @@ -51,6 +51,9 @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size, hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr); #endif /* !CONFIG_USER_ONLY */ +uint64_t read_fcc(CPULoongArchState *env); +void write_fcc(CPULoongArchState *env, uint64_t val); + int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n); int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n); void loongarch_cpu_register_gdb_regs_for_features(CPUState *cs); From 393296de19650e1400ca265914cfdeb313725363 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 5 Aug 2022 11:42:14 +0200 Subject: [PATCH 0115/1020] pc-bios/s390-ccw: Fix booting with logical block size < physical block size For accessing single blocks during boot, it's the logical block size that matters. (Physical block sizes are rather interesting e.g. for creating file systems with the correct alignment for speed reasons etc.). So the s390-ccw bios has to use the logical block size for calculating sector numbers during the boot phase, the "physical_block_exp" shift value must not be taken into account. This change fixes the boot process when the guest hast been installed on a disk where the logical block size differs from the physical one, e.g. if the guest has been installed like this: qemu-system-s390x -nographic -accel kvm -m 2G \ -drive if=none,id=d1,file=fedora.iso,format=raw,media=cdrom \ -device virtio-scsi -device scsi-cd,drive=d1 \ -drive if=none,id=d2,file=test.qcow2,format=qcow2 -device virtio-blk,drive=d2,physical_block_size=4096,logical_block_size=512 Linux correctly uses the logical block size of 512 for the installation, but the s390-ccw bios tries to boot from a disk with 4096 block size so far, as long as this patch has not been applied yet (well, it used to work by accident in the past due to the virtio_assume_scsi() hack that used to enforce 512 byte sectors on all virtio-block disks, but that hack has been well removed in commit 5447de2619050a0a4d to fix other scenarios). Fixes: 5447de2619 ("pc-bios/s390-ccw/virtio-blkdev: Remove virtio_assume_scsi()") Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2112303 Message-Id: <20220805094214.285223-1-thuth@redhat.com> Reviewed-by: Cornelia Huck Reviewed-by: Eric Farman Signed-off-by: Thomas Huth --- pc-bios/s390-ccw/virtio-blkdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/s390-ccw/virtio-blkdev.c b/pc-bios/s390-ccw/virtio-blkdev.c index 8271c47296..794f99b42c 100644 --- a/pc-bios/s390-ccw/virtio-blkdev.c +++ b/pc-bios/s390-ccw/virtio-blkdev.c @@ -173,7 +173,7 @@ int virtio_get_block_size(void) switch (vdev->senseid.cu_model) { case VIRTIO_ID_BLOCK: - return vdev->config.blk.blk_size << vdev->config.blk.physical_block_exp; + return vdev->config.blk.blk_size; case VIRTIO_ID_SCSI: return vdev->scsi_block_size; } From c3dd58ba6e0123806ef45e447eeee881203cd6ec Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Sun, 7 Aug 2022 18:22:35 +0200 Subject: [PATCH 0116/1020] pc-bios/s390-ccw: Update the s390-ccw.img with the block size fix The new binary now gets the block size of virtio-blk devices right. Signed-off-by: Thomas Huth --- pc-bios/s390-ccw.img | Bin 42608 -> 42608 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/pc-bios/s390-ccw.img b/pc-bios/s390-ccw.img index 39f9680a0ef1c57f8a0bac9e12ff77ce15150d37..554fcbd1b7af8ea5f8f0d887fba98d52b7a8611d 100644 GIT binary patch delta 4206 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 Date: Tue, 2 Aug 2022 13:36:06 +0300 Subject: [PATCH 0117/1020] tests/avocado: fix replay-linux test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Last line of the test is missing by accident. This patch fixes the script. Signed-off-by: Pavel Dovgalyuk Message-Id: <165943656662.362178.2086588841425038338.stgit@pasha-ThinkPad-X280> Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Thomas Huth --- tests/avocado/replay_linux.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/avocado/replay_linux.py b/tests/avocado/replay_linux.py index 40e4f6908e..e1f9981a34 100644 --- a/tests/avocado/replay_linux.py +++ b/tests/avocado/replay_linux.py @@ -189,3 +189,4 @@ class ReplayLinuxAarch64(ReplayLinux): self.run_rr(shift=3, args=(*self.get_common_args(), + "-machine", "virt,gic-version=3")) From 407634970dc5dba9330c360cfdc4e69e7aea3b37 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 2 Aug 2022 14:31:01 +0200 Subject: [PATCH 0118/1020] tests/qemu-iotests/264: Allow up to 5s for the BLOCK_JOB_CANCEL event to arrive It is possible to hit the assertTrue(delta_t < 2.0) on very loaded systems. Increase the value to 5.0 to ease the situation a little bit. Message-Id: <20220802123101.430757-1-thuth@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Thomas Huth --- tests/qemu-iotests/264 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qemu-iotests/264 b/tests/qemu-iotests/264 index bc431d1a19..289381e315 100755 --- a/tests/qemu-iotests/264 +++ b/tests/qemu-iotests/264 @@ -101,7 +101,7 @@ class TestNbdReconnect(iotests.QMPTestCase): start_t = time.time() self.vm.event_wait('BLOCK_JOB_CANCELLED') delta_t = time.time() - start_t - self.assertTrue(delta_t < 2.0) + self.assertTrue(delta_t < 5.0) def test_mirror_cancel(self): # Mirror speed limit doesn't work well enough, it seems that mirror From a32086de4919b9affb2ab2d0112d400eaf89f607 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 30 Jun 2022 10:52:19 +0200 Subject: [PATCH 0119/1020] contrib/vhost-user-blk: Clean up deallocation of VuVirtqElement We allocate VuVirtqElement with g_malloc() in virtqueue_alloc_element(), but free it with free() in vhost-user-blk.c. Harmless, but use g_free() anyway. One of the calls is guarded by a "not null" condition. Useless, because it cannot be null (it's dereferenced right before), and even it it could be, free() and g_free() do the right thing. Drop the conditional. Fixes: Coverity CID 1490290 Signed-off-by: Markus Armbruster Reviewed-by: Raphael Norwitz Acked-by: Michael S. Tsirkin Message-Id: <20220630085219.1305519-1-armbru@redhat.com> Signed-off-by: Laurent Vivier --- contrib/vhost-user-blk/vhost-user-blk.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/contrib/vhost-user-blk/vhost-user-blk.c b/contrib/vhost-user-blk/vhost-user-blk.c index 9cb78ca1d0..d6932a2645 100644 --- a/contrib/vhost-user-blk/vhost-user-blk.c +++ b/contrib/vhost-user-blk/vhost-user-blk.c @@ -106,10 +106,7 @@ static void vub_req_complete(VubReq *req) req->size + 1); vu_queue_notify(vu_dev, req->vq); - if (req->elem) { - free(req->elem); - } - + g_free(req->elem); g_free(req); } @@ -243,7 +240,7 @@ static int vub_virtio_process_req(VubDev *vdev_blk, /* refer to hw/block/virtio_blk.c */ if (elem->out_num < 1 || elem->in_num < 1) { fprintf(stderr, "virtio-blk request missing headers\n"); - free(elem); + g_free(elem); return -1; } @@ -325,7 +322,7 @@ static int vub_virtio_process_req(VubDev *vdev_blk, return 0; err: - free(elem); + g_free(elem); g_free(req); return -1; } From 9390da5ef29a5e0f98e5b482dceeeb287c452f17 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Mon, 8 Aug 2022 16:01:16 +0800 Subject: [PATCH 0120/1020] xlnx_dp: drop unsupported AUXCommand in xlnx_dp_aux_set_command In xlnx_dp_aux_set_command, when the command leads to the default branch, xlxn-dp will abort and then crash. This patch removes this abort and drops this operation. Fixes: 58ac482 ("introduce xlnx-dp") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/411 Reported-by: Qiang Liu Tested-by: Qiang Liu Suggested-by: Thomas Huth Signed-off-by: Qiang Liu Reviewed-by: Thomas Huth Reviewed-by: Frederic Konrad Message-Id: <20220808080116.2184881-1-cyruscyliu@gmail.com> Signed-off-by: Laurent Vivier --- hw/display/xlnx_dp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c index a071c81883..b0828d65aa 100644 --- a/hw/display/xlnx_dp.c +++ b/hw/display/xlnx_dp.c @@ -532,8 +532,8 @@ static void xlnx_dp_aux_set_command(XlnxDPState *s, uint32_t value) qemu_log_mask(LOG_UNIMP, "xlnx_dp: Write i2c status not implemented\n"); break; default: - error_report("%s: invalid command: %u", __func__, cmd); - abort(); + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid command: %u", __func__, cmd); + return; } s->core_registers[DP_INTERRUPT_SIGNAL_STATE] |= 0x04; From e12f0685e8f6ee57a00d3f304023665aa0e02b8c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 5 Aug 2022 12:01:51 +0200 Subject: [PATCH 0121/1020] vl: fix [memory] section with -readconfig The -M memory.* options do not have magic applied to them like the -m option, namely no "M" (for mebibytes) is tacked at the end of a suffixless value for "-M memory.size". This magic is performed by parse_memory_options, and we have to do it for both "-m" and the [memory] section of a config file. Storing [memory] sections directly to machine_opts_dict changed the meaning of [memory] size = "1024" in a -readconfig file from 1024MiB to 8KiB (1024 Bytes rounded up to 8KiB silently). To avoid this, the [memory] section has to be changed back to QemuOpts (combining [memory] and "-m" will work fine thanks to .merge_lists being true). Change parse_memory_options() so that, similar to the older function set_memory_options(), it operates after command line parsing is done; and also call it where set_memory_options() used to be. Note, the parsing code uses exit(1) instead of exit(EXIT_FAILURE) to match neighboring code. Reported-by: Markus Armbruster Reviewed-by: Markus Armbruster Fixes: ce9d03fb3f ("machine: add mem compound property", 2022-05-12) Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index aabd82e09a..45e919de9f 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1947,16 +1947,15 @@ static void qemu_resolve_machine_memdev(void) } } -static void parse_memory_options(const char *arg) +static void parse_memory_options(void) { - QemuOpts *opts; + QemuOpts *opts = qemu_find_opts_singleton("memory"); QDict *dict, *prop; const char *mem_str; + Location loc; - opts = qemu_opts_parse_noisily(qemu_find_opts("memory"), arg, true); - if (!opts) { - exit(EXIT_FAILURE); - } + loc_push_none(&loc); + qemu_opts_loc_restore(opts); prop = qdict_new(); @@ -1987,6 +1986,7 @@ static void parse_memory_options(const char *arg) qdict_put(dict, "memory", prop); keyval_merge(machine_opts_dict, dict, &error_fatal); qobject_unref(dict); + loc_pop(&loc); } static void qemu_create_machine(QDict *qdict) @@ -2053,8 +2053,7 @@ static bool is_qemuopts_group(const char *group) if (g_str_equal(group, "object") || g_str_equal(group, "machine") || g_str_equal(group, "smp-opts") || - g_str_equal(group, "boot-opts") || - g_str_equal(group, "memory")) { + g_str_equal(group, "boot-opts")) { return false; } return true; @@ -2078,8 +2077,6 @@ static void qemu_record_config_group(const char *group, QDict *dict, machine_merge_property("smp", dict, &error_fatal); } else if (g_str_equal(group, "boot-opts")) { machine_merge_property("boot", dict, &error_fatal); - } else if (g_str_equal(group, "memory")) { - machine_merge_property("memory", dict, &error_fatal); } else { abort(); } @@ -2882,7 +2879,10 @@ void qemu_init(int argc, char **argv, char **envp) exit(0); break; case QEMU_OPTION_m: - parse_memory_options(optarg); + opts = qemu_opts_parse_noisily(qemu_find_opts("memory"), optarg, true); + if (opts == NULL) { + exit(1); + } break; #ifdef CONFIG_TPM case QEMU_OPTION_tpmdev: @@ -3515,6 +3515,9 @@ void qemu_init(int argc, char **argv, char **envp) configure_rtc(qemu_find_opts_singleton("rtc")); + /* Transfer QemuOpts options into machine options */ + parse_memory_options(); + qemu_create_machine(machine_opts_dict); suspend_mux_open(); From 69c05a23787e9f5cdddbf3688c2e309a92a20af4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 5 Aug 2022 19:15:39 +0200 Subject: [PATCH 0122/1020] vl: remove dead code in parse_memory_options() mem_str will never be an empty string, because qemu_opt_get_size() fails if it encounters one: $ ./qemu-system-x86_64 -m size= qemu-system-x86_64: -m size=: Parameter size expects a non-negative number below 2^64 Optional suffix k, M, G, T, P or E means kilo-, mega-, giga-, tera-, peta- and exabytes, respectively. Suggested-by: Markus Armbruster Reviewed-by: Markus Armbruster Signed-off-by: Paolo Bonzini --- softmmu/vl.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/softmmu/vl.c b/softmmu/vl.c index 45e919de9f..706bd7cff7 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1960,13 +1960,8 @@ static void parse_memory_options(void) prop = qdict_new(); if (qemu_opt_get_size(opts, "size", 0) != 0) { - mem_str = qemu_opt_get(opts, "size"); - if (!*mem_str) { - error_report("missing 'size' option value"); - exit(EXIT_FAILURE); - } - /* Fix up legacy suffix-less format */ + mem_str = qemu_opt_get(opts, "size"); if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) { g_autofree char *mib_str = g_strdup_printf("%sM", mem_str); qdict_put_str(prop, "size", mib_str); From f6a5f380627ab2af384bf2f2940d29386dea11ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Fri, 5 Aug 2022 12:55:29 +0100 Subject: [PATCH 0123/1020] tests/qtest: add scenario for -readconfig handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This test of -readconfig validates the last three regressions we have fixed with -readconfig: * Interpretation of memory size units as MiB not bytes * Allow use of [spice] * Allow use of [object] Signed-off-by: Daniel P. BerrangĂ© Message-Id: <20220805115529.124544-2-berrange@redhat.com> Signed-off-by: Paolo Bonzini --- tests/qtest/meson.build | 1 + tests/qtest/readconfig-test.c | 195 ++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 tests/qtest/readconfig-test.c diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 3a474010e4..be4b30dea2 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -26,6 +26,7 @@ qtests_generic = [ 'qom-test', 'test-hmp', 'qos-test', + 'readconfig-test', ] if config_host.has_key('CONFIG_MODULES') qtests_generic += [ 'modules-test' ] diff --git a/tests/qtest/readconfig-test.c b/tests/qtest/readconfig-test.c new file mode 100644 index 0000000000..2e604d7c2d --- /dev/null +++ b/tests/qtest/readconfig-test.c @@ -0,0 +1,195 @@ +/* + * Validate -readconfig + * + * Copyright (c) 2022 Red Hat, Inc. + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "libqtest.h" +#include "qapi/error.h" +#include "qapi/qapi-visit-machine.h" +#include "qapi/qapi-visit-qom.h" +#include "qapi/qapi-visit-ui.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qmp/qlist.h" +#include "qapi/qobject-input-visitor.h" +#include "qapi/qmp/qstring.h" +#include "qemu/units.h" + +static QTestState *qtest_init_with_config(const char *cfgdata) +{ + GError *error = NULL; + g_autofree char *args = NULL; + int cfgfd = -1; + g_autofree char *cfgpath = NULL; + QTestState *qts; + ssize_t ret; + + cfgfd = g_file_open_tmp("readconfig-test-XXXXXX", &cfgpath, &error); + g_assert_no_error(error); + g_assert_cmpint(cfgfd, >=, 0); + + ret = qemu_write_full(cfgfd, cfgdata, strlen(cfgdata)); + if (ret < 0) { + unlink(cfgpath); + } + g_assert_cmpint(ret, ==, strlen(cfgdata)); + + close(cfgfd); + + args = g_strdup_printf("-nodefaults -machine none -readconfig %s", cfgpath); + + qts = qtest_init(args); + + unlink(cfgpath); + + return qts; +} + +static void test_x86_memdev_resp(QObject *res) +{ + Visitor *v; + g_autoptr(MemdevList) memdevs = NULL; + Memdev *memdev; + + g_assert(res); + v = qobject_input_visitor_new(res); + visit_type_MemdevList(v, NULL, &memdevs, &error_abort); + + g_assert(memdevs); + g_assert(memdevs->value); + g_assert(!memdevs->next); + + memdev = memdevs->value; + g_assert_cmpstr(memdev->id, ==, "ram"); + g_assert_cmpint(memdev->size, ==, 200 * MiB); + + visit_free(v); +} + +static void test_x86_memdev(void) +{ + QDict *resp; + QTestState *qts; + const char *cfgdata = + "[memory]\n" + "size = \"200\""; + + qts = qtest_init_with_config(cfgdata); + /* Test valid command */ + resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }"); + test_x86_memdev_resp(qdict_get(resp, "return")); + qobject_unref(resp); + + qtest_quit(qts); +} + + +#ifdef CONFIG_SPICE +static void test_spice_resp(QObject *res) +{ + Visitor *v; + g_autoptr(SpiceInfo) spice = NULL; + + g_assert(res); + v = qobject_input_visitor_new(res); + visit_type_SpiceInfo(v, "spcie", &spice, &error_abort); + + g_assert(spice); + g_assert(spice->enabled); + + visit_free(v); +} + +static void test_spice(void) +{ + QDict *resp; + QTestState *qts; + const char *cfgdata = + "[spice]\n" + "disable-ticketing = \"on\"\n" + "unix = \"on\"\n"; + + qts = qtest_init_with_config(cfgdata); + /* Test valid command */ + resp = qtest_qmp(qts, "{ 'execute': 'query-spice' }"); + test_spice_resp(qdict_get(resp, "return")); + qobject_unref(resp); + + qtest_quit(qts); +} +#endif + +static void test_object_rng_resp(QObject *res) +{ + Visitor *v; + g_autoptr(ObjectPropertyInfoList) objs = NULL; + ObjectPropertyInfoList *tmp; + ObjectPropertyInfo *obj; + bool seen_rng = false; + + g_assert(res); + v = qobject_input_visitor_new(res); + visit_type_ObjectPropertyInfoList(v, NULL, &objs, &error_abort); + + g_assert(objs); + tmp = objs; + while (tmp) { + g_assert(tmp->value); + + obj = tmp->value; + if (g_str_equal(obj->name, "rng0") && + g_str_equal(obj->type, "child")) { + seen_rng = true; + } + + tmp = tmp->next; + } + + g_assert(seen_rng); + + visit_free(v); +} + +static void test_object_rng(void) +{ + QDict *resp; + QTestState *qts; + const char *cfgdata = + "[object]\n" + "qom-type = \"rng-builtin\"\n" + "id = \"rng0\"\n"; + + qts = qtest_init_with_config(cfgdata); + /* Test valid command */ + resp = qtest_qmp(qts, + "{ 'execute': 'qom-list'," + " 'arguments': {'path': '/objects' }}"); + test_object_rng_resp(qdict_get(resp, "return")); + qobject_unref(resp); + + qtest_quit(qts); +} + +int main(int argc, char *argv[]) +{ + const char *arch; + g_test_init(&argc, &argv, NULL); + + arch = qtest_get_arch(); + + if (g_str_equal(arch, "i386") || + g_str_equal(arch, "x86_64")) { + qtest_add_func("readconfig/x86/memdev", test_x86_memdev); + } +#ifdef CONFIG_SPICE + qtest_add_func("readconfig/spice", test_spice); +#endif + + qtest_add_func("readconfig/object-rng", test_object_rng); + + return g_test_run(); +} From 8809baf4e40633ba01b47cd2257bbbbba14fc861 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 19 Jul 2022 20:17:37 +0100 Subject: [PATCH 0124/1020] target/mips: Handle lock_user() failure in UHI_plog semihosting call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverity notes that we forgot to check the error return from lock_user() in one place in the handling of the UHI_plog semihosting call. Add the missing error handling. report_fault() is rather brutal in that it will call abort(), but this is the same error-handling used in the rest of this file. Resolves: Coverity CID 1490684 Fixes: ea4210600db3c5 ("target/mips: Avoid qemu_semihosting_log_out for UHI_plog") Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220719191737.384744-1-peter.maydell@linaro.org> Signed-off-by: Philippe Mathieu-DaudĂ© --- target/mips/tcg/sysemu/mips-semi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/mips/tcg/sysemu/mips-semi.c b/target/mips/tcg/sysemu/mips-semi.c index 5fb1ad9092..85f0567a7f 100644 --- a/target/mips/tcg/sysemu/mips-semi.c +++ b/target/mips/tcg/sysemu/mips-semi.c @@ -321,6 +321,9 @@ void mips_semihosting(CPUMIPSState *env) if (use_gdb_syscalls()) { addr = gpr[29] - str->len; p = lock_user(VERIFY_WRITE, addr, str->len, 0); + if (!p) { + report_fault(env); + } memcpy(p, str->str, str->len); unlock_user(p, addr, str->len); semihost_sys_write(cs, uhi_cb, 2, addr, str->len); From bd64c210ce2bebba993ee49d34327706ec47f685 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 28 Jul 2022 07:50:34 -0400 Subject: [PATCH 0125/1020] hw/mips/malta: turn off x86 specific features of PIIX4_PM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QEMU crashes trying to save VMSTATE when only MIPS target are compiled in $ qemu-system-mips -monitor stdio (qemu) migrate "exec:gzip -c > STATEFILE.gz" Segmentation fault (core dumped) It happens due to PIIX4_PM trying to parse hotplug vmstate structures which are valid only for x86 and not for MIPS (as it requires ACPI tables support which is not existent for ithe later) Issue was probably exposed by trying to cleanup/compile out unused ACPI bits from MIPS target (but forgetting about migration bits). Disable compiled out features using compat properties as the least risky way to deal with issue. Signed-off-by: Igor Mammedov Resolves: https://gitlab.com/qemu-project/qemu/-/issues/995 Reviewed-by: Ani Sinha Acked-by: Michael S. Tsirkin Message-Id: <20220728115034.1327988-1-imammedo@redhat.com> Signed-off-by: Philippe Mathieu-DaudĂ© --- hw/mips/malta.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/mips/malta.c b/hw/mips/malta.c index 7a0ec513b0..0e932988e0 100644 --- a/hw/mips/malta.c +++ b/hw/mips/malta.c @@ -1442,6 +1442,14 @@ static const TypeInfo mips_malta_device = { .instance_init = mips_malta_instance_init, }; +GlobalProperty malta_compat[] = { + { "PIIX4_PM", "memory-hotplug-support", "off" }, + { "PIIX4_PM", "acpi-pci-hotplug-with-bridge-support", "off" }, + { "PIIX4_PM", "acpi-root-pci-hotplug", "off" }, + { "PIIX4_PM", "x-not-migrate-acpi-index", "true" }, +}; +const size_t malta_compat_len = G_N_ELEMENTS(malta_compat); + static void mips_malta_machine_init(MachineClass *mc) { mc->desc = "MIPS Malta Core LV"; @@ -1455,6 +1463,7 @@ static void mips_malta_machine_init(MachineClass *mc) mc->default_cpu_type = MIPS_CPU_TYPE_NAME("24Kf"); #endif mc->default_ram_id = "mips_malta.ram"; + compat_props_add(mc->compat_props, malta_compat, malta_compat_len); } DEFINE_MACHINE("malta", mips_malta_machine_init) From 09d12c81ec5d8dc9208e5739d17a56c34be96247 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 2 Aug 2022 14:19:25 +0100 Subject: [PATCH 0126/1020] hw/misc/grlib_ahb_apb_pnp: Support 8 and 16 bit accesses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In real hardware, the APB and AHB PNP data tables can be accessed with byte and halfword reads as well as word reads. Our implementation currently only handles word reads. Add support for the 8 and 16 bit accesses. Note that we only need to handle aligned accesses -- unaligned accesses should continue to trap, as happens on hardware. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1132 Signed-off-by: Peter Maydell Reviewed-by: Frederic Konrad Message-Id: <20220802131925.3380923-1-peter.maydell@linaro.org> Tested-by: Tomasz Martyniak Signed-off-by: Philippe Mathieu-DaudĂ© --- hw/misc/grlib_ahb_apb_pnp.c | 10 ++++++---- hw/misc/trace-events | 4 ++-- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/misc/grlib_ahb_apb_pnp.c b/hw/misc/grlib_ahb_apb_pnp.c index 43e001c3c7..5b05f15859 100644 --- a/hw/misc/grlib_ahb_apb_pnp.c +++ b/hw/misc/grlib_ahb_apb_pnp.c @@ -136,7 +136,8 @@ static uint64_t grlib_ahb_pnp_read(void *opaque, hwaddr offset, unsigned size) uint32_t val; val = ahb_pnp->regs[offset >> 2]; - trace_grlib_ahb_pnp_read(offset, val); + val = extract32(val, (4 - (offset & 3) - size) * 8, size * 8); + trace_grlib_ahb_pnp_read(offset, size, val); return val; } @@ -152,7 +153,7 @@ static const MemoryRegionOps grlib_ahb_pnp_ops = { .write = grlib_ahb_pnp_write, .endianness = DEVICE_BIG_ENDIAN, .impl = { - .min_access_size = 4, + .min_access_size = 1, .max_access_size = 4, }, }; @@ -247,7 +248,8 @@ static uint64_t grlib_apb_pnp_read(void *opaque, hwaddr offset, unsigned size) uint32_t val; val = apb_pnp->regs[offset >> 2]; - trace_grlib_apb_pnp_read(offset, val); + val = extract32(val, (4 - (offset & 3) - size) * 8, size * 8); + trace_grlib_apb_pnp_read(offset, size, val); return val; } @@ -263,7 +265,7 @@ static const MemoryRegionOps grlib_apb_pnp_ops = { .write = grlib_apb_pnp_write, .endianness = DEVICE_BIG_ENDIAN, .impl = { - .min_access_size = 4, + .min_access_size = 1, .max_access_size = 4, }, }; diff --git a/hw/misc/trace-events b/hw/misc/trace-events index 4d51a80de1..c18bc0605e 100644 --- a/hw/misc/trace-events +++ b/hw/misc/trace-events @@ -247,8 +247,8 @@ via1_adb_poll(uint8_t data, const char *vadbint, int status, int index, int size via1_auxmode(int mode) "setting auxmode to %d" # grlib_ahb_apb_pnp.c -grlib_ahb_pnp_read(uint64_t addr, uint32_t value) "AHB PnP read addr:0x%03"PRIx64" data:0x%08x" -grlib_apb_pnp_read(uint64_t addr, uint32_t value) "APB PnP read addr:0x%03"PRIx64" data:0x%08x" +grlib_ahb_pnp_read(uint64_t addr, unsigned size, uint32_t value) "AHB PnP read addr:0x%03"PRIx64" size:%u data:0x%08x" +grlib_apb_pnp_read(uint64_t addr, unsigned size, uint32_t value) "APB PnP read addr:0x%03"PRIx64" size:%u data:0x%08x" # led.c led_set_intensity(const char *color, const char *desc, uint8_t intensity_percent) "LED desc:'%s' color:%s intensity: %u%%" From 10dcb08b03863221faa41f4f1aa835cdca441b96 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 6 Aug 2022 10:04:44 -0700 Subject: [PATCH 0127/1020] target/loongarch: Remove cpu_fcsr0 All of the fpu operations are defined with TCG_CALL_NO_WG, but they all modify FCSR0. The most efficient way to fix this is to remove cpu_fcsr0, and instead use explicit load and store operations for the two instructions that manipulate that value. Acked-by: Qi Hu Reviewed-by: Song Gao Reported-by: Feiyang Chen Signed-off-by: Richard Henderson --- target/loongarch/fpu_helper.c | 4 +-- target/loongarch/helper.h | 2 +- target/loongarch/insn_trans/trans_fmov.c.inc | 33 ++++++++++---------- target/loongarch/translate.c | 3 -- tests/tcg/loongarch64/Makefile.target | 1 + tests/tcg/loongarch64/test_fcsr.c | 15 +++++++++ 6 files changed, 36 insertions(+), 22 deletions(-) create mode 100644 tests/tcg/loongarch64/test_fcsr.c diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c index bd76529219..4b9637210a 100644 --- a/target/loongarch/fpu_helper.c +++ b/target/loongarch/fpu_helper.c @@ -872,8 +872,8 @@ uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t fj) return fd; } -void helper_set_rounding_mode(CPULoongArchState *env, uint32_t fcsr0) +void helper_set_rounding_mode(CPULoongArchState *env) { - set_float_rounding_mode(ieee_rm[(fcsr0 >> FCSR0_RM) & 0x3], + set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3], &env->fp_status); } diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h index cbbe008f32..9c01823a26 100644 --- a/target/loongarch/helper.h +++ b/target/loongarch/helper.h @@ -91,7 +91,7 @@ DEF_HELPER_2(ftint_w_d, i64, env, i64) DEF_HELPER_2(frint_s, i64, env, i64) DEF_HELPER_2(frint_d, i64, env, i64) -DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32) +DEF_HELPER_FLAGS_1(set_rounding_mode, TCG_CALL_NO_RWG, void, env) DEF_HELPER_1(rdtime_d, i64, env) diff --git a/target/loongarch/insn_trans/trans_fmov.c.inc b/target/loongarch/insn_trans/trans_fmov.c.inc index 24753d4568..5537e3dd35 100644 --- a/target/loongarch/insn_trans/trans_fmov.c.inc +++ b/target/loongarch/insn_trans/trans_fmov.c.inc @@ -60,38 +60,39 @@ static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a) TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE); if (mask == UINT32_MAX) { - tcg_gen_extrl_i64_i32(cpu_fcsr0, Rj); + tcg_gen_st32_i64(Rj, cpu_env, offsetof(CPULoongArchState, fcsr0)); } else { + TCGv_i32 fcsr0 = tcg_temp_new_i32(); TCGv_i32 temp = tcg_temp_new_i32(); + tcg_gen_ld_i32(fcsr0, cpu_env, offsetof(CPULoongArchState, fcsr0)); tcg_gen_extrl_i64_i32(temp, Rj); tcg_gen_andi_i32(temp, temp, mask); - tcg_gen_andi_i32(cpu_fcsr0, cpu_fcsr0, ~mask); - tcg_gen_or_i32(cpu_fcsr0, cpu_fcsr0, temp); + tcg_gen_andi_i32(fcsr0, fcsr0, ~mask); + tcg_gen_or_i32(fcsr0, fcsr0, temp); + tcg_gen_st_i32(fcsr0, cpu_env, offsetof(CPULoongArchState, fcsr0)); + tcg_temp_free_i32(temp); - - /* - * Install the new rounding mode to fpu_status, if changed. - * Note that FCSR3 is exactly the rounding mode field. - */ - if (mask != FCSR0_M3) { - return true; - } + tcg_temp_free_i32(fcsr0); } - gen_helper_set_rounding_mode(cpu_env, cpu_fcsr0); + /* + * Install the new rounding mode to fpu_status, if changed. + * Note that FCSR3 is exactly the rounding mode field. + */ + if (mask & FCSR0_M3) { + gen_helper_set_rounding_mode(cpu_env); + } return true; } static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a) { - TCGv_i32 temp = tcg_temp_new_i32(); TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE); - tcg_gen_andi_i32(temp, cpu_fcsr0, fcsr_mask[a->fcsrs]); - tcg_gen_ext_i32_i64(dest, temp); + tcg_gen_ld32u_i64(dest, cpu_env, offsetof(CPULoongArchState, fcsr0)); + tcg_gen_andi_i64(dest, dest, fcsr_mask[a->fcsrs]); gen_set_gpr(a->rd, dest, EXT_NONE); - tcg_temp_free_i32(temp); return true; } diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index c9afd11420..51ba291430 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -22,7 +22,6 @@ /* Global register indices */ TCGv cpu_gpr[32], cpu_pc; static TCGv cpu_lladdr, cpu_llval; -TCGv_i32 cpu_fcsr0; TCGv_i64 cpu_fpr[32]; #include "exec/gen-icount.h" @@ -266,8 +265,6 @@ void loongarch_translate_init(void) } cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPULoongArchState, pc), "pc"); - cpu_fcsr0 = tcg_global_mem_new_i32(cpu_env, - offsetof(CPULoongArchState, fcsr0), "fcsr0"); cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPULoongArchState, lladdr), "lladdr"); cpu_llval = tcg_global_mem_new(cpu_env, diff --git a/tests/tcg/loongarch64/Makefile.target b/tests/tcg/loongarch64/Makefile.target index 0115de78ef..00030a1026 100644 --- a/tests/tcg/loongarch64/Makefile.target +++ b/tests/tcg/loongarch64/Makefile.target @@ -15,5 +15,6 @@ LOONGARCH64_TESTS += test_div LOONGARCH64_TESTS += test_fclass LOONGARCH64_TESTS += test_fpcom LOONGARCH64_TESTS += test_pcadd +LOONGARCH64_TESTS += test_fcsr TESTS += $(LOONGARCH64_TESTS) diff --git a/tests/tcg/loongarch64/test_fcsr.c b/tests/tcg/loongarch64/test_fcsr.c new file mode 100644 index 0000000000..ad3609eb99 --- /dev/null +++ b/tests/tcg/loongarch64/test_fcsr.c @@ -0,0 +1,15 @@ +#include + +int main() +{ + unsigned fcsr; + + asm("movgr2fcsr $r0,$r0\n\t" + "movgr2fr.d $f0,$r0\n\t" + "fdiv.d $f0,$f0,$f0\n\t" + "movfcsr2gr %0,$r0" + : "=r"(fcsr) : : "f0"); + + assert(fcsr & (16 << 16)); /* Invalid */ + return 0; +} From 7cf745dd9c25f0740dc1009598b58dd8dd989876 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 29 Jul 2022 16:59:32 +0100 Subject: [PATCH 0128/1020] hw/net/rocker: Avoid undefined shifts with more than 31 ports In rocker_port_phys_link_status() and rocker_port_phys_enable_read() we construct a 64-bit value with one bit per front-panel port. However we accidentally do the shift as 32-bit arithmetic, which means that if there are more than 31 front-panel ports this is undefined behaviour. Fix the problem by ensuring we use 64-bit arithmetic for the whole calculation. (We won't ever shift off the 64-bit value because ROCKER_FP_PORTS_MAX is 62.) Resolves: Coverity CID 1487121, 1487160 Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Signed-off-by: Jason Wang --- hw/net/rocker/rocker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index 31f2340fb9..d8f3f16fe8 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -1010,7 +1010,7 @@ static uint64_t rocker_port_phys_link_status(Rocker *r) FpPort *port = r->fp_port[i]; if (fp_port_get_link_up(port)) { - status |= 1 << (i + 1); + status |= 1ULL << (i + 1); } } return status; @@ -1025,7 +1025,7 @@ static uint64_t rocker_port_phys_enable_read(Rocker *r) FpPort *port = r->fp_port[i]; if (fp_port_enabled(port)) { - ret |= 1 << (i + 1); + ret |= 1ULL << (i + 1); } } return ret; From c7f26ded6d5065e4116f630f6a490b55f6c5f58e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 9 Aug 2022 10:55:14 +0100 Subject: [PATCH 0129/1020] icount: Take iothread lock when running QEMU timers The function icount_prepare_for_run() is called with the iothread unlocked, but it can call icount_notify_aio_contexts() which will run qemu timer handlers. Those are supposed to be run only with the iothread lock held, so take the lock while we do that. Since icount mode runs everything on a single thread anyway, not holding the lock is likely mostly not going to introduce races, but it can cause us to trip over assertions that we do hold the lock, such as the one reported in issue 1130. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1130 Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Tested-by: Pavel Dovgalyuk Message-id: 20220801164527.3134765-1-peter.maydell@linaro.org --- accel/tcg/tcg-accel-ops-icount.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/accel/tcg/tcg-accel-ops-icount.c b/accel/tcg/tcg-accel-ops-icount.c index 8f1dda4344..84cc7421be 100644 --- a/accel/tcg/tcg-accel-ops-icount.c +++ b/accel/tcg/tcg-accel-ops-icount.c @@ -109,7 +109,13 @@ void icount_prepare_for_run(CPUState *cpu) replay_mutex_lock(); if (cpu->icount_budget == 0) { + /* + * We're called without the iothread lock, so must take it while + * we're calling timer handlers. + */ + qemu_mutex_lock_iothread(); icount_notify_aio_contexts(); + qemu_mutex_unlock_iothread(); } } From 61b6e67171c602cf6451e4928c9cdcc24c57a485 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 9 Aug 2022 19:25:15 -0700 Subject: [PATCH 0130/1020] Update version for v7.1.0-rc2 release Signed-off-by: Richard Henderson --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 38bd418901..79d1c8668a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0.91 +7.0.92 From 3cd3df2a9584e6f753bb62a0028bd67124ab5532 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 2 Aug 2022 12:41:34 -0400 Subject: [PATCH 0131/1020] linux-user: fix compat with glibc >= 2.36 sys/mount.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The latest glibc 2.36 has extended sys/mount.h so that it defines the FSCONFIG_* enum constants. These are historically defined in linux/mount.h, and thus if you include both headers the compiler complains: In file included from /usr/include/linux/fs.h:19, from ../linux-user/syscall.c:98: /usr/include/linux/mount.h:95:6: error: redeclaration of 'enum fsconfig_command' 95 | enum fsconfig_command { | ^~~~~~~~~~~~~~~~ In file included from ../linux-user/syscall.c:31: /usr/include/sys/mount.h:189:6: note: originally defined here 189 | enum fsconfig_command | ^~~~~~~~~~~~~~~~ /usr/include/linux/mount.h:96:9: error: redeclaration of enumerator 'FSCONFIG_SET_FLAG' 96 | FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */ | ^~~~~~~~~~~~~~~~~ /usr/include/sys/mount.h:191:3: note: previous definition of 'FSCONFIG_SET_FLAG' with type 'enum fsconfig_command' 191 | FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */ | ^~~~~~~~~~~~~~~~~ ...snip... QEMU doesn't include linux/mount.h, but it does use linux/fs.h and thus gets linux/mount.h indirectly. glibc acknowledges this problem but does not appear to be intending to fix it in the forseeable future, simply documenting it as a known incompatibility with no workaround: https://sourceware.org/glibc/wiki/Release/2.36#Usage_of_.3Clinux.2Fmount.h.3E_and_.3Csys.2Fmount.h.3E https://sourceware.org/glibc/wiki/Synchronizing_Headers To address this requires either removing use of sys/mount.h or linux/fs.h, despite QEMU needing declarations from both. This patch removes linux/fs.h, meaning we have to define various FS_IOC constants that are now unavailable. Signed-off-by: Daniel P. BerrangĂ© Tested-by: Richard W.M. Jones Message-Id: <20220802164134.1851910-1-berrange@redhat.com> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 18 ++++++++++++++++++ meson.build | 2 ++ 2 files changed, 20 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index ef53feb5ab..f409121202 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -95,7 +95,25 @@ #include #include #include + +#ifdef HAVE_SYS_MOUNT_FSCONFIG +/* + * glibc >= 2.36 linux/mount.h conflicts with sys/mount.h, + * which in turn prevents use of linux/fs.h. So we have to + * define the constants ourselves for now. + */ +#define FS_IOC_GETFLAGS _IOR('f', 1, long) +#define FS_IOC_SETFLAGS _IOW('f', 2, long) +#define FS_IOC_GETVERSION _IOR('v', 1, long) +#define FS_IOC_SETVERSION _IOW('v', 2, long) +#define FS_IOC_FIEMAP _IOWR('f', 11, struct fiemap) +#define FS_IOC32_GETFLAGS _IOR('f', 1, int) +#define FS_IOC32_SETFLAGS _IOW('f', 2, int) +#define FS_IOC32_GETVERSION _IOR('v', 1, int) +#define FS_IOC32_SETVERSION _IOW('v', 2, int) +#else #include +#endif #include #if defined(CONFIG_FIEMAP) #include diff --git a/meson.build b/meson.build index 294e9a8f32..30a380752c 100644 --- a/meson.build +++ b/meson.build @@ -1963,6 +1963,8 @@ config_host_data.set('HAVE_OPTRESET', cc.has_header_symbol('getopt.h', 'optreset')) config_host_data.set('HAVE_IPPROTO_MPTCP', cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP')) +config_host_data.set('HAVE_SYS_MOUNT_FSCONFIG', + cc.has_header_symbol('sys/mount.h', 'FSCONFIG_SET_FLAG')) # has_member config_host_data.set('HAVE_SIGEV_NOTIFY_THREAD_ID', From dbbf89751b14aa5d281bad3af273e9ffaae82262 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Mon, 11 Jul 2022 15:00:28 -0700 Subject: [PATCH 0132/1020] linux-user/aarch64: Reset target data on MADV_DONTNEED aarch64 stores MTE tags in target_date, and they should be reset by MADV_DONTNEED. Signed-off-by: Vitaly Buka Reviewed-by: Richard Henderson Message-Id: <20220711220028.2467290-1-vitalybuka@google.com> [lv: fix code style issues] Signed-off-by: Laurent Vivier --- accel/tcg/translate-all.c | 26 ++++++++++++++++++++++++++ include/exec/cpu-all.h | 1 + linux-user/mmap.c | 3 +++ 3 files changed, 30 insertions(+) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index ef62a199c7..b83161a081 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2314,6 +2314,32 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) } } +void page_reset_target_data(target_ulong start, target_ulong end) +{ + target_ulong addr, len; + + /* + * This function should never be called with addresses outside the + * guest address space. If this assert fires, it probably indicates + * a missing call to h2g_valid. + */ + assert(end - 1 <= GUEST_ADDR_MAX); + assert(start < end); + assert_memory_lock(); + + start = start & TARGET_PAGE_MASK; + end = TARGET_PAGE_ALIGN(end); + + for (addr = start, len = end - start; + len != 0; + len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { + PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1); + + g_free(p->target_data); + p->target_data = NULL; + } +} + void *page_get_target_data(target_ulong address) { PageDesc *p = page_find(address >> TARGET_PAGE_BITS); diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index f5bda2c3ca..491629b9ba 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -271,6 +271,7 @@ int walk_memory_regions(void *, walk_memory_regions_fn); int page_get_flags(target_ulong address); void page_set_flags(target_ulong start, target_ulong end, int flags); +void page_reset_target_data(target_ulong start, target_ulong end); int page_check_range(target_ulong start, target_ulong len, int flags); /** diff --git a/linux-user/mmap.c b/linux-user/mmap.c index edceaca4a8..048c4135af 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -894,6 +894,9 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice) if (advice == MADV_DONTNEED && can_passthrough_madv_dontneed(start, end)) { ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED)); + if (ret == 0) { + page_reset_target_data(start, start + len); + } } mmap_unlock(); From 2daf518dd1312be8405b4cb094cc7a9720428609 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 11 Aug 2022 14:11:27 +0100 Subject: [PATCH 0133/1020] target/arm: Don't report Statistical Profiling Extension in ID registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The newly added neoverse-n1 CPU has ID register values which indicate the presence of the Statistical Profiling Extension, because the real hardware has this feature. QEMU's TCG emulation does not yet implement SPE, though (not even as a minimal stub implementation), so guests will crash if they try to use it because the SPE system registers don't exist. Force ID_AA64DFR0_EL1.PMSVer to 0 in CPU realize for TCG, so that we don't advertise to the guest a feature that doesn't exist. (We could alternatively do this by editing the value that aarch64_neoverse_n1_initfn() sets for this ID register, but suppressing the field in realize means we won't re-introduce this bug when we add other CPUs that have SPE in hardware, such as the Neoverse-V1.) An example of a non-booting guest is current mainline Linux (5.19), when booting in EL2 on the virt board (ie with -machine virtualization=on). Reported-by: Zenghui Yu Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Reviewed-by: Zenghui Yu Message-id: 20220811131127.947334-1-peter.maydell@linaro.org --- target/arm/cpu.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 1b7b3d76bb..7ec3281da9 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1933,6 +1933,17 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) } #endif + if (tcg_enabled()) { + /* + * Don't report the Statistical Profiling Extension in the ID + * registers, because TCG doesn't implement it yet (not even a + * minimal stub version) and guests will fall over when they + * try to access the non-existent system registers for it. + */ + cpu->isar.id_aa64dfr0 = + FIELD_DP64(cpu->isar.id_aa64dfr0, ID_AA64DFR0, PMSVER, 0); + } + /* MPU can be configured out of a PMSA CPU either by setting has-mpu * to false or by setting pmsav7-dregion to 0. */ From 120f765e0320bc3284ccaa4182674cc3c1f78a3d Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 12 Aug 2022 09:56:42 +0200 Subject: [PATCH 0134/1020] Fix some typos in documentation (most of them found by codespell) Signed-off-by: Stefan Weil Reviewed-by: Hongren (Zenithal) Zheng Message-id: 20220812075642.1200578-1-sw@weilnetz.de Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- docs/about/deprecated.rst | 2 +- docs/specs/acpi_erst.rst | 4 ++-- docs/system/devices/canokey.rst | 8 ++++---- docs/system/devices/cxl.rst | 12 ++++++------ 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 7ee26626d5..91b03115ee 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -297,7 +297,7 @@ by using ``-machine graphics=off``. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In QEMU versions 6.1, 6.2 and 7.0, the ``nvme-ns`` generates an EUI-64 -identifer that is not globally unique. If an EUI-64 identifer is required, the +identifier that is not globally unique. If an EUI-64 identifier is required, the user must set it explicitly using the ``nvme-ns`` device parameter ``eui64``. ``-device nvme,use-intel-id=on|off`` (since 7.1) diff --git a/docs/specs/acpi_erst.rst b/docs/specs/acpi_erst.rst index a8a9d22d25..2339b60ad7 100644 --- a/docs/specs/acpi_erst.rst +++ b/docs/specs/acpi_erst.rst @@ -108,7 +108,7 @@ Slot 0 contains a backend storage header that identifies the contents as ERST and also facilitates efficient access to the records. Depending upon the size of the backend storage, additional slots will be designated to be a part of the slot 0 header. For example, at 8KiB, -the slot 0 header can accomodate 1021 records. Thus a storage size +the slot 0 header can accommodate 1021 records. Thus a storage size of 8MiB (8KiB * 1024) requires an additional slot for use by the header. In this scenario, slot 0 and slot 1 form the backend storage header, and records can be stored starting at slot 2. @@ -196,5 +196,5 @@ References [2] "Unified Extensible Firmware Interface Specification", version 2.1, October 2008. -[3] "Windows Hardware Error Architecture", specfically +[3] "Windows Hardware Error Architecture", specifically "Error Record Persistence Mechanism". diff --git a/docs/system/devices/canokey.rst b/docs/system/devices/canokey.rst index c2c58ae3e7..cfa6186e48 100644 --- a/docs/system/devices/canokey.rst +++ b/docs/system/devices/canokey.rst @@ -28,9 +28,9 @@ With the same software configuration as a hardware key, the guest OS can use all the functionalities of a secure key as if there was actually an hardware key plugged in. -CanoKey QEMU provides much convenience for debuging: +CanoKey QEMU provides much convenience for debugging: -* libcanokey-qemu supports debuging output thus developers can +* libcanokey-qemu supports debugging output thus developers can inspect what happens inside a secure key * CanoKey QEMU supports trace event thus event * QEMU USB stack supports pcap thus USB packet between the guest @@ -102,8 +102,8 @@ and find CanoKey QEMU there: You may setup the key as guided in [6]_. The console for the key is at [7]_. -Debuging -======== +Debugging +========= CanoKey QEMU consists of two parts, ``libcanokey-qemu.so`` and ``canokey.c``, the latter of which resides in QEMU. The former provides core functionality diff --git a/docs/system/devices/cxl.rst b/docs/system/devices/cxl.rst index 36031325cc..f25783a4ec 100644 --- a/docs/system/devices/cxl.rst +++ b/docs/system/devices/cxl.rst @@ -83,7 +83,7 @@ CXL Fixed Memory Windows (CFMW) A CFMW consists of a particular range of Host Physical Address space which is routed to particular CXL Host Bridges. At time of generic software initialization it will have a particularly interleaving -configuration and associated Quality of Serice Throtling Group (QTG). +configuration and associated Quality of Service Throttling Group (QTG). This information is available to system software, when making decisions about how to configure interleave across available CXL memory devices. It is provide as CFMW Structures (CFMWS) in @@ -98,7 +98,7 @@ specification defined register interface called CXL Host Bridge Component Registers (CHBCR). The location of this CHBCR MMIO space is described to system software via a CXL Host Bridge Structure (CHBS) in the CEDT ACPI table. The actual interfaces -are identical to those used for other parts of the CXL heirarchy +are identical to those used for other parts of the CXL hierarchy as CXL Component Registers in PCI BARs. Interfaces provided include: @@ -143,7 +143,7 @@ CXL Memory Devices - Type 3 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ CXL type 3 devices use a PCI class code and are intended to be supported by a generic operating system driver. They have HDM decoders -though in these EP devices, the decoder is reponsible not for +though in these EP devices, the decoder is responsible not for routing but for translation of the incoming host physical address (HPA) into a Device Physical Address (DPA). @@ -209,7 +209,7 @@ Notes: ranges of the system physical address map. Each CFMW has particular interleave setup across the CXL Host Bridges (HB) CFMW0 provides uninterleaved access to HB0, CFW2 provides - uninterleaved acess to HB1. CFW1 provides interleaved memory access + uninterleaved access to HB1. CFW1 provides interleaved memory access across HB0 and HB1. (2) **Two CXL Host Bridges**. Each of these has 2 CXL Root Ports and @@ -282,7 +282,7 @@ Example topology involving a switch:: --------------------------------------------------- | Switch 0 USP as PCI 0d:00.0 | | USP has HDM decoder which direct traffic to | - | appropiate downstream port | + | appropriate downstream port | | Switch BUS appears as 0e | |x__________________________________________________| | | | | @@ -366,7 +366,7 @@ An example of 4 devices below a switch suitable for 1, 2 or 4 way interleave:: Kernel Configuration Options ---------------------------- -In Linux 5.18 the followings options are necessary to make use of +In Linux 5.18 the following options are necessary to make use of OS management of CXL memory devices as described here. * CONFIG_CXL_BUS From 6a54ac2a9737057dc19aa584d823a3011717423b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 10 Aug 2022 16:15:13 +0400 Subject: [PATCH 0135/1020] tests/unit: fix a -Wformat-truncation warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ../tests/test-qobject-input-visitor.c: In function ‘test_visitor_in_list’: ../tests/test-qobject-input-visitor.c:454:49: warning: ‘%d’ directive output may be truncated writing between 1 and 10 bytes into a region of size 6 [-Wformat-truncation=] 454 | snprintf(string, sizeof(string), "string%d", i); | ^~ ../tests/test-qobject-input-visitor.c:454:42: note: directive argument in the range [0, 2147483606] 454 | snprintf(string, sizeof(string), "string%d", i); | ^~~~~~~~~~ ../tests/test-qobject-input-visitor.c:454:9: note: ‘snprintf’ output between 8 and 17 bytes into a destination of size 12 454 | snprintf(string, sizeof(string), "string%d", i); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Rather than trying to be clever, since this is called 3 times during tests, let's simply use g_strdup_printf(). Signed-off-by: Marc-AndrĂ© Lureau Reviewed-by: Markus Armbruster Message-id: 20220810121513.1356081-1-marcandre.lureau@redhat.com Reviewed-by: Peter Maydell [PMM: fixed commit message typos] Signed-off-by: Peter Maydell --- tests/unit/test-qobject-input-visitor.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/unit/test-qobject-input-visitor.c b/tests/unit/test-qobject-input-visitor.c index 14329dabcf..5f614afdbf 100644 --- a/tests/unit/test-qobject-input-visitor.c +++ b/tests/unit/test-qobject-input-visitor.c @@ -447,9 +447,8 @@ static void test_visitor_in_list(TestInputVisitorData *data, g_assert(head != NULL); for (i = 0, item = head; item; item = item->next, i++) { - char string[12]; + g_autofree char *string = g_strdup_printf("string%d", i); - snprintf(string, sizeof(string), "string%d", i); g_assert_cmpstr(item->value->string, ==, string); g_assert_cmpint(item->value->integer, ==, 42 + i); } From e1f045780ba60bc511b5acb168b32a6a41148d73 Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Fri, 12 Aug 2022 10:20:18 +0800 Subject: [PATCH 0136/1020] hw/arm/virt-acpi-build: Present the GICR structure properly for GICv4 With the introduction of the new TCG GICv4, build_madt() is badly broken as we do not present any GIC Redistributor structure in MADT for GICv4 guests, so that they have no idea about where the Redistributor register frames are. This fixes a Linux guest crash at boot time with ACPI enabled and '-machine gic-version=4'. While at it, let's convert the remaining hard coded gic_version into enumeration VIRT_GIC_VERSION_2 for consistency. Signed-off-by: Zenghui Yu Message-id: 20220812022018.1069-1-yuzenghui@huawei.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/virt-acpi-build.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 449fab0080..9b3aee01bf 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -732,7 +732,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) uint32_t pmu_interrupt = arm_feature(&armcpu->env, ARM_FEATURE_PMU) ? PPI(VIRTUAL_PMU_IRQ) : 0; - if (vms->gic_version == 2) { + if (vms->gic_version == VIRT_GIC_VERSION_2) { physical_base_address = memmap[VIRT_GIC_CPU].base; gicv = memmap[VIRT_GIC_VCPU].base; gich = memmap[VIRT_GIC_HYP].base; @@ -762,7 +762,7 @@ build_madt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) build_append_int_noprefix(table_data, armcpu->mp_affinity, 8); } - if (vms->gic_version == 3) { + if (vms->gic_version != VIRT_GIC_VERSION_2) { build_append_gicr(table_data, memmap[VIRT_GIC_REDIST].base, memmap[VIRT_GIC_REDIST].size); if (virt_gicv3_redist_region_count(vms) == 2) { From 4311682ea8293f720730f260e8a7601117d79e65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 10 Aug 2022 00:20:46 +0200 Subject: [PATCH 0137/1020] cutils: Add missing dyld(3) include on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 06680b15b4 moved qemu_*_exec_dir() to cutils but forgot to move the macOS dyld(3) include, resulting in the following error (when building with Homebrew GCC on macOS Monterey 12.4): [313/1197] Compiling C object libqemuutil.a.p/util_cutils.c.o FAILED: libqemuutil.a.p/util_cutils.c.o ../../util/cutils.c:1039:13: error: implicit declaration of function '_NSGetExecutablePath' [-Werror=implicit-function-declaration] 1039 | if (_NSGetExecutablePath(fpath, &len) == 0) { | ^~~~~~~~~~~~~~~~~~~~ ../../util/cutils.c:1039:13: error: nested extern declaration of '_NSGetExecutablePath' [-Werror=nested-externs] Fix by moving the include line to cutils. Fixes: 06680b15b4 ("include: move qemu_*_exec_dir() to cutils") Signed-off-by: Philippe Mathieu-DaudĂ© Message-id: 20220809222046.30812-1-f4bug@amsat.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- util/cutils.c | 4 ++++ util/oslib-posix.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/util/cutils.c b/util/cutils.c index cb43dda213..def9c746ce 100644 --- a/util/cutils.c +++ b/util/cutils.c @@ -39,6 +39,10 @@ #include #endif +#ifdef __APPLE__ +#include +#endif + #ifdef G_OS_WIN32 #include #include diff --git a/util/oslib-posix.c b/util/oslib-posix.c index bffec18869..d55af69c11 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -58,10 +58,6 @@ #include #endif -#ifdef __APPLE__ -#include -#endif - #include "qemu/mmap-alloc.h" #ifdef CONFIG_DEBUG_STACK_USAGE From 1f90ce64fc6043470209f825c7763950ec2067a1 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Fri, 12 Aug 2022 17:19:57 +0800 Subject: [PATCH 0138/1020] docs/system/loongarch: Update the LoongArch document 1. Add some information about how to boot the LoongArch virt machine by uefi bios and linux kernel and how to access the source code or binary file. 2. Move the explanation of LoongArch system emulation in the target/loongarch/README to docs/system/loongarch/loongson3.rst Signed-off-by: Xiaojuan Yang Reviewed-by: Song Gao Message-Id: <20220812091957.3338126-1-yangxiaojuan@loongson.cn> Signed-off-by: Richard Henderson --- docs/system/loongarch/loongson3.rst | 104 +++++++++++++++++++++++++--- target/loongarch/README | 49 +------------ 2 files changed, 97 insertions(+), 56 deletions(-) diff --git a/docs/system/loongarch/loongson3.rst b/docs/system/loongarch/loongson3.rst index fa3acd01c0..1bdab44e27 100644 --- a/docs/system/loongarch/loongson3.rst +++ b/docs/system/loongarch/loongson3.rst @@ -15,27 +15,115 @@ The ``virt`` machine supports: - Gpex host bridge - Ls7a RTC device - Ls7a IOAPIC device -- Ls7a ACPI device +- ACPI GED device - Fw_cfg device - PCI/PCIe devices - Memory device -- CPU device. Type: Loongson-3A5000. +- CPU device. Type: la464-loongarch-cpu. CPU and machine Type -------------------- The ``qemu-system-loongarch64`` provides emulation for virt machine. You can specify the machine type ``virt`` and -cpu type ``Loongson-3A5000``. +cpu type ``la464-loongarch-cpu``. Boot options ------------ -Now the ``virt`` machine can run test program in ELF format and the -method of compiling is in target/loongarch/README. +We can boot the LoongArch virt machine by specifying the uefi bios, +initrd, and linux kernel. And those source codes and binary files +can be accessed by following steps. + +(1) booting command: .. code-block:: bash - $ qemu-system-loongarch64 -machine virt -m 4G -cpu Loongson-3A5000 \ - -smp 1 -kernel hello -monitor none -display none \ - -chardev file,path=hello.out,id=output -serial chardev:output + $ qemu-system-loongarch64 -machine virt -m 4G -cpu la464-loongarch-cpu \ + -smp 1 -bios QEMU_EFI.fd -kernel vmlinuz.efi -initrd initrd.img \ + -append "root=/dev/ram rdinit=/sbin/init consol e=ttyS0,115200" \ + --nographic + +Note: The running speed may be a little slow, as the performance of our +qemu and uefi bios is not perfect, and it is being fixed. + +(2) cross compiler tools: + +.. code-block:: bash + + wget https://github.com/loongson/build-tools/releases/download/ \ + 2022.05.29/loongarch64-clfs-5.0-cross-tools-gcc-full.tar.xz + + tar -vxf loongarch64-clfs-5.0-cross-tools-gcc-full.tar.xz + +(3) qemu compile configure option: + +.. code-block:: bash + + ./configure --disable-rdma --disable-pvrdma --prefix=usr \ + --target-list="loongarch64-softmmu" \ + --disable-libiscsi --disable-libnfs --disable-libpmem \ + --disable-glusterfs --enable-libusb --enable-usb-redir \ + --disable-opengl --disable-xen --enable-spice \ + --enable-debug --disable-capstone --disable-kvm \ + --enable-profiler + make + +(4) uefi bios source code and compile method: + +.. code-block:: bash + + git clone https://github.com/loongson/edk2-LoongarchVirt.git + + cd edk2-LoongarchVirt + + git submodule update --init + + export PATH=$YOUR_COMPILER_PATH/bin:$PATH + + export WORKSPACE=`pwd` + + export PACKAGES_PATH=$WORKSPACE/edk2-LoongarchVirt + + export GCC5_LOONGARCH64_PREFIX=loongarch64-unknown-linux-gnu- + + edk2-LoongarchVirt/edksetup.sh + + make -C edk2-LoongarchVirt/BaseTools + + build --buildtarget=DEBUG --tagname=GCC5 --arch=LOONGARCH64 --platform=OvmfPkg/LoongArchQemu/Loongson.dsc + + build --buildtarget=RELEASE --tagname=GCC5 --arch=LOONGARCH64 --platform=OvmfPkg/LoongArchQemu/Loongson.dsc + +The efi binary file path: + + Build/LoongArchQemu/DEBUG_GCC5/FV/QEMU_EFI.fd + + Build/LoongArchQemu/RELEASE_GCC5/FV/QEMU_EFI.fd + +(5) linux kernel source code and compile method: + +.. code-block:: bash + + git clone https://github.com/loongson/linux.git + + export PATH=$YOUR_COMPILER_PATH/bin:$PATH + + export LD_LIBRARY_PATH=$YOUR_COMPILER_PATH/lib:$LD_LIBRARY_PATH + + export LD_LIBRARY_PATH=$YOUR_COMPILER_PATH/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH + + make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- loongson3_defconfig + + make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- + + make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- install + + make ARCH=loongarch CROSS_COMPILE=loongarch64-unknown-linux-gnu- modules_install + +Note: The branch of linux source code is loongarch-next. + +(6) initrd file: + + You can use busybox tool and the linux modules to make a initrd file. Or you can access the + binary files: https://github.com/yangxiaojuan-loongson/qemu-binary diff --git a/target/loongarch/README b/target/loongarch/README index 1823375d04..0b9dc0d40a 100644 --- a/target/loongarch/README +++ b/target/loongarch/README @@ -11,54 +11,7 @@ - System emulation - Mainly emulate a virt 3A5000 board and ls7a bridge that is not exactly the same as the host. - 3A5000 support multiple interrupt cascading while here we just emulate the extioi interrupt - cascading. LS7A1000 host bridge support multiple devices, such as sata, gmac, uart, rtc - and so on. But we just realize the rtc. Others use the qemu common devices. It does not affect - the general use. We also introduced the emulation of devices at docs/system/loongarch/virt.rst. - - This version only supports running binary files in ELF format, and does not depend on BIOS and kernel file. - You can compile the test program with 'make & make check-tcg' and run the test case with the following command: - - 1. Install LoongArch cross-tools on X86 machines. - - Download cross-tools. - - wget https://github.com/loongson/build-tools/releases/download/2022.05.29/loongarch64-clfs-5.0-cross-tools-gcc-full.tar.xz - - tar -vxf loongarch64-clfs-5.0-cross-tools-gcc-full.tar.xz -C /opt - - Config cross-tools env. - - . setenv.sh - - setenv.sh: - - #!/bin/sh - set -x - CC_PREFIX=/opt/cross-tools - - export PATH=$CC_PREFIX/bin:$PATH - export LD_LIBRARY_PATH=$CC_PREFIX/lib:$LD_LIBRARY_PATH - export LD_LIBRARY_PATH=$CC_PREFIX/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH - set +x - - 2. Test tests/tcg/multiarch. - - ./configure --disable-rdma --disable-pvrdma --prefix=/usr \ - --target-list="loongarch64-softmmu" \ - --disable-libiscsi --disable-libnfs --disable-libpmem \ - --disable-glusterfs --enable-libusb --enable-usb-redir \ - --disable-opengl --disable-xen --enable-spice --disable-werror \ - --enable-debug --disable-capstone --disable-kvm --enable-profiler - - cd build/ - - make && make check-tcg - - or - - ./build/qemu-system-loongarch64 -machine virt -m 4G -cpu Loongson-3A5000 -smp 1 -kernel build/tests/tcg/loongarch64-softmmu/hello -monitor none -display none -chardev file,path=hello.out,id=output -serial chardev:output + You can reference docs/system/loongarch/loongson3.rst to get the information about system emulation of LoongArch. - Linux-user emulation From 52f0c1607671293afcdb2acc2f83e9bccbfa74bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 11 Aug 2022 16:14:06 +0100 Subject: [PATCH 0139/1020] linux-user: un-parent OBJECT(cpu) when closing thread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While forcing the CPU to unrealize by hand does trigger the clean-up code we never fully free resources because refcount never reaches zero. This is because QOM automatically added objects without an explicit parent to /unattached/, incrementing the refcount. Instead of manually triggering unrealization just unparent the object and let the device machinery deal with that for us. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/866 Signed-off-by: Alex BennĂ©e Reviewed-by: Laurent Vivier Message-Id: <20220811151413.3350684-2-alex.bennee@linaro.org> --- linux-user/syscall.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f409121202..bfdd60136b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8594,7 +8594,13 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, if (CPU_NEXT(first_cpu)) { TaskState *ts = cpu->opaque; - object_property_set_bool(OBJECT(cpu), "realized", false, NULL); + if (ts->child_tidptr) { + put_user_u32(0, ts->child_tidptr); + do_sys_futex(g2h(cpu, ts->child_tidptr), + FUTEX_WAKE, INT_MAX, NULL, NULL, 0); + } + + object_unparent(OBJECT(cpu)); object_unref(OBJECT(cpu)); /* * At this point the CPU should be unrealized and removed @@ -8604,11 +8610,6 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, pthread_mutex_unlock(&clone_lock); - if (ts->child_tidptr) { - put_user_u32(0, ts->child_tidptr); - do_sys_futex(g2h(cpu, ts->child_tidptr), - FUTEX_WAKE, INT_MAX, NULL, NULL, 0); - } thread_cpu = NULL; g_free(ts); rcu_unregister_thread(); From b1ceae2f5bc477217dd292bffa7b4abb34d78a2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 11 Aug 2022 16:14:11 +0100 Subject: [PATCH 0140/1020] tests/avocado: add timeout to the aspeed tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On some systems the test can hang. At least defining a timeout stops it from hanging forever. Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220811151413.3350684-7-alex.bennee@linaro.org> --- tests/avocado/machine_aspeed.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py index b4e35a3d07..c54da0fd8f 100644 --- a/tests/avocado/machine_aspeed.py +++ b/tests/avocado/machine_aspeed.py @@ -40,6 +40,8 @@ class AST1030Machine(QemuSystemTest): class AST2x00Machine(QemuSystemTest): + timeout = 90 + def wait_for_console_pattern(self, success_message, vm=None): wait_for_console_pattern(self, success_message, failure_message='Kernel panic - not syncing', From 65711f9a87874a9ec61108c6009f8baec07c8b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 11 Aug 2022 16:14:12 +0100 Subject: [PATCH 0141/1020] tests/avocado: apply a band aid to aspeed-evb login MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is really a limitation of the underlying console code which doesn't allow us to detect the login: and following "#" prompts because it reads input line wise. By adding a small delay we ensure that the login prompt has appeared so we don't accidentally spaff the shell commands to a confused getty in the guest. Signed-off-by: Alex BennĂ©e Reviewed-by: CĂ©dric Le Goater Acked-by: John Snow Message-Id: <20220811151413.3350684-8-alex.bennee@linaro.org> --- tests/avocado/machine_aspeed.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py index c54da0fd8f..65d38f4efa 100644 --- a/tests/avocado/machine_aspeed.py +++ b/tests/avocado/machine_aspeed.py @@ -101,7 +101,9 @@ class AST2x00Machine(QemuSystemTest): self.wait_for_console_pattern('Starting kernel ...') self.wait_for_console_pattern('Booting Linux on physical CPU ' + cpu_id) self.wait_for_console_pattern('lease of 10.0.2.15') + # the line before login: self.wait_for_console_pattern('Aspeed EVB') + time.sleep(0.1) exec_command(self, 'root') time.sleep(0.1) From 9c23d7193497bbada5915351ce06b7952dd86f6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Tue, 9 Aug 2022 05:38:54 -0400 Subject: [PATCH 0142/1020] tests/qtest: misc tweaks to readconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The property name parameter is ignored when visiting a top level type, but the obvious typo should be fixed to avoid confusion. A few indentation issues were tidied up. We can break out of the loop when finding the RNG device. Finally, close the temp FD immediately when no longer needed. Signed-off-by: Daniel P. BerrangĂ© Message-Id: <20220809093854.168438-1-berrange@redhat.com> Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Thomas Huth Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Thomas Huth --- tests/qtest/readconfig-test.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/qtest/readconfig-test.c b/tests/qtest/readconfig-test.c index 2e604d7c2d..c7a9b0c7dd 100644 --- a/tests/qtest/readconfig-test.c +++ b/tests/qtest/readconfig-test.c @@ -33,13 +33,12 @@ static QTestState *qtest_init_with_config(const char *cfgdata) g_assert_cmpint(cfgfd, >=, 0); ret = qemu_write_full(cfgfd, cfgdata, strlen(cfgdata)); + close(cfgfd); if (ret < 0) { unlink(cfgpath); } g_assert_cmpint(ret, ==, strlen(cfgdata)); - close(cfgfd); - args = g_strdup_printf("-nodefaults -machine none -readconfig %s", cfgpath); qts = qtest_init(args); @@ -79,7 +78,7 @@ static void test_x86_memdev(void) "size = \"200\""; qts = qtest_init_with_config(cfgdata); - /* Test valid command */ + /* Test valid command */ resp = qtest_qmp(qts, "{ 'execute': 'query-memdev' }"); test_x86_memdev_resp(qdict_get(resp, "return")); qobject_unref(resp); @@ -96,7 +95,7 @@ static void test_spice_resp(QObject *res) g_assert(res); v = qobject_input_visitor_new(res); - visit_type_SpiceInfo(v, "spcie", &spice, &error_abort); + visit_type_SpiceInfo(v, "spice", &spice, &error_abort); g_assert(spice); g_assert(spice->enabled); @@ -114,7 +113,7 @@ static void test_spice(void) "unix = \"on\"\n"; qts = qtest_init_with_config(cfgdata); - /* Test valid command */ + /* Test valid command */ resp = qtest_qmp(qts, "{ 'execute': 'query-spice' }"); test_spice_resp(qdict_get(resp, "return")); qobject_unref(resp); @@ -144,6 +143,7 @@ static void test_object_rng_resp(QObject *res) if (g_str_equal(obj->name, "rng0") && g_str_equal(obj->type, "child")) { seen_rng = true; + break; } tmp = tmp->next; @@ -164,7 +164,7 @@ static void test_object_rng(void) "id = \"rng0\"\n"; qts = qtest_init_with_config(cfgdata); - /* Test valid command */ + /* Test valid command */ resp = qtest_qmp(qts, "{ 'execute': 'qom-list'," " 'arguments': {'path': '/objects' }}"); From effaf5a240e03020f4ae953e10b764622c3e87cc Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Thu, 4 Aug 2022 15:13:00 +0200 Subject: [PATCH 0143/1020] hw/usb/hcd-xhci: Fix unbounded loop in xhci_ring_chain_length() (CVE-2020-14394) The loop condition in xhci_ring_chain_length() is under control of the guest, and additionally the code does not check for failed DMA transfers (e.g. if reaching the end of the RAM), so the loop there could run for a very long time or even forever. Fix it by checking the return value of dma_memory_read() and by introducing a maximum loop length. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/646 Message-Id: <20220804131300.96368-1-thuth@redhat.com> Reviewed-by: Mauro Matteo Cascella Acked-by: Gerd Hoffmann Signed-off-by: Thomas Huth --- hw/usb/hcd-xhci.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 296cc6c8e6..3c48b58dde 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include "qemu/timer.h" +#include "qemu/log.h" #include "qemu/module.h" #include "qemu/queue.h" #include "migration/vmstate.h" @@ -725,10 +726,14 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) bool control_td_set = 0; uint32_t link_cnt = 0; - while (1) { + do { TRBType type; - dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE, - MEMTXATTRS_UNSPECIFIED); + if (dma_memory_read(xhci->as, dequeue, &trb, TRB_SIZE, + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n", + __func__); + return -1; + } le64_to_cpus(&trb.parameter); le32_to_cpus(&trb.status); le32_to_cpus(&trb.control); @@ -762,7 +767,17 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring) if (!control_td_set && !(trb.control & TRB_TR_CH)) { return length; } - } + + /* + * According to the xHCI spec, Transfer Ring segments should have + * a maximum size of 64 kB (see chapter "6 Data Structures") + */ + } while (length < TRB_LINK_LIMIT * 65536 / TRB_SIZE); + + qemu_log_mask(LOG_GUEST_ERROR, "%s: exceeded maximum tranfer ring size!\n", + __func__); + + return -1; } static void xhci_er_reset(XHCIState *xhci, int v) From c7208a6e0d049f9e8af15df908168a79b1f99685 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Aug 2022 20:45:19 -0500 Subject: [PATCH 0144/1020] Update version for v7.1.0-rc3 release Signed-off-by: Richard Henderson --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 79d1c8668a..1c944b9863 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0.92 +7.0.93 From 9a4b6a63aee885931622549c85669dcca03bed39 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Mon, 8 Aug 2022 12:21:34 -0400 Subject: [PATCH 0145/1020] virtio-scsi: fix race in virtio_scsi_dataplane_start() As soon as virtio_scsi_data_plane_start() attaches host notifiers the IOThread may start virtqueue processing. There is a race between IOThread virtqueue processing and virtio_scsi_data_plane_start() because it only assigns s->dataplane_started after attaching host notifiers. When a virtqueue handler function in the IOThread calls virtio_scsi_defer_to_dataplane() it may see !s->dataplane_started and attempt to start dataplane even though we're already in the IOThread: #0 0x00007f67b360857c __pthread_kill_implementation (libc.so.6 + 0xa257c) #1 0x00007f67b35bbd56 raise (libc.so.6 + 0x55d56) #2 0x00007f67b358e833 abort (libc.so.6 + 0x28833) #3 0x00007f67b358e75b __assert_fail_base.cold (libc.so.6 + 0x2875b) #4 0x00007f67b35b4cd6 __assert_fail (libc.so.6 + 0x4ecd6) #5 0x000055ca87fd411b memory_region_transaction_commit (qemu-kvm + 0x67511b) #6 0x000055ca87e17811 virtio_pci_ioeventfd_assign (qemu-kvm + 0x4b8811) #7 0x000055ca87e14836 virtio_bus_set_host_notifier (qemu-kvm + 0x4b5836) #8 0x000055ca87f8e14e virtio_scsi_set_host_notifier (qemu-kvm + 0x62f14e) #9 0x000055ca87f8dd62 virtio_scsi_dataplane_start (qemu-kvm + 0x62ed62) #10 0x000055ca87e14610 virtio_bus_start_ioeventfd (qemu-kvm + 0x4b5610) #11 0x000055ca87f8c29a virtio_scsi_handle_ctrl (qemu-kvm + 0x62d29a) #12 0x000055ca87fa5902 virtio_queue_host_notifier_read (qemu-kvm + 0x646902) #13 0x000055ca882c099e aio_dispatch_handler (qemu-kvm + 0x96199e) #14 0x000055ca882c1761 aio_poll (qemu-kvm + 0x962761) #15 0x000055ca880e1052 iothread_run (qemu-kvm + 0x782052) #16 0x000055ca882c562a qemu_thread_start (qemu-kvm + 0x96662a) This patch assigns s->dataplane_started before attaching host notifiers so that virtqueue handler functions that run in the IOThread before virtio_scsi_data_plane_start() returns correctly identify that dataplane does not need to be started. This fix is taken from the virtio-blk dataplane code and it's worth adding a comment in virtio-blk as well to explain why it works. Note that s->dataplane_started does not need the AioContext lock because it is set before attaching host notifiers and cleared after detaching host notifiers. In other words, the IOThread always sees the value true and the main loop thread does not modify it while the IOThread is active. Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2099541 Reported-by: Qing Wang Signed-off-by: Stefan Hajnoczi Message-Id: <20220808162134.240405-1-stefanha@redhat.com> Reviewed-by: Emanuele Giuseppe Esposito Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/block/dataplane/virtio-blk.c | 5 +++++ hw/scsi/virtio-scsi-dataplane.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c index 49276e46f2..26f965cabc 100644 --- a/hw/block/dataplane/virtio-blk.c +++ b/hw/block/dataplane/virtio-blk.c @@ -219,6 +219,11 @@ int virtio_blk_data_plane_start(VirtIODevice *vdev) memory_region_transaction_commit(); + /* + * These fields are visible to the IOThread so we rely on implicit barriers + * in aio_context_acquire() on the write side and aio_notify_accept() on + * the read side. + */ s->starting = false; vblk->dataplane_started = true; trace_virtio_blk_data_plane_start(s); diff --git a/hw/scsi/virtio-scsi-dataplane.c b/hw/scsi/virtio-scsi-dataplane.c index 8bb6e6acfc..20bb91766e 100644 --- a/hw/scsi/virtio-scsi-dataplane.c +++ b/hw/scsi/virtio-scsi-dataplane.c @@ -136,6 +136,14 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev) memory_region_transaction_commit(); + /* + * These fields are visible to the IOThread so we rely on implicit barriers + * in aio_context_acquire() on the write side and aio_notify_accept() on + * the read side. + */ + s->dataplane_starting = false; + s->dataplane_started = true; + aio_context_acquire(s->ctx); virtio_queue_aio_attach_host_notifier(vs->ctrl_vq, s->ctx); virtio_queue_aio_attach_host_notifier_no_poll(vs->event_vq, s->ctx); @@ -143,9 +151,6 @@ int virtio_scsi_dataplane_start(VirtIODevice *vdev) for (i = 0; i < vs->conf.num_queues; i++) { virtio_queue_aio_attach_host_notifier(vs->cmd_vqs[i], s->ctx); } - - s->dataplane_starting = false; - s->dataplane_started = true; aio_context_release(s->ctx); return 0; From f20400ed0de62ba7682b864e270804ceb3df784a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 28 Jul 2022 14:55:01 +0100 Subject: [PATCH 0146/1020] hw/virtio: gracefully handle unset vhost_dev vdev MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I've noticed asserts firing because we query the status of vdev after a vhost connection is closed down. Rather than faulting on the NULL indirect just quietly reply false. Signed-off-by: Alex BennĂ©e Message-Id: <20220728135503.1060062-3-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 0827d631c0..f758f177bb 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -306,7 +306,7 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) dev->log_size = size; } -static int vhost_dev_has_iommu(struct vhost_dev *dev) +static bool vhost_dev_has_iommu(struct vhost_dev *dev) { VirtIODevice *vdev = dev->vdev; @@ -316,8 +316,12 @@ static int vhost_dev_has_iommu(struct vhost_dev *dev) * does not have IOMMU, there's no need to enable this feature * which may cause unnecessary IOTLB miss/update transactions. */ - return virtio_bus_device_iommu_enabled(vdev) && - virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + if (vdev) { + return virtio_bus_device_iommu_enabled(vdev) && + virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + } else { + return false; + } } static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, From 5a9d5f09b1f61bc7072c2389ba5b11350ae76b0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 28 Jul 2022 14:55:02 +0100 Subject: [PATCH 0147/1020] hw/virtio: handle un-configured shutdown in virtio-pci MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The assert() protecting against leakage is a little aggressive and causes needless crashes if a device is shutdown without having been configured. In this case no descriptors are lost because none have been assigned. Signed-off-by: Alex BennĂ©e Message-Id: <20220728135503.1060062-4-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 45327f0b31..5ce61f9b45 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -996,9 +996,14 @@ static int virtio_pci_set_guest_notifiers(DeviceState *d, int nvqs, bool assign) nvqs = MIN(nvqs, VIRTIO_QUEUE_MAX); - /* When deassigning, pass a consistent nvqs value - * to avoid leaking notifiers. + /* + * When deassigning, pass a consistent nvqs value to avoid leaking + * notifiers. But first check we've actually been configured, exit + * early if we haven't. */ + if (!assign && !proxy->nvqs_with_notifiers) { + return 0; + } assert(assign || nvqs == proxy->nvqs_with_notifiers); proxy->nvqs_with_notifiers = nvqs; From 643a943554041a10f372a33a5ce7c9ef51007a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 28 Jul 2022 14:55:03 +0100 Subject: [PATCH 0148/1020] hw/virtio: fix vhost_user_read tracepoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As reads happen in the callback we were never seeing them. We only really care about the header so move the tracepoint to when the header is complete. Fixes: 6ca6d8ee9d (hw/virtio: add vhost_user_[read|write] trace points) Signed-off-by: Alex BennĂ©e Acked-by: Jason Wang Message-Id: <20220728135503.1060062-5-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-user.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 75b8df21a4..bd24741be8 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -295,6 +295,8 @@ static int vhost_user_read_header(struct vhost_dev *dev, VhostUserMsg *msg) return -EPROTO; } + trace_vhost_user_read(msg->hdr.request, msg->hdr.flags); + return 0; } @@ -544,8 +546,6 @@ static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, } } - trace_vhost_user_read(msg.hdr.request, msg.hdr.flags); - return 0; } From 3824e25db1a84fadc50b88dfbe27047aa2f7f85d Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 17 Aug 2022 10:39:40 +0200 Subject: [PATCH 0149/1020] x86: disable rng seeding via setup_data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Causes regressions when doing direct kernel boots with OVMF. At this point in the release cycle the only sensible action is to just disable this for 7.1 and sort it properly in the 7.2 devel cycle. Cc: Jason A. Donenfeld Cc: Marcel Apfelbaum Cc: Paolo Bonzini Cc: Richard Henderson Cc: Eduardo Habkost Cc: Peter Maydell Cc: Philippe Mathieu-DaudĂ© Cc: Laurent Vivier Signed-off-by: Gerd Hoffmann Message-Id: <20220817083940.3174933-1-kraxel@redhat.com> Cc: Jason A. Donenfeld Cc: Marcel Apfelbaum Cc: Paolo Bonzini Cc: Richard Henderson Cc: Eduardo Habkost Cc: Peter Maydell Cc: Philippe Mathieu-DaudĂ© Cc: Laurent Vivier Signed-off-by: Gerd Hoffmann --- hw/i386/microvm.c | 2 +- hw/i386/pc_piix.c | 2 +- hw/i386/pc_q35.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 7fe8cce03e..52cafa003d 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -332,7 +332,7 @@ static void microvm_memory_init(MicrovmMachineState *mms) rom_set_fw(fw_cfg); if (machine->kernel_filename != NULL) { - x86_load_linux(x86ms, fw_cfg, 0, true, false); + x86_load_linux(x86ms, fw_cfg, 0, true, true); } if (mms->option_roms) { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index a5c65c1c35..20962c34e7 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -439,6 +439,7 @@ static void pc_i440fx_7_1_machine_options(MachineClass *m) m->alias = "pc"; m->is_default = true; pcmc->default_cpu_version = 1; + pcmc->legacy_no_rng_seed = true; } DEFINE_I440FX_MACHINE(v7_1, "pc-i440fx-7.1", NULL, @@ -450,7 +451,6 @@ static void pc_i440fx_7_0_machine_options(MachineClass *m) pc_i440fx_7_1_machine_options(m); m->alias = NULL; m->is_default = false; - pcmc->legacy_no_rng_seed = true; pcmc->enforce_amd_1tb_hole = false; compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len); compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 3a35193ff7..2e5dae9a89 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -376,6 +376,7 @@ static void pc_q35_7_1_machine_options(MachineClass *m) pc_q35_machine_options(m); m->alias = "q35"; pcmc->default_cpu_version = 1; + pcmc->legacy_no_rng_seed = true; } DEFINE_Q35_MACHINE(v7_1, "pc-q35-7.1", NULL, @@ -386,7 +387,6 @@ static void pc_q35_7_0_machine_options(MachineClass *m) PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_7_1_machine_options(m); m->alias = NULL; - pcmc->legacy_no_rng_seed = true; pcmc->enforce_amd_1tb_hole = false; compat_props_add(m->compat_props, hw_compat_7_0, hw_compat_7_0_len); compat_props_add(m->compat_props, pc_compat_7_0, pc_compat_7_0_len); From a99fbb003b2558cb4ff426d8144eff7cc1e2d7dc Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Mon, 8 Aug 2022 13:20:50 +0100 Subject: [PATCH 0150/1020] hw/cxl: Fix memory leak in error paths Use g_autofree to free the CXLFixedWindow structure if an error occurs in configuration before we have added to the list (via g_steal_pointer()) Fix Coverity CID: 1488872 Reported-by: Peter Maydell Signed-off-by: Jonathan Cameron Message-Id: <20220808122051.14822-2-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/cxl/cxl-host.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c index 483d8eb13f..faa68ef038 100644 --- a/hw/cxl/cxl-host.c +++ b/hw/cxl/cxl-host.c @@ -26,7 +26,7 @@ static void cxl_fixed_memory_window_config(CXLState *cxl_state, CXLFixedMemoryWindowOptions *object, Error **errp) { - CXLFixedWindow *fw = g_malloc0(sizeof(*fw)); + g_autofree CXLFixedWindow *fw = g_malloc0(sizeof(*fw)); strList *target; int i; @@ -64,7 +64,8 @@ static void cxl_fixed_memory_window_config(CXLState *cxl_state, fw->enc_int_gran = 0; } - cxl_state->fixed_windows = g_list_append(cxl_state->fixed_windows, fw); + cxl_state->fixed_windows = g_list_append(cxl_state->fixed_windows, + g_steal_pointer(&fw)); return; } From d2289b524e71970ea8ca5602f219cc92b8e5896b Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Mon, 8 Aug 2022 13:20:51 +0100 Subject: [PATCH 0151/1020] hw/cxl: Fix wrong query of target ports Two issues were present in this code: 1) Check on which register to look in was inverted. 2) Both branches use the _LO register. Whilst here moved to extract32() rather than hand rolling the field extraction as simpler and hopefully less error prone. Fixes Coverity CID: 1488873 Reported-by: Peter Maydell Signed-off-by: Jonathan Cameron Message-Id: <20220808122051.14822-3-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/cxl/cxl-host.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/hw/cxl/cxl-host.c b/hw/cxl/cxl-host.c index faa68ef038..1adf61231a 100644 --- a/hw/cxl/cxl-host.c +++ b/hw/cxl/cxl-host.c @@ -104,7 +104,6 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr, uint32_t ctrl; uint32_t ig_enc; uint32_t iw_enc; - uint32_t target_reg; uint32_t target_idx; ctrl = cache_mem[R_CXL_HDM_DECODER0_CTRL]; @@ -116,14 +115,13 @@ static bool cxl_hdm_find_target(uint32_t *cache_mem, hwaddr addr, iw_enc = FIELD_EX32(ctrl, CXL_HDM_DECODER0_CTRL, IW); target_idx = (addr / cxl_decode_ig(ig_enc)) % (1 << iw_enc); - if (target_idx > 4) { - target_reg = cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_LO]; - target_reg >>= target_idx * 8; + if (target_idx < 4) { + *target = extract32(cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_LO], + target_idx * 8, 8); } else { - target_reg = cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_LO]; - target_reg >>= (target_idx - 4) * 8; + *target = extract32(cache_mem[R_CXL_HDM_DECODER0_TARGET_LIST_HI], + (target_idx - 4) * 8, 8); } - *target = target_reg & 0xff; return true; } From 29d1fbc6c6ff04492fc67626aec5ebf2439739d0 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 17 Aug 2022 15:57:57 +0100 Subject: [PATCH 0152/1020] hw/cxl: Add stub write function for RO MemoryRegionOps entries. There is no checking on the availability of a write callback. Hence QEMU crashes if a write does occur to one of these regions. Discovered whilst chasing a Linux kernel bug that incorrectly wrote into one of these regions. Fixes: 6364adacdf ("hw/cxl/device: Implement the CAP array (8.2.8.1-2)") Reported-by: Bobo WL Signed-off-by: Jonathan Cameron Message-Id: <20220817145759.32603-2-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/cxl/cxl-device-utils.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/hw/cxl/cxl-device-utils.c b/hw/cxl/cxl-device-utils.c index 687759b301..83ce7a8270 100644 --- a/hw/cxl/cxl-device-utils.c +++ b/hw/cxl/cxl-device-utils.c @@ -141,9 +141,15 @@ static uint64_t mdev_reg_read(void *opaque, hwaddr offset, unsigned size) return retval; } +static void ro_reg_write(void *opaque, hwaddr offset, uint64_t value, + unsigned size) +{ + /* Many register sets are read only */ +} + static const MemoryRegionOps mdev_ops = { .read = mdev_reg_read, - .write = NULL, /* memory device register is read only */ + .write = ro_reg_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, @@ -173,7 +179,7 @@ static const MemoryRegionOps mailbox_ops = { static const MemoryRegionOps dev_ops = { .read = dev_reg_read, - .write = NULL, /* status register is read only */ + .write = ro_reg_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, @@ -188,7 +194,7 @@ static const MemoryRegionOps dev_ops = { static const MemoryRegionOps caps_ops = { .read = caps_reg_read, - .write = NULL, /* caps registers are read only */ + .write = ro_reg_write, .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, From 66a2356485895f82b14585bda8e04bd190841fc0 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 17 Aug 2022 15:57:58 +0100 Subject: [PATCH 0153/1020] hw/cxl: Fix Get LSA input payload size which should be 8 bytes. Get LSA needs 4 byte offset and 4 byte length arguments. CXL rev 2.0 Table 178. Fixes: 3ebe676a34 ("hw/cxl/device: Implement get/set Label Storage Area (LSA)") Signed-off-by: Jonathan Cameron Message-Id: <20220817145759.32603-3-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/cxl/cxl-mailbox-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index bb66c765a5..3cea8b17a8 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -406,7 +406,7 @@ static struct cxl_cmd cxl_cmd_set[256][256] = { cmd_identify_memory_device, 0, 0 }, [CCLS][GET_PARTITION_INFO] = { "CCLS_GET_PARTITION_INFO", cmd_ccls_get_partition_info, 0, 0 }, - [CCLS][GET_LSA] = { "CCLS_GET_LSA", cmd_ccls_get_lsa, 0, 0 }, + [CCLS][GET_LSA] = { "CCLS_GET_LSA", cmd_ccls_get_lsa, 8, 0 }, [CCLS][SET_LSA] = { "CCLS_SET_LSA", cmd_ccls_set_lsa, ~0, IMMEDIATE_CONFIG_CHANGE | IMMEDIATE_DATA_CHANGE }, }; From 4f41b4e445d09651988df36615c3a64853d5bc4a Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Wed, 17 Aug 2022 15:57:59 +0100 Subject: [PATCH 0154/1020] hw/cxl: Correctly handle variable sized mailbox input payloads. A placeholder of ~0 is used to indicate variable payload size. Whilst the checks for output payload correctly took this into account, those for input payload did not. This results in failure of the Set LSA command. Fixes: 464e14ac43 ("hw/cxl/device: Implement basic mailbox (8.2.8.4)") Signed-off-by: Jonathan Cameron Message-Id: <20220817145759.32603-4-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/cxl/cxl-mailbox-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/cxl/cxl-mailbox-utils.c b/hw/cxl/cxl-mailbox-utils.c index 3cea8b17a8..bc1bb18844 100644 --- a/hw/cxl/cxl-mailbox-utils.c +++ b/hw/cxl/cxl-mailbox-utils.c @@ -425,7 +425,7 @@ void cxl_process_mailbox(CXLDeviceState *cxl_dstate) cxl_cmd = &cxl_cmd_set[set][cmd]; h = cxl_cmd->handler; if (h) { - if (len == cxl_cmd->in) { + if (len == cxl_cmd->in || cxl_cmd->in == ~0) { cxl_cmd->payload = cxl_dstate->mbox_reg_state + A_CXL_DEV_CMD_PAYLOAD; ret = (*h)(cxl_cmd, cxl_dstate, &len); From 888fbaaf029dde7b86d2be24bded6fda6bd80b6c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Thu, 28 Jul 2022 09:37:13 -0400 Subject: [PATCH 0155/1020] tests: acpi: silence applesmc warning about invalid key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OSK value is irrelevant for ACPI test case. Supply fake OSK explicitly to prevent QEMU complaining about invalid key when it fallbacks to default_osk. Suggested-by: Daniel P. BerrangĂ© Signed-off-by: Igor Mammedov Message-Id: <20220728133713.1369596-1-imammedo@redhat.com> Reviewed-by: Daniel P. BerrangĂ© Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 359916c228..7c5f736b51 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1632,7 +1632,9 @@ static void test_acpi_q35_applesmc(void) .variant = ".applesmc", }; - test_acpi_one("-device isa-applesmc", &data); + /* supply fake 64-byte OSK to silence missing key warning */ + test_acpi_one("-device isa-applesmc,osk=any64characterfakeoskisenough" + "topreventinvalidkeywarningsonstderr", &data); free_test_data(&data); } From 9afb4177d66ac1eee858aba07fa2fc729b274eb4 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Wed, 27 Jul 2022 12:10:38 -0400 Subject: [PATCH 0156/1020] virtio-pci: don't touch pci on virtio reset virtio level reset should not affect pci express registers such as PM, error or link. Fixes: 27ce0f3afc ("hw/virtio: fix Power Management Control Register for PCI Express virtio devices") Fixes: d584f1b9ca ("hw/virtio: fix Link Control Register for PCI Express virtio devices") Fixes: c2cabb3422 ("hw/virtio: fix error enabling flags in Device Control register") Cc: "Marcel Apfelbaum" Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-pci.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 5ce61f9b45..a50c5a57d7 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1947,7 +1947,6 @@ static void virtio_pci_reset(DeviceState *qdev) { VirtIOPCIProxy *proxy = VIRTIO_PCI(qdev); VirtioBusState *bus = VIRTIO_BUS(&proxy->bus); - PCIDevice *dev = PCI_DEVICE(qdev); int i; virtio_bus_reset(bus); @@ -1960,6 +1959,13 @@ static void virtio_pci_reset(DeviceState *qdev) proxy->vqs[i].avail[0] = proxy->vqs[i].avail[1] = 0; proxy->vqs[i].used[0] = proxy->vqs[i].used[1] = 0; } +} + +static void virtio_pci_bus_reset(DeviceState *qdev) +{ + PCIDevice *dev = PCI_DEVICE(qdev); + + virtio_pci_reset(qdev); if (pci_is_express(dev)) { pcie_cap_deverr_reset(dev); @@ -2027,7 +2033,7 @@ static void virtio_pci_class_init(ObjectClass *klass, void *data) k->class_id = PCI_CLASS_OTHERS; device_class_set_parent_realize(dc, virtio_pci_dc_realize, &vpciklass->parent_dc_realize); - dc->reset = virtio_pci_reset; + dc->reset = virtio_pci_bus_reset; } static const TypeInfo virtio_pci_info = { From 2748583211d6e4d14f8862c65276b2d6cc1681ad Mon Sep 17 00:00:00 2001 From: Priyankar Jain Date: Fri, 26 Nov 2021 14:15:17 +0000 Subject: [PATCH 0157/1020] dbus-vmstate: Restrict error checks to registered proxies in dbus_get_proxies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of dbus_get_proxies to construct the proxies corresponding to the IDs registered to dbus-vmstate. Currenty, this function returns an error in case there is any failure while instantiating proxy for "all" the names on dbus. Ideally this function should error out only if it is not able to find and validate the proxies registered to the backend otherwise any offending process(for eg: the process purposefully may not export its Id property on the dbus) may connect to the dbus and can lead to migration failures. This commit ensures that dbus_get_proxies returns an error if it is not able to find and validate the proxies of interest(the IDs registered during the dbus-vmstate instantiation). Signed-off-by: Priyankar Jain Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <1637936117-37977-1-git-send-email-priyankar.jain@nutanix.com> --- backends/dbus-vmstate.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/backends/dbus-vmstate.c b/backends/dbus-vmstate.c index 9cfd758c42..57369ec0f2 100644 --- a/backends/dbus-vmstate.c +++ b/backends/dbus-vmstate.c @@ -114,14 +114,19 @@ dbus_get_proxies(DBusVMState *self, GError **err) "org.qemu.VMState1", NULL, err); if (!proxy) { - return NULL; + if (err != NULL && *err != NULL) { + warn_report("%s: Failed to create proxy: %s", + __func__, (*err)->message); + g_clear_error(err); + } + continue; } result = g_dbus_proxy_get_cached_property(proxy, "Id"); if (!result) { - g_set_error_literal(err, G_IO_ERROR, G_IO_ERROR_FAILED, - "VMState Id property is missing."); - return NULL; + warn_report("%s: VMState Id property is missing.", __func__); + g_clear_object(&proxy); + continue; } id = g_variant_dup_string(result, &size); From f0caba4475b630c79aa34ee7385d0fbe8a2d1ea8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 28 Jun 2022 17:23:15 +0400 Subject: [PATCH 0158/1020] build-sys: disable vhost-user-gpu if !opengl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vhost-user-gpu uses epoxy/glflush and thus requires opengl. Signed-off-by: Marc-AndrĂ© Lureau Message-Id: <20220628132315.664026-1-marcandre.lureau@redhat.com> --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 30a380752c..20fddbd707 100644 --- a/meson.build +++ b/meson.build @@ -1097,7 +1097,7 @@ if (have_system or have_tools) and (virgl.found() or opengl.found()) gbm = dependency('gbm', method: 'pkg-config', required: false, kwargs: static_kwargs) endif -have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and gbm.found() +have_vhost_user_gpu = have_vhost_user_gpu and virgl.found() and opengl.found() and gbm.found() gnutls = not_found gnutls_crypto = not_found From 88738ea40bee4c2cf9aae05edd2ec87e0cbeaf36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 25 Jul 2022 15:58:15 +0400 Subject: [PATCH 0159/1020] ui/console: fix qemu_console_resize() regression MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The display may be corrupted when changing screen colour depth in qemu-system-ppc/MacOS since 7.0. Do not short-cut qemu_console_resize() if the surface is backed by vga vram. When the scanout isn't set, or it is already allocated, or opengl, and the size is fitting, we still avoid the reallocation & replace path. Fixes: commit cb8962c1 ("ui: do not create a surface when resizing a GL scanout") Reported-by: Mark Cave-Ayland Signed-off-by: Marc-AndrĂ© Lureau Acked-by: Gerd Hoffmann Tested-by: Mark Cave-Ayland Message-Id: <20220725115815.2461322-1-marcandre.lureau@redhat.com> --- ui/console.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ui/console.c b/ui/console.c index e139f7115e..765892f84f 100644 --- a/ui/console.c +++ b/ui/console.c @@ -2575,11 +2575,13 @@ static void vc_chr_open(Chardev *chr, void qemu_console_resize(QemuConsole *s, int width, int height) { - DisplaySurface *surface; + DisplaySurface *surface = qemu_console_surface(s); assert(s->console_type == GRAPHIC_CONSOLE); - if (qemu_console_get_width(s, -1) == width && + if ((s->scanout.kind != SCANOUT_SURFACE || + (surface && surface->flags & QEMU_ALLOCATED_FLAG)) && + qemu_console_get_width(s, -1) == width && qemu_console_get_height(s, -1) == height) { return; } From a9197ad2101cfc885cc316af299f49ba89039e54 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 18 Aug 2022 14:08:24 +0200 Subject: [PATCH 0160/1020] kvm: fix segfault with query-stats-schemas and -M none -M none creates a guest without a vCPU, causing the following error: $ ./qemu-system-x86_64 -qmp stdio -M none -accel kvm {execute:qmp_capabilities} {"return": {}} {execute: query-stats-schemas} Segmentation fault (core dumped) Fix it by not querying the vCPU stats if first_cpu is NULL. Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 645f0a249a..8d81ab74de 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -4131,7 +4131,9 @@ void query_stats_schemas_cb(StatsSchemaList **result, Error **errp) query_stats_schema(result, STATS_TARGET_VM, stats_fd, errp); close(stats_fd); - stats_args.result.schema = result; - stats_args.errp = errp; - run_on_cpu(first_cpu, query_stats_schema_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args)); + if (first_cpu) { + stats_args.result.schema = result; + stats_args.errp = errp; + run_on_cpu(first_cpu, query_stats_schema_vcpu, RUN_ON_CPU_HOST_PTR(&stats_args)); + } } From 976a55c0fe427a0084823152447cf5bb9092d24f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 18 Aug 2022 18:03:52 -0700 Subject: [PATCH 0161/1020] Revert "linux-user: un-parent OBJECT(cpu) when closing thread" This reverts commit 52f0c1607671293afcdb2acc2f83e9bccbfa74bb. This caused a regression in arm/aarch64. We are hard-coding ARMCPRegInfo pointers into TranslationBlocks, for calling into helper_{get,set}cp_reg{,64}. So we have a race condition between whichever cpu thread translates the code first (encoding the pointer), and that cpu thread exiting, so that the next execution of the TB references a freed data structure. Signed-off-by: Richard Henderson --- linux-user/syscall.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index bfdd60136b..f409121202 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8594,13 +8594,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, if (CPU_NEXT(first_cpu)) { TaskState *ts = cpu->opaque; - if (ts->child_tidptr) { - put_user_u32(0, ts->child_tidptr); - do_sys_futex(g2h(cpu, ts->child_tidptr), - FUTEX_WAKE, INT_MAX, NULL, NULL, 0); - } - - object_unparent(OBJECT(cpu)); + object_property_set_bool(OBJECT(cpu), "realized", false, NULL); object_unref(OBJECT(cpu)); /* * At this point the CPU should be unrealized and removed @@ -8610,6 +8604,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, pthread_mutex_unlock(&clone_lock); + if (ts->child_tidptr) { + put_user_u32(0, ts->child_tidptr); + do_sys_futex(g2h(cpu, ts->child_tidptr), + FUTEX_WAKE, INT_MAX, NULL, NULL, 0); + } thread_cpu = NULL; g_free(ts); rcu_unregister_thread(); From 6fab0c182dabaca5b3d56e60a8de3122ce9afbea Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 16 Aug 2022 09:58:14 +0200 Subject: [PATCH 0162/1020] target/hppa: Fix proberi instruction emulation for linux-user The proberi assembler instruction checks the read/write access rights for the page of a given address and shall return a value of 1 if the test succeeds and a value of 0 on failure in the target register. But when run in linux-user mode, qemu currently simply returns the return code of page_check_range() which returns 0 on success and -1 on failure, which is the opposite of what proberi should return. Fix it by checking the return code of page_check_range() and return the expected return value. The easiest way to reproduce the issue is by running "/lib/ld.so.1 --version" in a chroot which fails without this patch. At startup of ld.so the __canonicalize_funcptr_for_compare() function is used to resolve the function address out of a function descriptor, which fails because proberi (due to the wrong return code) seems to indicate that the given address isn't accessible. Signed-off-by: Helge Deller --- target/hppa/op_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/hppa/op_helper.c b/target/hppa/op_helper.c index cd304f051e..fbd80e4248 100644 --- a/target/hppa/op_helper.c +++ b/target/hppa/op_helper.c @@ -170,7 +170,7 @@ target_ureg HELPER(probe)(CPUHPPAState *env, target_ulong addr, uint32_t level, uint32_t want) { #ifdef CONFIG_USER_ONLY - return page_check_range(addr, 1, want); + return (page_check_range(addr, 1, want) == 0) ? 1 : 0; #else int prot, excp; hwaddr phys; From 51e15194b0a091e5c40aab2eb234a1d36c5c58ee Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Mon, 22 Aug 2022 14:53:20 +0200 Subject: [PATCH 0163/1020] scsi-generic: Fix emulated block limits VPD page Commits 01ef8185b80 amd 24b36e9813e updated the way that the maximum transfer length is calculated for patching block limits VPD page in an INQUIRY response. The same updates also need to be made for the case where the host device does not support the block limits VPD page at all and we emulate the whole page. Without this fix, on host block devices a maximum transfer length of (INT_MAX - sector_size) bytes is advertised to the guest, resulting in I/O errors when a request that exceeds the host limits is made by the guest. (Prior to commit 24b36e9813e, this code path would use the max_transfer value from the host instead of INT_MAX, but still miss the fix from 01ef8185b80 where max_transfer is also capped to max_iov host pages, so it would be less wrong, but still wrong.) Cc: qemu-stable@nongnu.org Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2096251 Fixes: 01ef8185b809af9d287e1a03a3f9d8ea8231118a Fixes: 24b36e9813ec15da7db62e3b3621730710c5f020 Signed-off-by: Kevin Wolf Message-Id: <20220822125320.48257-1-kwolf@redhat.com> Reviewed-by: Stefan Hajnoczi Signed-off-by: Kevin Wolf --- hw/scsi/scsi-generic.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index ada24d7486..3d35d307e1 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -147,6 +147,18 @@ static int execute_command(BlockBackend *blk, return 0; } +static uint64_t calculate_max_transfer(SCSIDevice *s) +{ + uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk); + uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk); + + assert(max_transfer); + max_transfer = MIN_NON_ZERO(max_transfer, + max_iov * qemu_real_host_page_size()); + + return max_transfer / s->blocksize; +} + static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len) { uint8_t page, page_idx; @@ -179,12 +191,7 @@ static int scsi_handle_inquiry_reply(SCSIGenericReq *r, SCSIDevice *s, int len) (r->req.cmd.buf[1] & 0x01)) { page = r->req.cmd.buf[2]; if (page == 0xb0) { - uint64_t max_transfer = blk_get_max_hw_transfer(s->conf.blk); - uint32_t max_iov = blk_get_max_hw_iov(s->conf.blk); - - assert(max_transfer); - max_transfer = MIN_NON_ZERO(max_transfer, max_iov * qemu_real_host_page_size()) - / s->blocksize; + uint64_t max_transfer = calculate_max_transfer(s); stl_be_p(&r->buf[8], max_transfer); /* Also take care of the opt xfer len. */ stl_be_p(&r->buf[12], @@ -230,7 +237,7 @@ static int scsi_generic_emulate_block_limits(SCSIGenericReq *r, SCSIDevice *s) uint8_t buf[64]; SCSIBlockLimits bl = { - .max_io_sectors = blk_get_max_transfer(s->conf.blk) / s->blocksize + .max_io_sectors = calculate_max_transfer(s), }; memset(r->buf, 0, r->buflen); From 48acf68cfe08496284fb12bf598721dea82d74a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 22 Aug 2022 17:56:03 +0100 Subject: [PATCH 0164/1020] tests/avocado: push default timeout to QemuBaseTest MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All of the QEMU tests eventually end up derrived from this class. Move the default timeout from LinuxTest to ensure we catch them all. We keep the 15 minute timeout as currently some of the more heavyweight CFI and TCG tests can overrun. We should aim to drop it down to 2 minutes which is a more reasonable target for tests to aim for but we want to get this release out. Signed-off-by: Alex BennĂ©e [AJB: revert to 15 min timeout for v2] Reviewed-by: Richard Henderson Message-Id: <20220822165608.2980552-2-alex.bennee@linaro.org> --- tests/avocado/avocado_qemu/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index ed4853c805..9d17a287cf 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -227,6 +227,10 @@ def exec_command_and_wait_for_pattern(test, command, _console_interaction(test, success_message, failure_message, command + '\r') class QemuBaseTest(avocado.Test): + + # default timeout for all tests, can be overridden + timeout = 900 + def _get_unique_tag_val(self, tag_name): """ Gets a tag value, if unique for a key @@ -512,7 +516,6 @@ class LinuxTest(LinuxSSHMixIn, QemuSystemTest): to start with than the more vanilla `QemuSystemTest` class. """ - timeout = 900 distro = None username = 'root' password = 'password' From e25636a12a1cc0a136aaa611a0cfbe6ebfa4aed4 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 22 Aug 2022 17:56:04 +0100 Subject: [PATCH 0165/1020] tests/qtest/migration-test: Only wait for serial output where migration succeeds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Waiting for the serial output can take a couple of seconds - and since we're doing a lot of migration tests, this time easily sums up to multiple minutes. But if a test is supposed to fail, it does not make much sense to wait for the source to be in the right state first, so we can skip the waiting here. This way we can speed up all tests where the migration is supposed to fail. In the gitlab-CI gprov-gcov test, each of the migration-tests now run two minutes faster! Reviewed-by: Dr. David Alan Gilbert Signed-off-by: Thomas Huth Message-Id: <20220819053802.296584-2-thuth@redhat.com> Signed-off-by: Alex BennĂ©e Reviewed-by: Juan Quintela Message-Id: <20220822165608.2980552-3-alex.bennee@linaro.org> --- tests/qtest/migration-test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 520a5f917c..7be321b62d 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -1307,7 +1307,9 @@ static void test_precopy_common(MigrateCommon *args) } /* Wait for the first serial output from the source */ - wait_for_serial("src_serial"); + if (args->result == MIG_TEST_SUCCEED) { + wait_for_serial("src_serial"); + } if (!args->connect_uri) { g_autofree char *local_connect_uri = From c398c7618737d7ff36ae49ba31dae1925683a605 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 22 Aug 2022 17:56:05 +0100 Subject: [PATCH 0166/1020] tests/migration/aarch64: Speed up the aarch64 migration test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The migration tests spend a lot of time waiting for a sign of live of the guest on the serial console. The aarch64 migration code only outputs "B"s every couple of seconds (at least it takes more than 4 seconds between each characeter on my x86 laptop). There are a lot of migration tests, and if each test that checks for a successful migration waits for these characters before and after migration, the wait time sums up to multiple minutes! Let's use a shorter delay to speed things up. While we're at it, also remove a superfluous masking with 0xff - we're reading and storing bytes, so the upper bits of the register do not matter anyway. With these changes, the test runs twice as fast on my laptop, decreasing the total run time from approx. 8 minutes to only 4 minutes! Signed-off-by: Thomas Huth Reviewed-by: Daniel P. BerrangĂ© Message-Id: <20220819053802.296584-3-thuth@redhat.com> Signed-off-by: Alex BennĂ©e Message-Id: <20220822165608.2980552-4-alex.bennee@linaro.org> --- tests/migration/aarch64/a-b-kernel.S | 3 +-- tests/migration/aarch64/a-b-kernel.h | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/migration/aarch64/a-b-kernel.S b/tests/migration/aarch64/a-b-kernel.S index 0225945348..a4103ecb71 100644 --- a/tests/migration/aarch64/a-b-kernel.S +++ b/tests/migration/aarch64/a-b-kernel.S @@ -53,7 +53,6 @@ innerloop: /* increment the first byte of each page by 1 */ ldrb w3, [x4] add w3, w3, #1 - and w3, w3, #0xff strb w3, [x4] /* make sure QEMU user space can see consistent data as MMU is off */ @@ -64,7 +63,7 @@ innerloop: blt innerloop add w5, w5, #1 - and w5, w5, #0xff + and w5, w5, #0x1f cmp w5, #0 bne mainloop diff --git a/tests/migration/aarch64/a-b-kernel.h b/tests/migration/aarch64/a-b-kernel.h index 0a9b01137e..34e518d061 100644 --- a/tests/migration/aarch64/a-b-kernel.h +++ b/tests/migration/aarch64/a-b-kernel.h @@ -10,9 +10,9 @@ unsigned char aarch64_kernel[] = { 0x03, 0x00, 0x80, 0x52, 0xe4, 0x03, 0x00, 0xaa, 0x83, 0x00, 0x00, 0x39, 0x84, 0x04, 0x40, 0x91, 0x9f, 0x00, 0x01, 0xeb, 0xad, 0xff, 0xff, 0x54, 0x05, 0x00, 0x80, 0x52, 0xe4, 0x03, 0x00, 0xaa, 0x83, 0x00, 0x40, 0x39, - 0x63, 0x04, 0x00, 0x11, 0x63, 0x1c, 0x00, 0x12, 0x83, 0x00, 0x00, 0x39, - 0x24, 0x7e, 0x0b, 0xd5, 0x84, 0x04, 0x40, 0x91, 0x9f, 0x00, 0x01, 0xeb, - 0x2b, 0xff, 0xff, 0x54, 0xa5, 0x04, 0x00, 0x11, 0xa5, 0x1c, 0x00, 0x12, - 0xbf, 0x00, 0x00, 0x71, 0x81, 0xfe, 0xff, 0x54, 0x43, 0x08, 0x80, 0x52, - 0x43, 0x00, 0x00, 0x39, 0xf1, 0xff, 0xff, 0x17 + 0x63, 0x04, 0x00, 0x11, 0x83, 0x00, 0x00, 0x39, 0x24, 0x7e, 0x0b, 0xd5, + 0x84, 0x04, 0x40, 0x91, 0x9f, 0x00, 0x01, 0xeb, 0x4b, 0xff, 0xff, 0x54, + 0xa5, 0x04, 0x00, 0x11, 0xa5, 0x10, 0x00, 0x12, 0xbf, 0x00, 0x00, 0x71, + 0xa1, 0xfe, 0xff, 0x54, 0x43, 0x08, 0x80, 0x52, 0x43, 0x00, 0x00, 0x39, + 0xf2, 0xff, 0xff, 0x17 }; From 41adc59640b786575ebf002a4ede8169b0a9541e Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 22 Aug 2022 17:56:06 +0100 Subject: [PATCH 0167/1020] tests/migration/i386: Speed up the i386 migration test (when using TCG) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When KVM is not available, the i386 migration test also runs in a rather slow fashion, since the guest code takes a couple of seconds to print the "B"s on the serial console, and the migration test has to wait for this each time. Let's increase the frequency here, too, so that the delays in the migration tests get smaller. Signed-off-by: Thomas Huth Reviewed-by: Daniel P. BerrangĂ© Message-Id: <20220819053802.296584-4-thuth@redhat.com> Signed-off-by: Alex BennĂ©e Message-Id: <20220822165608.2980552-5-alex.bennee@linaro.org> --- tests/migration/i386/a-b-bootblock.S | 1 + tests/migration/i386/a-b-bootblock.h | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/tests/migration/i386/a-b-bootblock.S b/tests/migration/i386/a-b-bootblock.S index 3f97f28023..3d464c7568 100644 --- a/tests/migration/i386/a-b-bootblock.S +++ b/tests/migration/i386/a-b-bootblock.S @@ -50,6 +50,7 @@ innerloop: jl innerloop inc %bl + andb $0x3f,%bl jnz mainloop mov $66,%ax diff --git a/tests/migration/i386/a-b-bootblock.h b/tests/migration/i386/a-b-bootblock.h index 7d459d4fde..b7b0fce2ee 100644 --- a/tests/migration/i386/a-b-bootblock.h +++ b/tests/migration/i386/a-b-bootblock.h @@ -4,17 +4,17 @@ * the header and the assembler differences in your patch submission. */ unsigned char x86_bootsect[] = { - 0xfa, 0x0f, 0x01, 0x16, 0x74, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00, + 0xfa, 0x0f, 0x01, 0x16, 0x78, 0x7c, 0x66, 0xb8, 0x01, 0x00, 0x00, 0x00, 0x0f, 0x22, 0xc0, 0x66, 0xea, 0x20, 0x7c, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe4, 0x92, 0x0c, 0x02, 0xe6, 0x92, 0xb8, 0x10, 0x00, 0x00, 0x00, 0x8e, 0xd8, 0x66, 0xb8, 0x41, 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xb3, 0x00, 0xb8, 0x00, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x05, 0x00, 0x10, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x40, - 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x75, 0xe9, 0x66, 0xb8, 0x42, 0x00, 0x66, - 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xde, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00, - 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, 0x27, 0x00, 0x5c, 0x7c, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x7c, 0xf2, 0xfe, 0xc3, 0x80, 0xe3, 0x3f, 0x75, 0xe6, 0x66, 0xb8, + 0x42, 0x00, 0x66, 0xba, 0xf8, 0x03, 0xee, 0xeb, 0xdb, 0x8d, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, + 0x00, 0x9a, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, + 0x27, 0x00, 0x60, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, From 00269477c2184393d23865a089a3d71b03ef3d17 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 22 Aug 2022 17:56:07 +0100 Subject: [PATCH 0168/1020] tests/qtest/migration-test: Remove duplicated test_postcopy from the test plan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test_postcopy() is currently run twice - which is just a waste of resources and time. The commit d1a27b169b2d that introduced the duplicate talked about renaming the "postcopy/unix" test, but apparently it forgot to remove the old entry. Let's do that now. Fixes: d1a27b169b ("tests: Add postcopy tls migration test") Signed-off-by: Thomas Huth Reviewed-by: Daniel P. BerrangĂ© Message-Id: <20220819053802.296584-5-thuth@redhat.com> Signed-off-by: Alex BennĂ©e Reviewed-by: Juan Quintela Message-Id: <20220822165608.2980552-6-alex.bennee@linaro.org> --- tests/qtest/migration-test.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 7be321b62d..f63edd0bc8 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -2461,7 +2461,6 @@ int main(int argc, char **argv) module_call_init(MODULE_INIT_QOM); if (has_uffd) { - qtest_add_func("/migration/postcopy/unix", test_postcopy); qtest_add_func("/migration/postcopy/plain", test_postcopy); qtest_add_func("/migration/postcopy/recovery/plain", test_postcopy_recovery); From 5af2b0f6eace7b368ed5cad9677e3bc995b6a7e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 22 Aug 2022 17:56:08 +0100 Subject: [PATCH 0169/1020] qemu-options: try and clarify preferred block semantics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Try to correct any confusion about QEMU's Byzantine disk options by laying out the preferred "modern" options as-per: " (best: -device + -blockdev, 2nd obsolete syntax: -device + -drive, 3rd obsolete syntax: -drive, 4th obsolete syntax: -hdNN)" Signed-off-by: Alex BennĂ©e Acked-by: Kevin Wolf Reviewed-by: Daniel P. BerrangĂ© Cc: qemu-block@nongnu.org Cc: Kevin Wolf Cc: Hanna Reitz Cc: Thomas Huth Message-Id: <20220822165608.2980552-7-alex.bennee@linaro.org> --- qemu-options.hx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/qemu-options.hx b/qemu-options.hx index 3f23a42fa8..31c04f7eea 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1105,6 +1105,19 @@ DEFHEADING() DEFHEADING(Block device options:) +SRST +The QEMU block device handling options have a long history and +have gone through several iterations as the feature set and complexity +of the block layer have grown. Many online guides to QEMU often +reference older and deprecated options, which can lead to confusion. + +The recommended modern way to describe disks is to use a combination of +``-device`` to specify the hardware device and ``-blockdev`` to +describe the backend. The device defines what the guest sees and the +backend describes how QEMU handles the data. + +ERST + DEF("fda", HAS_ARG, QEMU_OPTION_fda, "-fda/-fdb file use 'file' as floppy disk 0/1 image\n", QEMU_ARCH_ALL) DEF("fdb", HAS_ARG, QEMU_OPTION_fdb, "", QEMU_ARCH_ALL) From 9a99f964b152f8095949bbddca7841744ad418da Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 24 Aug 2022 19:27:56 -0700 Subject: [PATCH 0170/1020] Update version for v7.1.0-rc4 release Signed-off-by: Richard Henderson --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 1c944b9863..b8d5f3ebb6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0.93 +7.0.94 From a47ea61de593a8243a66caba9d436040ecae25d5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:39 +0800 Subject: [PATCH 0171/1020] tests/qtest: Use g_setenv() Windows does not provide a setenv() API, but glib does. Replace setenv() call with the glib version. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-2-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/fuzz/generic_fuzz.c | 8 ++++---- tests/qtest/libqtest.c | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/qtest/fuzz/generic_fuzz.c b/tests/qtest/fuzz/generic_fuzz.c index 447ffe8178..afc1d20355 100644 --- a/tests/qtest/fuzz/generic_fuzz.c +++ b/tests/qtest/fuzz/generic_fuzz.c @@ -994,16 +994,16 @@ static GString *generic_fuzz_predefined_config_cmdline(FuzzTarget *t) g_assert(t->opaque); config = t->opaque; - setenv("QEMU_AVOID_DOUBLE_FETCH", "1", 1); + g_setenv("QEMU_AVOID_DOUBLE_FETCH", "1", 1); if (config->argfunc) { args = config->argfunc(); - setenv("QEMU_FUZZ_ARGS", args, 1); + g_setenv("QEMU_FUZZ_ARGS", args, 1); g_free(args); } else { g_assert_nonnull(config->args); - setenv("QEMU_FUZZ_ARGS", config->args, 1); + g_setenv("QEMU_FUZZ_ARGS", config->args, 1); } - setenv("QEMU_FUZZ_OBJECTS", config->objects, 1); + g_setenv("QEMU_FUZZ_OBJECTS", config->objects, 1); return generic_fuzz_cmdline(t); } diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 8c159eacf5..ad6860d774 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -1424,7 +1424,7 @@ QTestState *qtest_inproc_init(QTestState **s, bool log, const char* arch, * way, qtest_get_arch works for inproc qtest. */ gchar *bin_path = g_strconcat("/qemu-system-", arch, NULL); - setenv("QTEST_QEMU_BINARY", bin_path, 0); + g_setenv("QTEST_QEMU_BINARY", bin_path, 0); g_free(bin_path); return qts; From 3c239aa77ed19521992a0b14594907adc0d79a6c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:40 +0800 Subject: [PATCH 0172/1020] tests/qtest: Use g_mkdtemp() Windows does not provide a mkdtemp() API, but glib does. Replace mkdtemp() call with the glib version. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-3-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/cdrom-test.c | 2 +- tests/qtest/cxl-test.c | 6 +++--- tests/qtest/fuzz/generic_fuzz_configs.h | 2 +- tests/qtest/ivshmem-test.c | 4 ++-- tests/qtest/libqos/virtio-9p.c | 4 ++-- tests/qtest/libqtest.c | 2 +- tests/qtest/migration-test.c | 4 ++-- tests/qtest/qmp-test.c | 4 ++-- tests/qtest/vhost-user-test.c | 4 ++-- tests/unit/test-qga.c | 2 +- 10 files changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/qtest/cdrom-test.c b/tests/qtest/cdrom-test.c index a7766a9e65..26a2400181 100644 --- a/tests/qtest/cdrom-test.c +++ b/tests/qtest/cdrom-test.c @@ -52,7 +52,7 @@ static int prepare_image(const char *arch, char *isoimage) perror("Error creating temporary iso image file"); return -1; } - if (!mkdtemp(srcdir)) { + if (!g_mkdtemp(srcdir)) { perror("Error creating temporary directory"); goto cleanup; } diff --git a/tests/qtest/cxl-test.c b/tests/qtest/cxl-test.c index 2133e973f4..4e6d285061 100644 --- a/tests/qtest/cxl-test.c +++ b/tests/qtest/cxl-test.c @@ -95,7 +95,7 @@ static void cxl_t3d(void) char template[] = "/tmp/cxl-test-XXXXXX"; const char *tmpfs; - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); g_string_printf(cmdline, QEMU_PXB_CMD QEMU_RP QEMU_T3D, tmpfs, tmpfs); @@ -109,7 +109,7 @@ static void cxl_1pxb_2rp_2t3d(void) char template[] = "/tmp/cxl-test-XXXXXX"; const char *tmpfs; - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); g_string_printf(cmdline, QEMU_PXB_CMD QEMU_2RP QEMU_2T3D, tmpfs, tmpfs, tmpfs, tmpfs); @@ -124,7 +124,7 @@ static void cxl_2pxb_4rp_4t3d(void) char template[] = "/tmp/cxl-test-XXXXXX"; const char *tmpfs; - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); g_string_printf(cmdline, QEMU_2PXB_CMD QEMU_4RP QEMU_4T3D, tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 004c701915..0775e6702b 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -21,7 +21,7 @@ typedef struct generic_fuzz_config { static inline gchar *generic_fuzzer_virtio_9p_args(void){ char tmpdir[] = "/tmp/qemu-fuzz.XXXXXX"; - g_assert_nonnull(mkdtemp(tmpdir)); + g_assert_nonnull(g_mkdtemp(tmpdir)); return g_strdup_printf("-machine q35 -nodefaults " "-device virtio-9p,fsdev=hshare,mount_tag=hshare " diff --git a/tests/qtest/ivshmem-test.c b/tests/qtest/ivshmem-test.c index e23a97fa8e..9611d05eb5 100644 --- a/tests/qtest/ivshmem-test.c +++ b/tests/qtest/ivshmem-test.c @@ -481,8 +481,8 @@ int main(int argc, char **argv) tmpshmem = mmap(0, TMPSHMSIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); g_assert(tmpshmem != MAP_FAILED); /* server */ - if (mkdtemp(dir) == NULL) { - g_error("mkdtemp: %s", g_strerror(errno)); + if (g_mkdtemp(dir) == NULL) { + g_error("g_mkdtemp: %s", g_strerror(errno)); } tmpdir = dir; tmpserver = g_strconcat(tmpdir, "/server", NULL); diff --git a/tests/qtest/libqos/virtio-9p.c b/tests/qtest/libqos/virtio-9p.c index 70aea8bf62..ae9b0a20e2 100644 --- a/tests/qtest/libqos/virtio-9p.c +++ b/tests/qtest/libqos/virtio-9p.c @@ -48,9 +48,9 @@ void virtio_9p_create_local_test_dir(void) */ char *template = concat_path(pwd, "qtest-9p-local-XXXXXX"); - local_test_path = mkdtemp(template); + local_test_path = g_mkdtemp(template); if (!local_test_path) { - g_test_message("mkdtemp('%s') failed: %s", template, strerror(errno)); + g_test_message("g_mkdtemp('%s') failed: %s", template, strerror(errno)); } g_assert(local_test_path != NULL); diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index ad6860d774..7c9fc07de4 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -393,7 +393,7 @@ QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd) char *sock_path, sock_dir[] = "/tmp/qtest-serial-XXXXXX"; QTestState *qts; - g_assert_true(mkdtemp(sock_dir) != NULL); + g_assert_true(g_mkdtemp(sock_dir) != NULL); sock_path = g_strdup_printf("%s/sock", sock_dir); sock_fd_init = init_socket(sock_path); diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index f63edd0bc8..60f3d4e9d2 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -2452,9 +2452,9 @@ int main(int argc, char **argv) return g_test_run(); } - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); if (!tmpfs) { - g_test_message("mkdtemp on path (%s): %s", template, strerror(errno)); + g_test_message("g_mkdtemp on path (%s): %s", template, strerror(errno)); } g_assert(tmpfs); diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c index 9a42480cef..bf7304c7dc 100644 --- a/tests/qtest/qmp-test.c +++ b/tests/qtest/qmp-test.c @@ -166,8 +166,8 @@ char *fifo_name; static void setup_blocking_cmd(void) { - if (!mkdtemp(tmpdir)) { - g_error("mkdtemp: %s", strerror(errno)); + if (!g_mkdtemp(tmpdir)) { + g_error("g_mkdtemp: %s", strerror(errno)); } fifo_name = g_strdup_printf("%s/fifo", tmpdir); if (mkfifo(fifo_name, 0666)) { diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 8bf390be20..d7d6cfc9bd 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -491,9 +491,9 @@ static TestServer *test_server_new(const gchar *name, /* run the main loop thread so the chardev may operate */ server->thread = g_thread_new(NULL, thread_function, server->loop); - tmpfs = mkdtemp(template); + tmpfs = g_mkdtemp(template); if (!tmpfs) { - g_test_message("mkdtemp on path (%s): %s", template, strerror(errno)); + g_test_message("g_mkdtemp on path (%s): %s", template, strerror(errno)); } g_assert(tmpfs); diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c index b27c77a695..a05a4628ed 100644 --- a/tests/unit/test-qga.c +++ b/tests/unit/test-qga.c @@ -60,7 +60,7 @@ fixture_setup(TestFixture *fixture, gconstpointer data, gchar **envp) fixture->loop = g_main_loop_new(NULL, FALSE); fixture->test_dir = g_strdup("/tmp/qgatest.XXXXXX"); - g_assert_nonnull(mkdtemp(fixture->test_dir)); + g_assert_nonnull(g_mkdtemp(fixture->test_dir)); path = g_build_filename(fixture->test_dir, "sock", NULL); cwd = g_get_current_dir(); From 413bebc04603d87d1889c919fbdd4adf30d4ebb5 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:50 +0800 Subject: [PATCH 0173/1020] tests: Use g_mkdir_with_parents() Use the same g_mkdir_with_parents() call to create a directory on all platforms. Signed-off-by: Bin Meng Reviewed-by: Dr. David Alan Gilbert Message-Id: <20220824094029.1634519-13-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/migration/stress.c | 2 +- tests/qtest/migration-test.c | 6 +++--- tests/unit/test-crypto-tlscredsx509.c | 4 ++-- tests/unit/test-crypto-tlssession.c | 6 +++--- tests/unit/test-io-channel-tls.c | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tests/migration/stress.c b/tests/migration/stress.c index b7240a15c8..88acf8dc25 100644 --- a/tests/migration/stress.c +++ b/tests/migration/stress.c @@ -232,7 +232,7 @@ static void stress(unsigned long long ramsizeGB, int ncpus) static int mount_misc(const char *fstype, const char *dir) { - if (mkdir(dir, 0755) < 0 && errno != EEXIST) { + if (g_mkdir_with_parents(dir, 0755) < 0 && errno != EEXIST) { fprintf(stderr, "%s (%05d): ERROR: cannot create %s: %s\n", argv0, gettid(), dir, strerror(errno)); return -1; diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 60f3d4e9d2..21bd76be19 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -761,14 +761,14 @@ test_migrate_tls_psk_start_common(QTestState *from, data->workdir = g_strdup_printf("%s/tlscredspsk0", tmpfs); data->pskfile = g_strdup_printf("%s/%s", data->workdir, QCRYPTO_TLS_CREDS_PSKFILE); - mkdir(data->workdir, 0700); + g_mkdir_with_parents(data->workdir, 0700); test_tls_psk_init(data->pskfile); if (mismatch) { data->workdiralt = g_strdup_printf("%s/tlscredspskalt0", tmpfs); data->pskfilealt = g_strdup_printf("%s/%s", data->workdiralt, QCRYPTO_TLS_CREDS_PSKFILE); - mkdir(data->workdiralt, 0700); + g_mkdir_with_parents(data->workdiralt, 0700); test_tls_psk_init_alt(data->pskfilealt); } @@ -873,7 +873,7 @@ test_migrate_tls_x509_start_common(QTestState *from, data->clientcert = g_strdup_printf("%s/client-cert.pem", data->workdir); } - mkdir(data->workdir, 0700); + g_mkdir_with_parents(data->workdir, 0700); test_tls_init(data->keyfile); g_assert(link(data->keyfile, data->serverkey) == 0); diff --git a/tests/unit/test-crypto-tlscredsx509.c b/tests/unit/test-crypto-tlscredsx509.c index aab4149b56..3c25d75ca1 100644 --- a/tests/unit/test-crypto-tlscredsx509.c +++ b/tests/unit/test-crypto-tlscredsx509.c @@ -75,7 +75,7 @@ static void test_tls_creds(const void *opaque) QCryptoTLSCreds *creds; #define CERT_DIR "tests/test-crypto-tlscredsx509-certs/" - mkdir(CERT_DIR, 0700); + g_mkdir_with_parents(CERT_DIR, 0700); unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); if (data->isServer) { @@ -141,7 +141,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); g_setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1); - mkdir(WORKDIR, 0700); + g_mkdir_with_parents(WORKDIR, 0700); test_tls_init(KEYFILE); diff --git a/tests/unit/test-crypto-tlssession.c b/tests/unit/test-crypto-tlssession.c index f222959d36..615a1344b4 100644 --- a/tests/unit/test-crypto-tlssession.c +++ b/tests/unit/test-crypto-tlssession.c @@ -249,8 +249,8 @@ static void test_crypto_tls_session_x509(const void *opaque) #define CLIENT_CERT_DIR "tests/test-crypto-tlssession-client/" #define SERVER_CERT_DIR "tests/test-crypto-tlssession-server/" - mkdir(CLIENT_CERT_DIR, 0700); - mkdir(SERVER_CERT_DIR, 0700); + g_mkdir_with_parents(CLIENT_CERT_DIR, 0700); + g_mkdir_with_parents(SERVER_CERT_DIR, 0700); unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT); @@ -398,7 +398,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); g_setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1); - mkdir(WORKDIR, 0700); + g_mkdir_with_parents(WORKDIR, 0700); test_tls_init(KEYFILE); test_tls_psk_init(PSKFILE); diff --git a/tests/unit/test-io-channel-tls.c b/tests/unit/test-io-channel-tls.c index f6fb988c01..cc39247556 100644 --- a/tests/unit/test-io-channel-tls.c +++ b/tests/unit/test-io-channel-tls.c @@ -125,8 +125,8 @@ static void test_io_channel_tls(const void *opaque) #define CLIENT_CERT_DIR "tests/test-io-channel-tls-client/" #define SERVER_CERT_DIR "tests/test-io-channel-tls-server/" - mkdir(CLIENT_CERT_DIR, 0700); - mkdir(SERVER_CERT_DIR, 0700); + g_mkdir_with_parents(CLIENT_CERT_DIR, 0700); + g_mkdir_with_parents(SERVER_CERT_DIR, 0700); unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); unlink(SERVER_CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT); @@ -273,7 +273,7 @@ int main(int argc, char **argv) g_test_init(&argc, &argv, NULL); g_setenv("GNUTLS_FORCE_FIPS_MODE", "2", 1); - mkdir(WORKDIR, 0700); + g_mkdir_with_parents(WORKDIR, 0700); test_tls_init(KEYFILE); From 2549f6102e3ac9cab1954b44331c18b16faa3d97 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:51 +0800 Subject: [PATCH 0174/1020] tests/qtest: migration-test: Handle link() for win32 Windows does not provide a link() API like POSIX. Instead it provides a similar API CreateHardLink() that does the same thing, but with different argument order and return value. Signed-off-by: Bin Meng Reviewed-by: Dr. David Alan Gilbert Message-Id: <20220824094029.1634519-14-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/migration-test.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 21bd76be19..18d30bfc3c 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -876,9 +876,17 @@ test_migrate_tls_x509_start_common(QTestState *from, g_mkdir_with_parents(data->workdir, 0700); test_tls_init(data->keyfile); +#ifndef _WIN32 g_assert(link(data->keyfile, data->serverkey) == 0); +#else + g_assert(CreateHardLink(data->serverkey, data->keyfile, NULL) != 0); +#endif if (args->clientcert) { +#ifndef _WIN32 g_assert(link(data->keyfile, data->clientkey) == 0); +#else + g_assert(CreateHardLink(data->clientkey, data->keyfile, NULL) != 0); +#endif } TLS_ROOT_REQ_SIMPLE(cacertreq, data->cacert); From d1c637ecff6f8c13cc9983b96a7aad2922d283f9 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:52 +0800 Subject: [PATCH 0175/1020] backends/tpm: Exclude headers and macros that don't exist on win32 These headers and macros do not exist on Windows. Exclude them. Signed-off-by: Bin Meng Reviewed-by: Stefan Berger Message-Id: <20220824094029.1634519-15-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- backends/tpm/tpm_ioctl.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backends/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h index bd6c12cb86..d67bf0283b 100644 --- a/backends/tpm/tpm_ioctl.h +++ b/backends/tpm/tpm_ioctl.h @@ -9,8 +9,10 @@ #ifndef TPM_IOCTL_H #define TPM_IOCTL_H +#ifndef _WIN32 #include #include +#endif #ifdef HAVE_SYS_IOCCOM_H #include @@ -222,6 +224,7 @@ typedef struct ptm_setbuffersize ptm_setbuffersize; #define PTM_CAP_SET_DATAFD (1 << 12) #define PTM_CAP_SET_BUFFERSIZE (1 << 13) +#ifndef _WIN32 enum { PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap), PTM_INIT = _IOWR('P', 1, ptm_init), @@ -241,6 +244,7 @@ enum { PTM_SET_DATAFD = _IOR('P', 15, ptm_res), PTM_SET_BUFFERSIZE = _IOWR('P', 16, ptm_setbuffersize), }; +#endif /* * Commands used by the non-CUSE TPMs From f10225d7d67815df745da82b6bdd8d233609767b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:53 +0800 Subject: [PATCH 0176/1020] tests/qtest: Adapt {m48t59,rtc}-test cases for win32 There is no tm_gmtoff member in 'struct tm' on Windows. Update rtc-test.c and m48t59-test.c accordingly. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-16-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/m48t59-test.c | 2 +- tests/qtest/rtc-test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/m48t59-test.c b/tests/qtest/m48t59-test.c index b94a1230f7..843d2ced8e 100644 --- a/tests/qtest/m48t59-test.c +++ b/tests/qtest/m48t59-test.c @@ -137,7 +137,7 @@ static void cmos_get_date_time(QTestState *s, struct tm *date) date->tm_mday = mday; date->tm_mon = mon - 1; date->tm_year = base_year + year - 1900; -#ifndef __sun__ +#if !defined(__sun__) && !defined(_WIN32) date->tm_gmtoff = 0; #endif diff --git a/tests/qtest/rtc-test.c b/tests/qtest/rtc-test.c index 8126ab1bdb..02ed4e1238 100644 --- a/tests/qtest/rtc-test.c +++ b/tests/qtest/rtc-test.c @@ -111,7 +111,7 @@ static void cmos_get_date_time(struct tm *date) date->tm_mday = mday; date->tm_mon = mon - 1; date->tm_year = base_year + year - 1900; -#ifndef __sun__ +#if !defined(__sun__) && !defined(_WIN32) date->tm_gmtoff = 0; #endif From bc67e31c3ebc284bf3fee284c1cd8f2f8ef489d1 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:54 +0800 Subject: [PATCH 0177/1020] tests/qtest: Build e1000e-test for posix only The whole e1000e-test test case relies on socketpair() which does not exist on win32. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-17-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/meson.build | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index be4b30dea2..9d0f82bf1c 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -239,7 +239,6 @@ qos_test_ss.add( 'adm1272-test.c', 'ds1338-test.c', 'e1000-test.c', - 'e1000e-test.c', 'eepro100-test.c', 'es1370-test.c', 'ipoctal232-test.c', @@ -267,6 +266,9 @@ qos_test_ss.add( 'virtio-iommu-test.c', 'vmxnet3-test.c', ) +if config_host.has_key('CONFIG_POSIX') + qos_test_ss.add(files('e1000e-test.c')) +endif if have_virtfs qos_test_ss.add(files('virtio-9p-test.c')) endif From 84efa8aa4e7c568c996b9575947474c734f128b3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:56 +0800 Subject: [PATCH 0178/1020] tests/qtest: Build cases that use memory-backend-file for posix only As backends/meson.build tells us, hostmem-file.c is only supported on POSIX platforms, hence any test case that utilizes the memory backend file should be guarded by CONFIG_POSIX too. Signed-off-by: Bin Meng Acked-by: Thomas Huth Message-Id: <20220824094029.1634519-19-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/bios-tables-test.c | 10 ++++++++++ tests/qtest/cxl-test.c | 4 ++++ tests/qtest/meson.build | 3 ++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 7c5f736b51..36783966b0 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1461,6 +1461,7 @@ static void test_acpi_piix4_tcg_acpi_hmat(void) test_acpi_tcg_acpi_hmat(MACHINE_PC); } +#ifdef CONFIG_POSIX static void test_acpi_erst(const char *machine) { gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XXXXXX", NULL); @@ -1511,6 +1512,7 @@ static void test_acpi_microvm_acpi_erst(void) g_free(tmp_path); free_test_data(&data); } +#endif /* CONFIG_POSIX */ static void test_acpi_virt_tcg(void) { @@ -1551,6 +1553,7 @@ static void test_acpi_q35_viot(void) free_test_data(&data); } +#ifdef CONFIG_POSIX static void test_acpi_q35_cxl(void) { gchar *tmp_path = g_dir_make_tmp("qemu-test-cxl.XXXXXX", NULL); @@ -1593,6 +1596,7 @@ static void test_acpi_q35_cxl(void) g_free(tmp_path); free_test_data(&data); } +#endif /* CONFIG_POSIX */ static void test_acpi_virt_viot(void) { @@ -1805,8 +1809,10 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); +#ifdef CONFIG_POSIX qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst); +#endif qtest_add_func("acpi/q35/applesmc", test_acpi_q35_applesmc); qtest_add_func("acpi/q35/pvpanic-isa", test_acpi_q35_pvpanic_isa); qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); @@ -1818,7 +1824,9 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs); if (strcmp(arch, "x86_64") == 0) { qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg); +#ifdef CONFIG_POSIX qtest_add_func("acpi/microvm/acpierst", test_acpi_microvm_acpi_erst); +#endif } } if (has_kvm) { @@ -1826,7 +1834,9 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar); } qtest_add_func("acpi/q35/viot", test_acpi_q35_viot); +#ifdef CONFIG_POSIX qtest_add_func("acpi/q35/cxl", test_acpi_q35_cxl); +#endif qtest_add_func("acpi/q35/slic", test_acpi_q35_slic); } else if (strcmp(arch, "aarch64") == 0) { if (has_tcg) { diff --git a/tests/qtest/cxl-test.c b/tests/qtest/cxl-test.c index 4e6d285061..2e14da7dee 100644 --- a/tests/qtest/cxl-test.c +++ b/tests/qtest/cxl-test.c @@ -89,6 +89,7 @@ static void cxl_2root_port(void) qtest_end(); } +#ifdef CONFIG_POSIX static void cxl_t3d(void) { g_autoptr(GString) cmdline = g_string_new(NULL); @@ -133,6 +134,7 @@ static void cxl_2pxb_4rp_4t3d(void) qtest_start(cmdline->str); qtest_end(); } +#endif /* CONFIG_POSIX */ int main(int argc, char **argv) { @@ -144,8 +146,10 @@ int main(int argc, char **argv) qtest_add_func("/pci/cxl/pxb_x2_with_window", cxl_2pxb_with_window); qtest_add_func("/pci/cxl/rp", cxl_root_port); qtest_add_func("/pci/cxl/rp_x2", cxl_2root_port); +#ifdef CONFIG_POSIX qtest_add_func("/pci/cxl/type3_device", cxl_t3d); qtest_add_func("/pci/cxl/rp_x2_type3_x2", cxl_1pxb_2rp_2t3d); qtest_add_func("/pci/cxl/pxb_x2_root_port_x4_type3_x4", cxl_2pxb_4rp_4t3d); +#endif return g_test_run(); } diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 9d0f82bf1c..e910cb32ca 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -71,7 +71,8 @@ qtests_i386 = \ (config_all_devices.has_key('CONFIG_SB16') ? ['fuzz-sb16-test'] : []) + \ (config_all_devices.has_key('CONFIG_SDHCI_PCI') ? ['fuzz-sdcard-test'] : []) + \ (config_all_devices.has_key('CONFIG_ESP_PCI') ? ['am53c974-test'] : []) + \ - (config_all_devices.has_key('CONFIG_ACPI_ERST') ? ['erst-test'] : []) + \ + (config_host.has_key('CONFIG_POSIX') and \ + config_all_devices.has_key('CONFIG_ACPI_ERST') ? ['erst-test'] : []) + \ (config_all_devices.has_key('CONFIG_VIRTIO_NET') and \ config_all_devices.has_key('CONFIG_Q35') and \ config_all_devices.has_key('CONFIG_VIRTIO_PCI') and \ From 8b1525b702448396fa3e1b61ff05ae029e367dae Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:58 +0800 Subject: [PATCH 0179/1020] tests/qtest: i440fx-test: Skip running request_{bios, pflash} for win32 The request_{bios,pflash} test cases call mmap() which does not exist on win32. Exclude them. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-21-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/i440fx-test.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/qtest/i440fx-test.c b/tests/qtest/i440fx-test.c index 6d7d4d8d8f..3890f1237c 100644 --- a/tests/qtest/i440fx-test.c +++ b/tests/qtest/i440fx-test.c @@ -278,6 +278,8 @@ static void test_i440fx_pam(gconstpointer opaque) qtest_end(); } +#ifndef _WIN32 + #define BLOB_SIZE ((size_t)65536) #define ISA_BIOS_MAXSZ ((size_t)(128 * 1024)) @@ -396,6 +398,8 @@ static void request_pflash(FirmwareTestFixture *fixture, fixture->is_bios = false; } +#endif /* _WIN32 */ + int main(int argc, char **argv) { TestData data; @@ -406,8 +410,10 @@ int main(int argc, char **argv) qtest_add_data_func("i440fx/defaults", &data, test_i440fx_defaults); qtest_add_data_func("i440fx/pam", &data, test_i440fx_pam); +#ifndef _WIN32 add_firmware_test("i440fx/firmware/bios", request_bios); add_firmware_test("i440fx/firmware/pflash", request_pflash); +#endif return g_test_run(); } From d7613ee2165769303d0fa31069c4b6a840f0dae2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:39:59 +0800 Subject: [PATCH 0180/1020] tests/qtest: migration-test: Skip running test_migrate_fd_proto on win32 The test case 'test_migrate_fd_proto' calls socketpair() which does not exist on win32. Exclude it. The helper function wait_command_fd() is not needed anymore, hence exclude it too. Signed-off-by: Bin Meng Reviewed-by: Dr. David Alan Gilbert Message-Id: <20220824094029.1634519-22-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/migration-helpers.c | 2 ++ tests/qtest/migration-helpers.h | 2 ++ tests/qtest/migration-test.c | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/tests/qtest/migration-helpers.c b/tests/qtest/migration-helpers.c index c6fbeb3974..f6f3c6680f 100644 --- a/tests/qtest/migration-helpers.c +++ b/tests/qtest/migration-helpers.c @@ -34,6 +34,7 @@ static void check_stop_event(QTestState *who) } } +#ifndef _WIN32 /* * Events can get in the way of responses we are actually waiting for. */ @@ -58,6 +59,7 @@ QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...) return ret; } +#endif /* * Events can get in the way of responses we are actually waiting for. diff --git a/tests/qtest/migration-helpers.h b/tests/qtest/migration-helpers.h index 59561898d0..db0684de48 100644 --- a/tests/qtest/migration-helpers.h +++ b/tests/qtest/migration-helpers.h @@ -17,8 +17,10 @@ extern bool got_stop; +#ifndef _WIN32 G_GNUC_PRINTF(3, 4) QDict *wait_command_fd(QTestState *who, int fd, const char *command, ...); +#endif G_GNUC_PRINTF(2, 3) QDict *wait_command(QTestState *who, const char *command, ...); diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 18d30bfc3c..4728d528bb 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -1631,6 +1631,7 @@ static void test_precopy_tcp_tls_x509_reject_anon_client(void) #endif /* CONFIG_TASN1 */ #endif /* CONFIG_GNUTLS */ +#ifndef _WIN32 static void *test_migrate_fd_start_hook(QTestState *from, QTestState *to) { @@ -1699,6 +1700,7 @@ static void test_migrate_fd_proto(void) }; test_precopy_common(&args); } +#endif /* _WIN32 */ static void do_test_validate_uuid(MigrateStart *args, bool should_fail) { @@ -2531,7 +2533,9 @@ int main(int argc, char **argv) #endif /* CONFIG_GNUTLS */ /* qtest_add_func("/migration/ignore_shared", test_ignore_shared); */ +#ifndef _WIN32 qtest_add_func("/migration/fd_proto", test_migrate_fd_proto); +#endif qtest_add_func("/migration/validate_uuid", test_validate_uuid); qtest_add_func("/migration/validate_uuid_error", test_validate_uuid_error); qtest_add_func("/migration/validate_uuid_src_not_set", From f514e1477f0d098f00d739c49e91944e04612e13 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 27 Jul 2022 14:17:55 +0200 Subject: [PATCH 0181/1020] hw: Add compat machines for 7.2 Add 7.2 machine types for arm/i440fx/m68k/q35/s390x/spapr. Signed-off-by: Cornelia Huck Reviewed-by: Daniel Henrique Barboza Reviewed-by: Michael S. Tsirkin Message-Id: <20220727121755.395894-1-cohuck@redhat.com> [thuth: fixed conflict with pcmc->legacy_no_rng_seed] Signed-off-by: Thomas Huth --- hw/arm/virt.c | 11 +++++++++-- hw/core/machine.c | 3 +++ hw/i386/pc.c | 3 +++ hw/i386/pc_piix.c | 14 +++++++++++++- hw/i386/pc_q35.c | 13 ++++++++++++- hw/m68k/virt.c | 11 +++++++++-- hw/ppc/spapr.c | 17 ++++++++++++++--- hw/s390x/s390-virtio-ccw.c | 14 +++++++++++++- include/hw/boards.h | 3 +++ include/hw/i386/pc.h | 3 +++ 10 files changed, 82 insertions(+), 10 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 9633f822f3..1a6480fd2a 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -3094,10 +3094,17 @@ static void machvirt_machine_init(void) } type_init(machvirt_machine_init); -static void virt_machine_7_1_options(MachineClass *mc) +static void virt_machine_7_2_options(MachineClass *mc) { } -DEFINE_VIRT_MACHINE_AS_LATEST(7, 1) +DEFINE_VIRT_MACHINE_AS_LATEST(7, 2) + +static void virt_machine_7_1_options(MachineClass *mc) +{ + virt_machine_7_2_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); +} +DEFINE_VIRT_MACHINE(7, 1) static void virt_machine_7_0_options(MachineClass *mc) { diff --git a/hw/core/machine.c b/hw/core/machine.c index a673302cce..aa520e74a8 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -40,6 +40,9 @@ #include "hw/virtio/virtio-pci.h" #include "qom/object_interfaces.h" +GlobalProperty hw_compat_7_1[] = {}; +const size_t hw_compat_7_1_len = G_N_ELEMENTS(hw_compat_7_1); + GlobalProperty hw_compat_7_0[] = { { "arm-gicv3-common", "force-8-bit-prio", "on" }, { "nvme-ns", "eui64-default", "on"}, diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 7280c02ce3..566accf7e6 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -107,6 +107,9 @@ { "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\ { "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, }, +GlobalProperty pc_compat_7_1[] = {}; +const size_t pc_compat_7_1_len = G_N_ELEMENTS(pc_compat_7_1); + GlobalProperty pc_compat_7_0[] = {}; const size_t pc_compat_7_0_len = G_N_ELEMENTS(pc_compat_7_0); diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 20962c34e7..8043a250ad 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -432,7 +432,7 @@ static void pc_i440fx_machine_options(MachineClass *m) machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE); } -static void pc_i440fx_7_1_machine_options(MachineClass *m) +static void pc_i440fx_7_2_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_machine_options(m); @@ -442,6 +442,18 @@ static void pc_i440fx_7_1_machine_options(MachineClass *m) pcmc->legacy_no_rng_seed = true; } +DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL, + pc_i440fx_7_2_machine_options); + +static void pc_i440fx_7_1_machine_options(MachineClass *m) +{ + pc_i440fx_7_2_machine_options(m); + m->alias = NULL; + m->is_default = false; + compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len); + compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len); +} + DEFINE_I440FX_MACHINE(v7_1, "pc-i440fx-7.1", NULL, pc_i440fx_7_1_machine_options); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 2e5dae9a89..53eda50e81 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -370,7 +370,7 @@ static void pc_q35_machine_options(MachineClass *m) m->max_cpus = 288; } -static void pc_q35_7_1_machine_options(MachineClass *m) +static void pc_q35_7_2_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_options(m); @@ -379,6 +379,17 @@ static void pc_q35_7_1_machine_options(MachineClass *m) pcmc->legacy_no_rng_seed = true; } +DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL, + pc_q35_7_2_machine_options); + +static void pc_q35_7_1_machine_options(MachineClass *m) +{ + pc_q35_7_2_machine_options(m); + m->alias = NULL; + compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len); + compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len); +} + DEFINE_Q35_MACHINE(v7_1, "pc-q35-7.1", NULL, pc_q35_7_1_machine_options); diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 0aa383fa6b..3122c8ef2c 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -322,10 +322,17 @@ type_init(virt_machine_register_types) } \ type_init(machvirt_machine_##major##_##minor##_init); -static void virt_machine_7_1_options(MachineClass *mc) +static void virt_machine_7_2_options(MachineClass *mc) { } -DEFINE_VIRT_MACHINE(7, 1, true) +DEFINE_VIRT_MACHINE(7, 2, true) + +static void virt_machine_7_1_options(MachineClass *mc) +{ + virt_machine_7_2_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); +} +DEFINE_VIRT_MACHINE(7, 1, false) static void virt_machine_7_0_options(MachineClass *mc) { diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index bc9ba6e6dc..fb790b61e4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -4731,14 +4731,25 @@ static void spapr_machine_latest_class_options(MachineClass *mc) type_init(spapr_machine_register_##suffix) /* - * pseries-7.1 + * pseries-7.2 */ -static void spapr_machine_7_1_class_options(MachineClass *mc) +static void spapr_machine_7_2_class_options(MachineClass *mc) { /* Defaults for the latest behaviour inherited from the base class */ } -DEFINE_SPAPR_MACHINE(7_1, "7.1", true); +DEFINE_SPAPR_MACHINE(7_2, "7.2", true); + +/* + * pseries-7.1 + */ +static void spapr_machine_7_1_class_options(MachineClass *mc) +{ + spapr_machine_7_2_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); +} + +DEFINE_SPAPR_MACHINE(7_1, "7.1", false); /* * pseries-7.0 diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index cc3097bfee..bf1b36d824 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -792,14 +792,26 @@ bool css_migration_enabled(void) } \ type_init(ccw_machine_register_##suffix) +static void ccw_machine_7_2_instance_options(MachineState *machine) +{ +} + +static void ccw_machine_7_2_class_options(MachineClass *mc) +{ +} +DEFINE_CCW_MACHINE(7_2, "7.2", true); + static void ccw_machine_7_1_instance_options(MachineState *machine) { + ccw_machine_7_2_instance_options(machine); } static void ccw_machine_7_1_class_options(MachineClass *mc) { + ccw_machine_7_2_class_options(mc); + compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); } -DEFINE_CCW_MACHINE(7_1, "7.1", true); +DEFINE_CCW_MACHINE(7_1, "7.1", false); static void ccw_machine_7_0_instance_options(MachineState *machine) { diff --git a/include/hw/boards.h b/include/hw/boards.h index 7b416c9787..311ed17e18 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -379,6 +379,9 @@ struct MachineState { } \ type_init(machine_initfn##_register_types) +extern GlobalProperty hw_compat_7_1[]; +extern const size_t hw_compat_7_1_len; + extern GlobalProperty hw_compat_7_0[]; extern const size_t hw_compat_7_0_len; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 8435733bd6..c95333514e 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -200,6 +200,9 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid, /* sgx.c */ void pc_machine_init_sgx_epc(PCMachineState *pcms); +extern GlobalProperty pc_compat_7_1[]; +extern const size_t pc_compat_7_1_len; + extern GlobalProperty pc_compat_7_0[]; extern const size_t pc_compat_7_0_len; From 1d41de5f0524b00a3e1ac0a5b66958466f4332fa Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 27 Jul 2022 13:51:20 +0000 Subject: [PATCH 0182/1020] s390x/cpumodel: add stfl197 processor-activity-instrumentation extension 1 Add stfle 197 (processor-activity-instrumentation extension 1) to the gen16 default model and fence it off for 7.1 and older. Signed-off-by: Christian Borntraeger Reviewed-by: David Hildenbrand Message-Id: <20220727135120.12784-1-borntraeger@linux.ibm.com> Acked-by: Cornelia Huck Signed-off-by: Thomas Huth --- hw/s390x/s390-virtio-ccw.c | 1 + target/s390x/cpu_features_def.h.inc | 1 + target/s390x/gen-features.c | 2 ++ 3 files changed, 4 insertions(+) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index bf1b36d824..9a2467c889 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -804,6 +804,7 @@ DEFINE_CCW_MACHINE(7_2, "7.2", true); static void ccw_machine_7_1_instance_options(MachineState *machine) { ccw_machine_7_2_instance_options(machine); + s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAIE); } static void ccw_machine_7_1_class_options(MachineClass *mc) diff --git a/target/s390x/cpu_features_def.h.inc b/target/s390x/cpu_features_def.h.inc index 3603e5fb12..e3cfe63735 100644 --- a/target/s390x/cpu_features_def.h.inc +++ b/target/s390x/cpu_features_def.h.inc @@ -114,6 +114,7 @@ DEF_FEAT(VECTOR_PACKED_DECIMAL_ENH2, "vxpdeh2", STFL, 192, "Vector-Packed-Decima DEF_FEAT(BEAR_ENH, "beareh", STFL, 193, "BEAR-enhancement facility") DEF_FEAT(RDP, "rdp", STFL, 194, "Reset-DAT-protection facility") DEF_FEAT(PAI, "pai", STFL, 196, "Processor-Activity-Instrumentation facility") +DEF_FEAT(PAIE, "paie", STFL, 197, "Processor-Activity-Instrumentation extension-1") /* Features exposed via SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ DEF_FEAT(SIE_GSLS, "gsls", SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility") diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index ad140184b9..1558c52626 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -575,6 +575,7 @@ static uint16_t full_GEN16_GA1[] = { S390_FEAT_BEAR_ENH, S390_FEAT_RDP, S390_FEAT_PAI, + S390_FEAT_PAIE, }; @@ -669,6 +670,7 @@ static uint16_t default_GEN16_GA1[] = { S390_FEAT_BEAR_ENH, S390_FEAT_RDP, S390_FEAT_PAI, + S390_FEAT_PAIE, }; /* QEMU (CPU model) features */ From d324c21ba0b84b3033baa097e44a7fbbec815fad Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 17 Aug 2022 18:15:29 +0200 Subject: [PATCH 0183/1020] target/s390x: Fix CLFIT and CLGIT immediate size I2 is 16 bits, not 32. Found by running valgrind's none/tests/s390x/traps. Fixes: 1c2687518235 ("target-s390: Implement COMPARE AND TRAP") Signed-off-by: Ilya Leoshkevich Message-Id: <20220817161529.597414-1-iii@linux.ibm.com> Reviewed-by: David Hildenbrand Signed-off-by: Thomas Huth --- target/s390x/tcg/insn-data.def | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def index 5e448bb2c4..6d2cfe5fa2 100644 --- a/target/s390x/tcg/insn-data.def +++ b/target/s390x/tcg/insn-data.def @@ -290,8 +290,8 @@ D(0xb961, CLGRT, RRF_c, GIE, r1_o, r2_o, 0, 0, ct, 0, 1) D(0xeb23, CLT, RSY_b, MIE, r1_32u, m2_32u, 0, 0, ct, 0, 1) D(0xeb2b, CLGT, RSY_b, MIE, r1_o, m2_64, 0, 0, ct, 0, 1) - D(0xec73, CLFIT, RIE_a, GIE, r1_32u, i2_32u, 0, 0, ct, 0, 1) - D(0xec71, CLGIT, RIE_a, GIE, r1_o, i2_32u, 0, 0, ct, 0, 1) + D(0xec73, CLFIT, RIE_a, GIE, r1_32u, i2_16u, 0, 0, ct, 0, 1) + D(0xec71, CLGIT, RIE_a, GIE, r1_o, i2_16u, 0, 0, ct, 0, 1) /* CONVERT TO DECIMAL */ C(0x4e00, CVD, RX_a, Z, r1_o, a2, 0, 0, cvd, 0) From 8be934b70e923104da883b990dee18f02552d40e Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 10 Aug 2022 14:57:18 +0200 Subject: [PATCH 0184/1020] backends/hostmem: Fix support of memory-backend-memfd in qemu_maxrampagesize() It is currently not possible yet to use "memory-backend-memfd" on s390x with hugepages enabled. This problem is caused by qemu_maxrampagesize() not taking memory-backend-memfd objects into account yet, so the code in s390_memory_init() fails to enable the huge page support there via s390_set_max_pagesize(). Fix it by generalizing the code, so that it looks at qemu_ram_pagesize(memdev->mr.ram_block) instead of re-trying to get the information from the filesystem. Suggested-by: David Hildenbrand Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=2116496 Message-Id: <20220810125720.3849835-2-thuth@redhat.com> Reviewed-by: David Hildenbrand Reviewed-by: Claudio Imbrenda Signed-off-by: Thomas Huth --- backends/hostmem.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/backends/hostmem.c b/backends/hostmem.c index 624bb7ecd3..4428e06738 100644 --- a/backends/hostmem.c +++ b/backends/hostmem.c @@ -306,22 +306,12 @@ bool host_memory_backend_is_mapped(HostMemoryBackend *backend) return backend->is_mapped; } -#ifdef __linux__ size_t host_memory_backend_pagesize(HostMemoryBackend *memdev) { - Object *obj = OBJECT(memdev); - char *path = object_property_get_str(obj, "mem-path", NULL); - size_t pagesize = qemu_mempath_getpagesize(path); - - g_free(path); + size_t pagesize = qemu_ram_pagesize(memdev->mr.ram_block); + g_assert(pagesize >= qemu_real_host_page_size()); return pagesize; } -#else -size_t host_memory_backend_pagesize(HostMemoryBackend *memdev) -{ - return qemu_real_host_page_size(); -} -#endif static void host_memory_backend_memory_complete(UserCreatable *uc, Error **errp) From 90de559a669b99919e2a95ee85cb6b9b2e7256cb Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 10 Aug 2022 14:57:19 +0200 Subject: [PATCH 0185/1020] softmmu/physmem: Remove the ifdef __linux__ around the pagesize functions Now that host_memory_backend_pagesize() is not depending on the hugetlb memory path handling anymore, we can also remove the #ifdef and the TOCTTOU comment from the calling functions - the code should now work equally well on all host architectures. Message-Id: <20220810125720.3849835-3-thuth@redhat.com> Reviewed-by: Claudio Imbrenda Acked-by: David Hildenbrand Signed-off-by: Thomas Huth --- softmmu/physmem.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/softmmu/physmem.c b/softmmu/physmem.c index dc3c3e5f2e..50231bab30 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -1331,13 +1331,6 @@ GString *ram_block_format(void) return buf; } -#ifdef __linux__ -/* - * FIXME TOCTTOU: this iterates over memory backends' mem-path, which - * may or may not name the same files / on the same filesystem now as - * when we actually open and map them. Iterate over the file - * descriptors instead, and use qemu_fd_getpagesize(). - */ static int find_min_backend_pagesize(Object *obj, void *opaque) { long *hpsize_min = opaque; @@ -1391,16 +1384,6 @@ long qemu_maxrampagesize(void) object_child_foreach(memdev_root, find_max_backend_pagesize, &pagesize); return pagesize; } -#else -long qemu_minrampagesize(void) -{ - return qemu_real_host_page_size(); -} -long qemu_maxrampagesize(void) -{ - return qemu_real_host_page_size(); -} -#endif #ifdef CONFIG_POSIX static int64_t get_file_size(int fd) From 90d994619383c2665cf4f4712872c43ad2728bec Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 10 Aug 2022 14:57:20 +0200 Subject: [PATCH 0186/1020] util/mmap-alloc: Remove qemu_mempath_getpagesize() The last user of this function has just been removed, so we can drop this function now, too. Message-Id: <20220810125720.3849835-4-thuth@redhat.com> Reviewed-by: David Hildenbrand Reviewed-by: Claudio Imbrenda Signed-off-by: Thomas Huth --- include/qemu/mmap-alloc.h | 2 -- util/mmap-alloc.c | 31 ------------------------------- 2 files changed, 33 deletions(-) diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h index 5076695cc8..2825e231a7 100644 --- a/include/qemu/mmap-alloc.h +++ b/include/qemu/mmap-alloc.h @@ -4,8 +4,6 @@ size_t qemu_fd_getpagesize(int fd); -size_t qemu_mempath_getpagesize(const char *mem_path); - /** * qemu_ram_mmap: mmap anonymous memory, the specified file or device. * diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c index 5b90cb68ea..5ed7d29183 100644 --- a/util/mmap-alloc.c +++ b/util/mmap-alloc.c @@ -53,37 +53,6 @@ size_t qemu_fd_getpagesize(int fd) return qemu_real_host_page_size(); } -size_t qemu_mempath_getpagesize(const char *mem_path) -{ -#ifdef CONFIG_LINUX - struct statfs fs; - int ret; - - if (mem_path) { - do { - ret = statfs(mem_path, &fs); - } while (ret != 0 && errno == EINTR); - - if (ret != 0) { - fprintf(stderr, "Couldn't statfs() memory path: %s\n", - strerror(errno)); - exit(1); - } - - if (fs.f_type == HUGETLBFS_MAGIC) { - /* It's hugepage, return the huge page size */ - return fs.f_bsize; - } - } -#ifdef __sparc__ - /* SPARC Linux needs greater alignment than the pagesize */ - return QEMU_VMALLOC_ALIGN; -#endif -#endif - - return qemu_real_host_page_size(); -} - #define OVERCOMMIT_MEMORY_PATH "/proc/sys/vm/overcommit_memory" static bool map_noreserve_effective(int fd, uint32_t qemu_map_flags) { From e0e4c27c6f3a34fe8965ee46a301ccf61a31d3b6 Mon Sep 17 00:00:00 2001 From: Xuzhou Cheng Date: Wed, 24 Aug 2022 17:40:02 +0800 Subject: [PATCH 0187/1020] tests/qtest: libqos: Drop inclusion of There is no in the Windows build environment. Actually this is not needed in the non-win32 builds too. Drop it. Signed-off-by: Xuzhou Cheng Signed-off-by: Bin Meng Tested-by: Thomas Huth Message-Id: <20220824094029.1634519-25-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/libqos/libqos.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/qtest/libqos/libqos.c b/tests/qtest/libqos/libqos.c index 85c7641add..5ffda080ec 100644 --- a/tests/qtest/libqos/libqos.c +++ b/tests/qtest/libqos/libqos.c @@ -1,6 +1,4 @@ #include "qemu/osdep.h" -#include - #include "../libqtest.h" #include "libqos.h" #include "pci.h" From b243c73cf4dc7017e28577c4056df0655427a76e Mon Sep 17 00:00:00 2001 From: Xuzhou Cheng Date: Wed, 24 Aug 2022 17:40:03 +0800 Subject: [PATCH 0188/1020] tests/qtest: libqos: Rename malloc.h to libqos-malloc.h The qtest/libqos directory is included via the "-I" option to search for header files when building qtest. Unfortunately the malloc.h has a name conflict with the standard libc header, leading to a build failure on the Windows host, due to the MinGW libc stdlib.h header file includes malloc.h and it now gets wrongly pointed to the one in the qtest/libqos directory. Rename "qtest/libqos/malloc.h" to "qtest/libqos/libqos-malloc.h" to avoid the namespace pollution. Signed-off-by: Xuzhou Cheng Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-26-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/e1000e-test.c | 2 +- tests/qtest/fuzz/qos_fuzz.c | 2 +- tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c | 2 +- tests/qtest/libqos/arm-imx25-pdk-machine.c | 2 +- tests/qtest/libqos/arm-n800-machine.c | 2 +- tests/qtest/libqos/arm-raspi2-machine.c | 2 +- tests/qtest/libqos/arm-sabrelite-machine.c | 2 +- tests/qtest/libqos/arm-smdkc210-machine.c | 2 +- tests/qtest/libqos/arm-virt-machine.c | 2 +- tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c | 2 +- tests/qtest/libqos/e1000e.c | 2 +- tests/qtest/libqos/generic-pcihost.h | 2 +- tests/qtest/libqos/{malloc.c => libqos-malloc.c} | 2 +- tests/qtest/libqos/{malloc.h => libqos-malloc.h} | 0 tests/qtest/libqos/libqos.h | 2 +- tests/qtest/libqos/malloc-pc.h | 2 +- tests/qtest/libqos/malloc-spapr.h | 2 +- tests/qtest/libqos/meson.build | 2 +- tests/qtest/libqos/pci-pc.h | 2 +- tests/qtest/libqos/pci-spapr.h | 2 +- tests/qtest/libqos/qgraph.h | 2 +- tests/qtest/libqos/qos_external.c | 2 +- tests/qtest/libqos/qos_external.h | 2 +- tests/qtest/libqos/rtas.h | 2 +- tests/qtest/libqos/virtio-mmio.c | 2 +- tests/qtest/libqos/virtio-pci.c | 2 +- tests/qtest/libqos/virtio.h | 2 +- tests/qtest/qos-test.c | 2 +- 28 files changed, 27 insertions(+), 27 deletions(-) rename tests/qtest/libqos/{malloc.c => libqos-malloc.c} (99%) rename tests/qtest/libqos/{malloc.h => libqos-malloc.h} (100%) diff --git a/tests/qtest/e1000e-test.c b/tests/qtest/e1000e-test.c index c98779c7c0..4cdd8238f2 100644 --- a/tests/qtest/e1000e-test.c +++ b/tests/qtest/e1000e-test.c @@ -31,7 +31,7 @@ #include "qemu/iov.h" #include "qemu/module.h" #include "qemu/bitops.h" -#include "libqos/malloc.h" +#include "libqos/libqos-malloc.h" #include "libqos/e1000e.h" static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc) diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c index c856d3d500..3a3d9c16dd 100644 --- a/tests/qtest/fuzz/qos_fuzz.c +++ b/tests/qtest/fuzz/qos_fuzz.c @@ -23,7 +23,7 @@ #include "qemu/main-loop.h" #include "tests/qtest/libqtest.h" -#include "tests/qtest/libqos/malloc.h" +#include "tests/qtest/libqos/libqos-malloc.h" #include "tests/qtest/libqos/qgraph.h" #include "tests/qtest/libqos/qgraph_internal.h" #include "tests/qtest/libqos/qos_external.h" diff --git a/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c b/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c index c8a3ea11eb..ab24add8eb 100644 --- a/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c +++ b/tests/qtest/libqos/aarch64-xlnx-zcu102-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/arm-imx25-pdk-machine.c b/tests/qtest/libqos/arm-imx25-pdk-machine.c index 54d0c95330..8fe128fae8 100644 --- a/tests/qtest/libqos/arm-imx25-pdk-machine.c +++ b/tests/qtest/libqos/arm-imx25-pdk-machine.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "i2c.h" diff --git a/tests/qtest/libqos/arm-n800-machine.c b/tests/qtest/libqos/arm-n800-machine.c index ecd46b1daf..4e5afe0164 100644 --- a/tests/qtest/libqos/arm-n800-machine.c +++ b/tests/qtest/libqos/arm-n800-machine.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "i2c.h" diff --git a/tests/qtest/libqos/arm-raspi2-machine.c b/tests/qtest/libqos/arm-raspi2-machine.c index 0a2943440b..367c6c17a5 100644 --- a/tests/qtest/libqos/arm-raspi2-machine.c +++ b/tests/qtest/libqos/arm-raspi2-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/arm-sabrelite-machine.c b/tests/qtest/libqos/arm-sabrelite-machine.c index ec19a01660..94f6a20fc7 100644 --- a/tests/qtest/libqos/arm-sabrelite-machine.c +++ b/tests/qtest/libqos/arm-sabrelite-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/arm-smdkc210-machine.c b/tests/qtest/libqos/arm-smdkc210-machine.c index 4bff249ee8..9bbce924ea 100644 --- a/tests/qtest/libqos/arm-smdkc210-machine.c +++ b/tests/qtest/libqos/arm-smdkc210-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/arm-virt-machine.c b/tests/qtest/libqos/arm-virt-machine.c index 139eaba142..4e87405b58 100644 --- a/tests/qtest/libqos/arm-virt-machine.c +++ b/tests/qtest/libqos/arm-virt-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "virtio-mmio.h" #include "generic-pcihost.h" diff --git a/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c b/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c index 3be80020a6..daac762a06 100644 --- a/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c +++ b/tests/qtest/libqos/arm-xilinx-zynq-a9-machine.c @@ -19,7 +19,7 @@ #include "qemu/osdep.h" #include "../libqtest.h" #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "sdhci.h" diff --git a/tests/qtest/libqos/e1000e.c b/tests/qtest/libqos/e1000e.c index f87e0e84b2..fc14b07884 100644 --- a/tests/qtest/libqos/e1000e.c +++ b/tests/qtest/libqos/e1000e.c @@ -23,7 +23,7 @@ #include "qemu/iov.h" #include "qemu/module.h" #include "qemu/bitops.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "e1000e.h" diff --git a/tests/qtest/libqos/generic-pcihost.h b/tests/qtest/libqos/generic-pcihost.h index c693c769df..6493a8712a 100644 --- a/tests/qtest/libqos/generic-pcihost.h +++ b/tests/qtest/libqos/generic-pcihost.h @@ -14,7 +14,7 @@ #define LIBQOS_GENERIC_PCIHOST_H #include "pci.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" typedef struct QGenericPCIBus { diff --git a/tests/qtest/libqos/malloc.c b/tests/qtest/libqos/libqos-malloc.c similarity index 99% rename from tests/qtest/libqos/malloc.c rename to tests/qtest/libqos/libqos-malloc.c index f0c8f950c8..d7566972c4 100644 --- a/tests/qtest/libqos/malloc.c +++ b/tests/qtest/libqos/libqos-malloc.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qemu/host-utils.h" typedef struct MemBlock { diff --git a/tests/qtest/libqos/malloc.h b/tests/qtest/libqos/libqos-malloc.h similarity index 100% rename from tests/qtest/libqos/malloc.h rename to tests/qtest/libqos/libqos-malloc.h diff --git a/tests/qtest/libqos/libqos.h b/tests/qtest/libqos/libqos.h index ba7df448ca..9b4dd509f0 100644 --- a/tests/qtest/libqos/libqos.h +++ b/tests/qtest/libqos/libqos.h @@ -3,7 +3,7 @@ #include "../libqtest.h" #include "pci.h" -#include "malloc.h" +#include "libqos-malloc.h" typedef struct QOSState QOSState; diff --git a/tests/qtest/libqos/malloc-pc.h b/tests/qtest/libqos/malloc-pc.h index d8d79853c8..e531473601 100644 --- a/tests/qtest/libqos/malloc-pc.h +++ b/tests/qtest/libqos/malloc-pc.h @@ -13,7 +13,7 @@ #ifndef LIBQOS_MALLOC_PC_H #define LIBQOS_MALLOC_PC_H -#include "malloc.h" +#include "libqos-malloc.h" void pc_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags); diff --git a/tests/qtest/libqos/malloc-spapr.h b/tests/qtest/libqos/malloc-spapr.h index f99572fd71..f544c0d611 100644 --- a/tests/qtest/libqos/malloc-spapr.h +++ b/tests/qtest/libqos/malloc-spapr.h @@ -8,7 +8,7 @@ #ifndef LIBQOS_MALLOC_SPAPR_H #define LIBQOS_MALLOC_SPAPR_H -#include "malloc.h" +#include "libqos-malloc.h" void spapr_alloc_init(QGuestAllocator *s, QTestState *qts, QAllocOpts flags); diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build index fd5d6e5ae1..cff83c86d9 100644 --- a/tests/qtest/libqos/meson.build +++ b/tests/qtest/libqos/meson.build @@ -6,7 +6,7 @@ libqos_srcs = files( 'qos_external.c', 'pci.c', 'fw_cfg.c', - 'malloc.c', + 'libqos-malloc.c', 'libqos.c', 'sdhci-cmd.c', diff --git a/tests/qtest/libqos/pci-pc.h b/tests/qtest/libqos/pci-pc.h index 49ec9507f2..849bd493de 100644 --- a/tests/qtest/libqos/pci-pc.h +++ b/tests/qtest/libqos/pci-pc.h @@ -14,7 +14,7 @@ #define LIBQOS_PCI_PC_H #include "pci.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" typedef struct QPCIBusPC { diff --git a/tests/qtest/libqos/pci-spapr.h b/tests/qtest/libqos/pci-spapr.h index 20a43718b7..3dbf1e58ae 100644 --- a/tests/qtest/libqos/pci-spapr.h +++ b/tests/qtest/libqos/pci-spapr.h @@ -8,7 +8,7 @@ #ifndef LIBQOS_PCI_SPAPR_H #define LIBQOS_PCI_SPAPR_H -#include "malloc.h" +#include "libqos-malloc.h" #include "pci.h" #include "qgraph.h" diff --git a/tests/qtest/libqos/qgraph.h b/tests/qtest/libqos/qgraph.h index 871740c0dc..6e94824d09 100644 --- a/tests/qtest/libqos/qgraph.h +++ b/tests/qtest/libqos/qgraph.h @@ -21,7 +21,7 @@ #include #include "qemu/module.h" -#include "malloc.h" +#include "libqos-malloc.h" /* maximum path length */ #define QOS_PATH_MAX_ELEMENT_SIZE 50 diff --git a/tests/qtest/libqos/qos_external.c b/tests/qtest/libqos/qos_external.c index b7a0b873a3..c6bb8bff09 100644 --- a/tests/qtest/libqos/qos_external.c +++ b/tests/qtest/libqos/qos_external.c @@ -24,7 +24,7 @@ #include "qapi/qmp/qstring.h" #include "qemu/module.h" #include "qapi/qmp/qlist.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "qgraph_internal.h" #include "qos_external.h" diff --git a/tests/qtest/libqos/qos_external.h b/tests/qtest/libqos/qos_external.h index 8446e3df0b..ea37364887 100644 --- a/tests/qtest/libqos/qos_external.h +++ b/tests/qtest/libqos/qos_external.h @@ -21,7 +21,7 @@ #include "qgraph.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qapi/qapi-types-machine.h" #include "qapi/qapi-types-qom.h" diff --git a/tests/qtest/libqos/rtas.h b/tests/qtest/libqos/rtas.h index f38f99dfab..be8353d505 100644 --- a/tests/qtest/libqos/rtas.h +++ b/tests/qtest/libqos/rtas.h @@ -5,7 +5,7 @@ #ifndef LIBQOS_RTAS_H #define LIBQOS_RTAS_H -#include "malloc.h" +#include "libqos-malloc.h" int qrtas_get_time_of_day(QTestState *qts, QGuestAllocator *alloc, struct tm *tm, uint32_t *ns); diff --git a/tests/qtest/libqos/virtio-mmio.c b/tests/qtest/libqos/virtio-mmio.c index a6cca8613b..bd0b1d890b 100644 --- a/tests/qtest/libqos/virtio-mmio.c +++ b/tests/qtest/libqos/virtio-mmio.c @@ -12,7 +12,7 @@ #include "qemu/module.h" #include "virtio.h" #include "virtio-mmio.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "qgraph.h" #include "standard-headers/linux/virtio_ring.h" diff --git a/tests/qtest/libqos/virtio-pci.c b/tests/qtest/libqos/virtio-pci.c index 67c2498c84..485b8f6b7e 100644 --- a/tests/qtest/libqos/virtio-pci.c +++ b/tests/qtest/libqos/virtio-pci.c @@ -13,7 +13,7 @@ #include "virtio-pci.h" #include "pci.h" #include "pci-pc.h" -#include "malloc.h" +#include "libqos-malloc.h" #include "malloc-pc.h" #include "qgraph.h" #include "standard-headers/linux/virtio_ring.h" diff --git a/tests/qtest/libqos/virtio.h b/tests/qtest/libqos/virtio.h index b8bd06e1b8..7adc7cbd10 100644 --- a/tests/qtest/libqos/virtio.h +++ b/tests/qtest/libqos/virtio.h @@ -10,7 +10,7 @@ #ifndef LIBQOS_VIRTIO_H #define LIBQOS_VIRTIO_H -#include "malloc.h" +#include "libqos-malloc.h" #include "standard-headers/linux/virtio_ring.h" #define QVIRTIO_F_BAD_FEATURE 0x40000000ull diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c index f97d0a08fd..831db5cf2a 100644 --- a/tests/qtest/qos-test.c +++ b/tests/qtest/qos-test.c @@ -25,7 +25,7 @@ #include "qapi/qobject-input-visitor.h" #include "qapi/qapi-visit-machine.h" #include "qapi/qapi-visit-qom.h" -#include "libqos/malloc.h" +#include "libqos/libqos-malloc.h" #include "libqos/qgraph.h" #include "libqos/qgraph_internal.h" #include "libqos/qos_external.h" From fbde3ae8e7b73f4d5c46206ae3d22bcc470c55e1 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:40:13 +0800 Subject: [PATCH 0189/1020] tests/qtest: device-plug-test: Reverse the usage of double/single quotes The usage of double/single quotes in test_pci_unplug_json_request() should be reversed to work on both win32 and non-win32 platforms: - The value of -device parameter needs to be surrounded by "" as Windows does not drop '' when passing it to QEMU which causes QEMU command line option parser failure. - The JSON key/value pairs need to be surrounded by '' to make the JSON parser happy on Windows. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-36-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/device-plug-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c index 2e3137843e..a1fb99c8ff 100644 --- a/tests/qtest/device-plug-test.c +++ b/tests/qtest/device-plug-test.c @@ -95,7 +95,7 @@ static void test_pci_unplug_json_request(void) } QTestState *qtest = qtest_initf( - "%s -device '{\"driver\": \"virtio-mouse-pci\", \"id\": \"dev0\"}'", + "%s -device \"{'driver': 'virtio-mouse-pci', 'id': 'dev0'}\"", machine_addition); /* From de56338e068c97709febaf7ac45088b4b4eb0037 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:40:14 +0800 Subject: [PATCH 0190/1020] tests/qtest: machine-none-test: Use double quotes to pass the cpu option Single quotes in the arguments (e.g.: -cpu 'qemu64,apic-id=0') are not removed in the Windows environment before it is passed to the QEMU executable. Such argument causes a failure in the QEMU CPU option parser codes. Change to use double quotes which works fine on all platforms. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-37-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/machine-none-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/machine-none-test.c b/tests/qtest/machine-none-test.c index f92fab479f..31cc0bfb01 100644 --- a/tests/qtest/machine-none-test.c +++ b/tests/qtest/machine-none-test.c @@ -81,7 +81,7 @@ static void test_machine_cpu_cli(void) " add it to cpus_map\n", arch); return; /* TODO: die here to force all targets have a test */ } - qts = qtest_initf("-machine none -cpu '%s'", cpu_model); + qts = qtest_initf("-machine none -cpu \"%s\"", cpu_model); response = qtest_qmp(qts, "{ 'execute': 'quit' }"); g_assert(qdict_haskey(response, "return")); From bf3267e790f2877e99a6aa3c24ce6e4e9f65220d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:40:21 +0800 Subject: [PATCH 0191/1020] tests/qtest: npcm7xx_emc-test: Skip running test_{tx, rx} on win32 The test cases 'test_{tx,rx}' call socketpair() which does not exist on win32. Exclude them. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-44-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/npcm7xx_emc-test.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c index a353fef0ca..c373d24e1e 100644 --- a/tests/qtest/npcm7xx_emc-test.c +++ b/tests/qtest/npcm7xx_emc-test.c @@ -209,6 +209,7 @@ static int emc_module_index(const EMCModule *mod) return diff; } +#ifndef _WIN32 static void packet_test_clear(void *sockets) { int *test_sockets = sockets; @@ -243,6 +244,7 @@ static int *packet_test_init(int module_num, GString *cmd_line) g_test_queue_destroy(packet_test_clear, test_sockets); return test_sockets; } +#endif /* _WIN32 */ static uint32_t emc_read(QTestState *qts, const EMCModule *mod, NPCM7xxPWMRegister regno) @@ -250,6 +252,7 @@ static uint32_t emc_read(QTestState *qts, const EMCModule *mod, return qtest_readl(qts, mod->base_addr + regno * sizeof(uint32_t)); } +#ifndef _WIN32 static void emc_write(QTestState *qts, const EMCModule *mod, NPCM7xxPWMRegister regno, uint32_t value) { @@ -339,6 +342,7 @@ static bool emc_soft_reset(QTestState *qts, const EMCModule *mod) g_message("%s: Timeout expired", __func__); return false; } +#endif /* _WIN32 */ /* Check emc registers are reset to default value. */ static void test_init(gconstpointer test_data) @@ -387,6 +391,7 @@ static void test_init(gconstpointer test_data) qtest_quit(qts); } +#ifndef _WIN32 static bool emc_wait_irq(QTestState *qts, const EMCModule *mod, int step, bool is_tx) { @@ -843,6 +848,7 @@ static void test_rx(gconstpointer test_data) qtest_quit(qts); } +#endif /* _WIN32 */ static void emc_add_test(const char *name, const TestData* td, GTestDataFunc fn) @@ -865,8 +871,10 @@ int main(int argc, char **argv) td->module = &emc_module_list[i]; add_test(init, td); +#ifndef _WIN32 add_test(tx, td); add_test(rx, td); +#endif } return g_test_run(); From 94add6ee24d55be96dd029fc506ea9a2df38f8e8 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 24 Aug 2022 17:40:23 +0800 Subject: [PATCH 0192/1020] tests/qtest: prom-env-test: Use double quotes to pass the prom-env option Single quotes like -prom-env 'nvramrc=cafec0de 4000 l!' in the arguments are not removed in the Windows environment before it is passed to the QEMU executable. Such argument causes a failure in the QEMU prom-env option parser codes. Change to use double quotes which works fine on all platforms. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220824094029.1634519-46-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/prom-env-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/prom-env-test.c b/tests/qtest/prom-env-test.c index c2b0448e55..39ccb59797 100644 --- a/tests/qtest/prom-env-test.c +++ b/tests/qtest/prom-env-test.c @@ -58,8 +58,8 @@ static void test_machine(const void *machine) " -machine " PSERIES_DEFAULT_CAPABILITIES; } - qts = qtest_initf("-M %s -accel tcg %s -prom-env 'use-nvramrc?=true' " - "-prom-env 'nvramrc=%x %x l!' ", (const char *)machine, + qts = qtest_initf("-M %s -accel tcg %s -prom-env \"use-nvramrc?=true\" " + "-prom-env \"nvramrc=%x %x l!\" ", (const char *)machine, extra_args, MAGIC, ADDRESS); check_guest_memory(qts); qtest_quit(qts); From 0026be1d0f836ee899b47c6b925fdfc9baa9fd2f Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 24 Aug 2022 17:11:18 +0200 Subject: [PATCH 0193/1020] tests/vm: Add libslirp to the VM tests We are going to remove the slirp submodule from the QEMU repository, so we should make sure to install the distro's libslirp to get the same test coverage as before in the VMs. Message-Id: <20220824151122.704946-3-thuth@redhat.com> Acked-by: Samuel Thibault Signed-off-by: Thomas Huth --- tests/vm/freebsd | 3 +++ tests/vm/haiku.x86_64 | 3 ++- tests/vm/netbsd | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/vm/freebsd b/tests/vm/freebsd index cd1fabde52..3643fe325d 100755 --- a/tests/vm/freebsd +++ b/tests/vm/freebsd @@ -63,6 +63,9 @@ class FreeBSDVM(basevm.BaseVM): # libs: migration "zstd", + + # libs: networking + "libslirp", ] BUILD_SCRIPT = """ diff --git a/tests/vm/haiku.x86_64 b/tests/vm/haiku.x86_64 index 936f7d2ae2..29668bc272 100755 --- a/tests/vm/haiku.x86_64 +++ b/tests/vm/haiku.x86_64 @@ -71,6 +71,7 @@ class HaikuVM(basevm.BaseVM): "devel:libpixman_1", "devel:libpng16", "devel:libsdl2_2.0", + "devel:libslirp", "devel:libsnappy", "devel:libssh2", "devel:libtasn1", @@ -89,7 +90,7 @@ class HaikuVM(basevm.BaseVM): mkdir -p /usr/bin ln -s /boot/system/bin/env /usr/bin/env cd ../build - ../src/configure --disable-slirp {configure_opts}; + ../src/configure {configure_opts}; make --output-sync -j{jobs} {target} {verbose}; """ diff --git a/tests/vm/netbsd b/tests/vm/netbsd index aa883ec23c..da6773ff59 100755 --- a/tests/vm/netbsd +++ b/tests/vm/netbsd @@ -54,6 +54,9 @@ class NetBSDVM(basevm.BaseVM): # libs: migration "zstd", + + # libs: networking + "libslirp", ] BUILD_SCRIPT = """ From 0fc389fe9208f0bfd9fa41cd7e6315a0989a3729 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 24 Aug 2022 17:11:21 +0200 Subject: [PATCH 0194/1020] tests/avocado: Do not run tests that require libslirp if it is not available Some avocado tests blindly assume that QEMU has been compiled with libslirp enabled and fail badly if it is missing. Add a proper check to cancel the tests in this case. Message-Id: <20220824151122.704946-6-thuth@redhat.com> Acked-by: Samuel Thibault Signed-off-by: Thomas Huth --- tests/avocado/avocado_qemu/__init__.py | 7 +++++++ tests/avocado/info_usernet.py | 1 + tests/avocado/replay_linux.py | 1 + 3 files changed, 9 insertions(+) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index 9d17a287cf..3b5b8e7f2d 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -299,6 +299,12 @@ class QemuSystemTest(QemuBaseTest): self.cancel("%s accelerator does not seem to be " "available" % accelerator) + def require_netdev(self, netdevname): + netdevhelp = run_cmd([self.qemu_bin, + '-M', 'none', '-netdev', 'help'])[0]; + if netdevhelp.find('\n' + netdevname + '\n') < 0: + self.cancel('no support for user networking') + def _new_vm(self, name, *args): self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") vm = QEMUMachine(self.qemu_bin, base_temp_dir=self.workdir, @@ -550,6 +556,7 @@ class LinuxTest(LinuxSSHMixIn, QemuSystemTest): def setUp(self, ssh_pubkey=None, network_device_type='virtio-net'): super().setUp() + self.require_netdev('user') self._set_distro() self.vm.add_args('-smp', self.smp) self.vm.add_args('-m', self.memory) diff --git a/tests/avocado/info_usernet.py b/tests/avocado/info_usernet.py index dc01f74150..b862a47dba 100644 --- a/tests/avocado/info_usernet.py +++ b/tests/avocado/info_usernet.py @@ -16,6 +16,7 @@ from qemu.utils import get_info_usernet_hostfwd_port class InfoUsernet(QemuSystemTest): def test_hostfwd(self): + self.require_netdev('user') self.vm.add_args('-netdev', 'user,id=vnet,hostfwd=:127.0.0.1:0-:22') self.vm.launch() res = self.vm.command('human-monitor-command', diff --git a/tests/avocado/replay_linux.py b/tests/avocado/replay_linux.py index e1f9981a34..a76dd507fc 100644 --- a/tests/avocado/replay_linux.py +++ b/tests/avocado/replay_linux.py @@ -55,6 +55,7 @@ class ReplayLinux(LinuxTest): '%s,drive=disk%s-rr%s' % (device, id, bus_string)) def launch_and_wait(self, record, args, shift): + self.require_netdev('user') vm = self.get_vm() vm.add_args('-smp', '1') vm.add_args('-m', '1024') From 0aeefd5fcb6538074391a5281349bf1dbeb20688 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 24 Aug 2022 10:09:26 +0200 Subject: [PATCH 0195/1020] tests/avocado: Fix trivial typo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intention was likely to use "intend" instead of "indent" here. Message-Id: <20220824080926.568935-1-thuth@redhat.com> Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Thomas Huth --- tests/avocado/avocado_qemu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index 3b5b8e7f2d..5f1d3e551c 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -518,7 +518,7 @@ class LinuxDistro: class LinuxTest(LinuxSSHMixIn, QemuSystemTest): """Facilitates having a cloud-image Linux based available. - For tests that indent to interact with guests, this is a better choice + For tests that intend to interact with guests, this is a better choice to start with than the more vanilla `QemuSystemTest` class. """ From 0285a0ec60484b2cfe0da1c39e992b8735675482 Mon Sep 17 00:00:00 2001 From: Matheus Tavares Bernardino Date: Tue, 23 Aug 2022 10:46:19 -0300 Subject: [PATCH 0196/1020] docs/devel/testing: fix minor typo Signed-off-by: Matheus Tavares Bernardino Message-Id: <421fb28678d1077c0b14978e359b4e1469cc0168.1661262376.git.quic_mathbern@quicinc.com> Signed-off-by: Thomas Huth --- docs/devel/testing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index 3f6ebd5073..f35f117d95 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -297,7 +297,7 @@ build and test QEMU in predefined and widely accessible Linux environments. This makes it possible to expand the test coverage across distros, toolchain flavors and library versions. The support was originally written for Docker although we also support Podman as -an alternative container runtime. Although the many of the target +an alternative container runtime. Although many of the target names and scripts are prefixed with "docker" the system will automatically run on whichever is configured. From 5f2992fe1ec5594e5cf5b17d1a9979f46054a7cc Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 23 Aug 2022 13:20:36 +0200 Subject: [PATCH 0197/1020] gitlab-ci: Only use one process in Windows jobs for compilation The Windows jobs are currently aborting at weird places - and there's the suspicion that it's due to memory constraints in the Windows containers. Let's switch to single-threaded compilation to decrease the pressure on the memory load, and to make the job more deterministic for further investigations. Message-Id: <20220825193323.104768-1-thuth@redhat.com> Reviewed-by: Bin Meng Signed-off-by: Thomas Huth --- .gitlab-ci.d/windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index c4bde758be..da6013904a 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -61,7 +61,7 @@ msys2-64bit: - .\msys64\usr\bin\bash -lc './configure --target-list=x86_64-softmmu --enable-capstone --without-default-devices' - .\msys64\usr\bin\bash -lc "sed -i '/^ROMS=/d' build/config-host.mak" - - .\msys64\usr\bin\bash -lc 'make -j2' + - .\msys64\usr\bin\bash -lc 'make' - .\msys64\usr\bin\bash -lc 'make check' msys2-32bit: @@ -94,5 +94,5 @@ msys2-32bit: - mkdir output - cd output - ..\msys64\usr\bin\bash -lc "../configure --target-list=ppc64-softmmu" - - ..\msys64\usr\bin\bash -lc 'make -j2' + - ..\msys64\usr\bin\bash -lc 'make' - ..\msys64\usr\bin\bash -lc 'make check' From 146f39d7f3b08caa3a2a0645474465437cf085b8 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Mon, 29 Aug 2022 17:33:01 +0900 Subject: [PATCH 0198/1020] tests/qtest/ac97-test: Correct reference to driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Akihiko Odaki Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220829083301.143527-1-akihiko.odaki@daynix.com> Signed-off-by: Thomas Huth --- tests/qtest/ac97-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/ac97-test.c b/tests/qtest/ac97-test.c index b084e31bff..74103efdfa 100644 --- a/tests/qtest/ac97-test.c +++ b/tests/qtest/ac97-test.c @@ -28,7 +28,7 @@ static void *ac97_get_driver(void *obj, const char *interface) return &ac97->dev; } - fprintf(stderr, "%s not present in e1000e\n", interface); + fprintf(stderr, "%s not present in ac97\n", interface); g_assert_not_reached(); } From da55be562ea2b082da5d55cc12730fe8fe118852 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Mon, 29 Aug 2022 14:19:39 +0200 Subject: [PATCH 0199/1020] tests/avocado/migration: Get find_free_port() from the ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In upstream Avocado, the find_free_port() function is not available from "network" anymore, but must be used via "ports", see: https://github.com/avocado-framework/avocado/commit/22fc98c6ff76cc55c48 To be able to update to a newer Avocado version later, let's use the new way for accessing the find_free_port() function here. Signed-off-by: Thomas Huth Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220829121939.209329-1-thuth@redhat.com> Signed-off-by: Thomas Huth --- tests/avocado/migration.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/avocado/migration.py b/tests/avocado/migration.py index 584d6ef53f..4b25680c50 100644 --- a/tests/avocado/migration.py +++ b/tests/avocado/migration.py @@ -14,7 +14,7 @@ import tempfile from avocado_qemu import QemuSystemTest from avocado import skipUnless -from avocado.utils import network +from avocado.utils.network import ports from avocado.utils import wait from avocado.utils.path import find_command @@ -57,7 +57,7 @@ class Migration(QemuSystemTest): self.assert_migration(source_vm, dest_vm) def _get_free_port(self): - port = network.find_free_port() + port = ports.find_free_port() if port is None: self.cancel('Failed to find a free port') return port From 621da7789083b80d6f1ff1c0fb499334007b4f51 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 30 Aug 2022 09:40:11 -0700 Subject: [PATCH 0200/1020] Update version for v7.1.0 release Signed-off-by: Richard Henderson --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index b8d5f3ebb6..a3fcc7121b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.0.94 +7.1.0 From 93fac696d241dccb04ebb9d23da55fc1e9d8ee36 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 30 Aug 2022 09:40:41 -0700 Subject: [PATCH 0201/1020] Open 7.2 development tree Signed-off-by: Richard Henderson --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index a3fcc7121b..72cf60d0ec 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -7.1.0 +7.1.50 From c49b67f72b1a875ca355a170759303b0faa959ca Mon Sep 17 00:00:00 2001 From: Alexey Kardashevskiy Date: Tue, 19 Jul 2022 17:48:03 +1000 Subject: [PATCH 0202/1020] pseries: Update SLOF firmware image The only change is that now SLOF can also boot big endian zImage but kernel-addr=0 is still required. Signed-off-by: Alexey Kardashevskiy Signed-off-by: Daniel Henrique Barboza --- docs/system/ppc/pseries.rst | 2 +- pc-bios/README | 2 +- pc-bios/slof.bin | Bin 992384 -> 995176 bytes roms/SLOF | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/system/ppc/pseries.rst b/docs/system/ppc/pseries.rst index 3e1bbe6726..a876d897b6 100644 --- a/docs/system/ppc/pseries.rst +++ b/docs/system/ppc/pseries.rst @@ -62,7 +62,7 @@ Booting via ``-kernel`` supports the following: +-------------------+-------------------+------------------+ | vmlinux LE | ✓ | ✓ | +-------------------+-------------------+------------------+ -| zImage.pseries BE | x | ✓¹ | +| zImage.pseries BE | ✓¹ | ✓¹ | +-------------------+-------------------+------------------+ | zImage.pseries LE | ✓ | ✓ | +-------------------+-------------------+------------------+ diff --git a/pc-bios/README b/pc-bios/README index ba6c15e769..b94f3fb081 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -14,7 +14,7 @@ - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware implementation for certain IBM POWER hardware. The sources are at https://github.com/aik/SLOF, and the image currently in qemu is - built from git tag qemu-slof-20220110. + built from git tag qemu-slof-20220719. - VOF (Virtual Open Firmware) is a minimalistic firmware to work with -machine pseries,x-vof=on. When enabled, the firmware acts as a slim shim and diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin index cbbe23e9107575c64c3264badacfad8b0a7ca090..ef9b81d6282b536e3b715e900e9504d2d7b6b916 100644 GIT binary patch literal 995176 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

fYcvuoXG_N1<;8i5b)VMft!?|FcbE&gQDwk4 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�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 literal 992384 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 gja5ikA6`A5R8 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%0DWs^7iKo)HD?@n!gekS!nH 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 Date: Sun, 31 Jul 2022 11:33:58 +1000 Subject: [PATCH 0203/1020] target/ppc: Fix host PVR matching for KVM ppc_cpu_compare_class_pvr_mask() should match the best CPU class in the family, because it is used by the KVM subsystem to find the host CPU class. Since commit 03ae4133ab8 ("target-ppc: Add pvr_match() callback"), it matches any class in the family (the first one in the comparison list). Since commit f30c843ced5 ("ppc/pnv: Introduce PowerNV machines with fixed CPU models"), pnv has relied on pnv_match having these new semantics to check machine compatibility with a CPU family. Resolve this by adding a parameter to the pvr_match function to select the best or any match, and restore the old behaviour for the KVM case. Prior to this fix, e.g., a POWER9 DD2.3 KVM host matches to the power9_v1.0 class (because that happens to be the first POWER9 family CPU compared). After the patch, it matches the power9_v2.0 class. This approach requires pnv_match contain knowledge of the CPU classes implemented in the same family, which feels ugly. But pushing the 'best' match down to the class would still require they know about one another which is not obviously much better. For now this gets things working. Fixes: 03ae4133ab8 ("target-ppc: Add pvr_match() callback") Signed-off-by: Nicholas Piggin Reviewed-by: Daniel Henrique Barboza Message-Id: <20220731013358.170187-1-npiggin@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/pnv.c | 2 +- target/ppc/cpu-qom.h | 6 ++- target/ppc/cpu_init.c | 91 +++++++++++++++++++++++++++++++++---------- target/ppc/machine.c | 2 +- 4 files changed, 77 insertions(+), 24 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index d3f77c8367..a4cb4cf10b 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -714,7 +714,7 @@ static bool pnv_match_cpu(const char *default_type, const char *cpu_type) PowerPCCPUClass *ppc = POWERPC_CPU_CLASS(object_class_by_name(cpu_type)); - return ppc_default->pvr_match(ppc_default, ppc->pvr); + return ppc_default->pvr_match(ppc_default, ppc->pvr, false); } static void pnv_ipmi_bt_init(ISABus *bus, IPMIBmc *bmc, uint32_t irq) diff --git a/target/ppc/cpu-qom.h b/target/ppc/cpu-qom.h index ad7e3c3db9..89ff88f28c 100644 --- a/target/ppc/cpu-qom.h +++ b/target/ppc/cpu-qom.h @@ -158,7 +158,11 @@ struct PowerPCCPUClass { void (*parent_parse_features)(const char *type, char *str, Error **errp); uint32_t pvr; - bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr); + /* + * If @best is false, match if pcc is in the family of pvr + * Else match only if pcc is the best match for pvr in this family. + */ + bool (*pvr_match)(struct PowerPCCPUClass *pcc, uint32_t pvr, bool best); uint64_t pcr_mask; /* Available bits in PCR register */ uint64_t pcr_supported; /* Bits for supported PowerISA versions */ uint32_t svr; diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index d1493a660c..899c4a586e 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5912,15 +5912,25 @@ static void init_proc_POWER7(CPUPPCState *env) ppcPOWER7_irq_init(env_archcpu(env)); } -static bool ppc_pvr_match_power7(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_power7(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER7P_BASE) { - return true; + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best) { + if (base == CPU_POWERPC_POWER7_BASE) { + return true; + } + if (base == CPU_POWERPC_POWER7P_BASE) { + return true; + } } - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER7_BASE) { - return true; + + if (base != pcc_base) { + return false; } - return false; + + return true; } static bool cpu_has_work_POWER7(CPUState *cs) @@ -6073,18 +6083,27 @@ static void init_proc_POWER8(CPUPPCState *env) ppcPOWER7_irq_init(env_archcpu(env)); } -static bool ppc_pvr_match_power8(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_power8(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8NVL_BASE) { - return true; + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best) { + if (base == CPU_POWERPC_POWER8_BASE) { + return true; + } + if (base == CPU_POWERPC_POWER8E_BASE) { + return true; + } + if (base == CPU_POWERPC_POWER8NVL_BASE) { + return true; + } } - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8E_BASE) { - return true; + if (base != pcc_base) { + return false; } - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER8_BASE) { - return true; - } - return false; + + return true; } static bool cpu_has_work_POWER8(CPUState *cs) @@ -6282,11 +6301,26 @@ static void init_proc_POWER9(CPUPPCState *env) ppcPOWER9_irq_init(env_archcpu(env)); } -static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER9_BASE) { + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best) { + if (base == CPU_POWERPC_POWER9_BASE) { + return true; + } + } + + if (base != pcc_base) { + return false; + } + + if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) { + /* Major DD version matches to power9_v1.0 and power9_v2.0 */ return true; } + return false; } @@ -6499,11 +6533,26 @@ static void init_proc_POWER10(CPUPPCState *env) ppcPOWER9_irq_init(env_archcpu(env)); } -static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { - if ((pvr & CPU_POWERPC_POWER_SERVER_MASK) == CPU_POWERPC_POWER10_BASE) { + uint32_t base = pvr & CPU_POWERPC_POWER_SERVER_MASK; + uint32_t pcc_base = pcc->pvr & CPU_POWERPC_POWER_SERVER_MASK; + + if (!best) { + if (base == CPU_POWERPC_POWER10_BASE) { + return true; + } + } + + if (base != pcc_base) { + return false; + } + + if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) { + /* Major DD version matches to power10_v1.0 and power10_v2.0 */ return true; } + return false; } @@ -6910,7 +6959,7 @@ static gint ppc_cpu_compare_class_pvr_mask(gconstpointer a, gconstpointer b) return -1; } - if (pcc->pvr_match(pcc, pvr)) { + if (pcc->pvr_match(pcc, pvr, true)) { return 0; } @@ -7308,7 +7357,7 @@ static void ppc_cpu_instance_finalize(Object *obj) ppc_hash64_finalize(cpu); } -static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr) +static bool ppc_pvr_match_default(PowerPCCPUClass *pcc, uint32_t pvr, bool best) { return pcc->pvr == pvr; } diff --git a/target/ppc/machine.c b/target/ppc/machine.c index a7d9036c09..be6eb3d968 100644 --- a/target/ppc/machine.c +++ b/target/ppc/machine.c @@ -234,7 +234,7 @@ static bool pvr_match(PowerPCCPU *cpu, uint32_t pvr) if (pvr == pcc->pvr) { return true; } - return pcc->pvr_match(pcc, pvr); + return pcc->pvr_match(pcc, pvr, true); } static int cpu_post_load(void *opaque, int version_id) From 0bf4d77e5922128506a3495d72ee9f432726c085 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 11 Aug 2022 19:37:26 +1000 Subject: [PATCH 0204/1020] ppc/pnv: Add initial P9/10 SBE model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SBE (Self Boot Engine) are on-chip microcontrollers that perform early boot steps, as well as provide some runtime facilities (e.g., timer, secure register access, MPIPL). The latter facilities are accessed mostly via a message system called SBEFIFO. This driver provides initial emulation for the SBE runtime registers and a very basic SBEFIFO implementation that provides the timer command. This covers the basic SBE behaviour expected by skiboot when booting. Reviewed-by: Cédric Le Goater Signed-off-by: Nicholas Piggin Message-Id: <20220811093726.1442343-1-npiggin@gmail.com> [danielhb: fixed SBE_HOST_RESPONSE_MASK long line] Signed-off-by: Daniel Henrique Barboza --- hw/ppc/meson.build | 1 + hw/ppc/pnv.c | 25 +++ hw/ppc/pnv_sbe.c | 414 +++++++++++++++++++++++++++++++++++++ hw/ppc/pnv_xscom.c | 3 + hw/ppc/trace-events | 11 + include/hw/ppc/pnv.h | 3 + include/hw/ppc/pnv_sbe.h | 55 +++++ include/hw/ppc/pnv_xscom.h | 12 ++ 8 files changed, 524 insertions(+) create mode 100644 hw/ppc/pnv_sbe.c create mode 100644 include/hw/ppc/pnv_sbe.h diff --git a/hw/ppc/meson.build b/hw/ppc/meson.build index aa4c8e6a2e..62801923f3 100644 --- a/hw/ppc/meson.build +++ b/hw/ppc/meson.build @@ -46,6 +46,7 @@ ppc_ss.add(when: 'CONFIG_POWERNV', if_true: files( 'pnv_lpc.c', 'pnv_psi.c', 'pnv_occ.c', + 'pnv_sbe.c', 'pnv_bmc.c', 'pnv_homer.c', 'pnv_pnor.c', diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index a4cb4cf10b..0c3aad430b 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1397,6 +1397,8 @@ static void pnv_chip_power9_instance_init(Object *obj) object_initialize_child(obj, "occ", &chip9->occ, TYPE_PNV9_OCC); + object_initialize_child(obj, "sbe", &chip9->sbe, TYPE_PNV9_SBE); + object_initialize_child(obj, "homer", &chip9->homer, TYPE_PNV9_HOMER); /* Number of PECs is the chip default */ @@ -1549,6 +1551,17 @@ static void pnv_chip_power9_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), PNV9_OCC_SENSOR_BASE(chip), &chip9->occ.sram_regs); + /* SBE */ + if (!qdev_realize(DEVICE(&chip9->sbe), NULL, errp)) { + return; + } + pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_CTRL_BASE, + &chip9->sbe.xscom_ctrl_regs); + pnv_xscom_add_subregion(chip, PNV9_XSCOM_SBE_MBOX_BASE, + &chip9->sbe.xscom_mbox_regs); + qdev_connect_gpio_out(DEVICE(&chip9->sbe), 0, qdev_get_gpio_in( + DEVICE(&chip9->psi), PSIHB9_IRQ_PSU)); + /* HOMER */ object_property_set_link(OBJECT(&chip9->homer), "chip", OBJECT(chip), &error_abort); @@ -1613,6 +1626,7 @@ static void pnv_chip_power10_instance_init(Object *obj) object_initialize_child(obj, "psi", &chip10->psi, TYPE_PNV10_PSI); object_initialize_child(obj, "lpc", &chip10->lpc, TYPE_PNV10_LPC); object_initialize_child(obj, "occ", &chip10->occ, TYPE_PNV10_OCC); + object_initialize_child(obj, "sbe", &chip10->sbe, TYPE_PNV10_SBE); object_initialize_child(obj, "homer", &chip10->homer, TYPE_PNV10_HOMER); chip->num_pecs = pcc->num_pecs; @@ -1754,6 +1768,17 @@ static void pnv_chip_power10_realize(DeviceState *dev, Error **errp) PNV10_OCC_SENSOR_BASE(chip), &chip10->occ.sram_regs); + /* SBE */ + if (!qdev_realize(DEVICE(&chip10->sbe), NULL, errp)) { + return; + } + pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_CTRL_BASE, + &chip10->sbe.xscom_ctrl_regs); + pnv_xscom_add_subregion(chip, PNV10_XSCOM_SBE_MBOX_BASE, + &chip10->sbe.xscom_mbox_regs); + qdev_connect_gpio_out(DEVICE(&chip10->sbe), 0, qdev_get_gpio_in( + DEVICE(&chip10->psi), PSIHB9_IRQ_PSU)); + /* HOMER */ object_property_set_link(OBJECT(&chip10->homer), "chip", OBJECT(chip), &error_abort); diff --git a/hw/ppc/pnv_sbe.c b/hw/ppc/pnv_sbe.c new file mode 100644 index 0000000000..1c7812a135 --- /dev/null +++ b/hw/ppc/pnv_sbe.c @@ -0,0 +1,414 @@ +/* + * QEMU PowerPC PowerNV Emulation of some SBE behaviour + * + * Copyright (c) 2022, IBM Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "qemu/osdep.h" +#include "target/ppc/cpu.h" +#include "qapi/error.h" +#include "qemu/log.h" +#include "qemu/module.h" +#include "hw/irq.h" +#include "hw/qdev-properties.h" +#include "hw/ppc/pnv.h" +#include "hw/ppc/pnv_xscom.h" +#include "hw/ppc/pnv_sbe.h" +#include "trace.h" + +/* + * Most register and command definitions come from skiboot. + * + * xscom addresses are adjusted to be relative to xscom subregion bases + */ + +/* + * SBE MBOX register address + * Reg 0 - 3 : Host to send command packets to SBE + * Reg 4 - 7 : SBE to send response packets to Host + */ +#define PSU_HOST_SBE_MBOX_REG0 0x00000000 +#define PSU_HOST_SBE_MBOX_REG1 0x00000001 +#define PSU_HOST_SBE_MBOX_REG2 0x00000002 +#define PSU_HOST_SBE_MBOX_REG3 0x00000003 +#define PSU_HOST_SBE_MBOX_REG4 0x00000004 +#define PSU_HOST_SBE_MBOX_REG5 0x00000005 +#define PSU_HOST_SBE_MBOX_REG6 0x00000006 +#define PSU_HOST_SBE_MBOX_REG7 0x00000007 +#define PSU_SBE_DOORBELL_REG_RW 0x00000010 +#define PSU_SBE_DOORBELL_REG_AND 0x00000011 +#define PSU_SBE_DOORBELL_REG_OR 0x00000012 +#define PSU_HOST_DOORBELL_REG_RW 0x00000013 +#define PSU_HOST_DOORBELL_REG_AND 0x00000014 +#define PSU_HOST_DOORBELL_REG_OR 0x00000015 + +/* + * Doorbell register to trigger SBE interrupt. Set by OPAL to inform + * the SBE about a waiting message in the Host/SBE mailbox registers + */ +#define HOST_SBE_MSG_WAITING PPC_BIT(0) + +/* + * Doorbell register for host bridge interrupt. Set by the SBE to inform + * host about a response message in the Host/SBE mailbox registers + */ +#define SBE_HOST_RESPONSE_WAITING PPC_BIT(0) +#define SBE_HOST_MSG_READ PPC_BIT(1) +#define SBE_HOST_STOP15_EXIT PPC_BIT(2) +#define SBE_HOST_RESET PPC_BIT(3) +#define SBE_HOST_PASSTHROUGH PPC_BIT(4) +#define SBE_HOST_TIMER_EXPIRY PPC_BIT(14) +#define SBE_HOST_RESPONSE_MASK (PPC_BITMASK(0, 4) | \ + SBE_HOST_TIMER_EXPIRY) + +/* SBE Control Register */ +#define SBE_CONTROL_REG_RW 0x00000000 + +/* SBE interrupt s0/s1 bits */ +#define SBE_CONTROL_REG_S0 PPC_BIT(14) +#define SBE_CONTROL_REG_S1 PPC_BIT(15) + +struct sbe_msg { + uint64_t reg[4]; +}; + +static uint64_t pnv_sbe_power9_xscom_ctrl_read(void *opaque, hwaddr addr, + unsigned size) +{ + uint32_t offset = addr >> 3; + uint64_t val = 0; + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented register: Ox%" + HWADDR_PRIx "\n", addr >> 3); + } + + trace_pnv_sbe_xscom_ctrl_read(addr, val); + + return val; +} + +static void pnv_sbe_power9_xscom_ctrl_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + uint32_t offset = addr >> 3; + + trace_pnv_sbe_xscom_ctrl_write(addr, val); + + switch (offset) { + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented register: Ox%" + HWADDR_PRIx "\n", addr >> 3); + } +} + +static const MemoryRegionOps pnv_sbe_power9_xscom_ctrl_ops = { + .read = pnv_sbe_power9_xscom_ctrl_read, + .write = pnv_sbe_power9_xscom_ctrl_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void pnv_sbe_set_host_doorbell(PnvSBE *sbe, uint64_t val) +{ + val &= SBE_HOST_RESPONSE_MASK; /* Is this right? What does HW do? */ + sbe->host_doorbell = val; + + trace_pnv_sbe_reg_set_host_doorbell(val); + qemu_set_irq(sbe->psi_irq, !!val); +} + +/* SBE Target Type */ +#define SBE_TARGET_TYPE_PROC 0x00 +#define SBE_TARGET_TYPE_EX 0x01 +#define SBE_TARGET_TYPE_PERV 0x02 +#define SBE_TARGET_TYPE_MCS 0x03 +#define SBE_TARGET_TYPE_EQ 0x04 +#define SBE_TARGET_TYPE_CORE 0x05 + +/* SBE MBOX command class */ +#define SBE_MCLASS_FIRST 0xD1 +#define SBE_MCLASS_CORE_STATE 0xD1 +#define SBE_MCLASS_SCOM 0xD2 +#define SBE_MCLASS_RING 0xD3 +#define SBE_MCLASS_TIMER 0xD4 +#define SBE_MCLASS_MPIPL 0xD5 +#define SBE_MCLASS_SECURITY 0xD6 +#define SBE_MCLASS_GENERIC 0xD7 +#define SBE_MCLASS_LAST 0xD7 + +/* + * Commands are provided in xxyy form where: + * - xx : command class + * - yy : command + * + * Both request and response message uses same seq ID, + * command class and command. + */ +#define SBE_CMD_CTRL_DEADMAN_LOOP 0xD101 +#define SBE_CMD_MULTI_SCOM 0xD201 +#define SBE_CMD_PUT_RING_FORM_IMAGE 0xD301 +#define SBE_CMD_CONTROL_TIMER 0xD401 +#define SBE_CMD_GET_ARCHITECTED_REG 0xD501 +#define SBE_CMD_CLR_ARCHITECTED_REG 0xD502 +#define SBE_CMD_SET_UNSEC_MEM_WINDOW 0xD601 +#define SBE_CMD_GET_SBE_FFDC 0xD701 +#define SBE_CMD_GET_CAPABILITY 0xD702 +#define SBE_CMD_READ_SBE_SEEPROM 0xD703 +#define SBE_CMD_SET_FFDC_ADDR 0xD704 +#define SBE_CMD_QUIESCE_SBE 0xD705 +#define SBE_CMD_SET_FABRIC_ID_MAP 0xD706 +#define SBE_CMD_STASH_MPIPL_CONFIG 0xD707 + +/* SBE MBOX control flags */ + +/* Generic flags */ +#define SBE_CMD_CTRL_RESP_REQ 0x0100 +#define SBE_CMD_CTRL_ACK_REQ 0x0200 + +/* Deadman loop */ +#define CTRL_DEADMAN_LOOP_START 0x0001 +#define CTRL_DEADMAN_LOOP_STOP 0x0002 + +/* Control timer */ +#define CONTROL_TIMER_START 0x0001 +#define CONTROL_TIMER_STOP 0x0002 + +/* Stash MPIPL config */ +#define SBE_STASH_KEY_SKIBOOT_BASE 0x03 + +static void sbe_timer(void *opaque) +{ + PnvSBE *sbe = opaque; + + trace_pnv_sbe_cmd_timer_expired(); + + pnv_sbe_set_host_doorbell(sbe, sbe->host_doorbell | SBE_HOST_TIMER_EXPIRY); +} + +static void do_sbe_msg(PnvSBE *sbe) +{ + struct sbe_msg msg; + uint16_t cmd, ctrl_flags, seq_id; + int i; + + memset(&msg, 0, sizeof(msg)); + + for (i = 0; i < 4; i++) { + msg.reg[i] = sbe->mbox[i]; + } + + cmd = msg.reg[0]; + seq_id = msg.reg[0] >> 16; + ctrl_flags = msg.reg[0] >> 32; + + trace_pnv_sbe_msg_recv(cmd, seq_id, ctrl_flags); + + if (ctrl_flags & SBE_CMD_CTRL_ACK_REQ) { + pnv_sbe_set_host_doorbell(sbe, sbe->host_doorbell | SBE_HOST_MSG_READ); + } + + switch (cmd) { + case SBE_CMD_CONTROL_TIMER: + if (ctrl_flags & CONTROL_TIMER_START) { + uint64_t us = msg.reg[1]; + trace_pnv_sbe_cmd_timer_start(us); + timer_mod(sbe->timer, qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + us); + } + if (ctrl_flags & CONTROL_TIMER_STOP) { + trace_pnv_sbe_cmd_timer_stop(); + timer_del(sbe->timer); + } + break; + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented command: 0x%x\n", cmd); + } +} + +static void pnv_sbe_set_sbe_doorbell(PnvSBE *sbe, uint64_t val) +{ + val &= HOST_SBE_MSG_WAITING; + sbe->sbe_doorbell = val; + + if (val & HOST_SBE_MSG_WAITING) { + sbe->sbe_doorbell &= ~HOST_SBE_MSG_WAITING; + do_sbe_msg(sbe); + } +} + +static uint64_t pnv_sbe_power9_xscom_mbox_read(void *opaque, hwaddr addr, + unsigned size) +{ + PnvSBE *sbe = PNV_SBE(opaque); + uint32_t offset = addr >> 3; + uint64_t val = 0; + + if (offset <= PSU_HOST_SBE_MBOX_REG7) { + uint32_t idx = offset - PSU_HOST_SBE_MBOX_REG0; + val = sbe->mbox[idx]; + } else { + switch (offset) { + case PSU_SBE_DOORBELL_REG_RW: + val = sbe->sbe_doorbell; + break; + case PSU_HOST_DOORBELL_REG_RW: + val = sbe->host_doorbell; + break; + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented register: Ox%" + HWADDR_PRIx "\n", addr >> 3); + } + } + + trace_pnv_sbe_xscom_mbox_read(addr, val); + + return val; +} + +static void pnv_sbe_power9_xscom_mbox_write(void *opaque, hwaddr addr, + uint64_t val, unsigned size) +{ + PnvSBE *sbe = PNV_SBE(opaque); + uint32_t offset = addr >> 3; + + trace_pnv_sbe_xscom_mbox_write(addr, val); + + if (offset <= PSU_HOST_SBE_MBOX_REG7) { + uint32_t idx = offset - PSU_HOST_SBE_MBOX_REG0; + sbe->mbox[idx] = val; + } else { + switch (offset) { + case PSU_SBE_DOORBELL_REG_RW: + pnv_sbe_set_sbe_doorbell(sbe, val); + break; + case PSU_SBE_DOORBELL_REG_AND: + pnv_sbe_set_sbe_doorbell(sbe, sbe->sbe_doorbell & val); + break; + case PSU_SBE_DOORBELL_REG_OR: + pnv_sbe_set_sbe_doorbell(sbe, sbe->sbe_doorbell | val); + break; + + case PSU_HOST_DOORBELL_REG_RW: + pnv_sbe_set_host_doorbell(sbe, val); + break; + case PSU_HOST_DOORBELL_REG_AND: + pnv_sbe_set_host_doorbell(sbe, sbe->host_doorbell & val); + break; + case PSU_HOST_DOORBELL_REG_OR: + pnv_sbe_set_host_doorbell(sbe, sbe->host_doorbell | val); + break; + + default: + qemu_log_mask(LOG_UNIMP, "SBE Unimplemented register: Ox%" + HWADDR_PRIx "\n", addr >> 3); + } + } +} + +static const MemoryRegionOps pnv_sbe_power9_xscom_mbox_ops = { + .read = pnv_sbe_power9_xscom_mbox_read, + .write = pnv_sbe_power9_xscom_mbox_write, + .valid.min_access_size = 8, + .valid.max_access_size = 8, + .impl.min_access_size = 8, + .impl.max_access_size = 8, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void pnv_sbe_power9_class_init(ObjectClass *klass, void *data) +{ + PnvSBEClass *psc = PNV_SBE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "PowerNV SBE Controller (POWER9)"; + psc->xscom_ctrl_size = PNV9_XSCOM_SBE_CTRL_SIZE; + psc->xscom_ctrl_ops = &pnv_sbe_power9_xscom_ctrl_ops; + psc->xscom_mbox_size = PNV9_XSCOM_SBE_MBOX_SIZE; + psc->xscom_mbox_ops = &pnv_sbe_power9_xscom_mbox_ops; +} + +static const TypeInfo pnv_sbe_power9_type_info = { + .name = TYPE_PNV9_SBE, + .parent = TYPE_PNV_SBE, + .instance_size = sizeof(PnvSBE), + .class_init = pnv_sbe_power9_class_init, +}; + +static void pnv_sbe_power10_class_init(ObjectClass *klass, void *data) +{ + PnvSBEClass *psc = PNV_SBE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->desc = "PowerNV SBE Controller (POWER10)"; + psc->xscom_ctrl_size = PNV10_XSCOM_SBE_CTRL_SIZE; + psc->xscom_ctrl_ops = &pnv_sbe_power9_xscom_ctrl_ops; + psc->xscom_mbox_size = PNV10_XSCOM_SBE_MBOX_SIZE; + psc->xscom_mbox_ops = &pnv_sbe_power9_xscom_mbox_ops; +} + +static const TypeInfo pnv_sbe_power10_type_info = { + .name = TYPE_PNV10_SBE, + .parent = TYPE_PNV9_SBE, + .class_init = pnv_sbe_power10_class_init, +}; + +static void pnv_sbe_realize(DeviceState *dev, Error **errp) +{ + PnvSBE *sbe = PNV_SBE(dev); + PnvSBEClass *psc = PNV_SBE_GET_CLASS(sbe); + + /* XScom regions for SBE registers */ + pnv_xscom_region_init(&sbe->xscom_ctrl_regs, OBJECT(dev), + psc->xscom_ctrl_ops, sbe, "xscom-sbe-ctrl", + psc->xscom_ctrl_size); + pnv_xscom_region_init(&sbe->xscom_mbox_regs, OBJECT(dev), + psc->xscom_mbox_ops, sbe, "xscom-sbe-mbox", + psc->xscom_mbox_size); + + qdev_init_gpio_out(DEVICE(dev), &sbe->psi_irq, 1); + + sbe->timer = timer_new_us(QEMU_CLOCK_VIRTUAL, sbe_timer, sbe); +} + +static void pnv_sbe_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + + dc->realize = pnv_sbe_realize; + dc->desc = "PowerNV SBE Controller"; + dc->user_creatable = false; +} + +static const TypeInfo pnv_sbe_type_info = { + .name = TYPE_PNV_SBE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(PnvSBE), + .class_init = pnv_sbe_class_init, + .class_size = sizeof(PnvSBEClass), + .abstract = true, +}; + +static void pnv_sbe_register_types(void) +{ + type_register_static(&pnv_sbe_type_info); + type_register_static(&pnv_sbe_power9_type_info); + type_register_static(&pnv_sbe_power10_type_info); +} + +type_init(pnv_sbe_register_types); diff --git a/hw/ppc/pnv_xscom.c b/hw/ppc/pnv_xscom.c index 9ce018dbc2..79f10de57f 100644 --- a/hw/ppc/pnv_xscom.c +++ b/hw/ppc/pnv_xscom.c @@ -295,6 +295,9 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset, _FDT((fdt_setprop(fdt, xscom_offset, "reg", reg, sizeof(reg)))); _FDT((fdt_setprop(fdt, xscom_offset, "compatible", compat, compat_size))); _FDT((fdt_setprop(fdt, xscom_offset, "scom-controller", NULL, 0))); + if (chip->chip_id == 0) { + _FDT((fdt_setprop(fdt, xscom_offset, "primary", NULL, 0))); + } args.fdt = fdt; args.xscom_offset = xscom_offset; diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 5c0a215cad..f6990439d1 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -95,6 +95,17 @@ vof_write(uint32_t ih, unsigned cb, const char *msg) "ih=0x%x [%u] \"%s\"" vof_avail(uint64_t start, uint64_t end, uint64_t size) "0x%"PRIx64"..0x%"PRIx64" size=0x%"PRIx64 vof_claimed(uint64_t start, uint64_t end, uint64_t size) "0x%"PRIx64"..0x%"PRIx64" size=0x%"PRIx64 +# pnv_sbe.c +pnv_sbe_xscom_ctrl_read(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64 +pnv_sbe_xscom_ctrl_write(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64 +pnv_sbe_xscom_mbox_read(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64 +pnv_sbe_xscom_mbox_write(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " val 0x%" PRIx64 +pnv_sbe_reg_set_host_doorbell(uint64_t val) "val 0x%" PRIx64 +pnv_sbe_cmd_timer_start(uint64_t ns) "ns 0x%" PRIu64 +pnv_sbe_cmd_timer_stop(void) "" +pnv_sbe_cmd_timer_expired(void) "" +pnv_sbe_msg_recv(uint16_t cmd, uint16_t seq, uint16_t ctrl_flags) "cmd 0x%" PRIx16 " seq %"PRIu16 " ctrl_flags 0x%" PRIx16 + # ppc.c ppc_tb_adjust(uint64_t offs1, uint64_t offs2, int64_t diff, int64_t seconds) "adjusted from 0x%"PRIx64" to 0x%"PRIx64", diff %"PRId64" (%"PRId64"s)" ppc_tb_load(uint64_t tb) "tb 0x%016" PRIx64 diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index b991194223..37c303bf36 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -27,6 +27,7 @@ #include "hw/ppc/pnv_pnor.h" #include "hw/ppc/pnv_psi.h" #include "hw/ppc/pnv_occ.h" +#include "hw/ppc/pnv_sbe.h" #include "hw/ppc/pnv_homer.h" #include "hw/ppc/pnv_xive.h" #include "hw/ppc/pnv_core.h" @@ -100,6 +101,7 @@ struct Pnv9Chip { Pnv9Psi psi; PnvLpcController lpc; PnvOCC occ; + PnvSBE sbe; PnvHomer homer; uint32_t nr_quads; @@ -129,6 +131,7 @@ struct Pnv10Chip { Pnv9Psi psi; PnvLpcController lpc; PnvOCC occ; + PnvSBE sbe; PnvHomer homer; uint32_t nr_quads; diff --git a/include/hw/ppc/pnv_sbe.h b/include/hw/ppc/pnv_sbe.h new file mode 100644 index 0000000000..f54a3ae9ba --- /dev/null +++ b/include/hw/ppc/pnv_sbe.h @@ -0,0 +1,55 @@ +/* + * QEMU PowerPC PowerNV Emulation of some SBE behaviour + * + * Copyright (c) 2022, IBM Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef PPC_PNV_SBE_H +#define PPC_PNV_SBE_H + +#include "qom/object.h" + +#define TYPE_PNV_SBE "pnv-sbe" +OBJECT_DECLARE_TYPE(PnvSBE, PnvSBEClass, PNV_SBE) +#define TYPE_PNV9_SBE TYPE_PNV_SBE "-POWER9" +DECLARE_INSTANCE_CHECKER(PnvSBE, PNV9_SBE, TYPE_PNV9_SBE) +#define TYPE_PNV10_SBE TYPE_PNV_SBE "-POWER10" +DECLARE_INSTANCE_CHECKER(PnvSBE, PNV10_SBE, TYPE_PNV10_SBE) + +struct PnvSBE { + DeviceState xd; + + uint64_t mbox[8]; + uint64_t sbe_doorbell; + uint64_t host_doorbell; + + qemu_irq psi_irq; + QEMUTimer *timer; + + MemoryRegion xscom_mbox_regs; + MemoryRegion xscom_ctrl_regs; +}; + +struct PnvSBEClass { + DeviceClass parent_class; + + int xscom_ctrl_size; + int xscom_mbox_size; + const MemoryRegionOps *xscom_ctrl_ops; + const MemoryRegionOps *xscom_mbox_ops; +}; + +#endif /* PPC_PNV_SBE_H */ diff --git a/include/hw/ppc/pnv_xscom.h b/include/hw/ppc/pnv_xscom.h index 7c7440de0c..c6e9ef8dd2 100644 --- a/include/hw/ppc/pnv_xscom.h +++ b/include/hw/ppc/pnv_xscom.h @@ -92,6 +92,12 @@ struct PnvXScomInterfaceClass { #define PNV9_XSCOM_OCC_BASE PNV_XSCOM_OCC_BASE #define PNV9_XSCOM_OCC_SIZE 0x8000 +#define PNV9_XSCOM_SBE_CTRL_BASE 0x00050008 +#define PNV9_XSCOM_SBE_CTRL_SIZE 0x1 + +#define PNV9_XSCOM_SBE_MBOX_BASE 0x000D0050 +#define PNV9_XSCOM_SBE_MBOX_SIZE 0x16 + #define PNV9_XSCOM_PBA_BASE 0x5012b00 #define PNV9_XSCOM_PBA_SIZE 0x40 @@ -134,6 +140,12 @@ struct PnvXScomInterfaceClass { #define PNV10_XSCOM_OCC_BASE PNV9_XSCOM_OCC_BASE #define PNV10_XSCOM_OCC_SIZE PNV9_XSCOM_OCC_SIZE +#define PNV10_XSCOM_SBE_CTRL_BASE PNV9_XSCOM_SBE_CTRL_BASE +#define PNV10_XSCOM_SBE_CTRL_SIZE PNV9_XSCOM_SBE_CTRL_SIZE + +#define PNV10_XSCOM_SBE_MBOX_BASE PNV9_XSCOM_SBE_MBOX_BASE +#define PNV10_XSCOM_SBE_MBOX_SIZE PNV9_XSCOM_SBE_MBOX_SIZE + #define PNV10_XSCOM_PBA_BASE 0x01010CDA #define PNV10_XSCOM_PBA_SIZE 0x40 From c40da5c6fb6dd243e906900de1d22cf20e32a8cd Mon Sep 17 00:00:00 2001 From: "Lucas Mateus Castro (alqotel)" Date: Fri, 5 Aug 2022 11:15:21 -0300 Subject: [PATCH 0205/1020] fpu: Add rebias bool, value and operation Added the possibility of recalculating a result if it overflows or underflows, if the result overflow and the rebias bool is true then the intermediate result should have 3/4 of the total range subtracted from the exponent. The same for underflow but it should be added to the exponent of the intermediate number instead. Signed-off-by: Lucas Mateus Castro (alqotel) Reviewed-by: Richard Henderson Message-Id: <20220805141522.412864-2-lucas.araujo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- fpu/softfloat-parts.c.inc | 21 +++++++++++++++++++-- fpu/softfloat.c | 2 ++ include/fpu/softfloat-types.h | 4 ++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/fpu/softfloat-parts.c.inc b/fpu/softfloat-parts.c.inc index bbeadaa189..a9f268fcab 100644 --- a/fpu/softfloat-parts.c.inc +++ b/fpu/softfloat-parts.c.inc @@ -214,18 +214,35 @@ static void partsN(uncanon_normal)(FloatPartsN *p, float_status *s, p->frac_lo &= ~round_mask; } } else if (unlikely(exp >= exp_max)) { - flags |= float_flag_overflow | float_flag_inexact; - if (overflow_norm) { + flags |= float_flag_overflow; + if (s->rebias_overflow) { + exp -= fmt->exp_re_bias; + } else if (overflow_norm) { + flags |= float_flag_inexact; exp = exp_max - 1; frac_allones(p); p->frac_lo &= ~round_mask; } else { + flags |= float_flag_inexact; p->cls = float_class_inf; exp = exp_max; frac_clear(p); } } frac_shr(p, frac_shift); + } else if (unlikely(s->rebias_underflow)) { + flags |= float_flag_underflow; + exp += fmt->exp_re_bias; + if (p->frac_lo & round_mask) { + flags |= float_flag_inexact; + if (frac_addi(p, p, inc)) { + frac_shr(p, 1); + p->frac_hi |= DECOMPOSED_IMPLICIT_BIT; + exp++; + } + p->frac_lo &= ~round_mask; + } + frac_shr(p, frac_shift); } else if (s->flush_to_zero) { flags |= float_flag_output_denormal; p->cls = float_class_zero; diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 4a871ef2a1..c7454c3eb1 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -521,6 +521,7 @@ typedef struct { typedef struct { int exp_size; int exp_bias; + int exp_re_bias; int exp_max; int frac_size; int frac_shift; @@ -532,6 +533,7 @@ typedef struct { #define FLOAT_PARAMS_(E) \ .exp_size = E, \ .exp_bias = ((1 << E) - 1) >> 1, \ + .exp_re_bias = (1 << (E - 1)) + (1 << (E - 2)), \ .exp_max = (1 << E) - 1 #define FLOAT_PARAMS(E, F) \ diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index 7a6ea881d8..0884ec4ef7 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -195,6 +195,10 @@ typedef struct float_status { bool snan_bit_is_one; bool use_first_nan; bool no_signaling_nans; + /* should overflowed results subtract re_bias to its exponent? */ + bool rebias_overflow; + /* should underflowed results add re_bias to its exponent? */ + bool rebias_underflow; } float_status; #endif /* SOFTFLOAT_TYPES_H */ From 08e185cadb24b038574dad676d4dae8488ba8b6e Mon Sep 17 00:00:00 2001 From: "Lucas Mateus Castro (alqotel)" Date: Fri, 5 Aug 2022 11:15:22 -0300 Subject: [PATCH 0206/1020] target/ppc: Bugfix FP when OE/UE are set When an overflow exception occurs and OE is set the intermediate result should be adjusted (by subtracting from the exponent) to avoid rounding to inf. The same applies to an underflow exceptionion and UE (but adding to the exponent). To do this set the fp_status.rebias_overflow when OE is set and fp_status.rebias_underflow when UE is set as the FPU will recalculate in case of a overflow/underflow if the according rebias* is set. Signed-off-by: Lucas Mateus Castro (alqotel) Reviewed-by: Richard Henderson Message-Id: <20220805141522.412864-3-lucas.araujo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu.c | 2 ++ target/ppc/fpu_helper.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c index 401b6f9e63..0ebac04bc4 100644 --- a/target/ppc/cpu.c +++ b/target/ppc/cpu.c @@ -120,6 +120,8 @@ void ppc_store_fpscr(CPUPPCState *env, target_ulong val) val |= FP_FEX; } env->fpscr = val; + env->fp_status.rebias_overflow = (FP_OE & env->fpscr) ? true : false; + env->fp_status.rebias_underflow = (FP_UE & env->fpscr) ? true : false; if (tcg_enabled()) { fpscr_set_rounding_mode(env); } diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 7ab6beadad..0f045b70f8 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -348,7 +348,6 @@ static inline int float_overflow_excp(CPUPPCState *env) bool overflow_enabled = !!(env->fpscr & FP_OE); if (overflow_enabled) { - /* XXX: should adjust the result */ /* Update the floating-point enabled exception summary */ env->fpscr |= FP_FEX; /* We must update the target FPR before raising the exception */ @@ -367,7 +366,6 @@ static inline void float_underflow_excp(CPUPPCState *env) /* Update the floating-point exception summary */ env->fpscr |= FP_FX; if (env->fpscr & FP_UE) { - /* XXX: should adjust the result */ /* Update the floating-point enabled exception summary */ env->fpscr |= FP_FEX; /* We must update the target FPR before raising the exception */ From 91bcee7157b0a1c627705d5a24076a3058ea01a7 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:10 -0300 Subject: [PATCH 0207/1020] ppc/pnv: add PHB3 bus init helper The PnvPHB3 bus init consists of initializing the pci_io and pci_mmio regions, registering it via pci_register_root_bus() and then setup the iommu. We'll want to init the bus from outside pnv_phb3.c when the bus is removed from the PnvPHB3 device and put into a new parent PnvPHB device. The new pnv_phb3_bus_init() helper will be used by the parent to init the bus when using the PHB3 backend. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-2-danielhb413@gmail.com> --- hw/pci-host/pnv_phb3.c | 39 ++++++++++++++++++++-------------- include/hw/pci-host/pnv_phb3.h | 1 + 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index d58d3c1701..058cbab555 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -986,6 +986,28 @@ static void pnv_phb3_instance_init(Object *obj) } +void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb) +{ + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + + /* + * PHB3 doesn't support IO space. However, qemu gets very upset if + * we don't have an IO region to anchor IO BARs onto so we just + * initialize one which we never hook up to anything + */ + memory_region_init(&phb->pci_io, OBJECT(phb), "pci-io", 0x10000); + memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio", + PCI_MMIO_TOTAL_SIZE); + + pci->bus = pci_register_root_bus(dev, + dev->id ? dev->id : NULL, + pnv_phb3_set_irq, pnv_phb3_map_irq, phb, + &phb->pci_mmio, &phb->pci_io, + 0, 4, TYPE_PNV_PHB3_ROOT_BUS); + + pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); +} + static void pnv_phb3_realize(DeviceState *dev, Error **errp) { PnvPHB3 *phb = PNV_PHB3(dev); @@ -1035,22 +1057,7 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb3_reg_ops, phb, "phb3-regs", 0x1000); - /* - * PHB3 doesn't support IO space. However, qemu gets very upset if - * we don't have an IO region to anchor IO BARs onto so we just - * initialize one which we never hook up to anything - */ - memory_region_init(&phb->pci_io, OBJECT(phb), "pci-io", 0x10000); - memory_region_init(&phb->pci_mmio, OBJECT(phb), "pci-mmio", - PCI_MMIO_TOTAL_SIZE); - - pci->bus = pci_register_root_bus(dev, - dev->id ? dev->id : NULL, - pnv_phb3_set_irq, pnv_phb3_map_irq, phb, - &phb->pci_mmio, &phb->pci_io, - 0, 4, TYPE_PNV_PHB3_ROOT_BUS); - - pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); + pnv_phb3_bus_init(dev, phb); pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT, phb->phb_id, phb->chip_id); diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index af6ec83cf6..1375f18fc1 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -164,5 +164,6 @@ uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size); void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size); void pnv_phb3_update_regions(PnvPHB3 *phb); void pnv_phb3_remap_irqs(PnvPHB3 *phb); +void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb); #endif /* PCI_HOST_PNV_PHB3_H */ From e4e6db5283f775e44879246c6c93cb2462cf742f Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:11 -0300 Subject: [PATCH 0208/1020] ppc/pnv: add PnvPHB base/proxy device The PnvPHB device is going to be the base device for all other powernv PHBs. It consists of a device that has the same user API as the other PHB, namely being a PCIHostBridge and having chip-id and index properties. It also has a 'backend' pointer that will be initialized with the PHB implementation that the device is going to use. The initialization of the PHB backend is done by checking the PHB version via a 'version' attribute that can be set via a global machine property. The 'version' field will be used to make adjustments based on the running version, e.g. PHB3 uses a 'chip' reference while PHB4 uses 'pec'. To init the PnvPHB bus we'll rely on helpers for each version. The version 3 helper is already added (pnv_phb3_bus_init), the PHB4 helper will be added later on. For now let's add the basic logic of the PnvPHB object, which consists mostly of pnv_phb_realize() doing all the work of checking the phb->version set, initializing the proper backend, passing through its attributes to the chosen backend, finalizing the backend realize and adding a root port in the end. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-3-danielhb413@gmail.com> --- hw/pci-host/meson.build | 3 +- hw/pci-host/pnv_phb.c | 124 ++++++++++++++++++++++++++++++++++++++++ hw/pci-host/pnv_phb.h | 39 +++++++++++++ 3 files changed, 165 insertions(+), 1 deletion(-) create mode 100644 hw/pci-host/pnv_phb.c create mode 100644 hw/pci-host/pnv_phb.h diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build index c07596d0d1..e832babc9d 100644 --- a/hw/pci-host/meson.build +++ b/hw/pci-host/meson.build @@ -35,5 +35,6 @@ specific_ss.add(when: 'CONFIG_PCI_POWERNV', if_true: files( 'pnv_phb3_msi.c', 'pnv_phb3_pbcq.c', 'pnv_phb4.c', - 'pnv_phb4_pec.c' + 'pnv_phb4_pec.c', + 'pnv_phb.c', )) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c new file mode 100644 index 0000000000..6fefff7d44 --- /dev/null +++ b/hw/pci-host/pnv_phb.c @@ -0,0 +1,124 @@ +/* + * QEMU PowerPC PowerNV Proxy PHB model + * + * Copyright (c) 2022, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "qapi/visitor.h" +#include "qapi/error.h" +#include "hw/pci-host/pnv_phb.h" +#include "hw/pci-host/pnv_phb3.h" +#include "hw/pci-host/pnv_phb4.h" +#include "hw/ppc/pnv.h" +#include "hw/qdev-properties.h" +#include "qom/object.h" + + +static void pnv_phb_realize(DeviceState *dev, Error **errp) +{ + PnvPHB *phb = PNV_PHB(dev); + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + g_autofree char *phb_typename = NULL; + g_autofree char *phb_rootport_typename = NULL; + + if (!phb->version) { + error_setg(errp, "version not specified"); + return; + } + + switch (phb->version) { + case 3: + phb_typename = g_strdup(TYPE_PNV_PHB3); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB3_ROOT_PORT); + break; + case 4: + phb_typename = g_strdup(TYPE_PNV_PHB4); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB4_ROOT_PORT); + break; + case 5: + phb_typename = g_strdup(TYPE_PNV_PHB5); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB5_ROOT_PORT); + break; + default: + g_assert_not_reached(); + } + + phb->backend = object_new(phb_typename); + object_property_add_child(OBJECT(dev), "phb-backend", phb->backend); + + /* Passthrough child device properties to the proxy device */ + object_property_set_uint(phb->backend, "index", phb->phb_id, errp); + object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp); + object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp); + + if (phb->version == 3) { + object_property_set_link(phb->backend, "chip", + OBJECT(phb->chip), errp); + } else { + object_property_set_link(phb->backend, "pec", OBJECT(phb->pec), errp); + } + + if (!qdev_realize(DEVICE(phb->backend), NULL, errp)) { + return; + } + + if (phb->version == 3) { + pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend)); + } + + pnv_phb_attach_root_port(pci, phb_rootport_typename, + phb->phb_id, phb->chip_id); +} + +static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + PnvPHB *phb = PNV_PHB(host_bridge); + + snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", + phb->chip_id, phb->phb_id); + return phb->bus_path; +} + +static Property pnv_phb_properties[] = { + DEFINE_PROP_UINT32("index", PnvPHB, phb_id, 0), + DEFINE_PROP_UINT32("chip-id", PnvPHB, chip_id, 0), + DEFINE_PROP_UINT32("version", PnvPHB, version, 0), + + DEFINE_PROP_LINK("chip", PnvPHB, chip, TYPE_PNV_CHIP, PnvChip *), + + DEFINE_PROP_LINK("pec", PnvPHB, pec, TYPE_PNV_PHB4_PEC, + PnvPhb4PecState *), + + DEFINE_PROP_END_OF_LIST(), +}; + +static void pnv_phb_class_init(ObjectClass *klass, void *data) +{ + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + + hc->root_bus_path = pnv_phb_root_bus_path; + dc->realize = pnv_phb_realize; + device_class_set_props(dc, pnv_phb_properties); + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + dc->user_creatable = false; +} + +static void pnv_phb_register_type(void) +{ + static const TypeInfo pnv_phb_type_info = { + .name = TYPE_PNV_PHB, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(PnvPHB), + .class_init = pnv_phb_class_init, + }; + + type_register_static(&pnv_phb_type_info); +} +type_init(pnv_phb_register_type) diff --git a/hw/pci-host/pnv_phb.h b/hw/pci-host/pnv_phb.h new file mode 100644 index 0000000000..a7cc8610e2 --- /dev/null +++ b/hw/pci-host/pnv_phb.h @@ -0,0 +1,39 @@ +/* + * QEMU PowerPC PowerNV Proxy PHB model + * + * Copyright (c) 2022, IBM Corporation. + * + * This code is licensed under the GPL version 2 or later. See the + * COPYING file in the top-level directory. + */ + +#ifndef PCI_HOST_PNV_PHB_H +#define PCI_HOST_PNV_PHB_H + +#include "hw/pci/pcie_host.h" +#include "hw/pci/pcie_port.h" +#include "qom/object.h" + +typedef struct PnvChip PnvChip; +typedef struct PnvPhb4PecState PnvPhb4PecState; + +struct PnvPHB { + PCIExpressHost parent_obj; + + uint32_t chip_id; + uint32_t phb_id; + uint32_t version; + char bus_path[8]; + + PnvChip *chip; + + PnvPhb4PecState *pec; + + /* The PHB backend (PnvPHB3, PnvPHB4 ...) being used */ + Object *backend; +}; + +#define TYPE_PNV_PHB "pnv-phb" +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB, PNV_PHB) + +#endif /* PCI_HOST_PNV_PHB_H */ From 1f5d6b2ad14df9daad17e81d9e247bd1fd2fd5fc Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:12 -0300 Subject: [PATCH 0209/1020] ppc/pnv: turn PnvPHB3 into a PnvPHB backend We need a handful of changes that needs to be done in a single swoop to turn PnvPHB3 into a PnvPHB backend. In the PnvPHB3, since the PnvPHB device implements PCIExpressHost and will hold the PCI bus, change PnvPHB3 parent to TYPE_DEVICE. There are a couple of instances in pnv_phb3.c that needs to access the PCI bus, so a phb_base pointer is added to allow access to the parent PnvPHB. The PnvPHB3 root port will now be connected to a PnvPHB object. In pnv.c, the powernv8 machine chip8 will now hold an array of PnvPHB objects. pnv_get_phb3_child() needs to be adapted to return the PnvPHB3 backend from the PnvPHB child. A global property is added in pnv_machine_power8_class_init() to ensure that all PnvPHBs are created with phb->version = 3. After all these changes we're still able to boot a powernv8 machine with default settings. The real gain will come with user created PnvPHB devices, coming up next. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-4-danielhb413@gmail.com> --- hw/pci-host/pnv_phb3.c | 27 +++++---------------------- hw/ppc/pnv.c | 21 +++++++++++++++------ include/hw/pci-host/pnv_phb3.h | 5 ++++- include/hw/ppc/pnv.h | 3 ++- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index 058cbab555..ad9e983fe9 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -11,6 +11,7 @@ #include "qapi/visitor.h" #include "qapi/error.h" #include "hw/pci-host/pnv_phb3_regs.h" +#include "hw/pci-host/pnv_phb.h" #include "hw/pci-host/pnv_phb3.h" #include "hw/pci/pcie_host.h" #include "hw/pci/pcie_port.h" @@ -26,7 +27,7 @@ static PCIDevice *pnv_phb3_find_cfg_dev(PnvPHB3 *phb) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t addr = phb->regs[PHB_CONFIG_ADDRESS >> 3]; uint8_t bus, devfn; @@ -590,7 +591,7 @@ void pnv_phb3_reg_write(void *opaque, hwaddr off, uint64_t val, unsigned size) uint64_t pnv_phb3_reg_read(void *opaque, hwaddr off, unsigned size) { PnvPHB3 *phb = opaque; - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t val; if ((off & 0xfffc) == PHB_CONFIG_DATA) { @@ -1011,7 +1012,6 @@ void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb) static void pnv_phb3_realize(DeviceState *dev, Error **errp) { PnvPHB3 *phb = PNV_PHB3(dev); - PCIHostState *pci = PCI_HOST_BRIDGE(dev); PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); int i; @@ -1056,11 +1056,6 @@ static void pnv_phb3_realize(DeviceState *dev, Error **errp) /* Controller Registers */ memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb3_reg_ops, phb, "phb3-regs", 0x1000); - - pnv_phb3_bus_init(dev, phb); - - pnv_phb_attach_root_port(pci, TYPE_PNV_PHB3_ROOT_PORT, - phb->phb_id, phb->chip_id); } void pnv_phb3_update_regions(PnvPHB3 *phb) @@ -1085,38 +1080,26 @@ void pnv_phb3_update_regions(PnvPHB3 *phb) pnv_phb3_check_all_m64s(phb); } -static const char *pnv_phb3_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - PnvPHB3 *phb = PNV_PHB3(host_bridge); - - snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", - phb->chip_id, phb->phb_id); - return phb->bus_path; -} - static Property pnv_phb3_properties[] = { DEFINE_PROP_UINT32("index", PnvPHB3, phb_id, 0), DEFINE_PROP_UINT32("chip-id", PnvPHB3, chip_id, 0), DEFINE_PROP_LINK("chip", PnvPHB3, chip, TYPE_PNV_CHIP, PnvChip *), + DEFINE_PROP_LINK("phb-base", PnvPHB3, phb_base, TYPE_PNV_PHB, PnvPHB *), DEFINE_PROP_END_OF_LIST(), }; static void pnv_phb3_class_init(ObjectClass *klass, void *data) { - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); - hc->root_bus_path = pnv_phb3_root_bus_path; dc->realize = pnv_phb3_realize; device_class_set_props(dc, pnv_phb3_properties); - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->user_creatable = false; } static const TypeInfo pnv_phb3_type_info = { .name = TYPE_PNV_PHB3, - .parent = TYPE_PCIE_HOST_BRIDGE, + .parent = TYPE_DEVICE, .instance_size = sizeof(PnvPHB3), .class_init = pnv_phb3_class_init, .instance_init = pnv_phb3_instance_init, diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 0c3aad430b..5b60735c7a 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -43,6 +43,7 @@ #include "hw/ipmi/ipmi.h" #include "target/ppc/mmu-hash64.h" #include "hw/pci/msi.h" +#include "hw/pci-host/pnv_phb.h" #include "hw/ppc/xics.h" #include "hw/qdev-properties.h" @@ -660,7 +661,8 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) ics_pic_print_info(&chip8->psi.ics, mon); for (i = 0; i < chip8->num_phbs; i++) { - PnvPHB3 *phb3 = &chip8->phbs[i]; + PnvPHB *phb = &chip8->phbs[i]; + PnvPHB3 *phb3 = PNV_PHB3(phb->backend); pnv_phb3_msi_pic_print_info(&phb3->msis, mon); ics_pic_print_info(&phb3->lsis, mon); @@ -1149,7 +1151,7 @@ static void pnv_chip_power8_instance_init(Object *obj) chip8->num_phbs = pcc->num_phbs; for (i = 0; i < chip8->num_phbs; i++) { - object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB3); + object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB); } } @@ -1287,9 +1289,9 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) memory_region_add_subregion(get_system_memory(), PNV_HOMER_BASE(chip), &chip8->homer.regs); - /* PHB3 controllers */ + /* PHB controllers */ for (i = 0; i < chip8->num_phbs; i++) { - PnvPHB3 *phb = &chip8->phbs[i]; + PnvPHB *phb = &chip8->phbs[i]; object_property_set_int(OBJECT(phb), "index", i, &error_fatal); object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, @@ -1982,7 +1984,8 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq) } for (j = 0; j < chip8->num_phbs; j++) { - PnvPHB3 *phb3 = &chip8->phbs[j]; + PnvPHB *phb = &chip8->phbs[j]; + PnvPHB3 *phb3 = PNV_PHB3(phb->backend); if (ics_valid_irq(&phb3->lsis, irq)) { return &phb3->lsis; @@ -2020,7 +2023,8 @@ static void pnv_ics_resend(XICSFabric *xi) ics_resend(&chip8->psi.ics); for (j = 0; j < chip8->num_phbs; j++) { - PnvPHB3 *phb3 = &chip8->phbs[j]; + PnvPHB *phb = &chip8->phbs[j]; + PnvPHB3 *phb3 = PNV_PHB3(phb->backend); ics_resend(&phb3->lsis); ics_resend(ICS(&phb3->msis)); @@ -2120,8 +2124,13 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); static const char compat[] = "qemu,powernv8\0qemu,powernv\0ibm,powernv"; + static GlobalProperty phb_compat[] = { + { TYPE_PNV_PHB, "version", "3" }, + }; + mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power8_v2.0"); + compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); xic->icp_get = pnv_icp_get; xic->ics_get = pnv_ics_get; diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index 1375f18fc1..3b9ff1096a 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -14,6 +14,7 @@ #include "hw/pci/pcie_port.h" #include "hw/ppc/xics.h" #include "qom/object.h" +#include "hw/pci-host/pnv_phb.h" typedef struct PnvPHB3 PnvPHB3; typedef struct PnvChip PnvChip; @@ -127,7 +128,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3, PNV_PHB3) #define PCI_MMIO_TOTAL_SIZE (0x1ull << 60) struct PnvPHB3 { - PCIExpressHost parent_obj; + DeviceState parent; + + PnvPHB *phb_base; uint32_t chip_id; uint32_t phb_id; diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 37c303bf36..21fa90aaff 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -33,6 +33,7 @@ #include "hw/ppc/pnv_core.h" #include "hw/pci-host/pnv_phb3.h" #include "hw/pci-host/pnv_phb4.h" +#include "hw/pci-host/pnv_phb.h" #include "qom/object.h" #define TYPE_PNV_CHIP "pnv-chip" @@ -81,7 +82,7 @@ struct Pnv8Chip { PnvHomer homer; #define PNV8_CHIP_PHB3_MAX 4 - PnvPHB3 phbs[PNV8_CHIP_PHB3_MAX]; + PnvPHB phbs[PNV8_CHIP_PHB3_MAX]; uint32_t num_phbs; XICSFabric *xics; From fe5bfd4bb816faa1b3fa8c3c23165cdbadfa5c91 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:13 -0300 Subject: [PATCH 0210/1020] ppc/pnv: add PHB4 bus init helper Similar to what we already did for the PnvPHB3 device, let's add a helper to init the bus when using a PnvPHB4. This helper will be used by PnvPHb when PnvPHB4 turns into a backend. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-5-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 2 ++ hw/pci-host/pnv_phb4.c | 49 +++++++++++++++++++--------------- include/hw/pci-host/pnv_phb4.h | 1 + 3 files changed, 31 insertions(+), 21 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 6fefff7d44..abcbcca445 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -69,6 +69,8 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) if (phb->version == 3) { pnv_phb3_bus_init(dev, PNV_PHB3(phb->backend)); + } else { + pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } pnv_phb_attach_root_port(pci, phb_rootport_typename, diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 67ddde4a6e..a7425927fb 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1528,6 +1528,33 @@ static void pnv_phb4_instance_init(Object *obj) object_initialize_child(obj, "source", &phb->xsrc, TYPE_XIVE_SOURCE); } +void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb) +{ + PCIHostState *pci = PCI_HOST_BRIDGE(dev); + char name[32]; + + /* + * PHB4 doesn't support IO space. However, qemu gets very upset if + * we don't have an IO region to anchor IO BARs onto so we just + * initialize one which we never hook up to anything + */ + snprintf(name, sizeof(name), "phb4-%d.%d-pci-io", phb->chip_id, + phb->phb_id); + memory_region_init(&phb->pci_io, OBJECT(phb), name, 0x10000); + + snprintf(name, sizeof(name), "phb4-%d.%d-pci-mmio", phb->chip_id, + phb->phb_id); + memory_region_init(&phb->pci_mmio, OBJECT(phb), name, + PCI_MMIO_TOTAL_SIZE); + + pci->bus = pci_register_root_bus(dev, dev->id ? dev->id : NULL, + pnv_phb4_set_irq, pnv_phb4_map_irq, phb, + &phb->pci_mmio, &phb->pci_io, + 0, 4, TYPE_PNV_PHB4_ROOT_BUS); + pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb); + pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; +} + static void pnv_phb4_realize(DeviceState *dev, Error **errp) { PnvPHB4 *phb = PNV_PHB4(dev); @@ -1546,27 +1573,7 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb4_reg_ops, phb, name, 0x2000); - /* - * PHB4 doesn't support IO space. However, qemu gets very upset if - * we don't have an IO region to anchor IO BARs onto so we just - * initialize one which we never hook up to anything - */ - - snprintf(name, sizeof(name), "phb4-%d.%d-pci-io", phb->chip_id, - phb->phb_id); - memory_region_init(&phb->pci_io, OBJECT(phb), name, 0x10000); - - snprintf(name, sizeof(name), "phb4-%d.%d-pci-mmio", phb->chip_id, - phb->phb_id); - memory_region_init(&phb->pci_mmio, OBJECT(phb), name, - PCI_MMIO_TOTAL_SIZE); - - pci->bus = pci_register_root_bus(dev, dev->id, - pnv_phb4_set_irq, pnv_phb4_map_irq, phb, - &phb->pci_mmio, &phb->pci_io, - 0, 4, TYPE_PNV_PHB4_ROOT_BUS); - pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb); - pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; + pnv_phb4_bus_init(dev, phb); /* Add a single Root port if running with defaults */ pnv_phb_attach_root_port(pci, pecc->rp_model, diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 19dcbd6f87..90843ac3a9 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -157,6 +157,7 @@ struct PnvPHB4 { void pnv_phb4_pic_print_info(PnvPHB4 *phb, Monitor *mon); int pnv_phb4_pec_get_phb_id(PnvPhb4PecState *pec, int stack_index); +void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb); extern const MemoryRegionOps pnv_phb4_xscom_ops; /* From 210aacb3b92707ecc5de811c743322ca395c0fa6 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:14 -0300 Subject: [PATCH 0211/1020] ppc/pnv: turn PnvPHB4 into a PnvPHB backend Change the parent type of the PnvPHB4 device to TYPE_PARENT since the PCI bus is going to be initialized by the PnvPHB parent. Functions that needs to access the bus via a PnvPHB4 object can do so via the phb4->phb_base pointer. pnv_phb4_pec now creates a PnvPHB object. The powernv9 machine class will create PnvPHB devices with version '4'. powernv10 will create using version '5'. Both are using global machine properties in their class_init() to do that. These changes will benefit us when adding PnvPHB user creatable devices for powernv9 and powernv10. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-6-danielhb413@gmail.com> --- hw/pci-host/pnv_phb4.c | 30 +++++------------------------- hw/pci-host/pnv_phb4_pec.c | 3 +-- hw/ppc/pnv.c | 20 +++++++++++++++++--- include/hw/pci-host/pnv_phb4.h | 5 ++++- 4 files changed, 27 insertions(+), 31 deletions(-) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index a7425927fb..144c437025 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -33,7 +33,7 @@ static PCIDevice *pnv_phb4_find_cfg_dev(PnvPHB4 *phb) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); uint64_t addr = phb->regs[PHB_CONFIG_ADDRESS >> 3]; uint8_t bus, devfn; @@ -129,7 +129,7 @@ static uint64_t pnv_phb4_config_read(PnvPHB4 *phb, unsigned off, static void pnv_phb4_rc_config_write(PnvPHB4 *phb, unsigned off, unsigned size, uint64_t val) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); PCIDevice *pdev; if (size != 4) { @@ -150,7 +150,7 @@ static void pnv_phb4_rc_config_write(PnvPHB4 *phb, unsigned off, static uint64_t pnv_phb4_rc_config_read(PnvPHB4 *phb, unsigned off, unsigned size) { - PCIHostState *pci = PCI_HOST_BRIDGE(phb); + PCIHostState *pci = PCI_HOST_BRIDGE(phb->phb_base); PCIDevice *pdev; uint64_t val; @@ -1558,8 +1558,6 @@ void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb) static void pnv_phb4_realize(DeviceState *dev, Error **errp) { PnvPHB4 *phb = PNV_PHB4(dev); - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(phb->pec); - PCIHostState *pci = PCI_HOST_BRIDGE(dev); XiveSource *xsrc = &phb->xsrc; int nr_irqs; char name[32]; @@ -1573,12 +1571,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) memory_region_init_io(&phb->mr_regs, OBJECT(phb), &pnv_phb4_reg_ops, phb, name, 0x2000); - pnv_phb4_bus_init(dev, phb); - - /* Add a single Root port if running with defaults */ - pnv_phb_attach_root_port(pci, pecc->rp_model, - phb->phb_id, phb->chip_id); - /* Setup XIVE Source */ if (phb->big_phb) { nr_irqs = PNV_PHB4_MAX_INTs; @@ -1598,16 +1590,6 @@ static void pnv_phb4_realize(DeviceState *dev, Error **errp) pnv_phb4_xscom_realize(phb); } -static const char *pnv_phb4_root_bus_path(PCIHostState *host_bridge, - PCIBus *rootbus) -{ - PnvPHB4 *phb = PNV_PHB4(host_bridge); - - snprintf(phb->bus_path, sizeof(phb->bus_path), "00%02x:%02x", - phb->chip_id, phb->phb_id); - return phb->bus_path; -} - /* * Address base trigger mode (POWER10) * @@ -1692,19 +1674,17 @@ static Property pnv_phb4_properties[] = { DEFINE_PROP_UINT32("chip-id", PnvPHB4, chip_id, 0), DEFINE_PROP_LINK("pec", PnvPHB4, pec, TYPE_PNV_PHB4_PEC, PnvPhb4PecState *), + DEFINE_PROP_LINK("phb-base", PnvPHB4, phb_base, TYPE_PNV_PHB, PnvPHB *), DEFINE_PROP_END_OF_LIST(), }; static void pnv_phb4_class_init(ObjectClass *klass, void *data) { - PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); XiveNotifierClass *xfc = XIVE_NOTIFIER_CLASS(klass); - hc->root_bus_path = pnv_phb4_root_bus_path; dc->realize = pnv_phb4_realize; device_class_set_props(dc, pnv_phb4_properties); - set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); dc->user_creatable = false; xfc->notify = pnv_phb4_xive_notify; @@ -1712,7 +1692,7 @@ static void pnv_phb4_class_init(ObjectClass *klass, void *data) static const TypeInfo pnv_phb4_type_info = { .name = TYPE_PNV_PHB4, - .parent = TYPE_PCIE_HOST_BRIDGE, + .parent = TYPE_DEVICE, .instance_init = pnv_phb4_instance_init, .instance_size = sizeof(PnvPHB4), .class_init = pnv_phb4_class_init, diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index c9aaf1c28e..4a0a9fbe8b 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -115,8 +115,7 @@ static void pnv_pec_default_phb_realize(PnvPhb4PecState *pec, int stack_no, Error **errp) { - PnvPhb4PecClass *pecc = PNV_PHB4_PEC_GET_CLASS(pec); - PnvPHB4 *phb = PNV_PHB4(qdev_new(pecc->phb_type)); + PnvPHB *phb = PNV_PHB(qdev_new(TYPE_PNV_PHB)); int phb_id = pnv_phb4_pec_get_phb_id(pec, stack_no); object_property_add_child(OBJECT(pec), "phb[*]", OBJECT(phb)); diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 5b60735c7a..ae6cd14a8a 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -672,11 +672,14 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) static int pnv_chip_power9_pic_print_info_child(Object *child, void *opaque) { Monitor *mon = opaque; - PnvPHB4 *phb4 = (PnvPHB4 *) object_dynamic_cast(child, TYPE_PNV_PHB4); + PnvPHB *phb = (PnvPHB *) object_dynamic_cast(child, TYPE_PNV_PHB); - if (phb4) { - pnv_phb4_pic_print_info(phb4, mon); + if (!phb) { + return 0; } + + pnv_phb4_pic_print_info(PNV_PHB4(phb->backend), mon); + return 0; } @@ -2147,8 +2150,14 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) PnvMachineClass *pmc = PNV_MACHINE_CLASS(oc); static const char compat[] = "qemu,powernv9\0ibm,powernv"; + static GlobalProperty phb_compat[] = { + { TYPE_PNV_PHB, "version", "4" }, + }; + mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power9_v2.0"); + compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); + xfc->match_nvt = pnv_match_nvt; mc->alias = "powernv"; @@ -2165,8 +2174,13 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) XiveFabricClass *xfc = XIVE_FABRIC_CLASS(oc); static const char compat[] = "qemu,powernv10\0ibm,powernv"; + static GlobalProperty phb_compat[] = { + { TYPE_PNV_PHB, "version", "5" }, + }; + mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0"); + compat_props_add(mc->compat_props, phb_compat, G_N_ELEMENTS(phb_compat)); pmc->compat = compat; pmc->compat_size = sizeof(compat); diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 90843ac3a9..f22253358f 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -18,6 +18,7 @@ typedef struct PnvPhb4PecState PnvPhb4PecState; typedef struct PnvPhb4PecStack PnvPhb4PecStack; typedef struct PnvPHB4 PnvPHB4; +typedef struct PnvPHB PnvPHB; typedef struct PnvChip PnvChip; /* @@ -78,7 +79,9 @@ OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4, PNV_PHB4) #define PCI_MMIO_TOTAL_SIZE (0x1ull << 60) struct PnvPHB4 { - PCIExpressHost parent_obj; + DeviceState parent; + + PnvPHB *phb_base; uint32_t chip_id; uint32_t phb_id; From 5ba76b61a2d3c90daa264bbaa14464eb3c49caa9 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:15 -0300 Subject: [PATCH 0212/1020] ppc/pnv: add pnv-phb-root-port device We have two very similar root-port devices, pnv-phb3-root-port and pnv-phb4-root-port. Both consist of a wrapper around the PCIESlot device that, until now, has no additional attributes. The main difference between the PHB3 and PHB4 root ports is that pnv-phb4-root-port has the pnv_phb4_root_port_reset() callback. All other differences can be merged in a single device without too much trouble. This patch introduces the unified pnv-phb-root-port that, in time, will be used as the default root port for the pnv-phb device. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-7-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 117 ++++++++++++++++++++++++++++++++++++++---- hw/pci-host/pnv_phb.h | 16 ++++++ 2 files changed, 124 insertions(+), 9 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index abcbcca445..5e61f85614 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -112,15 +112,114 @@ static void pnv_phb_class_init(ObjectClass *klass, void *data) dc->user_creatable = false; } -static void pnv_phb_register_type(void) +static void pnv_phb_root_port_reset(DeviceState *dev) { - static const TypeInfo pnv_phb_type_info = { - .name = TYPE_PNV_PHB, - .parent = TYPE_PCIE_HOST_BRIDGE, - .instance_size = sizeof(PnvPHB), - .class_init = pnv_phb_class_init, - }; + PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); + PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); + PCIDevice *d = PCI_DEVICE(dev); + uint8_t *conf = d->config; - type_register_static(&pnv_phb_type_info); + rpc->parent_reset(dev); + + if (phb_rp->version == 3) { + return; + } + + /* PHB4 and later requires these extra reset steps */ + pci_byte_test_and_set_mask(conf + PCI_IO_BASE, + PCI_IO_RANGE_MASK & 0xff); + pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT, + PCI_IO_RANGE_MASK & 0xff); + pci_set_word(conf + PCI_MEMORY_BASE, 0); + pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0); + pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1); + pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1); + pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */ + pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff); + pci_config_set_interrupt_pin(conf, 0); } -type_init(pnv_phb_register_type) + +static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) +{ + PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); + PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); + PCIDevice *pci = PCI_DEVICE(dev); + uint16_t device_id = 0; + Error *local_err = NULL; + + rpc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + switch (phb_rp->version) { + case 3: + device_id = PNV_PHB3_DEVICE_ID; + break; + case 4: + device_id = PNV_PHB4_DEVICE_ID; + break; + case 5: + device_id = PNV_PHB5_DEVICE_ID; + break; + default: + g_assert_not_reached(); + } + + pci_config_set_device_id(pci->config, device_id); + pci_config_set_interrupt_pin(pci->config, 0); +} + +static Property pnv_phb_root_port_properties[] = { + DEFINE_PROP_UINT32("version", PnvPHBRootPort, version, 0), + + DEFINE_PROP_END_OF_LIST(), +}; + +static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); + + dc->desc = "IBM PHB PCIE Root Port"; + + device_class_set_props(dc, pnv_phb_root_port_properties); + device_class_set_parent_realize(dc, pnv_phb_root_port_realize, + &rpc->parent_realize); + device_class_set_parent_reset(dc, pnv_phb_root_port_reset, + &rpc->parent_reset); + dc->reset = &pnv_phb_root_port_reset; + dc->user_creatable = false; + + k->vendor_id = PCI_VENDOR_ID_IBM; + /* device_id will be written during realize() */ + k->device_id = 0; + k->revision = 0; + + rpc->exp_offset = 0x48; + rpc->aer_offset = 0x100; +} + +static const TypeInfo pnv_phb_type_info = { + .name = TYPE_PNV_PHB, + .parent = TYPE_PCIE_HOST_BRIDGE, + .instance_size = sizeof(PnvPHB), + .class_init = pnv_phb_class_init, +}; + +static const TypeInfo pnv_phb_root_port_info = { + .name = TYPE_PNV_PHB_ROOT_PORT, + .parent = TYPE_PCIE_ROOT_PORT, + .instance_size = sizeof(PnvPHBRootPort), + .class_init = pnv_phb_root_port_class_init, +}; + +static void pnv_phb_register_types(void) +{ + type_register_static(&pnv_phb_type_info); + type_register_static(&pnv_phb_root_port_info); +} + +type_init(pnv_phb_register_types) diff --git a/hw/pci-host/pnv_phb.h b/hw/pci-host/pnv_phb.h index a7cc8610e2..58ebd6dd0f 100644 --- a/hw/pci-host/pnv_phb.h +++ b/hw/pci-host/pnv_phb.h @@ -36,4 +36,20 @@ struct PnvPHB { #define TYPE_PNV_PHB "pnv-phb" OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB, PNV_PHB) +/* + * PHB PCIe Root port + */ +#define PNV_PHB3_DEVICE_ID 0x03dc +#define PNV_PHB4_DEVICE_ID 0x04c1 +#define PNV_PHB5_DEVICE_ID 0x0652 + +typedef struct PnvPHBRootPort { + PCIESlot parent_obj; + + uint32_t version; +} PnvPHBRootPort; + +#define TYPE_PNV_PHB_ROOT_PORT "pnv-phb-root-port" +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHBRootPort, PNV_PHB_ROOT_PORT) + #endif /* PCI_HOST_PNV_PHB_H */ From 805150619e47eea910c760e1fde8d3e7e61a3a24 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:16 -0300 Subject: [PATCH 0213/1020] ppc/pnv: remove pnv-phb3-root-port The unified pnv-phb-root-port can be used in its place. There is no ABI breakage in doing so because no official QEMU release introduced user creatable pnv-phb3-root-port devices. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-8-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 2 +- hw/pci-host/pnv_phb3.c | 42 ---------------------------------- hw/ppc/pnv.c | 1 + include/hw/pci-host/pnv_phb3.h | 6 ----- 4 files changed, 2 insertions(+), 49 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 5e61f85614..cdddc6a389 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -34,7 +34,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) switch (phb->version) { case 3: phb_typename = g_strdup(TYPE_PNV_PHB3); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB3_ROOT_PORT); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; case 4: phb_typename = g_strdup(TYPE_PNV_PHB4); diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index ad9e983fe9..d4c04a281a 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -1122,51 +1122,9 @@ static const TypeInfo pnv_phb3_root_bus_info = { .class_init = pnv_phb3_root_bus_class_init, }; -static void pnv_phb3_root_port_realize(DeviceState *dev, Error **errp) -{ - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - PCIDevice *pci = PCI_DEVICE(dev); - Error *local_err = NULL; - - rpc->parent_realize(dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } - pci_config_set_interrupt_pin(pci->config, 0); -} - -static void pnv_phb3_root_port_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); - - dc->desc = "IBM PHB3 PCIE Root Port"; - - device_class_set_parent_realize(dc, pnv_phb3_root_port_realize, - &rpc->parent_realize); - dc->user_creatable = false; - - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = 0x03dc; - k->revision = 0; - - rpc->exp_offset = 0x48; - rpc->aer_offset = 0x100; -} - -static const TypeInfo pnv_phb3_root_port_info = { - .name = TYPE_PNV_PHB3_ROOT_PORT, - .parent = TYPE_PCIE_ROOT_PORT, - .instance_size = sizeof(PnvPHB3RootPort), - .class_init = pnv_phb3_root_port_class_init, -}; - static void pnv_phb3_register_types(void) { type_register_static(&pnv_phb3_root_bus_info); - type_register_static(&pnv_phb3_root_port_info); type_register_static(&pnv_phb3_type_info); type_register_static(&pnv_phb3_iommu_memory_region_info); } diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index ae6cd14a8a..672227a0e1 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -2129,6 +2129,7 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) static GlobalProperty phb_compat[] = { { TYPE_PNV_PHB, "version", "3" }, + { TYPE_PNV_PHB_ROOT_PORT, "version", "3" }, }; mc->desc = "IBM PowerNV (Non-Virtualized) POWER8"; diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index 3b9ff1096a..bff69201d9 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -108,12 +108,6 @@ struct PnvPBCQState { */ #define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root" -#define TYPE_PNV_PHB3_ROOT_PORT "pnv-phb3-root-port" - -typedef struct PnvPHB3RootPort { - PCIESlot parent_obj; -} PnvPHB3RootPort; - /* * PHB3 PCIe Host Bridge for PowerNV machines (POWER8) */ From c8d14603e998ee41313e989cec590c3ec8ddc923 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:17 -0300 Subject: [PATCH 0214/1020] ppc/pnv: remove pnv-phb4-root-port The unified pnv-phb-root-port can be used instead. The phb4-root-port device isn't exposed to the user in any official QEMU release so there's no ABI breakage in removing it. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-9-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 4 +- hw/pci-host/pnv_phb4.c | 85 ---------------------------------- hw/pci-host/pnv_phb4_pec.c | 4 +- hw/ppc/pnv.c | 2 + include/hw/pci-host/pnv_phb4.h | 9 ---- 5 files changed, 6 insertions(+), 98 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index cdddc6a389..da729e89e7 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -38,11 +38,11 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) break; case 4: phb_typename = g_strdup(TYPE_PNV_PHB4); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB4_ROOT_PORT); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; case 5: phb_typename = g_strdup(TYPE_PNV_PHB5); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB5_ROOT_PORT); + phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; default: g_assert_not_reached(); diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 144c437025..b98c394713 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1725,94 +1725,9 @@ static const TypeInfo pnv_phb4_root_bus_info = { .class_init = pnv_phb4_root_bus_class_init, }; -static void pnv_phb4_root_port_reset(DeviceState *dev) -{ - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - PCIDevice *d = PCI_DEVICE(dev); - uint8_t *conf = d->config; - - rpc->parent_reset(dev); - - pci_byte_test_and_set_mask(conf + PCI_IO_BASE, - PCI_IO_RANGE_MASK & 0xff); - pci_byte_test_and_clear_mask(conf + PCI_IO_LIMIT, - PCI_IO_RANGE_MASK & 0xff); - pci_set_word(conf + PCI_MEMORY_BASE, 0); - pci_set_word(conf + PCI_MEMORY_LIMIT, 0xfff0); - pci_set_word(conf + PCI_PREF_MEMORY_BASE, 0x1); - pci_set_word(conf + PCI_PREF_MEMORY_LIMIT, 0xfff1); - pci_set_long(conf + PCI_PREF_BASE_UPPER32, 0x1); /* Hack */ - pci_set_long(conf + PCI_PREF_LIMIT_UPPER32, 0xffffffff); - pci_config_set_interrupt_pin(conf, 0); -} - -static void pnv_phb4_root_port_realize(DeviceState *dev, Error **errp) -{ - PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); - Error *local_err = NULL; - - rpc->parent_realize(dev, &local_err); - if (local_err) { - error_propagate(errp, local_err); - return; - } -} - -static void pnv_phb4_root_port_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - PCIERootPortClass *rpc = PCIE_ROOT_PORT_CLASS(klass); - - dc->desc = "IBM PHB4 PCIE Root Port"; - dc->user_creatable = false; - - device_class_set_parent_realize(dc, pnv_phb4_root_port_realize, - &rpc->parent_realize); - device_class_set_parent_reset(dc, pnv_phb4_root_port_reset, - &rpc->parent_reset); - - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = PNV_PHB4_DEVICE_ID; - k->revision = 0; - - rpc->exp_offset = 0x48; - rpc->aer_offset = 0x100; - - dc->reset = &pnv_phb4_root_port_reset; -} - -static const TypeInfo pnv_phb4_root_port_info = { - .name = TYPE_PNV_PHB4_ROOT_PORT, - .parent = TYPE_PCIE_ROOT_PORT, - .instance_size = sizeof(PnvPHB4RootPort), - .class_init = pnv_phb4_root_port_class_init, -}; - -static void pnv_phb5_root_port_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); - - dc->desc = "IBM PHB5 PCIE Root Port"; - dc->user_creatable = false; - - k->vendor_id = PCI_VENDOR_ID_IBM; - k->device_id = PNV_PHB5_DEVICE_ID; -} - -static const TypeInfo pnv_phb5_root_port_info = { - .name = TYPE_PNV_PHB5_ROOT_PORT, - .parent = TYPE_PNV_PHB4_ROOT_PORT, - .instance_size = sizeof(PnvPHB4RootPort), - .class_init = pnv_phb5_root_port_class_init, -}; - static void pnv_phb4_register_types(void) { type_register_static(&pnv_phb4_root_bus_info); - type_register_static(&pnv_phb5_root_port_info); - type_register_static(&pnv_phb4_root_port_info); type_register_static(&pnv_phb4_type_info); type_register_static(&pnv_phb5_type_info); type_register_static(&pnv_phb4_iommu_memory_region_info); diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 4a0a9fbe8b..0ef66b9a9b 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -260,7 +260,7 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB4_VERSION; pecc->phb_type = TYPE_PNV_PHB4; pecc->num_phbs = pnv_pec_num_phbs; - pecc->rp_model = TYPE_PNV_PHB4_ROOT_PORT; + pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT; } static const TypeInfo pnv_pec_type_info = { @@ -313,7 +313,7 @@ static void pnv_phb5_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB5_VERSION; pecc->phb_type = TYPE_PNV_PHB5; pecc->num_phbs = pnv_phb5_pec_num_stacks; - pecc->rp_model = TYPE_PNV_PHB5_ROOT_PORT; + pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT; } static const TypeInfo pnv_phb5_pec_type_info = { diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 672227a0e1..576c0013ed 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -2153,6 +2153,7 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) static GlobalProperty phb_compat[] = { { TYPE_PNV_PHB, "version", "4" }, + { TYPE_PNV_PHB_ROOT_PORT, "version", "4" }, }; mc->desc = "IBM PowerNV (Non-Virtualized) POWER9"; @@ -2177,6 +2178,7 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) static GlobalProperty phb_compat[] = { { TYPE_PNV_PHB, "version", "5" }, + { TYPE_PNV_PHB_ROOT_PORT, "version", "5" }, }; mc->desc = "IBM PowerNV (Non-Virtualized) POWER10"; diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index f22253358f..29c49ac79c 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -45,16 +45,7 @@ typedef struct PnvPhb4DMASpace { QLIST_ENTRY(PnvPhb4DMASpace) list; } PnvPhb4DMASpace; -/* - * PHB4 PCIe Root port - */ #define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root" -#define TYPE_PNV_PHB4_ROOT_PORT "pnv-phb4-root-port" -#define TYPE_PNV_PHB5_ROOT_PORT "pnv-phb5-root-port" - -typedef struct PnvPHB4RootPort { - PCIESlot parent_obj; -} PnvPHB4RootPort; /* * PHB4 PCIe Host Bridge for PowerNV machines (POWER9) From 17c681e92ddd66b8a5c425ea6a1c6ec3a4e079d4 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:18 -0300 Subject: [PATCH 0215/1020] ppc/pnv: remove root port name from pnv_phb_attach_root_port() We support only a single root port, PNV_PHB_ROOT_PORT. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-10-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 7 +------ hw/ppc/pnv.c | 9 +++++---- include/hw/ppc/pnv.h | 3 +-- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index da729e89e7..cc15a949c9 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -24,7 +24,6 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) PnvPHB *phb = PNV_PHB(dev); PCIHostState *pci = PCI_HOST_BRIDGE(dev); g_autofree char *phb_typename = NULL; - g_autofree char *phb_rootport_typename = NULL; if (!phb->version) { error_setg(errp, "version not specified"); @@ -34,15 +33,12 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) switch (phb->version) { case 3: phb_typename = g_strdup(TYPE_PNV_PHB3); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; case 4: phb_typename = g_strdup(TYPE_PNV_PHB4); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; case 5: phb_typename = g_strdup(TYPE_PNV_PHB5); - phb_rootport_typename = g_strdup(TYPE_PNV_PHB_ROOT_PORT); break; default: g_assert_not_reached(); @@ -73,8 +69,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } - pnv_phb_attach_root_port(pci, phb_rootport_typename, - phb->phb_id, phb->chip_id); + pnv_phb_attach_root_port(pci, phb->phb_id, phb->chip_id); } static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 576c0013ed..6b94c373d1 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1195,11 +1195,12 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) * QOM id. 'chip_id' is going to be used as PCIE chassis for the * root port. */ -void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, - int index, int chip_id) +void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id) { - PCIDevice *root = pci_new(PCI_DEVFN(0, 0), name); - g_autofree char *default_id = g_strdup_printf("%s[%d]", name, index); + PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); + g_autofree char *default_id = g_strdup_printf("%s[%d]", + TYPE_PNV_PHB_ROOT_PORT, + index); const char *dev_id = DEVICE(root)->id; object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 21fa90aaff..0eda47da0c 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -193,8 +193,7 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, TYPE_PNV_CHIP_POWER10) PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); -void pnv_phb_attach_root_port(PCIHostState *pci, const char *name, - int index, int chip_id); +void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id); #define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv") typedef struct PnvMachineClass PnvMachineClass; From cb6a5c26446f797252a479f456da030dc7febb20 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:19 -0300 Subject: [PATCH 0216/1020] ppc/pnv: remove pecc->rp_model The attribute is unused. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-11-danielhb413@gmail.com> --- hw/pci-host/pnv_phb4_pec.c | 2 -- include/hw/pci-host/pnv_phb4.h | 1 - 2 files changed, 3 deletions(-) diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 0ef66b9a9b..8dc363d69c 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -260,7 +260,6 @@ static void pnv_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB4_VERSION; pecc->phb_type = TYPE_PNV_PHB4; pecc->num_phbs = pnv_pec_num_phbs; - pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT; } static const TypeInfo pnv_pec_type_info = { @@ -313,7 +312,6 @@ static void pnv_phb5_pec_class_init(ObjectClass *klass, void *data) pecc->version = PNV_PHB5_VERSION; pecc->phb_type = TYPE_PNV_PHB5; pecc->num_phbs = pnv_phb5_pec_num_stacks; - pecc->rp_model = TYPE_PNV_PHB_ROOT_PORT; } static const TypeInfo pnv_phb5_pec_type_info = { diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 29c49ac79c..61a0cb9989 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -200,7 +200,6 @@ struct PnvPhb4PecClass { uint64_t version; const char *phb_type; const uint32_t *num_phbs; - const char *rp_model; }; /* From d69db7dadfe7fd13731a9621520ffb2f382f1675 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:20 -0300 Subject: [PATCH 0217/1020] ppc/pnv: remove PnvPHB4.version It's unused. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-12-danielhb413@gmail.com> --- include/hw/pci-host/pnv_phb4.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 61a0cb9989..20aa4819d3 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -77,8 +77,6 @@ struct PnvPHB4 { uint32_t chip_id; uint32_t phb_id; - uint64_t version; - /* The owner PEC */ PnvPhb4PecState *pec; From e5ea94360eba4818467283a259d8d681f0da799f Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 24 Jun 2022 05:49:21 -0300 Subject: [PATCH 0218/1020] ppc/pnv: move attach_root_port helper to pnv-phb.c The helper is only used in this file. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220624084921.399219-13-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 24 ++++++++++++++++++++++++ hw/ppc/pnv.c | 25 ------------------------- include/hw/ppc/pnv.h | 1 - 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index cc15a949c9..c47ed92462 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -18,6 +18,30 @@ #include "hw/qdev-properties.h" #include "qom/object.h" +/* + * Attach a root port device. + * + * 'index' will be used both as a PCIE slot value and to calculate + * QOM id. 'chip_id' is going to be used as PCIE chassis for the + * root port. + */ +static void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id) +{ + PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); + g_autofree char *default_id = g_strdup_printf("%s[%d]", + TYPE_PNV_PHB_ROOT_PORT, + index); + const char *dev_id = DEVICE(root)->id; + + object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, + OBJECT(root)); + + /* Set unique chassis/slot values for the root port */ + qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id); + qdev_prop_set_uint16(DEVICE(root), "slot", index); + + pci_realize_and_unref(root, pci->bus, &error_fatal); +} static void pnv_phb_realize(DeviceState *dev, Error **errp) { diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 6b94c373d1..758e36132d 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1188,31 +1188,6 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp) } } -/* - * Attach a root port device. - * - * 'index' will be used both as a PCIE slot value and to calculate - * QOM id. 'chip_id' is going to be used as PCIE chassis for the - * root port. - */ -void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id) -{ - PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); - g_autofree char *default_id = g_strdup_printf("%s[%d]", - TYPE_PNV_PHB_ROOT_PORT, - index); - const char *dev_id = DEVICE(root)->id; - - object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, - OBJECT(root)); - - /* Set unique chassis/slot values for the root port */ - qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id); - qdev_prop_set_uint16(DEVICE(root), "slot", index); - - pci_realize_and_unref(root, pci->bus, &error_fatal); -} - static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) { PnvChipClass *pcc = PNV_CHIP_GET_CLASS(dev); diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 0eda47da0c..290adac76c 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -193,7 +193,6 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10, TYPE_PNV_CHIP_POWER10) PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir); -void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id); #define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv") typedef struct PnvMachineClass PnvMachineClass; From 8ec1e4f1ef974e901b416fef6c3b38a5cc2eeffa Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:40 -0300 Subject: [PATCH 0219/1020] ppc/pnv: add phb-id/chip-id PnvPHB3RootBus properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We rely on the phb-id and chip-id, which are PHB properties, to assign chassis and slot to the root port. For default devices this is no big deal: the root port is being created under pnv_phb_realize() and the values are being passed on via the 'index' and 'chip-id' of the pnv_phb_attach_root_port() helper. If we want to implement user created root ports we have a problem. The user created root port will not be aware of which PHB it belongs to, unless we're willing to violate QOM best practices and access the PHB via dev->parent_bus->parent. What we can do is to access the root bus parent bus. Since we're already assigning the root port as QOM child of the bus, and the bus is initiated using PHB properties, let's add phb-id and chip-id as properties of the bus. This will allow us trivial access to them, for both user-created and default root ports, without doing anything too shady with QOM. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-2-danielhb413@gmail.com> --- hw/pci-host/pnv_phb3.c | 50 ++++++++++++++++++++++++++++++++++ include/hw/pci-host/pnv_phb3.h | 9 +++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index d4c04a281a..af8575c007 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -1006,6 +1006,11 @@ void pnv_phb3_bus_init(DeviceState *dev, PnvPHB3 *phb) &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB3_ROOT_BUS); + object_property_set_int(OBJECT(pci->bus), "phb-id", phb->phb_id, + &error_abort); + object_property_set_int(OBJECT(pci->bus), "chip-id", phb->chip_id, + &error_abort); + pci_setup_iommu(pci->bus, pnv_phb3_dma_iommu, phb); } @@ -1105,10 +1110,55 @@ static const TypeInfo pnv_phb3_type_info = { .instance_init = pnv_phb3_instance_init, }; +static void pnv_phb3_root_bus_get_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + PnvPHB3RootBus *bus = PNV_PHB3_ROOT_BUS(obj); + uint64_t value = 0; + + if (strcmp(name, "phb-id") == 0) { + value = bus->phb_id; + } else { + value = bus->chip_id; + } + + visit_type_size(v, name, &value, errp); +} + +static void pnv_phb3_root_bus_set_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) + +{ + PnvPHB3RootBus *bus = PNV_PHB3_ROOT_BUS(obj); + uint64_t value; + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + + if (strcmp(name, "phb-id") == 0) { + bus->phb_id = value; + } else { + bus->chip_id = value; + } +} + static void pnv_phb3_root_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); + object_class_property_add(klass, "phb-id", "int", + pnv_phb3_root_bus_get_prop, + pnv_phb3_root_bus_set_prop, + NULL, NULL); + + object_class_property_add(klass, "chip-id", "int", + pnv_phb3_root_bus_get_prop, + pnv_phb3_root_bus_set_prop, + NULL, NULL); + /* * PHB3 has only a single root complex. Enforce the limit on the * parent bus diff --git a/include/hw/pci-host/pnv_phb3.h b/include/hw/pci-host/pnv_phb3.h index bff69201d9..4854f6d2f6 100644 --- a/include/hw/pci-host/pnv_phb3.h +++ b/include/hw/pci-host/pnv_phb3.h @@ -104,9 +104,16 @@ struct PnvPBCQState { }; /* - * PHB3 PCIe Root port + * PHB3 PCIe Root Bus */ #define TYPE_PNV_PHB3_ROOT_BUS "pnv-phb3-root" +struct PnvPHB3RootBus { + PCIBus parent; + + uint32_t chip_id; + uint32_t phb_id; +}; +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB3RootBus, PNV_PHB3_ROOT_BUS) /* * PHB3 PCIe Host Bridge for PowerNV machines (POWER8) From b7c1750dc440bb46ddc38dd0c391d6394db7bdb1 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:41 -0300 Subject: [PATCH 0220/1020] ppc/pnv: add phb-id/chip-id PnvPHB4RootBus properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The same rationale provided in the PHB3 bus case applies here. Note: we could have merged both buses in a single object, like we did with the root ports, and spare some boilerplate. The reason we opted to preserve both buses objects is twofold: - there's not user side advantage in doing so. Unifying the root ports presents a clear user QOL change when we enable user created devices back. The buses objects, aside from having a different QOM name, is transparent to the user; - we leave a door opened in case we want to increase the root port limit for phb4/5 later on without having to deal with phb3 code. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-3-danielhb413@gmail.com> --- hw/pci-host/pnv_phb4.c | 51 ++++++++++++++++++++++++++++++++++ include/hw/pci-host/pnv_phb4.h | 10 +++++++ 2 files changed, 61 insertions(+) diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index b98c394713..824e1a73fb 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1551,6 +1551,12 @@ void pnv_phb4_bus_init(DeviceState *dev, PnvPHB4 *phb) pnv_phb4_set_irq, pnv_phb4_map_irq, phb, &phb->pci_mmio, &phb->pci_io, 0, 4, TYPE_PNV_PHB4_ROOT_BUS); + + object_property_set_int(OBJECT(pci->bus), "phb-id", phb->phb_id, + &error_abort); + object_property_set_int(OBJECT(pci->bus), "chip-id", phb->chip_id, + &error_abort); + pci_setup_iommu(pci->bus, pnv_phb4_dma_iommu, phb); pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE; } @@ -1708,10 +1714,55 @@ static const TypeInfo pnv_phb5_type_info = { .instance_size = sizeof(PnvPHB4), }; +static void pnv_phb4_root_bus_get_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) +{ + PnvPHB4RootBus *bus = PNV_PHB4_ROOT_BUS(obj); + uint64_t value = 0; + + if (strcmp(name, "phb-id") == 0) { + value = bus->phb_id; + } else { + value = bus->chip_id; + } + + visit_type_size(v, name, &value, errp); +} + +static void pnv_phb4_root_bus_set_prop(Object *obj, Visitor *v, + const char *name, + void *opaque, Error **errp) + +{ + PnvPHB4RootBus *bus = PNV_PHB4_ROOT_BUS(obj); + uint64_t value; + + if (!visit_type_size(v, name, &value, errp)) { + return; + } + + if (strcmp(name, "phb-id") == 0) { + bus->phb_id = value; + } else { + bus->chip_id = value; + } +} + static void pnv_phb4_root_bus_class_init(ObjectClass *klass, void *data) { BusClass *k = BUS_CLASS(klass); + object_class_property_add(klass, "phb-id", "int", + pnv_phb4_root_bus_get_prop, + pnv_phb4_root_bus_set_prop, + NULL, NULL); + + object_class_property_add(klass, "chip-id", "int", + pnv_phb4_root_bus_get_prop, + pnv_phb4_root_bus_set_prop, + NULL, NULL); + /* * PHB4 has only a single root complex. Enforce the limit on the * parent bus diff --git a/include/hw/pci-host/pnv_phb4.h b/include/hw/pci-host/pnv_phb4.h index 20aa4819d3..50d4faa001 100644 --- a/include/hw/pci-host/pnv_phb4.h +++ b/include/hw/pci-host/pnv_phb4.h @@ -45,7 +45,17 @@ typedef struct PnvPhb4DMASpace { QLIST_ENTRY(PnvPhb4DMASpace) list; } PnvPhb4DMASpace; +/* + * PHB4 PCIe Root Bus + */ #define TYPE_PNV_PHB4_ROOT_BUS "pnv-phb4-root" +struct PnvPHB4RootBus { + PCIBus parent; + + uint32_t chip_id; + uint32_t phb_id; +}; +OBJECT_DECLARE_SIMPLE_TYPE(PnvPHB4RootBus, PNV_PHB4_ROOT_BUS) /* * PHB4 PCIe Host Bridge for PowerNV machines (POWER9) From c2f3f78af5fd664f95748ebc918ae86463690249 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:42 -0300 Subject: [PATCH 0221/1020] ppc/pnv: set root port chassis and slot using Bus properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For default root ports we have a way of accessing chassis and slot, before root_port_realize(), via pnv_phb_attach_root_port(). For the future user created root ports this won't be the case: we can't use this helper because we don't have access to the PHB phb-id/chip-id values. In earlier patches we've added phb-id and chip-id to pnv-phb-root-bus objects. We're now able to use the bus to retrieve them. The bus is reachable for both user created and default devices, so we're changing all the code paths. This also allow us to validate these changes with the existing default devices. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-4-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index c47ed92462..826c0c144e 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -25,21 +25,19 @@ * QOM id. 'chip_id' is going to be used as PCIE chassis for the * root port. */ -static void pnv_phb_attach_root_port(PCIHostState *pci, int index, int chip_id) +static void pnv_phb_attach_root_port(PCIHostState *pci) { PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); - g_autofree char *default_id = g_strdup_printf("%s[%d]", - TYPE_PNV_PHB_ROOT_PORT, - index); const char *dev_id = DEVICE(root)->id; + g_autofree char *default_id = NULL; + int index; + + index = object_property_get_int(OBJECT(pci->bus), "phb-id", &error_fatal); + default_id = g_strdup_printf("%s[%d]", TYPE_PNV_PHB_ROOT_PORT, index); object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, OBJECT(root)); - /* Set unique chassis/slot values for the root port */ - qdev_prop_set_uint8(DEVICE(root), "chassis", chip_id); - qdev_prop_set_uint16(DEVICE(root), "slot", index); - pci_realize_and_unref(root, pci->bus, &error_fatal); } @@ -93,7 +91,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } - pnv_phb_attach_root_port(pci, phb->phb_id, phb->chip_id); + pnv_phb_attach_root_port(pci); } static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, @@ -162,9 +160,18 @@ static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) { PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(dev); PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(dev); + PCIBus *bus = PCI_BUS(qdev_get_parent_bus(dev)); PCIDevice *pci = PCI_DEVICE(dev); uint16_t device_id = 0; Error *local_err = NULL; + int chip_id, index; + + chip_id = object_property_get_int(OBJECT(bus), "chip-id", &error_fatal); + index = object_property_get_int(OBJECT(bus), "phb-id", &error_fatal); + + /* Set unique chassis/slot values for the root port */ + qdev_prop_set_uint8(dev, "chassis", chip_id); + qdev_prop_set_uint16(dev, "slot", index); rpc->parent_realize(dev, &local_err); if (local_err) { From ba47c3a4f888e99dedde1fed740927e973f9bc32 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:43 -0300 Subject: [PATCH 0222/1020] ppc/pnv: add helpers for pnv-phb user devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pnv_parent_qom_fixup() and pnv_parent_bus_fixup() are versions of the helpers that were reverted by commit 9c10d86fee "ppc/pnv: Remove user-created PHB{3,4,5} devices". They are needed to amend the QOM and bus hierarchies of user created pnv-phbs, matching them with default pnv-phbs. A new helper pnv_phb_user_device_init() is created to handle user-created devices setup. We're going to call it inside pnv_phb_realize() in case we're realizing an user created device. This will centralize all user device realated in a single spot, leaving the realize functions of the phb3/phb4 backends untouched. Another helper called pnv_chip_add_phb() was added to handle the particularities of each chip version when adding a new PHB. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-5-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 75 +++++++++++++++++++++++++++++++++++++++++++ hw/ppc/pnv.c | 20 ++++++++++++ include/hw/ppc/pnv.h | 1 + 3 files changed, 96 insertions(+) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 826c0c144e..5dc44f45d1 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -18,6 +18,38 @@ #include "hw/qdev-properties.h" #include "qom/object.h" + +/* + * Set the QOM parent of an object child. If the device state + * associated with the child has an id, use it as QOM id. Otherwise + * use object_typename[index] as QOM id. + */ +static void pnv_parent_qom_fixup(Object *parent, Object *child, int index) +{ + g_autofree char *default_id = + g_strdup_printf("%s[%d]", object_get_typename(child), index); + const char *dev_id = DEVICE(child)->id; + + if (child->parent == parent) { + return; + } + + object_ref(child); + object_unparent(child); + object_property_add_child(parent, dev_id ? dev_id : default_id, child); + object_unref(child); +} + +static void pnv_parent_bus_fixup(DeviceState *parent, DeviceState *child, + Error **errp) +{ + BusState *parent_bus = qdev_get_parent_bus(parent); + + if (!qdev_set_parent_bus(child, parent_bus, errp)) { + return; + } +} + /* * Attach a root port device. * @@ -41,6 +73,39 @@ static void pnv_phb_attach_root_port(PCIHostState *pci) pci_realize_and_unref(root, pci->bus, &error_fatal); } +/* + * User created devices won't have the initial setup that default + * devices have. This setup consists of assigning a parent device + * (chip for PHB3, PEC for PHB4/5) that will be the QOM/bus parent + * of the PHB. + */ +static bool pnv_phb_user_device_init(PnvPHB *phb, Error **errp) +{ + PnvMachineState *pnv = PNV_MACHINE(qdev_get_machine()); + PnvChip *chip = pnv_get_chip(pnv, phb->chip_id); + Object *parent = NULL; + + if (!chip) { + error_setg(errp, "invalid chip id: %d", phb->chip_id); + return false; + } + + parent = pnv_chip_add_phb(chip, phb, errp); + if (!parent) { + return false; + } + + /* + * Reparent user created devices to the chip to build + * correctly the device tree. pnv_xscom_dt() needs every + * PHB to be a child of the chip to build the DT correctly. + */ + pnv_parent_qom_fixup(parent, OBJECT(phb), phb->phb_id); + pnv_parent_bus_fixup(DEVICE(chip), DEVICE(phb), errp); + + return true; +} + static void pnv_phb_realize(DeviceState *dev, Error **errp) { PnvPHB *phb = PNV_PHB(dev); @@ -74,6 +139,16 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) object_property_set_uint(phb->backend, "chip-id", phb->chip_id, errp); object_property_set_link(phb->backend, "phb-base", OBJECT(phb), errp); + /* + * Handle user created devices. User devices will not have a + * pointer to a chip (PHB3) and a PEC (PHB4/5). + */ + if (!phb->chip && !phb->pec) { + if (!pnv_phb_user_device_init(phb, errp)) { + return; + } + } + if (phb->version == 3) { object_property_set_link(phb->backend, "chip", OBJECT(phb->chip), errp); diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 758e36132d..737dee4980 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -281,6 +281,26 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, g_free(reg); } +/* + * Adds a PnvPHB to the chip. Returns the parent obj of the + * PHB which varies with each version (phb version 3 is parented + * by the chip, version 4 and 5 are parented by the PEC + * device). + * + * TODO: for version 3 we're still parenting the PHB with the + * chip. We should parent with a (so far not implemented) + * PHB3 PEC device. + */ +Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp) +{ + if (phb->version == 3) { + return OBJECT(chip); + } else { + /* phb4 support will be added later */ + return NULL; + } +} + static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) { static const char compat[] = "ibm,power8-xscom\0ibm,xscom"; diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index 290adac76c..c44f357bce 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -234,6 +234,7 @@ struct PnvMachineState { }; PnvChip *pnv_get_chip(PnvMachineState *pnv, uint32_t chip_id); +Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp); #define PNV_FDT_ADDR 0x01000000 #define PNV_TIMEBASE_FREQ 512000000ULL From 0d512c7120a2638da242436d45bd8a82ffffe27a Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:44 -0300 Subject: [PATCH 0223/1020] ppc/pnv: turn chip8->phbs[] into a PnvPHB* array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When enabling user created PHBs (a change reverted by commit 9c10d86fee) we were handling PHBs created by default versus by the user in different manners. The only difference between these PHBs is that one will have a valid phb3->chip that is assigned during pnv_chip_power8_realize(), while the user created needs to search which chip it belongs to. Aside from that there shouldn't be any difference. Making the default PHBs behave in line with the user created ones will make it easier to re-introduce them later on. It will also make the code easier to follow since we are dealing with them in equal manner. The first step is to turn chip8->phbs[] into a PnvPHB3 pointer array. This will allow us to assign user created PHBs into it later on. The way we initilize the default case is now more in line with that would happen with the user created case: the object is created, parented by the chip because pnv_xscom_dt() relies on it, and then assigned to the array. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-6-danielhb413@gmail.com> --- hw/ppc/pnv.c | 27 ++++++++++++++++++++++----- include/hw/ppc/pnv.h | 6 +++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 737dee4980..0208517f1a 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -294,6 +294,13 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp) { if (phb->version == 3) { + Pnv8Chip *chip8 = PNV8_CHIP(chip); + + phb->chip = chip; + + chip8->phbs[chip8->num_phbs] = phb; + chip8->num_phbs++; + return OBJECT(chip); } else { /* phb4 support will be added later */ @@ -681,7 +688,7 @@ static void pnv_chip_power8_pic_print_info(PnvChip *chip, Monitor *mon) ics_pic_print_info(&chip8->psi.ics, mon); for (i = 0; i < chip8->num_phbs; i++) { - PnvPHB *phb = &chip8->phbs[i]; + PnvPHB *phb = chip8->phbs[i]; PnvPHB3 *phb3 = PNV_PHB3(phb->backend); pnv_phb3_msi_pic_print_info(&phb3->msis, mon); @@ -1174,7 +1181,17 @@ static void pnv_chip_power8_instance_init(Object *obj) chip8->num_phbs = pcc->num_phbs; for (i = 0; i < chip8->num_phbs; i++) { - object_initialize_child(obj, "phb[*]", &chip8->phbs[i], TYPE_PNV_PHB); + Object *phb = object_new(TYPE_PNV_PHB); + + /* + * We need the chip to parent the PHB to allow the DT + * to build correctly (via pnv_xscom_dt()). + * + * TODO: the PHB should be parented by a PEC device that, at + * this moment, is not modelled powernv8/phb3. + */ + object_property_add_child(obj, "phb[*]", phb); + chip8->phbs[i] = PNV_PHB(phb); } } @@ -1290,7 +1307,7 @@ static void pnv_chip_power8_realize(DeviceState *dev, Error **errp) /* PHB controllers */ for (i = 0; i < chip8->num_phbs; i++) { - PnvPHB *phb = &chip8->phbs[i]; + PnvPHB *phb = chip8->phbs[i]; object_property_set_int(OBJECT(phb), "index", i, &error_fatal); object_property_set_int(OBJECT(phb), "chip-id", chip->chip_id, @@ -1983,7 +2000,7 @@ static ICSState *pnv_ics_get(XICSFabric *xi, int irq) } for (j = 0; j < chip8->num_phbs; j++) { - PnvPHB *phb = &chip8->phbs[j]; + PnvPHB *phb = chip8->phbs[j]; PnvPHB3 *phb3 = PNV_PHB3(phb->backend); if (ics_valid_irq(&phb3->lsis, irq)) { @@ -2022,7 +2039,7 @@ static void pnv_ics_resend(XICSFabric *xi) ics_resend(&chip8->psi.ics); for (j = 0; j < chip8->num_phbs; j++) { - PnvPHB *phb = &chip8->phbs[j]; + PnvPHB *phb = chip8->phbs[j]; PnvPHB3 *phb3 = PNV_PHB3(phb->backend); ics_resend(&phb3->lsis); diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h index c44f357bce..9ef7e2d0dc 100644 --- a/include/hw/ppc/pnv.h +++ b/include/hw/ppc/pnv.h @@ -82,7 +82,11 @@ struct Pnv8Chip { PnvHomer homer; #define PNV8_CHIP_PHB3_MAX 4 - PnvPHB phbs[PNV8_CHIP_PHB3_MAX]; + /* + * The array is used to allow quick access to the phbs by + * pnv_ics_get_child() and pnv_ics_resend_child(). + */ + PnvPHB *phbs[PNV8_CHIP_PHB3_MAX]; uint32_t num_phbs; XICSFabric *xics; From 892c3ad0d5d6bb9b1e414d61118e93362ecab782 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:45 -0300 Subject: [PATCH 0224/1020] ppc/pnv: enable user created pnv-phb for powernv8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bulk of the work was already done by previous patches. Use defaults_enabled() to determine whether we need to create the default devices or not. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-7-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 9 +++++++-- hw/ppc/pnv.c | 28 ++++++++++++++++------------ 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 5dc44f45d1..1f53ff77c5 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -17,6 +17,7 @@ #include "hw/ppc/pnv.h" #include "hw/qdev-properties.h" #include "qom/object.h" +#include "sysemu/sysemu.h" /* @@ -166,6 +167,10 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } + if (phb->version == 3 && !defaults_enabled()) { + return; + } + pnv_phb_attach_root_port(pci); } @@ -201,7 +206,7 @@ static void pnv_phb_class_init(ObjectClass *klass, void *data) dc->realize = pnv_phb_realize; device_class_set_props(dc, pnv_phb_properties); set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); - dc->user_creatable = false; + dc->user_creatable = true; } static void pnv_phb_root_port_reset(DeviceState *dev) @@ -292,7 +297,7 @@ static void pnv_phb_root_port_class_init(ObjectClass *klass, void *data) device_class_set_parent_reset(dc, pnv_phb_root_port_reset, &rpc->parent_reset); dc->reset = &pnv_phb_root_port_reset; - dc->user_creatable = false; + dc->user_creatable = true; k->vendor_id = PCI_VENDOR_ID_IBM; /* device_id will be written during realize() */ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 0208517f1a..9ce1ae7752 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -1178,20 +1178,22 @@ static void pnv_chip_power8_instance_init(Object *obj) object_initialize_child(obj, "homer", &chip8->homer, TYPE_PNV8_HOMER); - chip8->num_phbs = pcc->num_phbs; + if (defaults_enabled()) { + chip8->num_phbs = pcc->num_phbs; - for (i = 0; i < chip8->num_phbs; i++) { - Object *phb = object_new(TYPE_PNV_PHB); + for (i = 0; i < chip8->num_phbs; i++) { + Object *phb = object_new(TYPE_PNV_PHB); - /* - * We need the chip to parent the PHB to allow the DT - * to build correctly (via pnv_xscom_dt()). - * - * TODO: the PHB should be parented by a PEC device that, at - * this moment, is not modelled powernv8/phb3. - */ - object_property_add_child(obj, "phb[*]", phb); - chip8->phbs[i] = PNV_PHB(phb); + /* + * We need the chip to parent the PHB to allow the DT + * to build correctly (via pnv_xscom_dt()). + * + * TODO: the PHB should be parented by a PEC device that, at + * this moment, is not modelled powernv8/phb3. + */ + object_property_add_child(obj, "phb[*]", phb); + chip8->phbs[i] = PNV_PHB(phb); + } } } @@ -2155,6 +2157,8 @@ static void pnv_machine_power8_class_init(ObjectClass *oc, void *data) pmc->compat = compat; pmc->compat_size = sizeof(compat); + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); } static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) From c1471772772499b36659a0785d9a3de759d5aee2 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:46 -0300 Subject: [PATCH 0225/1020] ppc/pnv: add PHB4 helpers for user created pnv-phb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PHB4 backend relies on a link with the corresponding PEC element. This is trivial to do during machine_init() time for default devices, but not so much for user created ones. pnv_phb4_get_pec() is a small variation of the function that was reverted by commit 9c10d86fee "ppc/pnv: Remove user-created PHB{3,4,5} devices". We'll use it to determine the appropriate PEC for a given user created pnv-phb that uses a PHB4 backend. This is done during realize() time, in pnv_phb_user_device_init(). Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-8-danielhb413@gmail.com> --- hw/ppc/pnv.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 9ce1ae7752..c34967cac7 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -281,6 +281,34 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, g_free(reg); } +static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb, + Error **errp) +{ + Pnv9Chip *chip9 = PNV9_CHIP(chip); + int chip_id = phb->chip_id; + int index = phb->phb_id; + int i, j; + + for (i = 0; i < chip->num_pecs; i++) { + /* + * For each PEC, check the amount of phbs it supports + * and see if the given phb4 index matches an index. + */ + PnvPhb4PecState *pec = &chip9->pecs[i]; + + for (j = 0; j < pec->num_phbs; j++) { + if (index == pnv_phb4_pec_get_phb_id(pec, j)) { + return pec; + } + } + } + error_setg(errp, + "pnv-phb4 chip-id %d index %d didn't match any existing PEC", + chip_id, index); + + return NULL; +} + /* * Adds a PnvPHB to the chip. Returns the parent obj of the * PHB which varies with each version (phb version 3 is parented @@ -302,10 +330,11 @@ Object *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb, Error **errp) chip8->num_phbs++; return OBJECT(chip); - } else { - /* phb4 support will be added later */ - return NULL; } + + phb->pec = pnv_phb4_get_pec(chip, PNV_PHB4(phb->backend), errp); + + return OBJECT(phb->pec); } static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt) From d786be3fe7466ff96db96b86e6fee437136d63d7 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:47 -0300 Subject: [PATCH 0226/1020] ppc/pnv: enable user created pnv-phb for powernv9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enable pnv-phb user created devices for powernv9 now that we have everything in place. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-9-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 2 +- hw/pci-host/pnv_phb4_pec.c | 6 ++++-- hw/ppc/pnv.c | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 1f53ff77c5..17d9960aa1 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -167,7 +167,7 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } - if (phb->version == 3 && !defaults_enabled()) { + if (!defaults_enabled()) { return; } diff --git a/hw/pci-host/pnv_phb4_pec.c b/hw/pci-host/pnv_phb4_pec.c index 8dc363d69c..9871f462cd 100644 --- a/hw/pci-host/pnv_phb4_pec.c +++ b/hw/pci-host/pnv_phb4_pec.c @@ -146,8 +146,10 @@ static void pnv_pec_realize(DeviceState *dev, Error **errp) pec->num_phbs = pecc->num_phbs[pec->index]; /* Create PHBs if running with defaults */ - for (i = 0; i < pec->num_phbs; i++) { - pnv_pec_default_phb_realize(pec, i, errp); + if (defaults_enabled()) { + for (i = 0; i < pec->num_phbs; i++) { + pnv_pec_default_phb_realize(pec, i, errp); + } } /* Initialize the XSCOM regions for the PEC registers */ diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index c34967cac7..f45f02be4c 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -2213,6 +2213,8 @@ static void pnv_machine_power9_class_init(ObjectClass *oc, void *data) pmc->compat = compat; pmc->compat_size = sizeof(compat); pmc->dt_power_mgt = pnv_dt_power_mgt; + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); } static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) From 607e9316d3bd64ea6c1f7193ff9a7085a272244e Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:48 -0300 Subject: [PATCH 0227/1020] ppc/pnv: change pnv_phb4_get_pec() to also retrieve chip10->pecs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function assumes that we're always dealing with a PNV9_CHIP() object. This is not the case when the pnv-phb device belongs to a powernv10 machine. Change pnv_phb4_get_pec() to be able to work with PNV10_CHIP() if necessary. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-10-danielhb413@gmail.com> --- hw/ppc/pnv.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index f45f02be4c..c063d01f8d 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -284,17 +284,30 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, static PnvPhb4PecState *pnv_phb4_get_pec(PnvChip *chip, PnvPHB4 *phb, Error **errp) { - Pnv9Chip *chip9 = PNV9_CHIP(chip); + PnvPHB *phb_base = phb->phb_base; + PnvPhb4PecState *pecs = NULL; int chip_id = phb->chip_id; int index = phb->phb_id; int i, j; + if (phb_base->version == 4) { + Pnv9Chip *chip9 = PNV9_CHIP(chip); + + pecs = chip9->pecs; + } else if (phb_base->version == 5) { + Pnv10Chip *chip10 = PNV10_CHIP(chip); + + pecs = chip10->pecs; + } else { + g_assert_not_reached(); + } + for (i = 0; i < chip->num_pecs; i++) { /* * For each PEC, check the amount of phbs it supports * and see if the given phb4 index matches an index. */ - PnvPhb4PecState *pec = &chip9->pecs[i]; + PnvPhb4PecState *pec = &pecs[i]; for (j = 0; j < pec->num_phbs; j++) { if (index == pnv_phb4_pec_get_phb_id(pec, j)) { From f1327fde3556aeea17f721f4fa2bb8bcf13b2038 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 11 Aug 2022 13:39:49 -0300 Subject: [PATCH 0228/1020] ppc/pnv: user creatable pnv-phb for powernv10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Given that powernv9 and powernv10 uses the same pnv-phb backend, the logic to allow user created pnv-phbs for powernv10 is already in place. Let's flip the switch. Reviewed-by: Cédric Le Goater Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220811163950.578927-11-danielhb413@gmail.com> --- hw/ppc/pnv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index c063d01f8d..354aa289d1 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -2251,6 +2251,8 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data) pmc->dt_power_mgt = pnv_dt_power_mgt; xfc->match_nvt = pnv10_xive_match_nvt; + + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_PNV_PHB); } static bool pnv_machine_get_hb(Object *obj, Error **errp) From 3466bb50ec7c49a63b4a146c82d4030742451f40 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 19 Aug 2022 06:47:47 -0300 Subject: [PATCH 0229/1020] ppc/pnv: consolidate pnv_parent_*_fixup() helpers We have 2 helpers that amends the QOM and parent bus of a given object, repectively. These 2 helpers are called together, and not by accident. Due to QOM internals, doing an object_unparent() will result in the device being removed from its parent bus. This means that changing the QOM parent requires reassigning the parent bus again. Create a single helper called pnv_parent_fixup(), documenting some of the QOM specifics that we're dealing with the unparenting/parenting mechanics, and handle both the QOM and the parent bus assignment. Next patch will make use of this function to handle a case where we need to change the QOM parent while keeping the same parent bus assigned beforehand. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Frederic Barrat Message-Id: <20220819094748.400578-2-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 17d9960aa1..4ea33fb6ba 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -21,34 +21,45 @@ /* - * Set the QOM parent of an object child. If the device state - * associated with the child has an id, use it as QOM id. Otherwise - * use object_typename[index] as QOM id. + * Set the QOM parent and parent bus of an object child. If the device + * state associated with the child has an id, use it as QOM id. + * Otherwise use object_typename[index] as QOM id. + * + * This helper does both operations at the same time because seting + * a new QOM child will erase the bus parent of the device. This happens + * because object_unparent() will call object_property_del_child(), + * which in turn calls the property release callback prop->release if + * it's defined. In our case this callback is set to + * object_finalize_child_property(), which was assigned during the + * first object_property_add_child() call. This callback will end up + * calling device_unparent(), and this function removes the device + * from its parent bus. + * + * The QOM and parent bus to be set aren´t necessarily related, so + * let's receive both as arguments. */ -static void pnv_parent_qom_fixup(Object *parent, Object *child, int index) +static bool pnv_parent_fixup(Object *parent, BusState *parent_bus, + Object *child, int index, + Error **errp) { g_autofree char *default_id = g_strdup_printf("%s[%d]", object_get_typename(child), index); const char *dev_id = DEVICE(child)->id; if (child->parent == parent) { - return; + return true; } object_ref(child); object_unparent(child); object_property_add_child(parent, dev_id ? dev_id : default_id, child); object_unref(child); -} -static void pnv_parent_bus_fixup(DeviceState *parent, DeviceState *child, - Error **errp) -{ - BusState *parent_bus = qdev_get_parent_bus(parent); - - if (!qdev_set_parent_bus(child, parent_bus, errp)) { - return; + if (!qdev_set_parent_bus(DEVICE(child), parent_bus, errp)) { + return false; } + + return true; } /* @@ -101,8 +112,10 @@ static bool pnv_phb_user_device_init(PnvPHB *phb, Error **errp) * correctly the device tree. pnv_xscom_dt() needs every * PHB to be a child of the chip to build the DT correctly. */ - pnv_parent_qom_fixup(parent, OBJECT(phb), phb->phb_id); - pnv_parent_bus_fixup(DEVICE(chip), DEVICE(phb), errp); + if (!pnv_parent_fixup(parent, qdev_get_parent_bus(DEVICE(chip)), + OBJECT(phb), phb->phb_id, errp)) { + return false; + } return true; } From 6a1e1ce2efb9c22723f9f7cada5d5a31842eb37d Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Fri, 19 Aug 2022 06:47:48 -0300 Subject: [PATCH 0230/1020] ppc/pnv: fix QOM parenting of user creatable root ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit User creatable root ports are being parented by the 'peripheral' or the 'peripheral-anon' container. This happens because this is the regular QOM schema for sysbus devices that are added via the command line. Let's make this QOM hierarchy similar to what we have with default root ports, i.e. the root port must be parented by the pnv-root-bus. To do that we change the qom and bus parent of the root port during root_port_realize(). The realize() is shared by the default root port code path, so we can remove the code inside pnv_phb_attach_root_port() that was adding the root port as a child of the bus as well. After all that, remove pnv_phb_attach_root_port() and create the root port explictly in the 'default_enabled()' case of pnv_phb_realize(). Signed-off-by: Daniel Henrique Barboza Reviewed-by: Cédric Le Goater Reviewed-by: Frederic Barrat Message-Id: <20220819094748.400578-3-danielhb413@gmail.com> --- hw/pci-host/pnv_phb.c | 47 ++++++++++++++++++------------------------- 1 file changed, 20 insertions(+), 27 deletions(-) diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c index 4ea33fb6ba..7b11f1e8dd 100644 --- a/hw/pci-host/pnv_phb.c +++ b/hw/pci-host/pnv_phb.c @@ -62,29 +62,6 @@ static bool pnv_parent_fixup(Object *parent, BusState *parent_bus, return true; } -/* - * Attach a root port device. - * - * 'index' will be used both as a PCIE slot value and to calculate - * QOM id. 'chip_id' is going to be used as PCIE chassis for the - * root port. - */ -static void pnv_phb_attach_root_port(PCIHostState *pci) -{ - PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); - const char *dev_id = DEVICE(root)->id; - g_autofree char *default_id = NULL; - int index; - - index = object_property_get_int(OBJECT(pci->bus), "phb-id", &error_fatal); - default_id = g_strdup_printf("%s[%d]", TYPE_PNV_PHB_ROOT_PORT, index); - - object_property_add_child(OBJECT(pci->bus), dev_id ? dev_id : default_id, - OBJECT(root)); - - pci_realize_and_unref(root, pci->bus, &error_fatal); -} - /* * User created devices won't have the initial setup that default * devices have. This setup consists of assigning a parent device @@ -180,11 +157,11 @@ static void pnv_phb_realize(DeviceState *dev, Error **errp) pnv_phb4_bus_init(dev, PNV_PHB4(phb->backend)); } - if (!defaults_enabled()) { - return; - } + if (defaults_enabled()) { + PCIDevice *root = pci_new(PCI_DEVFN(0, 0), TYPE_PNV_PHB_ROOT_PORT); - pnv_phb_attach_root_port(pci); + pci_realize_and_unref(root, pci->bus, errp); + } } static const char *pnv_phb_root_bus_path(PCIHostState *host_bridge, @@ -259,6 +236,11 @@ static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) Error *local_err = NULL; int chip_id, index; + /* + * 'index' will be used both as a PCIE slot value and to calculate + * QOM id. 'chip_id' is going to be used as PCIE chassis for the + * root port. + */ chip_id = object_property_get_int(OBJECT(bus), "chip-id", &error_fatal); index = object_property_get_int(OBJECT(bus), "phb-id", &error_fatal); @@ -266,6 +248,17 @@ static void pnv_phb_root_port_realize(DeviceState *dev, Error **errp) qdev_prop_set_uint8(dev, "chassis", chip_id); qdev_prop_set_uint16(dev, "slot", index); + /* + * User created root ports are QOM parented to one of + * the peripheral containers but it's already at the right + * parent bus. Change the QOM parent to be the same as the + * parent bus it's already assigned to. + */ + if (!pnv_parent_fixup(OBJECT(bus), BUS(bus), OBJECT(dev), + index, errp)) { + return; + } + rpc->parent_realize(dev, &local_err); if (local_err) { error_propagate(errp, local_err); From 1335caf312a9522fe3abe6231891456ada721de2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 9 Aug 2022 17:38:41 +0200 Subject: [PATCH 0231/1020] ppc/ppc405: Remove taihu machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It has been deprecated since 7.0. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater Message-Id: <20220809153904.485018-2-clg@kaod.org> Signed-off-by: Daniel Henrique Barboza --- MAINTAINERS | 2 +- docs/about/deprecated.rst | 9 -- docs/about/removed-features.rst | 6 + docs/system/ppc/embedded.rst | 1 - hw/ppc/ppc405_boards.c | 232 -------------------------------- 5 files changed, 7 insertions(+), 243 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 5ce4227ff6..1729c0901c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1282,7 +1282,7 @@ F: hw/openrisc/openrisc_sim.c PowerPC Machines ---------------- -405 (ref405ep and taihu) +405 (ref405ep) L: qemu-ppc@nongnu.org S: Orphan F: hw/ppc/ppc405_boards.c diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 91b03115ee..c75a25daad 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -233,15 +233,6 @@ deprecated; use the new name ``dtb-randomness`` instead. The new name better reflects the way this property affects all random data within the device tree blob, not just the ``kaslr-seed`` node. -PPC 405 ``taihu`` machine (since 7.0) -''''''''''''''''''''''''''''''''''''' - -The PPC 405 CPU is a system-on-a-chip, so all 405 machines are very similar, -except for some external periphery. However, the periphery of the ``taihu`` -machine is hardly emulated at all (e.g. neither the LCD nor the USB part had -been implemented), so there is not much value added by this board. Use the -``ref405ep`` machine instead. - ``pc-i440fx-1.4`` up to ``pc-i440fx-1.7`` (since 7.0) ''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 925e22016f..a4aa3dca69 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -668,6 +668,12 @@ Aspeed ``swift-bmc`` machine (removed in 7.0) This machine was removed because it was unused. Alternative AST2500 based OpenPOWER machines are ``witherspoon-bmc`` and ``romulus-bmc``. +ppc ``taihu`` machine (removed in 7.2) +''''''''''''''''''''''''''''''''''''''''''''' + +This machine was removed because it was partially emulated and 405 +machines are very similar. Use the ``ref405ep`` machine instead. + linux-user mode CPUs -------------------- diff --git a/docs/system/ppc/embedded.rst b/docs/system/ppc/embedded.rst index cfffbda24d..af3b3d9fa4 100644 --- a/docs/system/ppc/embedded.rst +++ b/docs/system/ppc/embedded.rst @@ -6,5 +6,4 @@ Embedded family boards - ``ppce500`` generic paravirt e500 platform - ``ref405ep`` ref405ep - ``sam460ex`` aCube Sam460ex -- ``taihu`` taihu - ``virtex-ml507`` Xilinx Virtex ML507 reference design diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index a66ad05e3a..1a4e7588c5 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -342,241 +342,9 @@ static const TypeInfo ref405ep_type = { .class_init = ref405ep_class_init, }; -/*****************************************************************************/ -/* AMCC Taihu evaluation board */ -/* - PowerPC 405EP processor - * - SDRAM 128 MB at 0x00000000 - * - Boot flash 2 MB at 0xFFE00000 - * - Application flash 32 MB at 0xFC000000 - * - 2 serial ports - * - 2 ethernet PHY - * - 1 USB 1.1 device 0x50000000 - * - 1 LCD display 0x50100000 - * - 1 CPLD 0x50100000 - * - 1 I2C EEPROM - * - 1 I2C thermal sensor - * - a set of LEDs - * - bit-bang SPI port using GPIOs - * - 1 EBC interface connector 0 0x50200000 - * - 1 cardbus controller + expansion slot. - * - 1 PCI expansion slot. - */ -typedef struct taihu_cpld_t taihu_cpld_t; -struct taihu_cpld_t { - uint8_t reg0; - uint8_t reg1; -}; - -static uint64_t taihu_cpld_read(void *opaque, hwaddr addr, unsigned size) -{ - taihu_cpld_t *cpld; - uint32_t ret; - - cpld = opaque; - switch (addr) { - case 0x0: - ret = cpld->reg0; - break; - case 0x1: - ret = cpld->reg1; - break; - default: - ret = 0; - break; - } - - return ret; -} - -static void taihu_cpld_write(void *opaque, hwaddr addr, - uint64_t value, unsigned size) -{ - taihu_cpld_t *cpld; - - cpld = opaque; - switch (addr) { - case 0x0: - /* Read only */ - break; - case 0x1: - cpld->reg1 = value; - break; - default: - break; - } -} - -static const MemoryRegionOps taihu_cpld_ops = { - .read = taihu_cpld_read, - .write = taihu_cpld_write, - .impl = { - .min_access_size = 1, - .max_access_size = 1, - }, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -static void taihu_cpld_reset (void *opaque) -{ - taihu_cpld_t *cpld; - - cpld = opaque; - cpld->reg0 = 0x01; - cpld->reg1 = 0x80; -} - -static void taihu_cpld_init(MemoryRegion *sysmem, uint32_t base) -{ - taihu_cpld_t *cpld; - MemoryRegion *cpld_memory = g_new(MemoryRegion, 1); - - cpld = g_new0(taihu_cpld_t, 1); - memory_region_init_io(cpld_memory, NULL, &taihu_cpld_ops, cpld, "cpld", 0x100); - memory_region_add_subregion(sysmem, base, cpld_memory); - qemu_register_reset(&taihu_cpld_reset, cpld); -} - -static void taihu_405ep_init(MachineState *machine) -{ - MachineClass *mc = MACHINE_GET_CLASS(machine); - const char *bios_name = machine->firmware ?: BIOS_FILENAME; - const char *kernel_filename = machine->kernel_filename; - const char *initrd_filename = machine->initrd_filename; - char *filename; - MemoryRegion *sysmem = get_system_memory(); - MemoryRegion *bios; - MemoryRegion *ram_memories = g_new(MemoryRegion, 2); - hwaddr ram_bases[2], ram_sizes[2]; - long bios_size; - target_ulong kernel_base, initrd_base; - long kernel_size, initrd_size; - int linux_boot; - int fl_idx; - DriveInfo *dinfo; - DeviceState *uicdev; - - if (machine->ram_size != mc->default_ram_size) { - char *sz = size_to_str(mc->default_ram_size); - error_report("Invalid RAM size, should be %s", sz); - g_free(sz); - exit(EXIT_FAILURE); - } - - ram_bases[0] = 0; - ram_sizes[0] = 0x04000000; - memory_region_init_alias(&ram_memories[0], NULL, - "taihu_405ep.ram-0", machine->ram, ram_bases[0], - ram_sizes[0]); - ram_bases[1] = 0x04000000; - ram_sizes[1] = 0x04000000; - memory_region_init_alias(&ram_memories[1], NULL, - "taihu_405ep.ram-1", machine->ram, ram_bases[1], - ram_sizes[1]); - ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, - 33333333, &uicdev, kernel_filename == NULL ? 0 : 1); - /* allocate and load BIOS */ - fl_idx = 0; -#if defined(USE_FLASH_BIOS) - dinfo = drive_get(IF_PFLASH, 0, fl_idx); - if (dinfo) { - bios_size = 2 * MiB; - pflash_cfi02_register(0xFFE00000, - "taihu_405ep.bios", bios_size, - blk_by_legacy_dinfo(dinfo), - 64 * KiB, 1, - 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, - 1); - fl_idx++; - } else -#endif - { - bios = g_new(MemoryRegion, 1); - memory_region_init_rom(bios, NULL, "taihu_405ep.bios", BIOS_SIZE, - &error_fatal); - filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); - if (filename) { - bios_size = load_image_size(filename, - memory_region_get_ram_ptr(bios), - BIOS_SIZE); - g_free(filename); - if (bios_size < 0) { - error_report("Could not load PowerPC BIOS '%s'", bios_name); - exit(1); - } - bios_size = (bios_size + 0xfff) & ~0xfff; - memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); - } else if (!qtest_enabled()) { - error_report("Could not load PowerPC BIOS '%s'", bios_name); - exit(1); - } - } - /* Register Linux flash */ - dinfo = drive_get(IF_PFLASH, 0, fl_idx); - if (dinfo) { - bios_size = 32 * MiB; - pflash_cfi02_register(0xfc000000, "taihu_405ep.flash", bios_size, - blk_by_legacy_dinfo(dinfo), - 64 * KiB, 1, - 4, 0x0001, 0x22DA, 0x0000, 0x0000, 0x555, 0x2AA, - 1); - fl_idx++; - } - /* Register CLPD & LCD display */ - taihu_cpld_init(sysmem, 0x50100000); - /* Load kernel */ - linux_boot = (kernel_filename != NULL); - if (linux_boot) { - kernel_base = KERNEL_LOAD_ADDR; - /* now we can load the kernel */ - kernel_size = load_image_targphys(kernel_filename, kernel_base, - machine->ram_size - kernel_base); - if (kernel_size < 0) { - error_report("could not load kernel '%s'", kernel_filename); - exit(1); - } - /* load initrd */ - if (initrd_filename) { - initrd_base = INITRD_LOAD_ADDR; - initrd_size = load_image_targphys(initrd_filename, initrd_base, - machine->ram_size - initrd_base); - if (initrd_size < 0) { - error_report("could not load initial ram disk '%s'", - initrd_filename); - exit(1); - } - } else { - initrd_base = 0; - initrd_size = 0; - } - } else { - kernel_base = 0; - kernel_size = 0; - initrd_base = 0; - initrd_size = 0; - } -} - -static void taihu_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - - mc->desc = "taihu"; - mc->init = taihu_405ep_init; - mc->default_ram_size = 0x08000000; - mc->default_ram_id = "taihu_405ep.ram"; - mc->deprecation_reason = "incomplete, use 'ref405ep' instead"; -} - -static const TypeInfo taihu_type = { - .name = MACHINE_TYPE_NAME("taihu"), - .parent = TYPE_MACHINE, - .class_init = taihu_class_init, -}; - static void ppc405_machine_init(void) { type_register_static(&ref405ep_type); - type_register_static(&taihu_type); } type_init(ppc405_machine_init) From e67b374d0806d75b33bd4bf0fd6c0d6d7cd5e913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 9 Aug 2022 17:38:42 +0200 Subject: [PATCH 0232/1020] ppc/ppc405: Introduce a PPC405 generic machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We will use this machine as a base to define the ref405ep and possibly the PPC405 hotfoot board as found in the Linux kernel. Reviewed-by: BALATON Zoltan Signed-off-by: Cédric Le Goater Message-Id: <20220809153904.485018-3-clg@kaod.org> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405_boards.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 1a4e7588c5..96700be74d 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -50,6 +50,15 @@ #define USE_FLASH_BIOS +#define TYPE_PPC405_MACHINE MACHINE_TYPE_NAME("ppc405") +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405MachineState, PPC405_MACHINE); + +struct Ppc405MachineState { + /* Private */ + MachineState parent_obj; + /* Public */ +}; + /*****************************************************************************/ /* PPC405EP reference board (IBM) */ /* Standalone board with: @@ -332,18 +341,34 @@ static void ref405ep_class_init(ObjectClass *oc, void *data) mc->desc = "ref405ep"; mc->init = ref405ep_init; - mc->default_ram_size = 0x08000000; - mc->default_ram_id = "ef405ep.ram"; } static const TypeInfo ref405ep_type = { .name = MACHINE_TYPE_NAME("ref405ep"), - .parent = TYPE_MACHINE, + .parent = TYPE_PPC405_MACHINE, .class_init = ref405ep_class_init, }; +static void ppc405_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "PPC405 generic machine"; + mc->default_ram_size = 128 * MiB; + mc->default_ram_id = "ppc405.ram"; +} + +static const TypeInfo ppc405_machine_type = { + .name = TYPE_PPC405_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(Ppc405MachineState), + .class_init = ppc405_machine_class_init, + .abstract = true, +}; + static void ppc405_machine_init(void) { + type_register_static(&ppc405_machine_type); type_register_static(&ref405ep_type); } From 041816c6d5e72896f3e829e8be6a80969c6cf047 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 9 Aug 2022 17:38:43 +0200 Subject: [PATCH 0233/1020] ppc/ppc405: Move devices under the ref405ep machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel Henrique Barboza Reviewed-by: BALATON Zoltan Signed-off-by: Cédric Le Goater Message-Id: <20220809153904.485018-4-clg@kaod.org> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405_boards.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 96700be74d..f4794ba40c 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -230,13 +230,11 @@ static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu) env->load_info = &boot_info; } -static void ref405ep_init(MachineState *machine) +static void ppc405_init(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); const char *kernel_filename = machine->kernel_filename; PowerPCCPU *cpu; - DeviceState *dev; - SysBusDevice *s; MemoryRegion *sram = g_new(MemoryRegion, 1); MemoryRegion *ram_memories = g_new(MemoryRegion, 2); hwaddr ram_bases[2], ram_sizes[2]; @@ -294,15 +292,6 @@ static void ref405ep_init(MachineState *machine) memory_region_add_subregion(sysmem, (uint32_t)(-bios_size), bios); } - /* Register FPGA */ - ref405ep_fpga_init(sysmem, PPC405EP_FPGA_BASE); - /* Register NVRAM */ - dev = qdev_new("sysbus-m48t08"); - qdev_prop_set_int32(dev, "base-year", 1968); - s = SYS_BUS_DEVICE(dev); - sysbus_realize_and_unref(s, &error_fatal); - sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE); - /* Load kernel and initrd using U-Boot images */ if (kernel_filename && machine->firmware) { target_ulong kernel_base, initrd_base; @@ -335,6 +324,23 @@ static void ref405ep_init(MachineState *machine) } } +static void ref405ep_init(MachineState *machine) +{ + DeviceState *dev; + SysBusDevice *s; + + ppc405_init(machine); + + /* Register FPGA */ + ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE); + /* Register NVRAM */ + dev = qdev_new("sysbus-m48t08"); + qdev_prop_set_int32(dev, "base-year", 1968); + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + sysbus_mmio_map(s, 0, PPC405EP_NVRAM_BASE); +} + static void ref405ep_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -354,6 +360,7 @@ static void ppc405_machine_class_init(ObjectClass *oc, void *data) MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "PPC405 generic machine"; + mc->init = ppc405_init; mc->default_ram_size = 128 * MiB; mc->default_ram_id = "ppc405.ram"; } From df2372086f8af030bf5c2d1e1a46812d59923b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 9 Aug 2022 17:38:44 +0200 Subject: [PATCH 0234/1020] ppc/ppc405: Move SRAM under the ref405ep machine MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It doesn't belong to the generic machine nor the SoC. Fix a typo in the name while we are at it. Signed-off-by: Cédric Le Goater Reviewed-by: BALATON Zoltan Message-Id: <20220809153904.485018-5-clg@kaod.org> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405_boards.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index f4794ba40c..381f39aa94 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -235,7 +235,6 @@ static void ppc405_init(MachineState *machine) MachineClass *mc = MACHINE_GET_CLASS(machine); const char *kernel_filename = machine->kernel_filename; PowerPCCPU *cpu; - MemoryRegion *sram = g_new(MemoryRegion, 1); MemoryRegion *ram_memories = g_new(MemoryRegion, 2); hwaddr ram_bases[2], ram_sizes[2]; MemoryRegion *sysmem = get_system_memory(); @@ -260,11 +259,6 @@ static void ppc405_init(MachineState *machine) cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, 33333333, &uicdev, kernel_filename == NULL ? 0 : 1); - /* allocate SRAM */ - memory_region_init_ram(sram, NULL, "ef405ep.sram", PPC405EP_SRAM_SIZE, - &error_fatal); - memory_region_add_subregion(sysmem, PPC405EP_SRAM_BASE, sram); - /* allocate and load BIOS */ if (machine->firmware) { MemoryRegion *bios = g_new(MemoryRegion, 1); @@ -328,9 +322,15 @@ static void ref405ep_init(MachineState *machine) { DeviceState *dev; SysBusDevice *s; + MemoryRegion *sram = g_new(MemoryRegion, 1); ppc405_init(machine); + /* allocate SRAM */ + memory_region_init_ram(sram, NULL, "ref405ep.sram", PPC405EP_SRAM_SIZE, + &error_fatal); + memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram); + /* Register FPGA */ ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE); /* Register NVRAM */ From 3b758ca2f05fccd73b49cf88eff7d2dbf489902e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 9 Aug 2022 17:38:45 +0200 Subject: [PATCH 0235/1020] ppc/ppc405: Introduce a PPC405 SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is an initial model to start QOMification of the PPC405 board. QOM'ified devices will be reintroduced one by one. Start with the memory regions, which name prefix is changed to "ppc405". Also, initialize only one RAM bank. The second bank is a dummy one (zero size) which is here to match the hard coded number of banks in ppc405ep_init(). Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater Reviewed-by: BALATON Zoltan Message-Id: <20220809153904.485018-6-clg@kaod.org> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 16 ++++++++++++++++ hw/ppc/ppc405_boards.c | 23 ++++++++++++----------- hw/ppc/ppc405_uc.c | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 83f156f585..66dc21cdfe 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -25,6 +25,7 @@ #ifndef PPC405_H #define PPC405_H +#include "qom/object.h" #include "hw/ppc/ppc4xx.h" #define PPC405EP_SDRAM_BASE 0x00000000 @@ -62,6 +63,21 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +#define TYPE_PPC405_SOC "ppc405-soc" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405SoCState, PPC405_SOC); + +struct Ppc405SoCState { + /* Private */ + DeviceState parent_obj; + + /* Public */ + MemoryRegion ram_banks[2]; + hwaddr ram_bases[2], ram_sizes[2]; + + MemoryRegion *dram_mr; + hwaddr ram_size; +}; + /* PowerPC 405 core */ ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size); diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 381f39aa94..f029d6f415 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -57,6 +57,8 @@ struct Ppc405MachineState { /* Private */ MachineState parent_obj; /* Public */ + + Ppc405SoCState soc; }; /*****************************************************************************/ @@ -232,11 +234,10 @@ static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu) static void ppc405_init(MachineState *machine) { + Ppc405MachineState *ppc405 = PPC405_MACHINE(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); const char *kernel_filename = machine->kernel_filename; PowerPCCPU *cpu; - MemoryRegion *ram_memories = g_new(MemoryRegion, 2); - hwaddr ram_bases[2], ram_sizes[2]; MemoryRegion *sysmem = get_system_memory(); DeviceState *uicdev; @@ -247,16 +248,16 @@ static void ppc405_init(MachineState *machine) exit(EXIT_FAILURE); } - /* XXX: fix this */ - memory_region_init_alias(&ram_memories[0], NULL, "ef405ep.ram.alias", - machine->ram, 0, machine->ram_size); - ram_bases[0] = 0; - ram_sizes[0] = machine->ram_size; - memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0); - ram_bases[1] = 0x00000000; - ram_sizes[1] = 0x00000000; + object_initialize_child(OBJECT(machine), "soc", &ppc405->soc, + TYPE_PPC405_SOC); + object_property_set_uint(OBJECT(&ppc405->soc), "ram-size", + machine->ram_size, &error_fatal); + object_property_set_link(OBJECT(&ppc405->soc), "dram", + OBJECT(machine->ram), &error_abort); + qdev_realize(DEVICE(&ppc405->soc), NULL, &error_fatal); - cpu = ppc405ep_init(sysmem, ram_memories, ram_bases, ram_sizes, + cpu = ppc405ep_init(sysmem, ppc405->soc.ram_banks, ppc405->soc.ram_bases, + ppc405->soc.ram_sizes, 33333333, &uicdev, kernel_filename == NULL ? 0 : 1); /* allocate and load BIOS */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index d6420c88d3..adadb3a0ae 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -30,6 +30,7 @@ #include "hw/ppc/ppc.h" #include "hw/i2c/ppc4xx_i2c.h" #include "hw/irq.h" +#include "hw/qdev-properties.h" #include "ppc405.h" #include "hw/char/serial.h" #include "qemu/timer.h" @@ -1530,3 +1531,42 @@ PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem, return cpu; } + +static void ppc405_soc_realize(DeviceState *dev, Error **errp) +{ + Ppc405SoCState *s = PPC405_SOC(dev); + + /* Initialize only one bank */ + s->ram_bases[0] = 0; + s->ram_sizes[0] = s->ram_size; + memory_region_init_alias(&s->ram_banks[0], OBJECT(s), + "ppc405.sdram0", s->dram_mr, + s->ram_bases[0], s->ram_sizes[0]); +} + +static Property ppc405_soc_properties[] = { + DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION, + MemoryRegion *), + DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc405_soc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_soc_realize; + dc->user_creatable = false; + device_class_set_props(dc, ppc405_soc_properties); +} + +static const TypeInfo ppc405_types[] = { + { + .name = TYPE_PPC405_SOC, + .parent = TYPE_DEVICE, + .instance_size = sizeof(Ppc405SoCState), + .class_init = ppc405_soc_class_init, + } +}; + +DEFINE_TYPES(ppc405_types) From 5b0f170a8aa2b83d04aa6769eef35013a24ac52f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 9 Aug 2022 17:38:46 +0200 Subject: [PATCH 0236/1020] ppc/ppc405: Start QOMification of the SoC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This moves all the code previously done in the ppc405ep_init() routine under ppc405_soc_realize(). We can also adjust the number of banks now that we have control on ppc4xx_sdram_init(). Signed-off-by: Cédric Le Goater Reviewed-by: BALATON Zoltan Message-Id: <20220809153904.485018-7-clg@kaod.org> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 12 ++- hw/ppc/ppc405_boards.c | 12 ++- hw/ppc/ppc405_uc.c | 200 ++++++++++++++++++++--------------------- 3 files changed, 109 insertions(+), 115 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 66dc21cdfe..dc862bc861 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -73,9 +73,14 @@ struct Ppc405SoCState { /* Public */ MemoryRegion ram_banks[2]; hwaddr ram_bases[2], ram_sizes[2]; + bool do_dram_init; MemoryRegion *dram_mr; hwaddr ram_size; + + uint32_t sysclk; + PowerPCCPU *cpu; + DeviceState *uic; }; /* PowerPC 405 core */ @@ -84,11 +89,4 @@ ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size); void ppc4xx_plb_init(CPUPPCState *env); void ppc405_ebc_init(CPUPPCState *env); -PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem, - MemoryRegion ram_memories[2], - hwaddr ram_bases[2], - hwaddr ram_sizes[2], - uint32_t sysclk, DeviceState **uicdev, - int do_init); - #endif /* PPC405_H */ diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index f029d6f415..b93e85b5d9 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -237,9 +237,7 @@ static void ppc405_init(MachineState *machine) Ppc405MachineState *ppc405 = PPC405_MACHINE(machine); MachineClass *mc = MACHINE_GET_CLASS(machine); const char *kernel_filename = machine->kernel_filename; - PowerPCCPU *cpu; MemoryRegion *sysmem = get_system_memory(); - DeviceState *uicdev; if (machine->ram_size != mc->default_ram_size) { char *sz = size_to_str(mc->default_ram_size); @@ -254,12 +252,12 @@ static void ppc405_init(MachineState *machine) machine->ram_size, &error_fatal); object_property_set_link(OBJECT(&ppc405->soc), "dram", OBJECT(machine->ram), &error_abort); + object_property_set_bool(OBJECT(&ppc405->soc), "dram-init", + kernel_filename != NULL, &error_abort); + object_property_set_uint(OBJECT(&ppc405->soc), "sys-clk", 33333333, + &error_abort); qdev_realize(DEVICE(&ppc405->soc), NULL, &error_fatal); - cpu = ppc405ep_init(sysmem, ppc405->soc.ram_banks, ppc405->soc.ram_bases, - ppc405->soc.ram_sizes, - 33333333, &uicdev, kernel_filename == NULL ? 0 : 1); - /* allocate and load BIOS */ if (machine->firmware) { MemoryRegion *bios = g_new(MemoryRegion, 1); @@ -315,7 +313,7 @@ static void ppc405_init(MachineState *machine) /* Load ELF kernel and rootfs.cpio */ } else if (kernel_filename && !machine->firmware) { - boot_from_kernel(machine, cpu); + boot_from_kernel(machine, ppc405->soc.cpu); } } diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index adadb3a0ae..c05ab60436 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1432,121 +1432,118 @@ static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8], #endif } -PowerPCCPU *ppc405ep_init(MemoryRegion *address_space_mem, - MemoryRegion ram_memories[2], - hwaddr ram_bases[2], - hwaddr ram_sizes[2], - uint32_t sysclk, DeviceState **uicdevp, - int do_init) -{ - clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; - qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; - PowerPCCPU *cpu; - CPUPPCState *env; - DeviceState *uicdev; - SysBusDevice *uicsbd; - - memset(clk_setup, 0, sizeof(clk_setup)); - /* init CPUs */ - cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"), - &clk_setup[PPC405EP_CPU_CLK], - &tlb_clk_setup, sysclk); - env = &cpu->env; - clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; - clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; - /* Internal devices init */ - /* Memory mapped devices registers */ - /* PLB arbitrer */ - ppc4xx_plb_init(env); - /* PLB to OPB bridge */ - ppc4xx_pob_init(env); - /* OBP arbitrer */ - ppc4xx_opba_init(0xef600600); - /* Universal interrupt controller */ - uicdev = qdev_new(TYPE_PPC_UIC); - uicsbd = SYS_BUS_DEVICE(uicdev); - - object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(cpu), - &error_fatal); - sysbus_realize_and_unref(uicsbd, &error_fatal); - - sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT, - qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); - sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT, - qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT)); - - *uicdevp = uicdev; - - /* SDRAM controller */ - /* XXX 405EP has no ECC interrupt */ - ppc4xx_sdram_init(env, qdev_get_gpio_in(uicdev, 17), 2, ram_memories, - ram_bases, ram_sizes, do_init); - /* External bus controller */ - ppc405_ebc_init(env); - /* DMA controller */ - dma_irqs[0] = qdev_get_gpio_in(uicdev, 5); - dma_irqs[1] = qdev_get_gpio_in(uicdev, 6); - dma_irqs[2] = qdev_get_gpio_in(uicdev, 7); - dma_irqs[3] = qdev_get_gpio_in(uicdev, 8); - ppc405_dma_init(env, dma_irqs); - /* IIC controller */ - sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, - qdev_get_gpio_in(uicdev, 2)); - /* GPIO */ - ppc405_gpio_init(0xef600700); - /* Serial ports */ - if (serial_hd(0) != NULL) { - serial_mm_init(address_space_mem, 0xef600300, 0, - qdev_get_gpio_in(uicdev, 0), - PPC_SERIAL_MM_BAUDBASE, serial_hd(0), - DEVICE_BIG_ENDIAN); - } - if (serial_hd(1) != NULL) { - serial_mm_init(address_space_mem, 0xef600400, 0, - qdev_get_gpio_in(uicdev, 1), - PPC_SERIAL_MM_BAUDBASE, serial_hd(1), - DEVICE_BIG_ENDIAN); - } - /* OCM */ - ppc405_ocm_init(env); - /* GPT */ - gpt_irqs[0] = qdev_get_gpio_in(uicdev, 19); - gpt_irqs[1] = qdev_get_gpio_in(uicdev, 20); - gpt_irqs[2] = qdev_get_gpio_in(uicdev, 21); - gpt_irqs[3] = qdev_get_gpio_in(uicdev, 22); - gpt_irqs[4] = qdev_get_gpio_in(uicdev, 23); - ppc4xx_gpt_init(0xef600000, gpt_irqs); - /* PCI */ - /* Uses UIC IRQs 3, 16, 18 */ - /* MAL */ - mal_irqs[0] = qdev_get_gpio_in(uicdev, 11); - mal_irqs[1] = qdev_get_gpio_in(uicdev, 12); - mal_irqs[2] = qdev_get_gpio_in(uicdev, 13); - mal_irqs[3] = qdev_get_gpio_in(uicdev, 14); - ppc4xx_mal_init(env, 4, 2, mal_irqs); - /* Ethernet */ - /* Uses UIC IRQs 9, 15, 17 */ - /* CPU control */ - ppc405ep_cpc_init(env, clk_setup, sysclk); - - return cpu; -} - static void ppc405_soc_realize(DeviceState *dev, Error **errp) { Ppc405SoCState *s = PPC405_SOC(dev); + clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; + qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; + CPUPPCState *env; - /* Initialize only one bank */ + memset(clk_setup, 0, sizeof(clk_setup)); + + /* init CPUs */ + s->cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"), + &clk_setup[PPC405EP_CPU_CLK], + &tlb_clk_setup, s->sysclk); + env = &s->cpu->env; + clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; + clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; + + /* CPU control */ + ppc405ep_cpc_init(env, clk_setup, s->sysclk); + + /* PLB arbitrer */ + ppc4xx_plb_init(env); + + /* PLB to OPB bridge */ + ppc4xx_pob_init(env); + + /* OBP arbitrer */ + ppc4xx_opba_init(0xef600600); + + /* Universal interrupt controller */ + s->uic = qdev_new(TYPE_PPC_UIC); + + object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(s->cpu), + &error_fatal); + if (!sysbus_realize(SYS_BUS_DEVICE(s->uic), errp)) { + return; + } + + sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_INT, + qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_INT)); + sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_CINT, + qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_CINT)); + + /* SDRAM controller */ + /* XXX 405EP has no ECC interrupt */ s->ram_bases[0] = 0; s->ram_sizes[0] = s->ram_size; memory_region_init_alias(&s->ram_banks[0], OBJECT(s), "ppc405.sdram0", s->dram_mr, s->ram_bases[0], s->ram_sizes[0]); + + ppc4xx_sdram_init(env, qdev_get_gpio_in(s->uic, 17), 1, + s->ram_banks, s->ram_bases, s->ram_sizes, + s->do_dram_init); + + /* External bus controller */ + ppc405_ebc_init(env); + + /* DMA controller */ + dma_irqs[0] = qdev_get_gpio_in(s->uic, 5); + dma_irqs[1] = qdev_get_gpio_in(s->uic, 6); + dma_irqs[2] = qdev_get_gpio_in(s->uic, 7); + dma_irqs[3] = qdev_get_gpio_in(s->uic, 8); + ppc405_dma_init(env, dma_irqs); + + /* I2C controller */ + sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, + qdev_get_gpio_in(s->uic, 2)); + /* GPIO */ + ppc405_gpio_init(0xef600700); + + /* Serial ports */ + if (serial_hd(0) != NULL) { + serial_mm_init(get_system_memory(), 0xef600300, 0, + qdev_get_gpio_in(s->uic, 0), + PPC_SERIAL_MM_BAUDBASE, serial_hd(0), + DEVICE_BIG_ENDIAN); + } + if (serial_hd(1) != NULL) { + serial_mm_init(get_system_memory(), 0xef600400, 0, + qdev_get_gpio_in(s->uic, 1), + PPC_SERIAL_MM_BAUDBASE, serial_hd(1), + DEVICE_BIG_ENDIAN); + } + + /* OCM */ + ppc405_ocm_init(env); + + /* GPT */ + gpt_irqs[0] = qdev_get_gpio_in(s->uic, 19); + gpt_irqs[1] = qdev_get_gpio_in(s->uic, 20); + gpt_irqs[2] = qdev_get_gpio_in(s->uic, 21); + gpt_irqs[3] = qdev_get_gpio_in(s->uic, 22); + gpt_irqs[4] = qdev_get_gpio_in(s->uic, 23); + ppc4xx_gpt_init(0xef600000, gpt_irqs); + + /* MAL */ + mal_irqs[0] = qdev_get_gpio_in(s->uic, 11); + mal_irqs[1] = qdev_get_gpio_in(s->uic, 12); + mal_irqs[2] = qdev_get_gpio_in(s->uic, 13); + mal_irqs[3] = qdev_get_gpio_in(s->uic, 14); + ppc4xx_mal_init(env, 4, 2, mal_irqs); + + /* Ethernet */ + /* Uses UIC IRQs 9, 15, 17 */ } static Property ppc405_soc_properties[] = { DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), + DEFINE_PROP_UINT32("sys-clk", Ppc405SoCState, sysclk, 0), + DEFINE_PROP_BOOL("dram-init", Ppc405SoCState, do_dram_init, 0), DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0), DEFINE_PROP_END_OF_LIST(), }; @@ -1556,6 +1553,7 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) DeviceClass *dc = DEVICE_CLASS(oc); dc->realize = ppc405_soc_realize; + /* Reason: only works as part of a ppc405 board/machine */ dc->user_creatable = false; device_class_set_props(dc, ppc405_soc_properties); } From b42ad437562f72b31e5743db4ddf183a8e810eb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Tue, 9 Aug 2022 17:38:47 +0200 Subject: [PATCH 0237/1020] ppc/ppc405: QOM'ify CPU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the use of ppc4xx_init() and duplicate a bit of code related to clocks in the SoC realize routine. We will clean that up in the following patches. ppc_dcr_init() simply allocates default DCR handlers for the CPU. Maybe this could be done in model initializer of the CPU families needing it. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater Reviewed-by: BALATON Zoltan Message-Id: <20220809153904.485018-8-clg@kaod.org> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 2 +- hw/ppc/ppc405_boards.c | 2 +- hw/ppc/ppc405_uc.c | 40 ++++++++++++++++++++++++++++++---------- hw/ppc/ppc4xx_devs.c | 32 -------------------------------- include/hw/ppc/ppc4xx.h | 5 ----- 5 files changed, 32 insertions(+), 49 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index dc862bc861..8cc76cc8b3 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -79,7 +79,7 @@ struct Ppc405SoCState { hwaddr ram_size; uint32_t sysclk; - PowerPCCPU *cpu; + PowerPCCPU cpu; DeviceState *uic; }; diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index b93e85b5d9..3677793adc 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -313,7 +313,7 @@ static void ppc405_init(MachineState *machine) /* Load ELF kernel and rootfs.cpio */ } else if (kernel_filename && !machine->firmware) { - boot_from_kernel(machine, ppc405->soc.cpu); + boot_from_kernel(machine, &ppc405->soc.cpu); } } diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index c05ab60436..14a525b2eb 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1432,22 +1432,41 @@ static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8], #endif } +static void ppc405_soc_instance_init(Object *obj) +{ + Ppc405SoCState *s = PPC405_SOC(obj); + + object_initialize_child(obj, "cpu", &s->cpu, + POWERPC_CPU_TYPE_NAME("405ep")); +} + +static void ppc405_reset(void *opaque) +{ + cpu_reset(CPU(opaque)); +} + static void ppc405_soc_realize(DeviceState *dev, Error **errp) { Ppc405SoCState *s = PPC405_SOC(dev); - clk_setup_t clk_setup[PPC405EP_CLK_NB], tlb_clk_setup; + clk_setup_t clk_setup[PPC405EP_CLK_NB]; qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; CPUPPCState *env; memset(clk_setup, 0, sizeof(clk_setup)); /* init CPUs */ - s->cpu = ppc4xx_init(POWERPC_CPU_TYPE_NAME("405ep"), - &clk_setup[PPC405EP_CPU_CLK], - &tlb_clk_setup, s->sysclk); - env = &s->cpu->env; - clk_setup[PPC405EP_CPU_CLK].cb = tlb_clk_setup.cb; - clk_setup[PPC405EP_CPU_CLK].opaque = tlb_clk_setup.opaque; + if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { + return; + } + qemu_register_reset(ppc405_reset, &s->cpu); + + env = &s->cpu.env; + + clk_setup[PPC405EP_CPU_CLK].cb = + ppc_40x_timers_init(env, s->sysclk, PPC_INTERRUPT_PIT); + clk_setup[PPC405EP_CPU_CLK].opaque = env; + + ppc_dcr_init(env, NULL, NULL); /* CPU control */ ppc405ep_cpc_init(env, clk_setup, s->sysclk); @@ -1464,16 +1483,16 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) /* Universal interrupt controller */ s->uic = qdev_new(TYPE_PPC_UIC); - object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(s->cpu), + object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(&s->cpu), &error_fatal); if (!sysbus_realize(SYS_BUS_DEVICE(s->uic), errp)) { return; } sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_INT, - qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_INT)); + qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_INT)); sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_CINT, - qdev_get_gpio_in(DEVICE(s->cpu), PPC40x_INPUT_CINT)); + qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_CINT)); /* SDRAM controller */ /* XXX 405EP has no ECC interrupt */ @@ -1563,6 +1582,7 @@ static const TypeInfo ppc405_types[] = { .name = TYPE_PPC405_SOC, .parent = TYPE_DEVICE, .instance_size = sizeof(Ppc405SoCState), + .instance_init = ppc405_soc_instance_init, .class_init = ppc405_soc_class_init, } }; diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 737c0896b4..069b511951 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -37,38 +37,6 @@ #include "qapi/error.h" #include "trace.h" -static void ppc4xx_reset(void *opaque) -{ - PowerPCCPU *cpu = opaque; - - cpu_reset(CPU(cpu)); -} - -/*****************************************************************************/ -/* Generic PowerPC 4xx processor instantiation */ -PowerPCCPU *ppc4xx_init(const char *cpu_type, - clk_setup_t *cpu_clk, clk_setup_t *tb_clk, - uint32_t sysclk) -{ - PowerPCCPU *cpu; - CPUPPCState *env; - - /* init CPUs */ - cpu = POWERPC_CPU(cpu_create(cpu_type)); - env = &cpu->env; - - cpu_clk->cb = NULL; /* We don't care about CPU clock frequency changes */ - cpu_clk->opaque = env; - /* Set time-base frequency to sysclk */ - tb_clk->cb = ppc_40x_timers_init(env, sysclk, PPC_INTERRUPT_PIT); - tb_clk->opaque = env; - ppc_dcr_init(env, NULL, NULL); - /* Register qemu callbacks */ - qemu_register_reset(ppc4xx_reset, cpu); - - return cpu; -} - /*****************************************************************************/ /* SDRAM controller */ typedef struct ppc4xx_sdram_t ppc4xx_sdram_t; diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index 980f964b5a..591e2421a3 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -28,11 +28,6 @@ #include "hw/ppc/ppc.h" #include "exec/memory.h" -/* PowerPC 4xx core initialization */ -PowerPCCPU *ppc4xx_init(const char *cpu_model, - clk_setup_t *cpu_clk, clk_setup_t *tb_clk, - uint32_t sysclk); - void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, MemoryRegion ram_memories[], hwaddr ram_bases[], hwaddr ram_sizes[], From 629cae617039e03d5bfdc0120ade69135a009d33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:18 +0200 Subject: [PATCH 0238/1020] ppc/ppc4xx: Introduce a DCR device model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Device Control Registers (DCR) of on-SoC devices are accessed by software through the use of the mtdcr and mfdcr instructions. These are converted in transactions on a side band bus, the DCR bus, which connects the on-SoC devices to the CPU. Ideally, we should model these accesses with a DCR namespace and DCR memory regions but today the DCR handlers are installed in a DCR table under the CPU. Instead, introduce a little device model wrapper to hold a CPU link and handle registration of DCR handlers. The DCR device inherits from SysBus because most of these devices also have MMIO regions and/or IRQs. Being a SysBusDevice makes things easier to install the device model in the overall SoC. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: Explicit opaque parameter for dcr callbacks] Signed-off-by: BALATON Zoltan Message-Id: <9b21bdf55e0a728f093bad299e030d98f302ded0.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc4xx_devs.c | 41 +++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/ppc4xx.h | 17 +++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 069b511951..f4d7ae9567 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -664,3 +664,44 @@ void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum, mal, &dcr_read_mal, &dcr_write_mal); } } + +/* PPC4xx_DCR_DEVICE */ + +void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, + dcr_read_cb dcr_read, dcr_write_cb dcr_write) +{ + assert(dev->cpu); + ppc_dcr_register(&dev->cpu->env, dcrn, opaque, dcr_read, dcr_write); +} + +bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu, + Error **errp) +{ + object_property_set_link(OBJECT(dev), "cpu", OBJECT(cpu), &error_abort); + return sysbus_realize(SYS_BUS_DEVICE(dev), errp); +} + +static Property ppc4xx_dcr_properties[] = { + DEFINE_PROP_LINK("cpu", Ppc4xxDcrDeviceState, cpu, TYPE_POWERPC_CPU, + PowerPCCPU *), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + device_class_set_props(dc, ppc4xx_dcr_properties); +} + +static const TypeInfo ppc4xx_types[] = { + { + .name = TYPE_PPC4xx_DCR_DEVICE, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ppc4xxDcrDeviceState), + .class_init = ppc4xx_dcr_class_init, + .abstract = true, + } +}; + +DEFINE_TYPES(ppc4xx_types) diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index 591e2421a3..a537a5567b 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -27,6 +27,7 @@ #include "hw/ppc/ppc.h" #include "exec/memory.h" +#include "hw/sysbus.h" void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, MemoryRegion ram_memories[], @@ -44,4 +45,20 @@ void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum, #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" +/* + * Generic DCR device + */ +#define TYPE_PPC4xx_DCR_DEVICE "ppc4xx-dcr-device" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxDcrDeviceState, PPC4xx_DCR_DEVICE); +struct Ppc4xxDcrDeviceState { + SysBusDevice parent_obj; + + PowerPCCPU *cpu; +}; + +void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, + dcr_read_cb dcr_read, dcr_write_cb dcr_write); +bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu, + Error **errp); + #endif /* PPC4XX_H */ From 4a7d2b7e5cebd00bdcc842517174ad33fd4934cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:20 +0200 Subject: [PATCH 0239/1020] ppc/ppc405: QOM'ify CPC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CPC controller is currently modeled as a DCR device. Now that all clock settings are handled at the CPC level, change the SoC "sys-clk" property to be an alias on the same property in the CPC model. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes] Signed-off-by: BALATON Zoltan Message-Id: <23393cb91a2c6c560a4461b3e9d1baa48ae28f74.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 35 ++++++++++- hw/ppc/ppc405_uc.c | 141 ++++++++++++++++++++------------------------- 2 files changed, 95 insertions(+), 81 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 8cc76cc8b3..2ba829988d 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,39 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +#define TYPE_PPC405_CPC "ppc405-cpc" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405CpcState, PPC405_CPC); + +enum { + PPC405EP_CPU_CLK = 0, + PPC405EP_PLB_CLK = 1, + PPC405EP_OPB_CLK = 2, + PPC405EP_EBC_CLK = 3, + PPC405EP_MAL_CLK = 4, + PPC405EP_PCI_CLK = 5, + PPC405EP_UART0_CLK = 6, + PPC405EP_UART1_CLK = 7, + PPC405EP_CLK_NB = 8, +}; + +struct Ppc405CpcState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t sysclk; + clk_setup_t clk_setup[PPC405EP_CLK_NB]; + uint32_t boot; + uint32_t epctl; + uint32_t pllmr[2]; + uint32_t ucr; + uint32_t srr; + uint32_t jtagid; + uint32_t pci; + /* Clock and power management */ + uint32_t er; + uint32_t fr; + uint32_t sr; +}; + #define TYPE_PPC405_SOC "ppc405-soc" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405SoCState, PPC405_SOC); @@ -78,9 +111,9 @@ struct Ppc405SoCState { MemoryRegion *dram_mr; hwaddr ram_size; - uint32_t sysclk; PowerPCCPU cpu; DeviceState *uic; + Ppc405CpcState cpc; }; /* PowerPC 405 core */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 14a525b2eb..ec83c292a5 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1178,36 +1178,7 @@ enum { #endif }; -enum { - PPC405EP_CPU_CLK = 0, - PPC405EP_PLB_CLK = 1, - PPC405EP_OPB_CLK = 2, - PPC405EP_EBC_CLK = 3, - PPC405EP_MAL_CLK = 4, - PPC405EP_PCI_CLK = 5, - PPC405EP_UART0_CLK = 6, - PPC405EP_UART1_CLK = 7, - PPC405EP_CLK_NB = 8, -}; - -typedef struct ppc405ep_cpc_t ppc405ep_cpc_t; -struct ppc405ep_cpc_t { - uint32_t sysclk; - clk_setup_t clk_setup[PPC405EP_CLK_NB]; - uint32_t boot; - uint32_t epctl; - uint32_t pllmr[2]; - uint32_t ucr; - uint32_t srr; - uint32_t jtagid; - uint32_t pci; - /* Clock and power management */ - uint32_t er; - uint32_t fr; - uint32_t sr; -}; - -static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) +static void ppc405ep_compute_clocks(Ppc405CpcState *cpc) { uint32_t CPU_clk, PLB_clk, OPB_clk, EBC_clk, MAL_clk, PCI_clk; uint32_t UART0_clk, UART1_clk; @@ -1300,12 +1271,11 @@ static void ppc405ep_compute_clocks (ppc405ep_cpc_t *cpc) clk_setup(&cpc->clk_setup[PPC405EP_UART1_CLK], UART1_clk); } -static uint32_t dcr_read_epcpc (void *opaque, int dcrn) +static uint32_t dcr_read_epcpc(void *opaque, int dcrn) { - ppc405ep_cpc_t *cpc; + Ppc405CpcState *cpc = opaque; uint32_t ret; - cpc = opaque; switch (dcrn) { case PPC405EP_CPC0_BOOT: ret = cpc->boot; @@ -1340,11 +1310,10 @@ static uint32_t dcr_read_epcpc (void *opaque, int dcrn) return ret; } -static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val) +static void dcr_write_epcpc(void *opaque, int dcrn, uint32_t val) { - ppc405ep_cpc_t *cpc; + Ppc405CpcState *cpc = opaque; - cpc = opaque; switch (dcrn) { case PPC405EP_CPC0_BOOT: /* Read-only register */ @@ -1377,9 +1346,9 @@ static void dcr_write_epcpc (void *opaque, int dcrn, uint32_t val) } } -static void ppc405ep_cpc_reset (void *opaque) +static void ppc405_cpc_reset(DeviceState *dev) { - ppc405ep_cpc_t *cpc = opaque; + Ppc405CpcState *cpc = PPC405_CPC(dev); cpc->boot = 0x00000010; /* Boot from PCI - IIC EEPROM disabled */ cpc->epctl = 0x00000000; @@ -1391,53 +1360,66 @@ static void ppc405ep_cpc_reset (void *opaque) cpc->er = 0x00000000; cpc->fr = 0x00000000; cpc->sr = 0x00000000; + cpc->jtagid = 0x20267049; ppc405ep_compute_clocks(cpc); } /* XXX: sysclk should be between 25 and 100 MHz */ -static void ppc405ep_cpc_init (CPUPPCState *env, clk_setup_t clk_setup[8], - uint32_t sysclk) +static void ppc405_cpc_realize(DeviceState *dev, Error **errp) { - ppc405ep_cpc_t *cpc; + Ppc405CpcState *cpc = PPC405_CPC(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - cpc = g_new0(ppc405ep_cpc_t, 1); - memcpy(cpc->clk_setup, clk_setup, - PPC405EP_CLK_NB * sizeof(clk_setup_t)); - cpc->jtagid = 0x20267049; - cpc->sysclk = sysclk; - qemu_register_reset(&ppc405ep_cpc_reset, cpc); - ppc_dcr_register(env, PPC405EP_CPC0_BOOT, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_EPCTL, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PLLMR0, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PLLMR1, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_UCR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_SRR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_JTAGID, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_PCI, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); -#if 0 - ppc_dcr_register(env, PPC405EP_CPC0_ER, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_FR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); - ppc_dcr_register(env, PPC405EP_CPC0_SR, cpc, - &dcr_read_epcpc, &dcr_write_epcpc); -#endif + assert(dcr->cpu); + cpc->clk_setup[PPC405EP_CPU_CLK].cb = + ppc_40x_timers_init(&dcr->cpu->env, cpc->sysclk, PPC_INTERRUPT_PIT); + cpc->clk_setup[PPC405EP_CPU_CLK].opaque = &dcr->cpu->env; + + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_BOOT, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_EPCTL, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_PLLMR0, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_PLLMR1, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_UCR, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_SRR, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_JTAGID, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); + ppc4xx_dcr_register(dcr, PPC405EP_CPC0_PCI, cpc, + &dcr_read_epcpc, &dcr_write_epcpc); } +static Property ppc405_cpc_properties[] = { + DEFINE_PROP_UINT32("sys-clk", Ppc405CpcState, sysclk, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc405_cpc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_cpc_realize; + dc->reset = ppc405_cpc_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; + device_class_set_props(dc, ppc405_cpc_properties); +} + +/* PPC405_SOC */ + static void ppc405_soc_instance_init(Object *obj) { Ppc405SoCState *s = PPC405_SOC(obj); object_initialize_child(obj, "cpu", &s->cpu, POWERPC_CPU_TYPE_NAME("405ep")); + + object_initialize_child(obj, "cpc", &s->cpc, TYPE_PPC405_CPC); + object_property_add_alias(obj, "sys-clk", OBJECT(&s->cpc), "sys-clk"); } static void ppc405_reset(void *opaque) @@ -1448,12 +1430,9 @@ static void ppc405_reset(void *opaque) static void ppc405_soc_realize(DeviceState *dev, Error **errp) { Ppc405SoCState *s = PPC405_SOC(dev); - clk_setup_t clk_setup[PPC405EP_CLK_NB]; qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; CPUPPCState *env; - memset(clk_setup, 0, sizeof(clk_setup)); - /* init CPUs */ if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { return; @@ -1462,14 +1441,12 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) env = &s->cpu.env; - clk_setup[PPC405EP_CPU_CLK].cb = - ppc_40x_timers_init(env, s->sysclk, PPC_INTERRUPT_PIT); - clk_setup[PPC405EP_CPU_CLK].opaque = env; - ppc_dcr_init(env, NULL, NULL); /* CPU control */ - ppc405ep_cpc_init(env, clk_setup, s->sysclk); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->cpc), &s->cpu, errp)) { + return; + } /* PLB arbitrer */ ppc4xx_plb_init(env); @@ -1561,7 +1538,6 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) static Property ppc405_soc_properties[] = { DEFINE_PROP_LINK("dram", Ppc405SoCState, dram_mr, TYPE_MEMORY_REGION, MemoryRegion *), - DEFINE_PROP_UINT32("sys-clk", Ppc405SoCState, sysclk, 0), DEFINE_PROP_BOOL("dram-init", Ppc405SoCState, do_dram_init, 0), DEFINE_PROP_UINT64("ram-size", Ppc405SoCState, ram_size, 0), DEFINE_PROP_END_OF_LIST(), @@ -1579,6 +1555,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_CPC, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405CpcState), + .class_init = ppc405_cpc_class_init, + }, { .name = TYPE_PPC405_SOC, .parent = TYPE_DEVICE, .instance_size = sizeof(Ppc405SoCState), From 269fbb5b8ac0506b872ad3df277f23de1856ed15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:21 +0200 Subject: [PATCH 0240/1020] ppc/ppc405: QOM'ify GPT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GPT controller is currently modeled as a SysBus device with a unique memory region, a couple of IRQs and a timer. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes, add finalize method] Signed-off-by: BALATON Zoltan Message-Id: <8950ab26e78173f94ba65bc61bcfd0631de1fe61.1660746880.git.balaton@eik.bme.hu> [danielhb: check if timer != NULL in ppc405_gpt_finalize()] Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 22 ++++++++++ hw/ppc/ppc405_uc.c | 102 ++++++++++++++++++++++++-------------------- hw/ppc/trace-events | 1 - 3 files changed, 78 insertions(+), 47 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 2ba829988d..bcf55e4f6b 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,27 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +/* General purpose timers */ +#define TYPE_PPC405_GPT "ppc405-gpt" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GptState, PPC405_GPT); +struct Ppc405GptState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + + int64_t tb_offset; + uint32_t tb_freq; + QEMUTimer *timer; + qemu_irq irqs[5]; + uint32_t oe; + uint32_t ol; + uint32_t im; + uint32_t is; + uint32_t ie; + uint32_t comp[5]; + uint32_t mask[5]; +}; + #define TYPE_PPC405_CPC "ppc405-cpc" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405CpcState, PPC405_CPC); @@ -114,6 +135,7 @@ struct Ppc405SoCState { PowerPCCPU cpu; DeviceState *uic; Ppc405CpcState cpc; + Ppc405GptState gpt; }; /* PowerPC 405 core */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index ec83c292a5..1994801abe 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -926,34 +926,18 @@ static void ppc405_ocm_init(CPUPPCState *env) /*****************************************************************************/ /* General purpose timers */ -typedef struct ppc4xx_gpt_t ppc4xx_gpt_t; -struct ppc4xx_gpt_t { - MemoryRegion iomem; - int64_t tb_offset; - uint32_t tb_freq; - QEMUTimer *timer; - qemu_irq irqs[5]; - uint32_t oe; - uint32_t ol; - uint32_t im; - uint32_t is; - uint32_t ie; - uint32_t comp[5]; - uint32_t mask[5]; -}; - -static int ppc4xx_gpt_compare (ppc4xx_gpt_t *gpt, int n) +static int ppc4xx_gpt_compare(Ppc405GptState *gpt, int n) { /* XXX: TODO */ return 0; } -static void ppc4xx_gpt_set_output (ppc4xx_gpt_t *gpt, int n, int level) +static void ppc4xx_gpt_set_output(Ppc405GptState *gpt, int n, int level) { /* XXX: TODO */ } -static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt) +static void ppc4xx_gpt_set_outputs(Ppc405GptState *gpt) { uint32_t mask; int i; @@ -974,7 +958,7 @@ static void ppc4xx_gpt_set_outputs (ppc4xx_gpt_t *gpt) } } -static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt) +static void ppc4xx_gpt_set_irqs(Ppc405GptState *gpt) { uint32_t mask; int i; @@ -989,14 +973,14 @@ static void ppc4xx_gpt_set_irqs (ppc4xx_gpt_t *gpt) } } -static void ppc4xx_gpt_compute_timer (ppc4xx_gpt_t *gpt) +static void ppc4xx_gpt_compute_timer(Ppc405GptState *gpt) { /* XXX: TODO */ } static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr addr, unsigned size) { - ppc4xx_gpt_t *gpt = opaque; + Ppc405GptState *gpt = opaque; uint32_t ret; int idx; @@ -1050,7 +1034,7 @@ static uint64_t ppc4xx_gpt_read(void *opaque, hwaddr addr, unsigned size) static void ppc4xx_gpt_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - ppc4xx_gpt_t *gpt = opaque; + Ppc405GptState *gpt = opaque; int idx; trace_ppc4xx_gpt_write(addr, size, value); @@ -1114,22 +1098,20 @@ static const MemoryRegionOps gpt_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void ppc4xx_gpt_cb (void *opaque) +static void ppc4xx_gpt_cb(void *opaque) { - ppc4xx_gpt_t *gpt; + Ppc405GptState *gpt = opaque; - gpt = opaque; ppc4xx_gpt_set_irqs(gpt); ppc4xx_gpt_set_outputs(gpt); ppc4xx_gpt_compute_timer(gpt); } -static void ppc4xx_gpt_reset (void *opaque) +static void ppc405_gpt_reset(DeviceState *dev) { - ppc4xx_gpt_t *gpt; + Ppc405GptState *gpt = PPC405_GPT(dev); int i; - gpt = opaque; timer_del(gpt->timer); gpt->oe = 0x00000000; gpt->ol = 0x00000000; @@ -1142,21 +1124,37 @@ static void ppc4xx_gpt_reset (void *opaque) } } -static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5]) +static void ppc405_gpt_realize(DeviceState *dev, Error **errp) { - ppc4xx_gpt_t *gpt; + Ppc405GptState *s = PPC405_GPT(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); int i; - trace_ppc4xx_gpt_init(base); + s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ppc4xx_gpt_cb, s); + memory_region_init_io(&s->iomem, OBJECT(s), &gpt_ops, s, "gpt", 0xd4); + sysbus_init_mmio(sbd, &s->iomem); - gpt = g_new0(ppc4xx_gpt_t, 1); - for (i = 0; i < 5; i++) { - gpt->irqs[i] = irqs[i]; + for (i = 0; i < ARRAY_SIZE(s->irqs); i++) { + sysbus_init_irq(sbd, &s->irqs[i]); } - gpt->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ppc4xx_gpt_cb, gpt); - memory_region_init_io(&gpt->iomem, NULL, &gpt_ops, gpt, "gpt", 0x0d4); - memory_region_add_subregion(get_system_memory(), base, &gpt->iomem); - qemu_register_reset(ppc4xx_gpt_reset, gpt); +} + +static void ppc405_gpt_finalize(Object *obj) +{ + /* timer will be NULL if the GPT wasn't realized */ + if (PPC405_GPT(obj)->timer) { + timer_del(PPC405_GPT(obj)->timer); + } +} + +static void ppc405_gpt_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_gpt_realize; + dc->reset = ppc405_gpt_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1420,6 +1418,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "cpc", &s->cpc, TYPE_PPC405_CPC); object_property_add_alias(obj, "sys-clk", OBJECT(&s->cpc), "sys-clk"); + + object_initialize_child(obj, "gpt", &s->gpt, TYPE_PPC405_GPT); } static void ppc405_reset(void *opaque) @@ -1430,8 +1430,10 @@ static void ppc405_reset(void *opaque) static void ppc405_soc_realize(DeviceState *dev, Error **errp) { Ppc405SoCState *s = PPC405_SOC(dev); - qemu_irq dma_irqs[4], gpt_irqs[5], mal_irqs[4]; + qemu_irq dma_irqs[4], mal_irqs[4]; CPUPPCState *env; + SysBusDevice *sbd; + int i; /* init CPUs */ if (!qdev_realize(DEVICE(&s->cpu), NULL, errp)) { @@ -1517,12 +1519,14 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) ppc405_ocm_init(env); /* GPT */ - gpt_irqs[0] = qdev_get_gpio_in(s->uic, 19); - gpt_irqs[1] = qdev_get_gpio_in(s->uic, 20); - gpt_irqs[2] = qdev_get_gpio_in(s->uic, 21); - gpt_irqs[3] = qdev_get_gpio_in(s->uic, 22); - gpt_irqs[4] = qdev_get_gpio_in(s->uic, 23); - ppc4xx_gpt_init(0xef600000, gpt_irqs); + sbd = SYS_BUS_DEVICE(&s->gpt); + if (!sysbus_realize(sbd, errp)) { + return; + } + sysbus_mmio_map(sbd, 0, 0xef600000); + for (i = 0; i < ARRAY_SIZE(s->gpt.irqs); i++) { + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(s->uic, 19 + i)); + } /* MAL */ mal_irqs[0] = qdev_get_gpio_in(s->uic, 11); @@ -1555,6 +1559,12 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_GPT, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ppc405GptState), + .instance_finalize = ppc405_gpt_finalize, + .class_init = ppc405_gpt_class_init, + }, { .name = TYPE_PPC405_CPC, .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(Ppc405CpcState), diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index f6990439d1..8d35521bf7 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -173,7 +173,6 @@ ocm_unmap(const char* prefix, uint32_t isarc) "OCM unmap %s 0x%08" PRIx32 ppc4xx_gpt_read(uint64_t addr, uint32_t size) "addr 0x%" PRIx64 " size %d" ppc4xx_gpt_write(uint64_t addr, uint32_t size, uint64_t val) "addr 0x%" PRIx64 " size %d = 0x%" PRIx64 -ppc4xx_gpt_init(uint64_t addr) "offet 0x%" PRIx64 ppc405ep_clocks_compute(const char *param, uint32_t param2, uint32_t val) "%s 0x%1" PRIx32 " %d" ppc405ep_clocks_setup(const char *trace) "%s" From 2847eb40891b252e66a178532d26a8f7f91c735e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:22 +0200 Subject: [PATCH 0241/1020] ppc/ppc405: QOM'ify OCM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OCM controller is currently modeled as a simple DCR device with a couple of memory regions. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes] Signed-off-by: BALATON Zoltan Message-Id: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 16 ++++++++++ hw/ppc/ppc405_uc.c | 77 +++++++++++++++++++++++----------------------- 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index bcf55e4f6b..a5b493d3e7 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,21 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +/* On Chip Memory */ +#define TYPE_PPC405_OCM "ppc405-ocm" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OcmState, PPC405_OCM); +struct Ppc405OcmState { + Ppc4xxDcrDeviceState parent_obj; + + MemoryRegion ram; + MemoryRegion isarc_ram; + MemoryRegion dsarc_ram; + uint32_t isarc; + uint32_t isacntl; + uint32_t dsarc; + uint32_t dsacntl; +}; + /* General purpose timers */ #define TYPE_PPC405_GPT "ppc405-gpt" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GptState, PPC405_GPT); @@ -136,6 +151,7 @@ struct Ppc405SoCState { DeviceState *uic; Ppc405CpcState cpc; Ppc405GptState gpt; + Ppc405OcmState ocm; }; /* PowerPC 405 core */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 1994801abe..8ee0357ac3 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -773,20 +773,9 @@ enum { OCM0_DSACNTL = 0x01B, }; -typedef struct ppc405_ocm_t ppc405_ocm_t; -struct ppc405_ocm_t { - MemoryRegion ram; - MemoryRegion isarc_ram; - MemoryRegion dsarc_ram; - uint32_t isarc; - uint32_t isacntl; - uint32_t dsarc; - uint32_t dsacntl; -}; - -static void ocm_update_mappings (ppc405_ocm_t *ocm, - uint32_t isarc, uint32_t isacntl, - uint32_t dsarc, uint32_t dsacntl) +static void ocm_update_mappings(Ppc405OcmState *ocm, + uint32_t isarc, uint32_t isacntl, + uint32_t dsarc, uint32_t dsacntl) { trace_ocm_update_mappings(isarc, isacntl, dsarc, dsacntl, ocm->isarc, ocm->isacntl, ocm->dsarc, ocm->dsacntl); @@ -828,12 +817,11 @@ static void ocm_update_mappings (ppc405_ocm_t *ocm, } } -static uint32_t dcr_read_ocm (void *opaque, int dcrn) +static uint32_t dcr_read_ocm(void *opaque, int dcrn) { - ppc405_ocm_t *ocm; + Ppc405OcmState *ocm = opaque; uint32_t ret; - ocm = opaque; switch (dcrn) { case OCM0_ISARC: ret = ocm->isarc; @@ -855,12 +843,11 @@ static uint32_t dcr_read_ocm (void *opaque, int dcrn) return ret; } -static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val) +static void dcr_write_ocm(void *opaque, int dcrn, uint32_t val) { - ppc405_ocm_t *ocm; + Ppc405OcmState *ocm = opaque; uint32_t isarc, dsarc, isacntl, dsacntl; - ocm = opaque; isarc = ocm->isarc; dsarc = ocm->dsarc; isacntl = ocm->isacntl; @@ -886,12 +873,11 @@ static void dcr_write_ocm (void *opaque, int dcrn, uint32_t val) ocm->dsacntl = dsacntl; } -static void ocm_reset (void *opaque) +static void ppc405_ocm_reset(DeviceState *dev) { - ppc405_ocm_t *ocm; + Ppc405OcmState *ocm = PPC405_OCM(dev); uint32_t isarc, dsarc, isacntl, dsacntl; - ocm = opaque; isarc = 0x00000000; isacntl = 0x00000000; dsarc = 0x00000000; @@ -903,25 +889,31 @@ static void ocm_reset (void *opaque) ocm->dsacntl = dsacntl; } -static void ppc405_ocm_init(CPUPPCState *env) +static void ppc405_ocm_realize(DeviceState *dev, Error **errp) { - ppc405_ocm_t *ocm; + Ppc405OcmState *ocm = PPC405_OCM(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - ocm = g_new0(ppc405_ocm_t, 1); /* XXX: Size is 4096 or 0x04000000 */ - memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4 * KiB, + memory_region_init_ram(&ocm->isarc_ram, OBJECT(ocm), "ppc405.ocm", 4 * KiB, &error_fatal); - memory_region_init_alias(&ocm->dsarc_ram, NULL, "ppc405.dsarc", + memory_region_init_alias(&ocm->dsarc_ram, OBJECT(ocm), "ppc405.dsarc", &ocm->isarc_ram, 0, 4 * KiB); - qemu_register_reset(&ocm_reset, ocm); - ppc_dcr_register(env, OCM0_ISARC, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_ISACNTL, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_DSARC, - ocm, &dcr_read_ocm, &dcr_write_ocm); - ppc_dcr_register(env, OCM0_DSACNTL, - ocm, &dcr_read_ocm, &dcr_write_ocm); + + ppc4xx_dcr_register(dcr, OCM0_ISARC, ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc4xx_dcr_register(dcr, OCM0_ISACNTL, ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc4xx_dcr_register(dcr, OCM0_DSARC, ocm, &dcr_read_ocm, &dcr_write_ocm); + ppc4xx_dcr_register(dcr, OCM0_DSACNTL, ocm, &dcr_read_ocm, &dcr_write_ocm); +} + +static void ppc405_ocm_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_ocm_realize; + dc->reset = ppc405_ocm_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1420,6 +1412,8 @@ static void ppc405_soc_instance_init(Object *obj) object_property_add_alias(obj, "sys-clk", OBJECT(&s->cpc), "sys-clk"); object_initialize_child(obj, "gpt", &s->gpt, TYPE_PPC405_GPT); + + object_initialize_child(obj, "ocm", &s->ocm, TYPE_PPC405_OCM); } static void ppc405_reset(void *opaque) @@ -1516,7 +1510,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) } /* OCM */ - ppc405_ocm_init(env); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->ocm), &s->cpu, errp)) { + return; + } /* GPT */ sbd = SYS_BUS_DEVICE(&s->gpt); @@ -1559,6 +1555,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_OCM, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405OcmState), + .class_init = ppc405_ocm_class_init, + }, { .name = TYPE_PPC405_GPT, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Ppc405GptState), From 125277c6a88d93760c2ec28c74bf3a1c30b90113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:23 +0200 Subject: [PATCH 0242/1020] ppc/ppc405: QOM'ify GPIO MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The GPIO controller is currently modeled as a simple SysBus device with a unique memory region. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: Simplify sysbus device casts for readability] Signed-off-by: BALATON Zoltan Message-Id: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 21 +++++++++++++++++++ hw/ppc/ppc405_uc.c | 50 ++++++++++++++++++++++----------------------- hw/ppc/trace-events | 1 - 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index a5b493d3e7..21f6cb3585 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,26 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +/* GPIO */ +#define TYPE_PPC405_GPIO "ppc405-gpio" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GpioState, PPC405_GPIO); +struct Ppc405GpioState { + SysBusDevice parent_obj; + + MemoryRegion io; + uint32_t or; + uint32_t tcr; + uint32_t osrh; + uint32_t osrl; + uint32_t tsrh; + uint32_t tsrl; + uint32_t odr; + uint32_t ir; + uint32_t rr1; + uint32_t isr1h; + uint32_t isr1l; +}; + /* On Chip Memory */ #define TYPE_PPC405_OCM "ppc405-ocm" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OcmState, PPC405_OCM); @@ -152,6 +172,7 @@ struct Ppc405SoCState { Ppc405CpcState cpc; Ppc405GptState gpt; Ppc405OcmState ocm; + Ppc405GpioState gpio; }; /* PowerPC 405 core */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 8ee0357ac3..3f4a5b36f5 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -714,22 +714,6 @@ static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4]) /*****************************************************************************/ /* GPIO */ -typedef struct ppc405_gpio_t ppc405_gpio_t; -struct ppc405_gpio_t { - MemoryRegion io; - uint32_t or; - uint32_t tcr; - uint32_t osrh; - uint32_t osrl; - uint32_t tsrh; - uint32_t tsrl; - uint32_t odr; - uint32_t ir; - uint32_t rr1; - uint32_t isr1h; - uint32_t isr1l; -}; - static uint64_t ppc405_gpio_read(void *opaque, hwaddr addr, unsigned size) { trace_ppc405_gpio_read(addr, size); @@ -748,20 +732,22 @@ static const MemoryRegionOps ppc405_gpio_ops = { .endianness = DEVICE_NATIVE_ENDIAN, }; -static void ppc405_gpio_reset (void *opaque) +static void ppc405_gpio_realize(DeviceState *dev, Error **errp) { + Ppc405GpioState *s = PPC405_GPIO(dev); + + memory_region_init_io(&s->io, OBJECT(s), &ppc405_gpio_ops, s, "gpio", + 0x38); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io); } -static void ppc405_gpio_init(hwaddr base) +static void ppc405_gpio_class_init(ObjectClass *oc, void *data) { - ppc405_gpio_t *gpio; + DeviceClass *dc = DEVICE_CLASS(oc); - trace_ppc405_gpio_init(base); - - gpio = g_new0(ppc405_gpio_t, 1); - memory_region_init_io(&gpio->io, NULL, &ppc405_gpio_ops, gpio, "pgio", 0x038); - memory_region_add_subregion(get_system_memory(), base, &gpio->io); - qemu_register_reset(&ppc405_gpio_reset, gpio); + dc->realize = ppc405_gpio_realize; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1414,6 +1400,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "gpt", &s->gpt, TYPE_PPC405_GPT); object_initialize_child(obj, "ocm", &s->ocm, TYPE_PPC405_OCM); + + object_initialize_child(obj, "gpio", &s->gpio, TYPE_PPC405_GPIO); } static void ppc405_reset(void *opaque) @@ -1492,8 +1480,13 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) /* I2C controller */ sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, qdev_get_gpio_in(s->uic, 2)); + /* GPIO */ - ppc405_gpio_init(0xef600700); + sbd = SYS_BUS_DEVICE(&s->gpio); + if (!sysbus_realize(sbd, errp)) { + return; + } + sysbus_mmio_map(sbd, 0, 0xef600700); /* Serial ports */ if (serial_hd(0) != NULL) { @@ -1555,6 +1548,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_GPIO, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ppc405GpioState), + .class_init = ppc405_gpio_class_init, + }, { .name = TYPE_PPC405_OCM, .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(Ppc405OcmState), diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 8d35521bf7..69a95f9f57 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -165,7 +165,6 @@ opba_init(uint64_t addr) "offet 0x%" PRIx64 ppc405_gpio_read(uint64_t addr, uint32_t size) "addr 0x%" PRIx64 " size %d" ppc405_gpio_write(uint64_t addr, uint32_t size, uint64_t val) "addr 0x%" PRIx64 " size %d = 0x%" PRIx64 -ppc405_gpio_init(uint64_t addr) "offet 0x%" PRIx64 ocm_update_mappings(uint32_t isarc, uint32_t isacntl, uint32_t dsarc, uint32_t dsacntl, uint32_t ocm_isarc, uint32_t ocm_isacntl, uint32_t ocm_dsarc, uint32_t ocm_dsacntl) "OCM update ISA 0x%08" PRIx32 " 0x%08" PRIx32 " (0x%08" PRIx32" 0x%08" PRIx32 ") DSA 0x%08" PRIx32 " 0x%08" PRIx32" (0x%08" PRIx32 " 0x%08" PRIx32 ")" ocm_map(const char* prefix, uint32_t isarc) "OCM map %s 0x%08" PRIx32 From 82c86e304ad9532308486c516fe9396658a72d72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:24 +0200 Subject: [PATCH 0243/1020] ppc/ppc405: QOM'ify DMA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DMA controller is currently modeled as a DCR device with a couple of IRQs. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes] Signed-off-by: BALATON Zoltan Message-Id: <4738b3c7cf18c328f05aaaddc555a46219431335.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 19 +++++++ hw/ppc/ppc405_uc.c | 139 ++++++++++++++++++++------------------------- 2 files changed, 80 insertions(+), 78 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 21f6cb3585..c75e4c7cb5 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,24 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +/* DMA controller */ +#define TYPE_PPC405_DMA "ppc405-dma" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405DmaState, PPC405_DMA); +struct Ppc405DmaState { + Ppc4xxDcrDeviceState parent_obj; + + qemu_irq irqs[4]; + uint32_t cr[4]; + uint32_t ct[4]; + uint32_t da[4]; + uint32_t sa[4]; + uint32_t sg[4]; + uint32_t sr; + uint32_t sgc; + uint32_t slp; + uint32_t pol; +}; + /* GPIO */ #define TYPE_PPC405_GPIO "ppc405-gpio" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405GpioState, PPC405_GPIO); @@ -173,6 +191,7 @@ struct Ppc405SoCState { Ppc405GptState gpt; Ppc405OcmState ocm; Ppc405GpioState gpio; + Ppc405DmaState dma; }; /* PowerPC 405 core */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 3f4a5b36f5..3845c0fec1 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -613,35 +613,20 @@ enum { DMA0_POL = 0x126, }; -typedef struct ppc405_dma_t ppc405_dma_t; -struct ppc405_dma_t { - qemu_irq irqs[4]; - uint32_t cr[4]; - uint32_t ct[4]; - uint32_t da[4]; - uint32_t sa[4]; - uint32_t sg[4]; - uint32_t sr; - uint32_t sgc; - uint32_t slp; - uint32_t pol; -}; - -static uint32_t dcr_read_dma (void *opaque, int dcrn) +static uint32_t dcr_read_dma(void *opaque, int dcrn) { return 0; } -static void dcr_write_dma (void *opaque, int dcrn, uint32_t val) +static void dcr_write_dma(void *opaque, int dcrn, uint32_t val) { } -static void ppc405_dma_reset (void *opaque) +static void ppc405_dma_reset(DeviceState *dev) { - ppc405_dma_t *dma; + Ppc405DmaState *dma = PPC405_DMA(dev); int i; - dma = opaque; for (i = 0; i < 4; i++) { dma->cr[i] = 0x00000000; dma->ct[i] = 0x00000000; @@ -655,61 +640,50 @@ static void ppc405_dma_reset (void *opaque) dma->pol = 0x00000000; } -static void ppc405_dma_init(CPUPPCState *env, qemu_irq irqs[4]) +static void ppc405_dma_realize(DeviceState *dev, Error **errp) { - ppc405_dma_t *dma; + Ppc405DmaState *dma = PPC405_DMA(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); + int i; - dma = g_new0(ppc405_dma_t, 1); - memcpy(dma->irqs, irqs, 4 * sizeof(qemu_irq)); - qemu_register_reset(&ppc405_dma_reset, dma); - ppc_dcr_register(env, DMA0_CR0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG0, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG1, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG2, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CR3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_CT3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_DA3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SA3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SG3, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SR, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SGC, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_SLP, - dma, &dcr_read_dma, &dcr_write_dma); - ppc_dcr_register(env, DMA0_POL, - dma, &dcr_read_dma, &dcr_write_dma); + for (i = 0; i < ARRAY_SIZE(dma->irqs); i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dma), &dma->irqs[i]); + } + + ppc4xx_dcr_register(dcr, DMA0_CR0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CT0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_DA0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SA0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SG0, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CR1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CT1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_DA1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SA1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SG1, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CR2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CT2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_DA2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SA2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SG2, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CR3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_CT3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_DA3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SA3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SG3, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SR, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SGC, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_SLP, dma, &dcr_read_dma, &dcr_write_dma); + ppc4xx_dcr_register(dcr, DMA0_POL, dma, &dcr_read_dma, &dcr_write_dma); +} + +static void ppc405_dma_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_dma_realize; + dc->reset = ppc405_dma_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1402,6 +1376,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "ocm", &s->ocm, TYPE_PPC405_OCM); object_initialize_child(obj, "gpio", &s->gpio, TYPE_PPC405_GPIO); + + object_initialize_child(obj, "dma", &s->dma, TYPE_PPC405_DMA); } static void ppc405_reset(void *opaque) @@ -1412,7 +1388,7 @@ static void ppc405_reset(void *opaque) static void ppc405_soc_realize(DeviceState *dev, Error **errp) { Ppc405SoCState *s = PPC405_SOC(dev); - qemu_irq dma_irqs[4], mal_irqs[4]; + qemu_irq mal_irqs[4]; CPUPPCState *env; SysBusDevice *sbd; int i; @@ -1471,11 +1447,13 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) ppc405_ebc_init(env); /* DMA controller */ - dma_irqs[0] = qdev_get_gpio_in(s->uic, 5); - dma_irqs[1] = qdev_get_gpio_in(s->uic, 6); - dma_irqs[2] = qdev_get_gpio_in(s->uic, 7); - dma_irqs[3] = qdev_get_gpio_in(s->uic, 8); - ppc405_dma_init(env, dma_irqs); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->dma), &s->cpu, errp)) { + return; + } + sbd = SYS_BUS_DEVICE(&s->dma); + for (i = 0; i < ARRAY_SIZE(s->dma.irqs); i++) { + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(s->uic, 5 + i)); + } /* I2C controller */ sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, @@ -1548,6 +1526,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_DMA, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405DmaState), + .class_init = ppc405_dma_class_init, + }, { .name = TYPE_PPC405_GPIO, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Ppc405GpioState), From 415a6333d44818b6ae23d4dda813fa8a8f0df2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:25 +0200 Subject: [PATCH 0244/1020] ppc/ppc405: QOM'ify EBC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit EBC is currently modeled as a DCR device. Also drop the ppc405_ebc_init() helper and adapt the sam460ex machine. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes] Signed-off-by: BALATON Zoltan Message-Id: <51a0769ab605c5158f4f2f1c896725d5fe7a073b.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 17 ++++++++++++- hw/ppc/ppc405_uc.c | 60 ++++++++++++++++++++++++---------------------- hw/ppc/sam460ex.c | 4 +++- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index c75e4c7cb5..82bf8dae93 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,21 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +/* Peripheral controller */ +#define TYPE_PPC405_EBC "ppc405-ebc" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405EbcState, PPC405_EBC); +struct Ppc405EbcState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t addr; + uint32_t bcr[8]; + uint32_t bap[8]; + uint32_t bear; + uint32_t besr0; + uint32_t besr1; + uint32_t cfg; +}; + /* DMA controller */ #define TYPE_PPC405_DMA "ppc405-dma" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405DmaState, PPC405_DMA); @@ -192,12 +207,12 @@ struct Ppc405SoCState { Ppc405OcmState ocm; Ppc405GpioState gpio; Ppc405DmaState dma; + Ppc405EbcState ebc; }; /* PowerPC 405 core */ ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size); void ppc4xx_plb_init(CPUPPCState *env); -void ppc405_ebc_init(CPUPPCState *env); #endif /* PPC405_H */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 3845c0fec1..ff81fb3e20 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -393,28 +393,16 @@ static void ppc4xx_opba_init(hwaddr base) /*****************************************************************************/ /* Peripheral controller */ -typedef struct ppc4xx_ebc_t ppc4xx_ebc_t; -struct ppc4xx_ebc_t { - uint32_t addr; - uint32_t bcr[8]; - uint32_t bap[8]; - uint32_t bear; - uint32_t besr0; - uint32_t besr1; - uint32_t cfg; -}; - enum { EBC0_CFGADDR = 0x012, EBC0_CFGDATA = 0x013, }; -static uint32_t dcr_read_ebc (void *opaque, int dcrn) +static uint32_t dcr_read_ebc(void *opaque, int dcrn) { - ppc4xx_ebc_t *ebc; + Ppc405EbcState *ebc = opaque; uint32_t ret; - ebc = opaque; switch (dcrn) { case EBC0_CFGADDR: ret = ebc->addr; @@ -494,11 +482,10 @@ static uint32_t dcr_read_ebc (void *opaque, int dcrn) return ret; } -static void dcr_write_ebc (void *opaque, int dcrn, uint32_t val) +static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val) { - ppc4xx_ebc_t *ebc; + Ppc405EbcState *ebc = opaque; - ebc = opaque; switch (dcrn) { case EBC0_CFGADDR: ebc->addr = val; @@ -554,12 +541,11 @@ static void dcr_write_ebc (void *opaque, int dcrn, uint32_t val) } } -static void ebc_reset (void *opaque) +static void ppc405_ebc_reset(DeviceState *dev) { - ppc4xx_ebc_t *ebc; + Ppc405EbcState *ebc = PPC405_EBC(dev); int i; - ebc = opaque; ebc->addr = 0x00000000; ebc->bap[0] = 0x7F8FFE80; ebc->bcr[0] = 0xFFE28000; @@ -572,16 +558,23 @@ static void ebc_reset (void *opaque) ebc->cfg = 0x80400000; } -void ppc405_ebc_init(CPUPPCState *env) +static void ppc405_ebc_realize(DeviceState *dev, Error **errp) { - ppc4xx_ebc_t *ebc; + Ppc405EbcState *ebc = PPC405_EBC(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - ebc = g_new0(ppc4xx_ebc_t, 1); - qemu_register_reset(&ebc_reset, ebc); - ppc_dcr_register(env, EBC0_CFGADDR, - ebc, &dcr_read_ebc, &dcr_write_ebc); - ppc_dcr_register(env, EBC0_CFGDATA, - ebc, &dcr_read_ebc, &dcr_write_ebc); + ppc4xx_dcr_register(dcr, EBC0_CFGADDR, ebc, &dcr_read_ebc, &dcr_write_ebc); + ppc4xx_dcr_register(dcr, EBC0_CFGDATA, ebc, &dcr_read_ebc, &dcr_write_ebc); +} + +static void ppc405_ebc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_ebc_realize; + dc->reset = ppc405_ebc_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1378,6 +1371,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "gpio", &s->gpio, TYPE_PPC405_GPIO); object_initialize_child(obj, "dma", &s->dma, TYPE_PPC405_DMA); + + object_initialize_child(obj, "ebc", &s->ebc, TYPE_PPC405_EBC); } static void ppc405_reset(void *opaque) @@ -1444,7 +1439,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) s->do_dram_init); /* External bus controller */ - ppc405_ebc_init(env); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->ebc), &s->cpu, errp)) { + return; + } /* DMA controller */ if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->dma), &s->cpu, errp)) { @@ -1526,6 +1523,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_EBC, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405EbcState), + .class_init = ppc405_ebc_class_init, + }, { .name = TYPE_PPC405_DMA, .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(Ppc405DmaState), diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 0357ee077f..320c61a7f3 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -371,7 +371,9 @@ static void sam460ex_init(MachineState *machine) qdev_get_gpio_in(uic[0], 3)); /* External bus controller */ - ppc405_ebc_init(env); + dev = qdev_new(TYPE_PPC405_EBC); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); + object_unref(OBJECT(dev)); /* CPR */ ppc4xx_cpr_init(env); From 72beecc20c72fefb97bc4a4e558ba4e884166629 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:26 +0200 Subject: [PATCH 0245/1020] ppc/ppc405: QOM'ify OPBA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The OPB arbitrer is currently modeled as a simple SysBus device with a unique memory region. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes] Signed-off-by: BALATON Zoltan Message-Id: <38476bc43d2332db2f09dbede9eff5234d6ce217.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 12 +++++++++++ hw/ppc/ppc405_uc.c | 49 +++++++++++++++++++++++++++------------------ hw/ppc/trace-events | 1 - 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 82bf8dae93..d63c2acdc7 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,17 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +/* OPB arbitrer */ +#define TYPE_PPC405_OPBA "ppc405-opba" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OpbaState, PPC405_OPBA); +struct Ppc405OpbaState { + SysBusDevice parent_obj; + + MemoryRegion io; + uint8_t cr; + uint8_t pr; +}; + /* Peripheral controller */ #define TYPE_PPC405_EBC "ppc405-ebc" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405EbcState, PPC405_EBC); @@ -208,6 +219,7 @@ struct Ppc405SoCState { Ppc405GpioState gpio; Ppc405DmaState dma; Ppc405EbcState ebc; + Ppc405OpbaState opba; }; /* PowerPC 405 core */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index ff81fb3e20..2c482bc25c 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -310,16 +310,9 @@ static void ppc4xx_pob_init(CPUPPCState *env) /*****************************************************************************/ /* OPB arbitrer */ -typedef struct ppc4xx_opba_t ppc4xx_opba_t; -struct ppc4xx_opba_t { - MemoryRegion io; - uint8_t cr; - uint8_t pr; -}; - static uint64_t opba_readb(void *opaque, hwaddr addr, unsigned size) { - ppc4xx_opba_t *opba = opaque; + Ppc405OpbaState *opba = opaque; uint32_t ret; switch (addr) { @@ -341,7 +334,7 @@ static uint64_t opba_readb(void *opaque, hwaddr addr, unsigned size) static void opba_writeb(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - ppc4xx_opba_t *opba = opaque; + Ppc405OpbaState *opba = opaque; trace_opba_writeb(addr, value); @@ -366,25 +359,30 @@ static const MemoryRegionOps opba_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void ppc4xx_opba_reset (void *opaque) +static void ppc405_opba_reset(DeviceState *dev) { - ppc4xx_opba_t *opba; + Ppc405OpbaState *opba = PPC405_OPBA(dev); - opba = opaque; opba->cr = 0x00; /* No dynamic priorities - park disabled */ opba->pr = 0x11; } -static void ppc4xx_opba_init(hwaddr base) +static void ppc405_opba_realize(DeviceState *dev, Error **errp) { - ppc4xx_opba_t *opba; + Ppc405OpbaState *s = PPC405_OPBA(dev); - trace_opba_init(base); + memory_region_init_io(&s->io, OBJECT(s), &opba_ops, s, "opba", 2); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->io); +} - opba = g_new0(ppc4xx_opba_t, 1); - memory_region_init_io(&opba->io, NULL, &opba_ops, opba, "opba", 0x002); - memory_region_add_subregion(get_system_memory(), base, &opba->io); - qemu_register_reset(ppc4xx_opba_reset, opba); +static void ppc405_opba_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_opba_realize; + dc->reset = ppc405_opba_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1373,6 +1371,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "dma", &s->dma, TYPE_PPC405_DMA); object_initialize_child(obj, "ebc", &s->ebc, TYPE_PPC405_EBC); + + object_initialize_child(obj, "opba", &s->opba, TYPE_PPC405_OPBA); } static void ppc405_reset(void *opaque) @@ -1410,7 +1410,11 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) ppc4xx_pob_init(env); /* OBP arbitrer */ - ppc4xx_opba_init(0xef600600); + sbd = SYS_BUS_DEVICE(&s->opba); + if (!sysbus_realize(sbd, errp)) { + return; + } + sysbus_mmio_map(sbd, 0, 0xef600600); /* Universal interrupt controller */ s->uic = qdev_new(TYPE_PPC_UIC); @@ -1523,6 +1527,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_OPBA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ppc405OpbaState), + .class_init = ppc405_opba_class_init, + }, { .name = TYPE_PPC405_EBC, .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(Ppc405EbcState), diff --git a/hw/ppc/trace-events b/hw/ppc/trace-events index 69a95f9f57..a07d5aca0f 100644 --- a/hw/ppc/trace-events +++ b/hw/ppc/trace-events @@ -161,7 +161,6 @@ ppc440_pcix_reg_write(uint64_t addr, uint32_t val, uint32_t size) "addr 0x%" PRI # ppc405_boards.c opba_readb(uint64_t addr, uint32_t val) "addr 0x%" PRIx64 " = 0x%" PRIx32 opba_writeb(uint64_t addr, uint64_t val) "addr 0x%" PRIx64 " = 0x%" PRIx64 -opba_init(uint64_t addr) "offet 0x%" PRIx64 ppc405_gpio_read(uint64_t addr, uint32_t size) "addr 0x%" PRIx64 " size %d" ppc405_gpio_write(uint64_t addr, uint32_t size, uint64_t val) "addr 0x%" PRIx64 " size %d = 0x%" PRIx64 From 2841430e6ae5cee6e58b1f0d86b77c6bbbc8c2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:27 +0200 Subject: [PATCH 0246/1020] ppc/ppc405: QOM'ify POB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit POB is currently modeled as a simple DCR device. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes] Signed-off-by: BALATON Zoltan Message-Id: <2bb1a89182523059ecb0e8d20c22a293534dec17.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 12 ++++++++++ hw/ppc/ppc405_uc.c | 56 ++++++++++++++++++++++++++-------------------- 2 files changed, 44 insertions(+), 24 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index d63c2acdc7..4140e811d5 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,17 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +/* PLB to OPB bridge */ +#define TYPE_PPC405_POB "ppc405-pob" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PobState, PPC405_POB); +struct Ppc405PobState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t bear; + uint32_t besr0; + uint32_t besr1; +}; + /* OPB arbitrer */ #define TYPE_PPC405_OPBA "ppc405-opba" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405OpbaState, PPC405_OPBA); @@ -220,6 +231,7 @@ struct Ppc405SoCState { Ppc405DmaState dma; Ppc405EbcState ebc; Ppc405OpbaState opba; + Ppc405PobState pob; }; /* PowerPC 405 core */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 2c482bc25c..e5604c3421 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -234,19 +234,11 @@ enum { POB0_BEAR = 0x0A4, }; -typedef struct ppc4xx_pob_t ppc4xx_pob_t; -struct ppc4xx_pob_t { - uint32_t bear; - uint32_t besr0; - uint32_t besr1; -}; - -static uint32_t dcr_read_pob (void *opaque, int dcrn) +static uint32_t dcr_read_pob(void *opaque, int dcrn) { - ppc4xx_pob_t *pob; + Ppc405PobState *pob = opaque; uint32_t ret; - pob = opaque; switch (dcrn) { case POB0_BEAR: ret = pob->bear; @@ -266,11 +258,10 @@ static uint32_t dcr_read_pob (void *opaque, int dcrn) return ret; } -static void dcr_write_pob (void *opaque, int dcrn, uint32_t val) +static void dcr_write_pob(void *opaque, int dcrn, uint32_t val) { - ppc4xx_pob_t *pob; + Ppc405PobState *pob = opaque; - pob = opaque; switch (dcrn) { case POB0_BEAR: /* Read only */ @@ -286,26 +277,34 @@ static void dcr_write_pob (void *opaque, int dcrn, uint32_t val) } } -static void ppc4xx_pob_reset (void *opaque) +static void ppc405_pob_reset(DeviceState *dev) { - ppc4xx_pob_t *pob; + Ppc405PobState *pob = PPC405_POB(dev); - pob = opaque; /* No error */ pob->bear = 0x00000000; pob->besr0 = 0x0000000; pob->besr1 = 0x0000000; } -static void ppc4xx_pob_init(CPUPPCState *env) +static void ppc405_pob_realize(DeviceState *dev, Error **errp) { - ppc4xx_pob_t *pob; + Ppc405PobState *pob = PPC405_POB(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - pob = g_new0(ppc4xx_pob_t, 1); - ppc_dcr_register(env, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob); - ppc_dcr_register(env, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob); - ppc_dcr_register(env, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob); - qemu_register_reset(ppc4xx_pob_reset, pob); + ppc4xx_dcr_register(dcr, POB0_BEAR, pob, &dcr_read_pob, &dcr_write_pob); + ppc4xx_dcr_register(dcr, POB0_BESR0, pob, &dcr_read_pob, &dcr_write_pob); + ppc4xx_dcr_register(dcr, POB0_BESR1, pob, &dcr_read_pob, &dcr_write_pob); +} + +static void ppc405_pob_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_pob_realize; + dc->reset = ppc405_pob_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1373,6 +1372,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "ebc", &s->ebc, TYPE_PPC405_EBC); object_initialize_child(obj, "opba", &s->opba, TYPE_PPC405_OPBA); + + object_initialize_child(obj, "pob", &s->pob, TYPE_PPC405_POB); } static void ppc405_reset(void *opaque) @@ -1407,7 +1408,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) ppc4xx_plb_init(env); /* PLB to OPB bridge */ - ppc4xx_pob_init(env); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->pob), &s->cpu, errp)) { + return; + } /* OBP arbitrer */ sbd = SYS_BUS_DEVICE(&s->opba); @@ -1527,6 +1530,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_POB, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405PobState), + .class_init = ppc405_pob_class_init, + }, { .name = TYPE_PPC405_OPBA, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Ppc405OpbaState), From 695bce07dc1c0f7de054fb471a494d572e649e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:28 +0200 Subject: [PATCH 0247/1020] ppc/ppc405: QOM'ify PLB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PLB is currently modeled as a simple DCR device. Also drop the ppc4xx_plb_init() helper and adapt the sam460ex machine. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes] Signed-off-by: BALATON Zoltan Message-Id: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 14 +++++++++-- hw/ppc/ppc405_uc.c | 62 ++++++++++++++++++++++++++-------------------- hw/ppc/sam460ex.c | 4 ++- 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 4140e811d5..cb34792daf 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,6 +63,17 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; +/* Peripheral local bus arbitrer */ +#define TYPE_PPC405_PLB "ppc405-plb" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PlbState, PPC405_PLB); +struct Ppc405PlbState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t acr; + uint32_t bear; + uint32_t besr; +}; + /* PLB to OPB bridge */ #define TYPE_PPC405_POB "ppc405-pob" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PobState, PPC405_POB); @@ -232,11 +243,10 @@ struct Ppc405SoCState { Ppc405EbcState ebc; Ppc405OpbaState opba; Ppc405PobState pob; + Ppc405PlbState plb; }; /* PowerPC 405 core */ ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size); -void ppc4xx_plb_init(CPUPPCState *env); - #endif /* PPC405_H */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index e5604c3421..9ed3ce4ebe 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -148,19 +148,11 @@ enum { PLB4A1_ACR = 0x089, }; -typedef struct ppc4xx_plb_t ppc4xx_plb_t; -struct ppc4xx_plb_t { - uint32_t acr; - uint32_t bear; - uint32_t besr; -}; - -static uint32_t dcr_read_plb (void *opaque, int dcrn) +static uint32_t dcr_read_plb(void *opaque, int dcrn) { - ppc4xx_plb_t *plb; + Ppc405PlbState *plb = opaque; uint32_t ret; - plb = opaque; switch (dcrn) { case PLB0_ACR: ret = plb->acr; @@ -180,11 +172,10 @@ static uint32_t dcr_read_plb (void *opaque, int dcrn) return ret; } -static void dcr_write_plb (void *opaque, int dcrn, uint32_t val) +static void dcr_write_plb(void *opaque, int dcrn, uint32_t val) { - ppc4xx_plb_t *plb; + Ppc405PlbState *plb = opaque; - plb = opaque; switch (dcrn) { case PLB0_ACR: /* We don't care about the actual parameters written as @@ -202,28 +193,36 @@ static void dcr_write_plb (void *opaque, int dcrn, uint32_t val) } } -static void ppc4xx_plb_reset (void *opaque) +static void ppc405_plb_reset(DeviceState *dev) { - ppc4xx_plb_t *plb; + Ppc405PlbState *plb = PPC405_PLB(dev); - plb = opaque; plb->acr = 0x00000000; plb->bear = 0x00000000; plb->besr = 0x00000000; } -void ppc4xx_plb_init(CPUPPCState *env) +static void ppc405_plb_realize(DeviceState *dev, Error **errp) { - ppc4xx_plb_t *plb; + Ppc405PlbState *plb = PPC405_PLB(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - plb = g_new0(ppc4xx_plb_t, 1); - ppc_dcr_register(env, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); - ppc_dcr_register(env, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb); - qemu_register_reset(ppc4xx_plb_reset, plb); + ppc4xx_dcr_register(dcr, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb); +} + +static void ppc405_plb_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_plb_realize; + dc->reset = ppc405_plb_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; } /*****************************************************************************/ @@ -1374,6 +1373,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "opba", &s->opba, TYPE_PPC405_OPBA); object_initialize_child(obj, "pob", &s->pob, TYPE_PPC405_POB); + + object_initialize_child(obj, "plb", &s->plb, TYPE_PPC405_PLB); } static void ppc405_reset(void *opaque) @@ -1405,7 +1406,9 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) } /* PLB arbitrer */ - ppc4xx_plb_init(env); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->plb), &s->cpu, errp)) { + return; + } /* PLB to OPB bridge */ if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->pob), &s->cpu, errp)) { @@ -1530,6 +1533,11 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { + .name = TYPE_PPC405_PLB, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405PlbState), + .class_init = ppc405_plb_class_init, + }, { .name = TYPE_PPC405_POB, .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(Ppc405PobState), diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 320c61a7f3..31139c1554 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -309,7 +309,9 @@ static void sam460ex_init(MachineState *machine) ppc_dcr_init(env, NULL, NULL); /* PLB arbitrer */ - ppc4xx_plb_init(env); + dev = qdev_new(TYPE_PPC405_PLB); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); + object_unref(OBJECT(dev)); /* interrupt controllers */ for (i = 0; i < ARRAY_SIZE(uic); i++) { From da116a8aab47695a8364708f2e1d14ed6fcc659f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:29 +0200 Subject: [PATCH 0248/1020] ppc/ppc405: QOM'ify MAL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Memory Access Layer (MAL) controller is currently modeled as a DCR device with 4 IRQs. Also drop the ppc4xx_mal_init() helper and adapt the sam460ex machine. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: ppc4xx_dcr_register changes, add finalize method] Signed-off-by: BALATON Zoltan Message-Id: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 1 + hw/ppc/ppc405_uc.c | 17 +++-- hw/ppc/ppc4xx_devs.c | 145 ++++++++++++++++++++-------------------- hw/ppc/sam460ex.c | 12 ++-- include/hw/ppc/ppc4xx.h | 28 +++++++- 5 files changed, 117 insertions(+), 86 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index cb34792daf..31c94e4742 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -244,6 +244,7 @@ struct Ppc405SoCState { Ppc405OpbaState opba; Ppc405PobState pob; Ppc405PlbState plb; + Ppc4xxMalState mal; }; /* PowerPC 405 core */ diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 9ed3ce4ebe..b02dab05b3 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1375,6 +1375,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "pob", &s->pob, TYPE_PPC405_POB); object_initialize_child(obj, "plb", &s->plb, TYPE_PPC405_PLB); + + object_initialize_child(obj, "mal", &s->mal, TYPE_PPC4xx_MAL); } static void ppc405_reset(void *opaque) @@ -1385,7 +1387,6 @@ static void ppc405_reset(void *opaque) static void ppc405_soc_realize(DeviceState *dev, Error **errp) { Ppc405SoCState *s = PPC405_SOC(dev); - qemu_irq mal_irqs[4]; CPUPPCState *env; SysBusDevice *sbd; int i; @@ -1503,11 +1504,15 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) } /* MAL */ - mal_irqs[0] = qdev_get_gpio_in(s->uic, 11); - mal_irqs[1] = qdev_get_gpio_in(s->uic, 12); - mal_irqs[2] = qdev_get_gpio_in(s->uic, 13); - mal_irqs[3] = qdev_get_gpio_in(s->uic, 14); - ppc4xx_mal_init(env, 4, 2, mal_irqs); + object_property_set_int(OBJECT(&s->mal), "txc-num", 4, &error_abort); + object_property_set_int(OBJECT(&s->mal), "rxc-num", 2, &error_abort); + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->mal), &s->cpu, errp)) { + return; + } + sbd = SYS_BUS_DEVICE(&s->mal); + for (i = 0; i < ARRAY_SIZE(s->mal.irqs); i++) { + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(s->uic, 11 + i)); + } /* Ethernet */ /* Uses UIC IRQs 9, 15, 17 */ diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index f4d7ae9567..7d40c1b68a 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -459,32 +459,10 @@ enum { MAL0_RCBS1 = 0x1E1, }; -typedef struct ppc4xx_mal_t ppc4xx_mal_t; -struct ppc4xx_mal_t { - qemu_irq irqs[4]; - uint32_t cfg; - uint32_t esr; - uint32_t ier; - uint32_t txcasr; - uint32_t txcarr; - uint32_t txeobisr; - uint32_t txdeir; - uint32_t rxcasr; - uint32_t rxcarr; - uint32_t rxeobisr; - uint32_t rxdeir; - uint32_t *txctpr; - uint32_t *rxctpr; - uint32_t *rcbs; - uint8_t txcnum; - uint8_t rxcnum; -}; - -static void ppc4xx_mal_reset(void *opaque) +static void ppc4xx_mal_reset(DeviceState *dev) { - ppc4xx_mal_t *mal; + Ppc4xxMalState *mal = PPC4xx_MAL(dev); - mal = opaque; mal->cfg = 0x0007C000; mal->esr = 0x00000000; mal->ier = 0x00000000; @@ -498,10 +476,9 @@ static void ppc4xx_mal_reset(void *opaque) static uint32_t dcr_read_mal(void *opaque, int dcrn) { - ppc4xx_mal_t *mal; + Ppc4xxMalState *mal = opaque; uint32_t ret; - mal = opaque; switch (dcrn) { case MAL0_CFG: ret = mal->cfg; @@ -555,13 +532,12 @@ static uint32_t dcr_read_mal(void *opaque, int dcrn) static void dcr_write_mal(void *opaque, int dcrn, uint32_t val) { - ppc4xx_mal_t *mal; + Ppc4xxMalState *mal = opaque; - mal = opaque; switch (dcrn) { case MAL0_CFG: if (val & 0x80000000) { - ppc4xx_mal_reset(mal); + ppc4xx_mal_reset(DEVICE(mal)); } mal->cfg = val & 0x00FFC087; break; @@ -612,57 +588,74 @@ static void dcr_write_mal(void *opaque, int dcrn, uint32_t val) } } -void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum, - qemu_irq irqs[4]) +static void ppc4xx_mal_realize(DeviceState *dev, Error **errp) { - ppc4xx_mal_t *mal; + Ppc4xxMalState *mal = PPC4xx_MAL(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); int i; - assert(txcnum <= 32 && rxcnum <= 32); - mal = g_malloc0(sizeof(*mal)); - mal->txcnum = txcnum; - mal->rxcnum = rxcnum; - mal->txctpr = g_new0(uint32_t, txcnum); - mal->rxctpr = g_new0(uint32_t, rxcnum); - mal->rcbs = g_new0(uint32_t, rxcnum); - for (i = 0; i < 4; i++) { - mal->irqs[i] = irqs[i]; + if (mal->txcnum > 32 || mal->rxcnum > 32) { + error_setg(errp, "invalid TXC/RXC number"); + return; } - qemu_register_reset(&ppc4xx_mal_reset, mal); - ppc_dcr_register(env, MAL0_CFG, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_ESR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_IER, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCASR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXCARR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXEOBISR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_TXDEIR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCASR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXCARR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXEOBISR, - mal, &dcr_read_mal, &dcr_write_mal); - ppc_dcr_register(env, MAL0_RXDEIR, - mal, &dcr_read_mal, &dcr_write_mal); - for (i = 0; i < txcnum; i++) { - ppc_dcr_register(env, MAL0_TXCTP0R + i, - mal, &dcr_read_mal, &dcr_write_mal); + + mal->txctpr = g_new0(uint32_t, mal->txcnum); + mal->rxctpr = g_new0(uint32_t, mal->rxcnum); + mal->rcbs = g_new0(uint32_t, mal->rxcnum); + + for (i = 0; i < ARRAY_SIZE(mal->irqs); i++) { + sysbus_init_irq(SYS_BUS_DEVICE(dev), &mal->irqs[i]); } - for (i = 0; i < rxcnum; i++) { - ppc_dcr_register(env, MAL0_RXCTP0R + i, - mal, &dcr_read_mal, &dcr_write_mal); + + ppc4xx_dcr_register(dcr, MAL0_CFG, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_ESR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_IER, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_TXCASR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_TXCARR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_TXEOBISR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_TXDEIR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_RXCASR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_RXCARR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_RXEOBISR, mal, &dcr_read_mal, &dcr_write_mal); + ppc4xx_dcr_register(dcr, MAL0_RXDEIR, mal, &dcr_read_mal, &dcr_write_mal); + for (i = 0; i < mal->txcnum; i++) { + ppc4xx_dcr_register(dcr, MAL0_TXCTP0R + i, + mal, &dcr_read_mal, &dcr_write_mal); } - for (i = 0; i < rxcnum; i++) { - ppc_dcr_register(env, MAL0_RCBS0 + i, - mal, &dcr_read_mal, &dcr_write_mal); + for (i = 0; i < mal->rxcnum; i++) { + ppc4xx_dcr_register(dcr, MAL0_RXCTP0R + i, + mal, &dcr_read_mal, &dcr_write_mal); } + for (i = 0; i < mal->rxcnum; i++) { + ppc4xx_dcr_register(dcr, MAL0_RCBS0 + i, + mal, &dcr_read_mal, &dcr_write_mal); + } +} + +static void ppc4xx_mal_finalize(Object *obj) +{ + Ppc4xxMalState *mal = PPC4xx_MAL(obj); + + g_free(mal->rcbs); + g_free(mal->rxctpr); + g_free(mal->txctpr); +} + +static Property ppc4xx_mal_properties[] = { + DEFINE_PROP_UINT8("txc-num", Ppc4xxMalState, txcnum, 0), + DEFINE_PROP_UINT8("rxc-num", Ppc4xxMalState, rxcnum, 0), + DEFINE_PROP_END_OF_LIST(), +}; + +static void ppc4xx_mal_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc4xx_mal_realize; + dc->reset = ppc4xx_mal_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; + device_class_set_props(dc, ppc4xx_mal_properties); } /* PPC4xx_DCR_DEVICE */ @@ -696,6 +689,12 @@ static void ppc4xx_dcr_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc4xx_types[] = { { + .name = TYPE_PPC4xx_MAL, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc4xxMalState), + .instance_finalize = ppc4xx_mal_finalize, + .class_init = ppc4xx_mal_class_init, + }, { .name = TYPE_PPC4xx_DCR_DEVICE, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Ppc4xxDcrDeviceState), diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 31139c1554..c16303462d 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -280,7 +280,6 @@ static void sam460ex_init(MachineState *machine) hwaddr ram_sizes[SDRAM_NR_BANKS] = {0}; MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); DeviceState *uic[4]; - qemu_irq mal_irqs[4]; int i; PCIBus *pci_bus; PowerPCCPU *cpu; @@ -387,10 +386,15 @@ static void sam460ex_init(MachineState *machine) ppc4xx_sdr_init(env); /* MAL */ - for (i = 0; i < ARRAY_SIZE(mal_irqs); i++) { - mal_irqs[i] = qdev_get_gpio_in(uic[2], 3 + i); + dev = qdev_new(TYPE_PPC4xx_MAL); + qdev_prop_set_uint32(dev, "txc-num", 4); + qdev_prop_set_uint32(dev, "rxc-num", 16); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); + object_unref(OBJECT(dev)); + sbdev = SYS_BUS_DEVICE(dev); + for (i = 0; i < ARRAY_SIZE(PPC4xx_MAL(dev)->irqs); i++) { + sysbus_connect_irq(sbdev, i, qdev_get_gpio_in(uic[2], 3 + i)); } - ppc4xx_mal_init(env, 4, 16, mal_irqs); /* DMA */ ppc4xx_dma_init(env, 0x200); diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index a537a5567b..f40bd49bc7 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -40,9 +40,6 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, hwaddr *ram_sizes, int do_init); -void ppc4xx_mal_init(CPUPPCState *env, uint8_t txcnum, uint8_t rxcnum, - qemu_irq irqs[4]); - #define TYPE_PPC4xx_PCI_HOST_BRIDGE "ppc4xx-pcihost" /* @@ -61,4 +58,29 @@ void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, bool ppc4xx_dcr_realize(Ppc4xxDcrDeviceState *dev, PowerPCCPU *cpu, Error **errp); +/* Memory Access Layer (MAL) */ +#define TYPE_PPC4xx_MAL "ppc4xx-mal" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxMalState, PPC4xx_MAL); +struct Ppc4xxMalState { + Ppc4xxDcrDeviceState parent_obj; + + qemu_irq irqs[4]; + uint32_t cfg; + uint32_t esr; + uint32_t ier; + uint32_t txcasr; + uint32_t txcarr; + uint32_t txeobisr; + uint32_t txdeir; + uint32_t rxcasr; + uint32_t rxcarr; + uint32_t rxeobisr; + uint32_t rxdeir; + uint32_t *txctpr; + uint32_t *rxctpr; + uint32_t *rcbs; + uint8_t txcnum; + uint8_t rxcnum; +}; + #endif /* PPC4XX_H */ From 2d54aaf121d7a94a57b05059b15e9cbe670734a2 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 17:08:30 +0200 Subject: [PATCH 0249/1020] ppc4xx: Move PLB model to ppc4xx_devs.c The PLB is shared between 405 and 440 so move it to the shared file. Reviewed-by: Daniel Henrique Barboza Signed-off-by: BALATON Zoltan Message-Id: <2498384bf3e18959ee8cb984d72fb66b8a6ecadc.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 11 ----- hw/ppc/ppc405_uc.c | 93 ---------------------------------------- hw/ppc/ppc4xx_devs.c | 94 +++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/ppc4xx.h | 11 +++++ 4 files changed, 105 insertions(+), 104 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 31c94e4742..d85c595f9d 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -63,17 +63,6 @@ struct ppc4xx_bd_info_t { uint32_t bi_iic_fast[2]; }; -/* Peripheral local bus arbitrer */ -#define TYPE_PPC405_PLB "ppc405-plb" -OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PlbState, PPC405_PLB); -struct Ppc405PlbState { - Ppc4xxDcrDeviceState parent_obj; - - uint32_t acr; - uint32_t bear; - uint32_t besr; -}; - /* PLB to OPB bridge */ #define TYPE_PPC405_POB "ppc405-pob" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PobState, PPC405_POB); diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index b02dab05b3..3382ed3252 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -137,94 +137,6 @@ ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size) /*****************************************************************************/ /* Shared peripherals */ -/*****************************************************************************/ -/* Peripheral local bus arbitrer */ -enum { - PLB3A0_ACR = 0x077, - PLB4A0_ACR = 0x081, - PLB0_BESR = 0x084, - PLB0_BEAR = 0x086, - PLB0_ACR = 0x087, - PLB4A1_ACR = 0x089, -}; - -static uint32_t dcr_read_plb(void *opaque, int dcrn) -{ - Ppc405PlbState *plb = opaque; - uint32_t ret; - - switch (dcrn) { - case PLB0_ACR: - ret = plb->acr; - break; - case PLB0_BEAR: - ret = plb->bear; - break; - case PLB0_BESR: - ret = plb->besr; - break; - default: - /* Avoid gcc warning */ - ret = 0; - break; - } - - return ret; -} - -static void dcr_write_plb(void *opaque, int dcrn, uint32_t val) -{ - Ppc405PlbState *plb = opaque; - - switch (dcrn) { - case PLB0_ACR: - /* We don't care about the actual parameters written as - * we don't manage any priorities on the bus - */ - plb->acr = val & 0xF8000000; - break; - case PLB0_BEAR: - /* Read only */ - break; - case PLB0_BESR: - /* Write-clear */ - plb->besr &= ~val; - break; - } -} - -static void ppc405_plb_reset(DeviceState *dev) -{ - Ppc405PlbState *plb = PPC405_PLB(dev); - - plb->acr = 0x00000000; - plb->bear = 0x00000000; - plb->besr = 0x00000000; -} - -static void ppc405_plb_realize(DeviceState *dev, Error **errp) -{ - Ppc405PlbState *plb = PPC405_PLB(dev); - Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - - ppc4xx_dcr_register(dcr, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc4xx_dcr_register(dcr, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc4xx_dcr_register(dcr, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); - ppc4xx_dcr_register(dcr, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); - ppc4xx_dcr_register(dcr, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); - ppc4xx_dcr_register(dcr, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb); -} - -static void ppc405_plb_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - dc->realize = ppc405_plb_realize; - dc->reset = ppc405_plb_reset; - /* Reason: only works as function of a ppc4xx SoC */ - dc->user_creatable = false; -} - /*****************************************************************************/ /* PLB to OPB bridge */ enum { @@ -1538,11 +1450,6 @@ static void ppc405_soc_class_init(ObjectClass *oc, void *data) static const TypeInfo ppc405_types[] = { { - .name = TYPE_PPC405_PLB, - .parent = TYPE_PPC4xx_DCR_DEVICE, - .instance_size = sizeof(Ppc405PlbState), - .class_init = ppc405_plb_class_init, - }, { .name = TYPE_PPC405_POB, .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(Ppc405PobState), diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 7d40c1b68a..843d759b1b 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -658,6 +658,95 @@ static void ppc4xx_mal_class_init(ObjectClass *oc, void *data) device_class_set_props(dc, ppc4xx_mal_properties); } +/*****************************************************************************/ +/* Peripheral local bus arbitrer */ +enum { + PLB3A0_ACR = 0x077, + PLB4A0_ACR = 0x081, + PLB0_BESR = 0x084, + PLB0_BEAR = 0x086, + PLB0_ACR = 0x087, + PLB4A1_ACR = 0x089, +}; + +static uint32_t dcr_read_plb(void *opaque, int dcrn) +{ + Ppc405PlbState *plb = opaque; + uint32_t ret; + + switch (dcrn) { + case PLB0_ACR: + ret = plb->acr; + break; + case PLB0_BEAR: + ret = plb->bear; + break; + case PLB0_BESR: + ret = plb->besr; + break; + default: + /* Avoid gcc warning */ + ret = 0; + break; + } + + return ret; +} + +static void dcr_write_plb(void *opaque, int dcrn, uint32_t val) +{ + Ppc405PlbState *plb = opaque; + + switch (dcrn) { + case PLB0_ACR: + /* + * We don't care about the actual parameters written as + * we don't manage any priorities on the bus + */ + plb->acr = val & 0xF8000000; + break; + case PLB0_BEAR: + /* Read only */ + break; + case PLB0_BESR: + /* Write-clear */ + plb->besr &= ~val; + break; + } +} + +static void ppc405_plb_reset(DeviceState *dev) +{ + Ppc405PlbState *plb = PPC405_PLB(dev); + + plb->acr = 0x00000000; + plb->bear = 0x00000000; + plb->besr = 0x00000000; +} + +static void ppc405_plb_realize(DeviceState *dev, Error **errp) +{ + Ppc405PlbState *plb = PPC405_PLB(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); + + ppc4xx_dcr_register(dcr, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB4A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_ACR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_BEAR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB0_BESR, plb, &dcr_read_plb, &dcr_write_plb); + ppc4xx_dcr_register(dcr, PLB4A1_ACR, plb, &dcr_read_plb, &dcr_write_plb); +} + +static void ppc405_plb_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_plb_realize; + dc->reset = ppc405_plb_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; +} + /* PPC4xx_DCR_DEVICE */ void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, @@ -694,6 +783,11 @@ static const TypeInfo ppc4xx_types[] = { .instance_size = sizeof(Ppc4xxMalState), .instance_finalize = ppc4xx_mal_finalize, .class_init = ppc4xx_mal_class_init, + }, { + .name = TYPE_PPC405_PLB, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405PlbState), + .class_init = ppc405_plb_class_init, }, { .name = TYPE_PPC4xx_DCR_DEVICE, .parent = TYPE_SYS_BUS_DEVICE, diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index f40bd49bc7..e696e159f3 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -83,4 +83,15 @@ struct Ppc4xxMalState { uint8_t rxcnum; }; +/* Peripheral local bus arbitrer */ +#define TYPE_PPC405_PLB "ppc405-plb" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PlbState, PPC405_PLB); +struct Ppc405PlbState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t acr; + uint32_t bear; + uint32_t besr; +}; + #endif /* PPC4XX_H */ From 052c779b4c2c08e07b77046e9acfbe30de2c3562 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 17:08:31 +0200 Subject: [PATCH 0250/1020] ppc4xx: Rename ppc405-plb to ppc4xx-plb This device is shared between different 4xx socs. Reviewed-by: Daniel Henrique Barboza Signed-off-by: BALATON Zoltan Message-Id: <5b13ebfd12a71a28035bed5a915cbeee81cf21d1.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 2 +- hw/ppc/ppc405_uc.c | 2 +- hw/ppc/ppc4xx_devs.c | 12 ++++++------ hw/ppc/sam460ex.c | 2 +- include/hw/ppc/ppc4xx.h | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index d85c595f9d..8521be317d 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -232,7 +232,7 @@ struct Ppc405SoCState { Ppc405EbcState ebc; Ppc405OpbaState opba; Ppc405PobState pob; - Ppc405PlbState plb; + Ppc4xxPlbState plb; Ppc4xxMalState mal; }; diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 3382ed3252..b7f6d1c9c1 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1286,7 +1286,7 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "pob", &s->pob, TYPE_PPC405_POB); - object_initialize_child(obj, "plb", &s->plb, TYPE_PPC405_PLB); + object_initialize_child(obj, "plb", &s->plb, TYPE_PPC4xx_PLB); object_initialize_child(obj, "mal", &s->mal, TYPE_PPC4xx_MAL); } diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 843d759b1b..3baa2fa2b3 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -671,7 +671,7 @@ enum { static uint32_t dcr_read_plb(void *opaque, int dcrn) { - Ppc405PlbState *plb = opaque; + Ppc4xxPlbState *plb = opaque; uint32_t ret; switch (dcrn) { @@ -695,7 +695,7 @@ static uint32_t dcr_read_plb(void *opaque, int dcrn) static void dcr_write_plb(void *opaque, int dcrn, uint32_t val) { - Ppc405PlbState *plb = opaque; + Ppc4xxPlbState *plb = opaque; switch (dcrn) { case PLB0_ACR: @@ -717,7 +717,7 @@ static void dcr_write_plb(void *opaque, int dcrn, uint32_t val) static void ppc405_plb_reset(DeviceState *dev) { - Ppc405PlbState *plb = PPC405_PLB(dev); + Ppc4xxPlbState *plb = PPC4xx_PLB(dev); plb->acr = 0x00000000; plb->bear = 0x00000000; @@ -726,7 +726,7 @@ static void ppc405_plb_reset(DeviceState *dev) static void ppc405_plb_realize(DeviceState *dev, Error **errp) { - Ppc405PlbState *plb = PPC405_PLB(dev); + Ppc4xxPlbState *plb = PPC4xx_PLB(dev); Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); ppc4xx_dcr_register(dcr, PLB3A0_ACR, plb, &dcr_read_plb, &dcr_write_plb); @@ -784,9 +784,9 @@ static const TypeInfo ppc4xx_types[] = { .instance_finalize = ppc4xx_mal_finalize, .class_init = ppc4xx_mal_class_init, }, { - .name = TYPE_PPC405_PLB, + .name = TYPE_PPC4xx_PLB, .parent = TYPE_PPC4xx_DCR_DEVICE, - .instance_size = sizeof(Ppc405PlbState), + .instance_size = sizeof(Ppc4xxPlbState), .class_init = ppc405_plb_class_init, }, { .name = TYPE_PPC4xx_DCR_DEVICE, diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index c16303462d..6b1c843eeb 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -308,7 +308,7 @@ static void sam460ex_init(MachineState *machine) ppc_dcr_init(env, NULL, NULL); /* PLB arbitrer */ - dev = qdev_new(TYPE_PPC405_PLB); + dev = qdev_new(TYPE_PPC4xx_PLB); ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); object_unref(OBJECT(dev)); diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index e696e159f3..b19e59271b 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -84,9 +84,9 @@ struct Ppc4xxMalState { }; /* Peripheral local bus arbitrer */ -#define TYPE_PPC405_PLB "ppc405-plb" -OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PlbState, PPC405_PLB); -struct Ppc405PlbState { +#define TYPE_PPC4xx_PLB "ppc4xx-plb" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxPlbState, PPC4xx_PLB); +struct Ppc4xxPlbState { Ppc4xxDcrDeviceState parent_obj; uint32_t acr; From 127ba8d03e270fcbb5d71ea7a90609680803027d Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 17:08:32 +0200 Subject: [PATCH 0251/1020] ppc4xx: Move EBC model to ppc4xx_devs.c The EBC is shared between 405 and 440 so move it to shared file. Reviewed-by: Daniel Henrique Barboza Signed-off-by: BALATON Zoltan Message-Id: <10eae70509ca4bd74858fc2c0a0f0e4eb9330199.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 15 ---- hw/ppc/ppc405_uc.c | 191 ---------------------------------------- hw/ppc/ppc4xx_devs.c | 191 ++++++++++++++++++++++++++++++++++++++++ include/hw/ppc/ppc4xx.h | 15 ++++ 4 files changed, 206 insertions(+), 206 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 8521be317d..57e1494b05 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -85,21 +85,6 @@ struct Ppc405OpbaState { uint8_t pr; }; -/* Peripheral controller */ -#define TYPE_PPC405_EBC "ppc405-ebc" -OBJECT_DECLARE_SIMPLE_TYPE(Ppc405EbcState, PPC405_EBC); -struct Ppc405EbcState { - Ppc4xxDcrDeviceState parent_obj; - - uint32_t addr; - uint32_t bcr[8]; - uint32_t bap[8]; - uint32_t bear; - uint32_t besr0; - uint32_t besr1; - uint32_t cfg; -}; - /* DMA controller */ #define TYPE_PPC405_DMA "ppc405-dma" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405DmaState, PPC405_DMA); diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index b7f6d1c9c1..c7bc40ba08 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -299,192 +299,6 @@ static void ppc405_opba_class_init(ObjectClass *oc, void *data) /* Code decompression controller */ /* XXX: TODO */ -/*****************************************************************************/ -/* Peripheral controller */ -enum { - EBC0_CFGADDR = 0x012, - EBC0_CFGDATA = 0x013, -}; - -static uint32_t dcr_read_ebc(void *opaque, int dcrn) -{ - Ppc405EbcState *ebc = opaque; - uint32_t ret; - - switch (dcrn) { - case EBC0_CFGADDR: - ret = ebc->addr; - break; - case EBC0_CFGDATA: - switch (ebc->addr) { - case 0x00: /* B0CR */ - ret = ebc->bcr[0]; - break; - case 0x01: /* B1CR */ - ret = ebc->bcr[1]; - break; - case 0x02: /* B2CR */ - ret = ebc->bcr[2]; - break; - case 0x03: /* B3CR */ - ret = ebc->bcr[3]; - break; - case 0x04: /* B4CR */ - ret = ebc->bcr[4]; - break; - case 0x05: /* B5CR */ - ret = ebc->bcr[5]; - break; - case 0x06: /* B6CR */ - ret = ebc->bcr[6]; - break; - case 0x07: /* B7CR */ - ret = ebc->bcr[7]; - break; - case 0x10: /* B0AP */ - ret = ebc->bap[0]; - break; - case 0x11: /* B1AP */ - ret = ebc->bap[1]; - break; - case 0x12: /* B2AP */ - ret = ebc->bap[2]; - break; - case 0x13: /* B3AP */ - ret = ebc->bap[3]; - break; - case 0x14: /* B4AP */ - ret = ebc->bap[4]; - break; - case 0x15: /* B5AP */ - ret = ebc->bap[5]; - break; - case 0x16: /* B6AP */ - ret = ebc->bap[6]; - break; - case 0x17: /* B7AP */ - ret = ebc->bap[7]; - break; - case 0x20: /* BEAR */ - ret = ebc->bear; - break; - case 0x21: /* BESR0 */ - ret = ebc->besr0; - break; - case 0x22: /* BESR1 */ - ret = ebc->besr1; - break; - case 0x23: /* CFG */ - ret = ebc->cfg; - break; - default: - ret = 0x00000000; - break; - } - break; - default: - ret = 0x00000000; - break; - } - - return ret; -} - -static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val) -{ - Ppc405EbcState *ebc = opaque; - - switch (dcrn) { - case EBC0_CFGADDR: - ebc->addr = val; - break; - case EBC0_CFGDATA: - switch (ebc->addr) { - case 0x00: /* B0CR */ - break; - case 0x01: /* B1CR */ - break; - case 0x02: /* B2CR */ - break; - case 0x03: /* B3CR */ - break; - case 0x04: /* B4CR */ - break; - case 0x05: /* B5CR */ - break; - case 0x06: /* B6CR */ - break; - case 0x07: /* B7CR */ - break; - case 0x10: /* B0AP */ - break; - case 0x11: /* B1AP */ - break; - case 0x12: /* B2AP */ - break; - case 0x13: /* B3AP */ - break; - case 0x14: /* B4AP */ - break; - case 0x15: /* B5AP */ - break; - case 0x16: /* B6AP */ - break; - case 0x17: /* B7AP */ - break; - case 0x20: /* BEAR */ - break; - case 0x21: /* BESR0 */ - break; - case 0x22: /* BESR1 */ - break; - case 0x23: /* CFG */ - break; - default: - break; - } - break; - default: - break; - } -} - -static void ppc405_ebc_reset(DeviceState *dev) -{ - Ppc405EbcState *ebc = PPC405_EBC(dev); - int i; - - ebc->addr = 0x00000000; - ebc->bap[0] = 0x7F8FFE80; - ebc->bcr[0] = 0xFFE28000; - for (i = 0; i < 8; i++) { - ebc->bap[i] = 0x00000000; - ebc->bcr[i] = 0x00000000; - } - ebc->besr0 = 0x00000000; - ebc->besr1 = 0x00000000; - ebc->cfg = 0x80400000; -} - -static void ppc405_ebc_realize(DeviceState *dev, Error **errp) -{ - Ppc405EbcState *ebc = PPC405_EBC(dev); - Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); - - ppc4xx_dcr_register(dcr, EBC0_CFGADDR, ebc, &dcr_read_ebc, &dcr_write_ebc); - ppc4xx_dcr_register(dcr, EBC0_CFGDATA, ebc, &dcr_read_ebc, &dcr_write_ebc); -} - -static void ppc405_ebc_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - dc->realize = ppc405_ebc_realize; - dc->reset = ppc405_ebc_reset; - /* Reason: only works as function of a ppc4xx SoC */ - dc->user_creatable = false; -} - /*****************************************************************************/ /* DMA controller */ enum { @@ -1459,11 +1273,6 @@ static const TypeInfo ppc405_types[] = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(Ppc405OpbaState), .class_init = ppc405_opba_class_init, - }, { - .name = TYPE_PPC405_EBC, - .parent = TYPE_PPC4xx_DCR_DEVICE, - .instance_size = sizeof(Ppc405EbcState), - .class_init = ppc405_ebc_class_init, }, { .name = TYPE_PPC405_DMA, .parent = TYPE_PPC4xx_DCR_DEVICE, diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 3baa2fa2b3..00bb3fe974 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -747,6 +747,192 @@ static void ppc405_plb_class_init(ObjectClass *oc, void *data) dc->user_creatable = false; } +/*****************************************************************************/ +/* Peripheral controller */ +enum { + EBC0_CFGADDR = 0x012, + EBC0_CFGDATA = 0x013, +}; + +static uint32_t dcr_read_ebc(void *opaque, int dcrn) +{ + Ppc405EbcState *ebc = opaque; + uint32_t ret; + + switch (dcrn) { + case EBC0_CFGADDR: + ret = ebc->addr; + break; + case EBC0_CFGDATA: + switch (ebc->addr) { + case 0x00: /* B0CR */ + ret = ebc->bcr[0]; + break; + case 0x01: /* B1CR */ + ret = ebc->bcr[1]; + break; + case 0x02: /* B2CR */ + ret = ebc->bcr[2]; + break; + case 0x03: /* B3CR */ + ret = ebc->bcr[3]; + break; + case 0x04: /* B4CR */ + ret = ebc->bcr[4]; + break; + case 0x05: /* B5CR */ + ret = ebc->bcr[5]; + break; + case 0x06: /* B6CR */ + ret = ebc->bcr[6]; + break; + case 0x07: /* B7CR */ + ret = ebc->bcr[7]; + break; + case 0x10: /* B0AP */ + ret = ebc->bap[0]; + break; + case 0x11: /* B1AP */ + ret = ebc->bap[1]; + break; + case 0x12: /* B2AP */ + ret = ebc->bap[2]; + break; + case 0x13: /* B3AP */ + ret = ebc->bap[3]; + break; + case 0x14: /* B4AP */ + ret = ebc->bap[4]; + break; + case 0x15: /* B5AP */ + ret = ebc->bap[5]; + break; + case 0x16: /* B6AP */ + ret = ebc->bap[6]; + break; + case 0x17: /* B7AP */ + ret = ebc->bap[7]; + break; + case 0x20: /* BEAR */ + ret = ebc->bear; + break; + case 0x21: /* BESR0 */ + ret = ebc->besr0; + break; + case 0x22: /* BESR1 */ + ret = ebc->besr1; + break; + case 0x23: /* CFG */ + ret = ebc->cfg; + break; + default: + ret = 0x00000000; + break; + } + break; + default: + ret = 0x00000000; + break; + } + + return ret; +} + +static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val) +{ + Ppc405EbcState *ebc = opaque; + + switch (dcrn) { + case EBC0_CFGADDR: + ebc->addr = val; + break; + case EBC0_CFGDATA: + switch (ebc->addr) { + case 0x00: /* B0CR */ + break; + case 0x01: /* B1CR */ + break; + case 0x02: /* B2CR */ + break; + case 0x03: /* B3CR */ + break; + case 0x04: /* B4CR */ + break; + case 0x05: /* B5CR */ + break; + case 0x06: /* B6CR */ + break; + case 0x07: /* B7CR */ + break; + case 0x10: /* B0AP */ + break; + case 0x11: /* B1AP */ + break; + case 0x12: /* B2AP */ + break; + case 0x13: /* B3AP */ + break; + case 0x14: /* B4AP */ + break; + case 0x15: /* B5AP */ + break; + case 0x16: /* B6AP */ + break; + case 0x17: /* B7AP */ + break; + case 0x20: /* BEAR */ + break; + case 0x21: /* BESR0 */ + break; + case 0x22: /* BESR1 */ + break; + case 0x23: /* CFG */ + break; + default: + break; + } + break; + default: + break; + } +} + +static void ppc405_ebc_reset(DeviceState *dev) +{ + Ppc405EbcState *ebc = PPC405_EBC(dev); + int i; + + ebc->addr = 0x00000000; + ebc->bap[0] = 0x7F8FFE80; + ebc->bcr[0] = 0xFFE28000; + for (i = 0; i < 8; i++) { + ebc->bap[i] = 0x00000000; + ebc->bcr[i] = 0x00000000; + } + ebc->besr0 = 0x00000000; + ebc->besr1 = 0x00000000; + ebc->cfg = 0x80400000; +} + +static void ppc405_ebc_realize(DeviceState *dev, Error **errp) +{ + Ppc405EbcState *ebc = PPC405_EBC(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); + + ppc4xx_dcr_register(dcr, EBC0_CFGADDR, ebc, &dcr_read_ebc, &dcr_write_ebc); + ppc4xx_dcr_register(dcr, EBC0_CFGDATA, ebc, &dcr_read_ebc, &dcr_write_ebc); +} + +static void ppc405_ebc_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ppc405_ebc_realize; + dc->reset = ppc405_ebc_reset; + /* Reason: only works as function of a ppc4xx SoC */ + dc->user_creatable = false; +} + /* PPC4xx_DCR_DEVICE */ void ppc4xx_dcr_register(Ppc4xxDcrDeviceState *dev, int dcrn, void *opaque, @@ -788,6 +974,11 @@ static const TypeInfo ppc4xx_types[] = { .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(Ppc4xxPlbState), .class_init = ppc405_plb_class_init, + }, { + .name = TYPE_PPC405_EBC, + .parent = TYPE_PPC4xx_DCR_DEVICE, + .instance_size = sizeof(Ppc405EbcState), + .class_init = ppc405_ebc_class_init, }, { .name = TYPE_PPC4xx_DCR_DEVICE, .parent = TYPE_SYS_BUS_DEVICE, diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index b19e59271b..4472ec254e 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -94,4 +94,19 @@ struct Ppc4xxPlbState { uint32_t besr; }; +/* Peripheral controller */ +#define TYPE_PPC405_EBC "ppc405-ebc" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc405EbcState, PPC405_EBC); +struct Ppc405EbcState { + Ppc4xxDcrDeviceState parent_obj; + + uint32_t addr; + uint32_t bcr[8]; + uint32_t bap[8]; + uint32_t bear; + uint32_t besr0; + uint32_t besr1; + uint32_t cfg; +}; + #endif /* PPC4XX_H */ From cba58aa7629b94d6938dcac1fd5443f51daee2c9 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 17:08:33 +0200 Subject: [PATCH 0252/1020] ppc4xx: Rename ppc405-ebc to ppc4xx-ebc This device is shared between different 4xx socs. Reviewed-by: Daniel Henrique Barboza Signed-off-by: BALATON Zoltan Message-Id: <63d9b14c8ff5f73e35bffca1036394b5235735ee.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 2 +- hw/ppc/ppc405_uc.c | 2 +- hw/ppc/ppc4xx_devs.c | 12 ++++++------ hw/ppc/sam460ex.c | 2 +- include/hw/ppc/ppc4xx.h | 6 +++--- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 57e1494b05..343a84c98e 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -214,7 +214,7 @@ struct Ppc405SoCState { Ppc405OcmState ocm; Ppc405GpioState gpio; Ppc405DmaState dma; - Ppc405EbcState ebc; + Ppc4xxEbcState ebc; Ppc405OpbaState opba; Ppc405PobState pob; Ppc4xxPlbState plb; diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index c7bc40ba08..247c4f3fa8 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1094,7 +1094,7 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "dma", &s->dma, TYPE_PPC405_DMA); - object_initialize_child(obj, "ebc", &s->ebc, TYPE_PPC405_EBC); + object_initialize_child(obj, "ebc", &s->ebc, TYPE_PPC4xx_EBC); object_initialize_child(obj, "opba", &s->opba, TYPE_PPC405_OPBA); diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 00bb3fe974..fbfb21c8e8 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -756,7 +756,7 @@ enum { static uint32_t dcr_read_ebc(void *opaque, int dcrn) { - Ppc405EbcState *ebc = opaque; + Ppc4xxEbcState *ebc = opaque; uint32_t ret; switch (dcrn) { @@ -840,7 +840,7 @@ static uint32_t dcr_read_ebc(void *opaque, int dcrn) static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val) { - Ppc405EbcState *ebc = opaque; + Ppc4xxEbcState *ebc = opaque; switch (dcrn) { case EBC0_CFGADDR: @@ -899,7 +899,7 @@ static void dcr_write_ebc(void *opaque, int dcrn, uint32_t val) static void ppc405_ebc_reset(DeviceState *dev) { - Ppc405EbcState *ebc = PPC405_EBC(dev); + Ppc4xxEbcState *ebc = PPC4xx_EBC(dev); int i; ebc->addr = 0x00000000; @@ -916,7 +916,7 @@ static void ppc405_ebc_reset(DeviceState *dev) static void ppc405_ebc_realize(DeviceState *dev, Error **errp) { - Ppc405EbcState *ebc = PPC405_EBC(dev); + Ppc4xxEbcState *ebc = PPC4xx_EBC(dev); Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); ppc4xx_dcr_register(dcr, EBC0_CFGADDR, ebc, &dcr_read_ebc, &dcr_write_ebc); @@ -975,9 +975,9 @@ static const TypeInfo ppc4xx_types[] = { .instance_size = sizeof(Ppc4xxPlbState), .class_init = ppc405_plb_class_init, }, { - .name = TYPE_PPC405_EBC, + .name = TYPE_PPC4xx_EBC, .parent = TYPE_PPC4xx_DCR_DEVICE, - .instance_size = sizeof(Ppc405EbcState), + .instance_size = sizeof(Ppc4xxEbcState), .class_init = ppc405_ebc_class_init, }, { .name = TYPE_PPC4xx_DCR_DEVICE, diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 6b1c843eeb..0d9259f0f2 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -372,7 +372,7 @@ static void sam460ex_init(MachineState *machine) qdev_get_gpio_in(uic[0], 3)); /* External bus controller */ - dev = qdev_new(TYPE_PPC405_EBC); + dev = qdev_new(TYPE_PPC4xx_EBC); ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(dev), cpu, &error_fatal); object_unref(OBJECT(dev)); diff --git a/include/hw/ppc/ppc4xx.h b/include/hw/ppc/ppc4xx.h index 4472ec254e..a1781afa8e 100644 --- a/include/hw/ppc/ppc4xx.h +++ b/include/hw/ppc/ppc4xx.h @@ -95,9 +95,9 @@ struct Ppc4xxPlbState { }; /* Peripheral controller */ -#define TYPE_PPC405_EBC "ppc405-ebc" -OBJECT_DECLARE_SIMPLE_TYPE(Ppc405EbcState, PPC405_EBC); -struct Ppc405EbcState { +#define TYPE_PPC4xx_EBC "ppc4xx-ebc" +OBJECT_DECLARE_SIMPLE_TYPE(Ppc4xxEbcState, PPC4xx_EBC); +struct Ppc4xxEbcState { Ppc4xxDcrDeviceState parent_obj; uint32_t addr; From e9d20f37175bc89d8bca37304404f118918a9911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:34 +0200 Subject: [PATCH 0253/1020] ppc/ppc405: Use an embedded PPCUIC model in SoC state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: Simplify sysbus device casts for readability] Signed-off-by: BALATON Zoltan Message-Id: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 3 ++- hw/ppc/ppc405_uc.c | 28 ++++++++++++++-------------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 343a84c98e..67f4c14f50 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -27,6 +27,7 @@ #include "qom/object.h" #include "hw/ppc/ppc4xx.h" +#include "hw/intc/ppc-uic.h" #define PPC405EP_SDRAM_BASE 0x00000000 #define PPC405EP_NVRAM_BASE 0xF0000000 @@ -208,7 +209,7 @@ struct Ppc405SoCState { hwaddr ram_size; PowerPCCPU cpu; - DeviceState *uic; + PPCUIC uic; Ppc405CpcState cpc; Ppc405GptState gpt; Ppc405OcmState ocm; diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 247c4f3fa8..47bb9f534a 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1083,6 +1083,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "cpu", &s->cpu, POWERPC_CPU_TYPE_NAME("405ep")); + object_initialize_child(obj, "uic", &s->uic, TYPE_PPC_UIC); + object_initialize_child(obj, "cpc", &s->cpc, TYPE_PPC405_CPC); object_property_add_alias(obj, "sys-clk", OBJECT(&s->cpc), "sys-clk"); @@ -1150,17 +1152,15 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(sbd, 0, 0xef600600); /* Universal interrupt controller */ - s->uic = qdev_new(TYPE_PPC_UIC); - - object_property_set_link(OBJECT(s->uic), "cpu", OBJECT(&s->cpu), + object_property_set_link(OBJECT(&s->uic), "cpu", OBJECT(&s->cpu), &error_fatal); - if (!sysbus_realize(SYS_BUS_DEVICE(s->uic), errp)) { + sbd = SYS_BUS_DEVICE(&s->uic); + if (!sysbus_realize(sbd, errp)) { return; } - - sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_INT, + sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_INT)); - sysbus_connect_irq(SYS_BUS_DEVICE(s->uic), PPCUIC_OUTPUT_CINT, + sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_CINT)); /* SDRAM controller */ @@ -1171,7 +1171,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) "ppc405.sdram0", s->dram_mr, s->ram_bases[0], s->ram_sizes[0]); - ppc4xx_sdram_init(env, qdev_get_gpio_in(s->uic, 17), 1, + ppc4xx_sdram_init(env, qdev_get_gpio_in(DEVICE(&s->uic), 17), 1, s->ram_banks, s->ram_bases, s->ram_sizes, s->do_dram_init); @@ -1186,12 +1186,12 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) } sbd = SYS_BUS_DEVICE(&s->dma); for (i = 0; i < ARRAY_SIZE(s->dma.irqs); i++) { - sysbus_connect_irq(sbd, i, qdev_get_gpio_in(s->uic, 5 + i)); + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(DEVICE(&s->uic), 5 + i)); } /* I2C controller */ sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, - qdev_get_gpio_in(s->uic, 2)); + qdev_get_gpio_in(DEVICE(&s->uic), 2)); /* GPIO */ sbd = SYS_BUS_DEVICE(&s->gpio); @@ -1203,13 +1203,13 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) /* Serial ports */ if (serial_hd(0) != NULL) { serial_mm_init(get_system_memory(), 0xef600300, 0, - qdev_get_gpio_in(s->uic, 0), + qdev_get_gpio_in(DEVICE(&s->uic), 0), PPC_SERIAL_MM_BAUDBASE, serial_hd(0), DEVICE_BIG_ENDIAN); } if (serial_hd(1) != NULL) { serial_mm_init(get_system_memory(), 0xef600400, 0, - qdev_get_gpio_in(s->uic, 1), + qdev_get_gpio_in(DEVICE(&s->uic), 1), PPC_SERIAL_MM_BAUDBASE, serial_hd(1), DEVICE_BIG_ENDIAN); } @@ -1226,7 +1226,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) } sysbus_mmio_map(sbd, 0, 0xef600000); for (i = 0; i < ARRAY_SIZE(s->gpt.irqs); i++) { - sysbus_connect_irq(sbd, i, qdev_get_gpio_in(s->uic, 19 + i)); + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(DEVICE(&s->uic), 19 + i)); } /* MAL */ @@ -1237,7 +1237,7 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) } sbd = SYS_BUS_DEVICE(&s->mal); for (i = 0; i < ARRAY_SIZE(s->mal.irqs); i++) { - sysbus_connect_irq(sbd, i, qdev_get_gpio_in(s->uic, 11 + i)); + sysbus_connect_irq(sbd, i, qdev_get_gpio_in(DEVICE(&s->uic), 11 + i)); } /* Ethernet */ From a55b213646d8a62515912490d259cf84d2f9e168 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 17:08:35 +0200 Subject: [PATCH 0254/1020] hw/intc/ppc-uic: Convert ppc-uic to a PPC4xx DCR device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make ppc-uic a subclass of ppc4xx-dcr-device which will handle the cpu link and make it uniform with the other PPC4xx devices. Signed-off-by: BALATON Zoltan Reviewed-by: Cédric Le Goater Message-Id: Signed-off-by: Daniel Henrique Barboza --- hw/intc/ppc-uic.c | 26 ++++++-------------------- hw/ppc/ppc405_uc.c | 6 ++---- hw/ppc/ppc440_bamboo.c | 7 ++----- hw/ppc/ppc4xx_devs.c | 1 - hw/ppc/sam460ex.c | 17 +++++++---------- hw/ppc/virtex_ml507.c | 7 ++----- include/hw/intc/ppc-uic.h | 6 ++---- 7 files changed, 21 insertions(+), 49 deletions(-) diff --git a/hw/intc/ppc-uic.c b/hw/intc/ppc-uic.c index 60013f2dde..dcf5de5d43 100644 --- a/hw/intc/ppc-uic.c +++ b/hw/intc/ppc-uic.c @@ -25,11 +25,8 @@ #include "qemu/osdep.h" #include "hw/intc/ppc-uic.h" #include "hw/irq.h" -#include "cpu.h" -#include "hw/ppc/ppc.h" #include "hw/qdev-properties.h" #include "migration/vmstate.h" -#include "qapi/error.h" enum { DCR_UICSR = 0x000, @@ -105,10 +102,9 @@ static void ppcuic_trigger_irq(PPCUIC *uic) static void ppcuic_set_irq(void *opaque, int irq_num, int level) { - PPCUIC *uic; + PPCUIC *uic = opaque; uint32_t mask, sr; - uic = opaque; mask = 1U << (31 - irq_num); LOG_UIC("%s: irq %d level %d uicsr %08" PRIx32 " mask %08" PRIx32 " => %08" PRIx32 " %08" PRIx32 "\n", @@ -144,10 +140,9 @@ static void ppcuic_set_irq(void *opaque, int irq_num, int level) static uint32_t dcr_read_uic(void *opaque, int dcrn) { - PPCUIC *uic; + PPCUIC *uic = opaque; uint32_t ret; - uic = opaque; dcrn -= uic->dcr_base; switch (dcrn) { case DCR_UICSR: @@ -192,9 +187,8 @@ static uint32_t dcr_read_uic(void *opaque, int dcrn) static void dcr_write_uic(void *opaque, int dcrn, uint32_t val) { - PPCUIC *uic; + PPCUIC *uic = opaque; - uic = opaque; dcrn -= uic->dcr_base; LOG_UIC("%s: dcr %d val 0x%x\n", __func__, dcrn, val); switch (dcrn) { @@ -251,19 +245,12 @@ static void ppc_uic_reset(DeviceState *dev) static void ppc_uic_realize(DeviceState *dev, Error **errp) { PPCUIC *uic = PPC_UIC(dev); + Ppc4xxDcrDeviceState *dcr = PPC4xx_DCR_DEVICE(dev); SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - PowerPCCPU *cpu; int i; - if (!uic->cpu) { - /* This is a programming error in the code using this device */ - error_setg(errp, "ppc-uic 'cpu' link property was not set"); - return; - } - - cpu = POWERPC_CPU(uic->cpu); for (i = 0; i < DCR_UICMAX; i++) { - ppc_dcr_register(&cpu->env, uic->dcr_base + i, uic, + ppc4xx_dcr_register(dcr, uic->dcr_base + i, uic, &dcr_read_uic, &dcr_write_uic); } @@ -273,7 +260,6 @@ static void ppc_uic_realize(DeviceState *dev, Error **errp) } static Property ppc_uic_properties[] = { - DEFINE_PROP_LINK("cpu", PPCUIC, cpu, TYPE_CPU, CPUState *), DEFINE_PROP_UINT32("dcr-base", PPCUIC, dcr_base, 0xc0), DEFINE_PROP_BOOL("use-vectors", PPCUIC, use_vectors, true), DEFINE_PROP_END_OF_LIST() @@ -308,7 +294,7 @@ static void ppc_uic_class_init(ObjectClass *klass, void *data) static const TypeInfo ppc_uic_info = { .name = TYPE_PPC_UIC, - .parent = TYPE_SYS_BUS_DEVICE, + .parent = TYPE_PPC4xx_DCR_DEVICE, .instance_size = sizeof(PPCUIC), .class_init = ppc_uic_class_init, }; diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 47bb9f534a..dc17d5bdb5 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1152,12 +1152,10 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(sbd, 0, 0xef600600); /* Universal interrupt controller */ - object_property_set_link(OBJECT(&s->uic), "cpu", OBJECT(&s->cpu), - &error_fatal); - sbd = SYS_BUS_DEVICE(&s->uic); - if (!sysbus_realize(sbd, errp)) { + if (!ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(&s->uic), &s->cpu, errp)) { return; } + sbd = SYS_BUS_DEVICE(&s->uic); sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(DEVICE(&s->cpu), PPC40x_INPUT_INT)); sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index 873f930c77..b14a9ef776 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -193,12 +193,9 @@ static void bamboo_init(MachineState *machine) /* interrupt controller */ uicdev = qdev_new(TYPE_PPC_UIC); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(uicdev), cpu, &error_fatal); + object_unref(OBJECT(uicdev)); uicsbd = SYS_BUS_DEVICE(uicdev); - - object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(cpu), - &error_fatal); - sysbus_realize_and_unref(uicsbd, &error_fatal); - sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT, diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index fbfb21c8e8..37e3b87c2e 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -29,7 +29,6 @@ #include "hw/irq.h" #include "hw/ppc/ppc.h" #include "hw/ppc/ppc4xx.h" -#include "hw/intc/ppc-uic.h" #include "hw/qdev-properties.h" #include "qemu/log.h" #include "exec/address-spaces.h" diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 0d9259f0f2..348ed27211 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -314,7 +314,6 @@ static void sam460ex_init(MachineState *machine) /* interrupt controllers */ for (i = 0; i < ARRAY_SIZE(uic); i++) { - SysBusDevice *sbd; /* * UICs 1, 2 and 3 are cascaded through UIC 0. * input_ints[n] is the interrupt number on UIC 0 which @@ -326,22 +325,20 @@ static void sam460ex_init(MachineState *machine) const int input_ints[] = { -1, 30, 10, 16 }; uic[i] = qdev_new(TYPE_PPC_UIC); - sbd = SYS_BUS_DEVICE(uic[i]); - qdev_prop_set_uint32(uic[i], "dcr-base", 0xc0 + i * 0x10); - object_property_set_link(OBJECT(uic[i]), "cpu", OBJECT(cpu), - &error_fatal); - sysbus_realize_and_unref(sbd, &error_fatal); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(uic[i]), cpu, &error_fatal); + object_unref(OBJECT(uic[i])); + sbdev = SYS_BUS_DEVICE(uic[i]); if (i == 0) { - sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, + sysbus_connect_irq(sbdev, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); - sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, + sysbus_connect_irq(sbdev, PPCUIC_OUTPUT_CINT, qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_CINT)); } else { - sysbus_connect_irq(sbd, PPCUIC_OUTPUT_INT, + sysbus_connect_irq(sbdev, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(uic[0], input_ints[i])); - sysbus_connect_irq(sbd, PPCUIC_OUTPUT_CINT, + sysbus_connect_irq(sbdev, PPCUIC_OUTPUT_CINT, qdev_get_gpio_in(uic[0], input_ints[i] + 1)); } } diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c index 53b126ff48..493ea0c19f 100644 --- a/hw/ppc/virtex_ml507.c +++ b/hw/ppc/virtex_ml507.c @@ -104,12 +104,9 @@ static PowerPCCPU *ppc440_init_xilinx(const char *cpu_type, uint32_t sysclk) /* interrupt controller */ uicdev = qdev_new(TYPE_PPC_UIC); + ppc4xx_dcr_realize(PPC4xx_DCR_DEVICE(uicdev), cpu, &error_fatal); + object_unref(OBJECT(uicdev)); uicsbd = SYS_BUS_DEVICE(uicdev); - - object_property_set_link(OBJECT(uicdev), "cpu", OBJECT(cpu), - &error_fatal); - sysbus_realize_and_unref(uicsbd, &error_fatal); - sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_INT, qdev_get_gpio_in(DEVICE(cpu), PPC40x_INPUT_INT)); sysbus_connect_irq(uicsbd, PPCUIC_OUTPUT_CINT, diff --git a/include/hw/intc/ppc-uic.h b/include/hw/intc/ppc-uic.h index 22dd5e5ac2..4d82e9a3c6 100644 --- a/include/hw/intc/ppc-uic.h +++ b/include/hw/intc/ppc-uic.h @@ -25,8 +25,7 @@ #ifndef HW_INTC_PPC_UIC_H #define HW_INTC_PPC_UIC_H -#include "hw/sysbus.h" -#include "qom/object.h" +#include "hw/ppc/ppc4xx.h" #define TYPE_PPC_UIC "ppc-uic" OBJECT_DECLARE_SIMPLE_TYPE(PPCUIC, PPC_UIC) @@ -56,14 +55,13 @@ enum { struct PPCUIC { /*< private >*/ - SysBusDevice parent_obj; + Ppc4xxDcrDeviceState parent_obj; /*< public >*/ qemu_irq output_int; qemu_irq output_cint; /* properties */ - CPUState *cpu; uint32_t dcr_base; bool use_vectors; From 111913fb2da19cb72e208a951b11f897f65cc8c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:36 +0200 Subject: [PATCH 0255/1020] ppc/ppc405: Use an explicit I2C object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Having an explicit I2C model object will help if one day we want to add I2C devices on the bus from the machine init routine. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater [balaton: Symplify sysbus device casts for readibility] Signed-off-by: BALATON Zoltan Message-Id: <68eb8b5ac408ca8cc981ebf53a3e154c0d34c7f6.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 2 ++ hw/ppc/ppc405_uc.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index 67f4c14f50..efa29fdfb1 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -28,6 +28,7 @@ #include "qom/object.h" #include "hw/ppc/ppc4xx.h" #include "hw/intc/ppc-uic.h" +#include "hw/i2c/ppc4xx_i2c.h" #define PPC405EP_SDRAM_BASE 0x00000000 #define PPC405EP_NVRAM_BASE 0xF0000000 @@ -215,6 +216,7 @@ struct Ppc405SoCState { Ppc405OcmState ocm; Ppc405GpioState gpio; Ppc405DmaState dma; + PPC4xxI2CState i2c; Ppc4xxEbcState ebc; Ppc405OpbaState opba; Ppc405PobState pob; diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index dc17d5bdb5..189f49a138 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -1096,6 +1096,8 @@ static void ppc405_soc_instance_init(Object *obj) object_initialize_child(obj, "dma", &s->dma, TYPE_PPC405_DMA); + object_initialize_child(obj, "i2c", &s->i2c, TYPE_PPC4xx_I2C); + object_initialize_child(obj, "ebc", &s->ebc, TYPE_PPC4xx_EBC); object_initialize_child(obj, "opba", &s->opba, TYPE_PPC405_OPBA); @@ -1188,8 +1190,12 @@ static void ppc405_soc_realize(DeviceState *dev, Error **errp) } /* I2C controller */ - sysbus_create_simple(TYPE_PPC4xx_I2C, 0xef600500, - qdev_get_gpio_in(DEVICE(&s->uic), 2)); + sbd = SYS_BUS_DEVICE(&s->i2c); + if (!sysbus_realize(sbd, errp)) { + return; + } + sysbus_mmio_map(sbd, 0, 0xef600500); + sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(DEVICE(&s->uic), 2)); /* GPIO */ sbd = SYS_BUS_DEVICE(&s->gpio); From ea9b3186954ff07efbaad771e4c5674518fe872f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:37 +0200 Subject: [PATCH 0256/1020] ppc/ppc405: QOM'ify FPGA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater Signed-off-by: BALATON Zoltan Message-Id: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405_boards.c | 56 +++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 3677793adc..7af0d7feef 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -71,18 +71,23 @@ struct Ppc405MachineState { * - NVRAM (0xF0000000) * - FPGA (0xF0300000) */ -typedef struct ref405ep_fpga_t ref405ep_fpga_t; -struct ref405ep_fpga_t { + +#define TYPE_REF405EP_FPGA "ref405ep-fpga" +OBJECT_DECLARE_SIMPLE_TYPE(Ref405epFpgaState, REF405EP_FPGA); +struct Ref405epFpgaState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + uint8_t reg0; uint8_t reg1; }; static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size) { - ref405ep_fpga_t *fpga; + Ref405epFpgaState *fpga = opaque; uint32_t ret; - fpga = opaque; switch (addr) { case 0x0: ret = fpga->reg0; @@ -101,9 +106,8 @@ static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size) static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, unsigned size) { - ref405ep_fpga_t *fpga; + Ref405epFpgaState *fpga = opaque; - fpga = opaque; switch (addr) { case 0x0: /* Read only */ @@ -126,27 +130,40 @@ static const MemoryRegionOps ref405ep_fpga_ops = { .endianness = DEVICE_BIG_ENDIAN, }; -static void ref405ep_fpga_reset (void *opaque) +static void ref405ep_fpga_reset(DeviceState *dev) { - ref405ep_fpga_t *fpga; + Ref405epFpgaState *fpga = REF405EP_FPGA(dev); - fpga = opaque; fpga->reg0 = 0x00; fpga->reg1 = 0x0F; } -static void ref405ep_fpga_init(MemoryRegion *sysmem, uint32_t base) +static void ref405ep_fpga_realize(DeviceState *dev, Error **errp) { - ref405ep_fpga_t *fpga; - MemoryRegion *fpga_memory = g_new(MemoryRegion, 1); + Ref405epFpgaState *s = REF405EP_FPGA(dev); - fpga = g_new0(ref405ep_fpga_t, 1); - memory_region_init_io(fpga_memory, NULL, &ref405ep_fpga_ops, fpga, + memory_region_init_io(&s->iomem, OBJECT(s), &ref405ep_fpga_ops, s, "fpga", 0x00000100); - memory_region_add_subregion(sysmem, base, fpga_memory); - qemu_register_reset(&ref405ep_fpga_reset, fpga); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); } +static void ref405ep_fpga_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ref405ep_fpga_realize; + dc->reset = ref405ep_fpga_reset; + /* Reason: only works as part of a ppc405 board */ + dc->user_creatable = false; +} + +static const TypeInfo ref405ep_fpga_type = { + .name = TYPE_REF405EP_FPGA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ref405epFpgaState), + .class_init = ref405ep_fpga_class_init, +}; + /* * CPU reset handler when booting directly from a loaded kernel */ @@ -331,7 +348,11 @@ static void ref405ep_init(MachineState *machine) memory_region_add_subregion(get_system_memory(), PPC405EP_SRAM_BASE, sram); /* Register FPGA */ - ref405ep_fpga_init(get_system_memory(), PPC405EP_FPGA_BASE); + dev = qdev_new(TYPE_REF405EP_FPGA); + object_property_add_child(OBJECT(machine), "fpga", OBJECT(dev)); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, PPC405EP_FPGA_BASE); + /* Register NVRAM */ dev = qdev_new("sysbus-m48t08"); qdev_prop_set_int32(dev, "base-year", 1968); @@ -376,6 +397,7 @@ static void ppc405_machine_init(void) { type_register_static(&ppc405_machine_type); type_register_static(&ref405ep_type); + type_register_static(&ref405ep_fpga_type); } type_init(ppc405_machine_init) From b5aae5f66098655f44cbacf463e358605e380889 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 17:08:38 +0200 Subject: [PATCH 0257/1020] ppc405: Move machine specific code to ppc405_boards.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are only used by the board code so move out from the shared SoC model and put it in the boards file. Signed-off-by: BALATON Zoltan Reviewed-by: Cédric Le Goater Message-Id: <2b23bcaaf191f96b217cbd06a6038694024862c3.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405.h | 38 ----- hw/ppc/ppc405_boards.c | 375 +++++++++++++++++++++++++++-------------- hw/ppc/ppc405_uc.c | 92 ---------- 3 files changed, 251 insertions(+), 254 deletions(-) diff --git a/hw/ppc/ppc405.h b/hw/ppc/ppc405.h index efa29fdfb1..1e558c7831 100644 --- a/hw/ppc/ppc405.h +++ b/hw/ppc/ppc405.h @@ -30,41 +30,6 @@ #include "hw/intc/ppc-uic.h" #include "hw/i2c/ppc4xx_i2c.h" -#define PPC405EP_SDRAM_BASE 0x00000000 -#define PPC405EP_NVRAM_BASE 0xF0000000 -#define PPC405EP_FPGA_BASE 0xF0300000 -#define PPC405EP_SRAM_BASE 0xFFF00000 -#define PPC405EP_SRAM_SIZE (512 * KiB) -#define PPC405EP_FLASH_BASE 0xFFF80000 - -/* Bootinfo as set-up by u-boot */ -typedef struct ppc4xx_bd_info_t ppc4xx_bd_info_t; -struct ppc4xx_bd_info_t { - uint32_t bi_memstart; - uint32_t bi_memsize; - uint32_t bi_flashstart; - uint32_t bi_flashsize; - uint32_t bi_flashoffset; /* 0x10 */ - uint32_t bi_sramstart; - uint32_t bi_sramsize; - uint32_t bi_bootflags; - uint32_t bi_ipaddr; /* 0x20 */ - uint8_t bi_enetaddr[6]; - uint16_t bi_ethspeed; - uint32_t bi_intfreq; - uint32_t bi_busfreq; /* 0x30 */ - uint32_t bi_baudrate; - uint8_t bi_s_version[4]; - uint8_t bi_r_version[32]; - uint32_t bi_procfreq; - uint32_t bi_plb_busfreq; - uint32_t bi_pci_busfreq; - uint8_t bi_pci_enetaddr[6]; - uint8_t bi_pci_enetaddr2[6]; /* PPC405EP specific */ - uint32_t bi_opbfreq; - uint32_t bi_iic_fast[2]; -}; - /* PLB to OPB bridge */ #define TYPE_PPC405_POB "ppc405-pob" OBJECT_DECLARE_SIMPLE_TYPE(Ppc405PobState, PPC405_POB); @@ -224,7 +189,4 @@ struct Ppc405SoCState { Ppc4xxMalState mal; }; -/* PowerPC 405 core */ -ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size); - #endif /* PPC405_H */ diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c index 7af0d7feef..083f12b23e 100644 --- a/hw/ppc/ppc405_boards.c +++ b/hw/ppc/ppc405_boards.c @@ -48,6 +48,10 @@ #define KERNEL_LOAD_ADDR 0x01000000 #define INITRD_LOAD_ADDR 0x01800000 +#define PPC405EP_SDRAM_BASE 0x00000000 +#define PPC405EP_SRAM_BASE 0xFFF00000 +#define PPC405EP_SRAM_SIZE (512 * KiB) + #define USE_FLASH_BIOS #define TYPE_PPC405_MACHINE MACHINE_TYPE_NAME("ppc405") @@ -61,112 +65,7 @@ struct Ppc405MachineState { Ppc405SoCState soc; }; -/*****************************************************************************/ -/* PPC405EP reference board (IBM) */ -/* Standalone board with: - * - PowerPC 405EP CPU - * - SDRAM (0x00000000) - * - Flash (0xFFF80000) - * - SRAM (0xFFF00000) - * - NVRAM (0xF0000000) - * - FPGA (0xF0300000) - */ - -#define TYPE_REF405EP_FPGA "ref405ep-fpga" -OBJECT_DECLARE_SIMPLE_TYPE(Ref405epFpgaState, REF405EP_FPGA); -struct Ref405epFpgaState { - SysBusDevice parent_obj; - - MemoryRegion iomem; - - uint8_t reg0; - uint8_t reg1; -}; - -static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size) -{ - Ref405epFpgaState *fpga = opaque; - uint32_t ret; - - switch (addr) { - case 0x0: - ret = fpga->reg0; - break; - case 0x1: - ret = fpga->reg1; - break; - default: - ret = 0; - break; - } - - return ret; -} - -static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, - unsigned size) -{ - Ref405epFpgaState *fpga = opaque; - - switch (addr) { - case 0x0: - /* Read only */ - break; - case 0x1: - fpga->reg1 = value; - break; - default: - break; - } -} - -static const MemoryRegionOps ref405ep_fpga_ops = { - .read = ref405ep_fpga_readb, - .write = ref405ep_fpga_writeb, - .impl.min_access_size = 1, - .impl.max_access_size = 1, - .valid.min_access_size = 1, - .valid.max_access_size = 4, - .endianness = DEVICE_BIG_ENDIAN, -}; - -static void ref405ep_fpga_reset(DeviceState *dev) -{ - Ref405epFpgaState *fpga = REF405EP_FPGA(dev); - - fpga->reg0 = 0x00; - fpga->reg1 = 0x0F; -} - -static void ref405ep_fpga_realize(DeviceState *dev, Error **errp) -{ - Ref405epFpgaState *s = REF405EP_FPGA(dev); - - memory_region_init_io(&s->iomem, OBJECT(s), &ref405ep_fpga_ops, s, - "fpga", 0x00000100); - sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); -} - -static void ref405ep_fpga_class_init(ObjectClass *oc, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(oc); - - dc->realize = ref405ep_fpga_realize; - dc->reset = ref405ep_fpga_reset; - /* Reason: only works as part of a ppc405 board */ - dc->user_creatable = false; -} - -static const TypeInfo ref405ep_fpga_type = { - .name = TYPE_REF405EP_FPGA, - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(Ref405epFpgaState), - .class_init = ref405ep_fpga_class_init, -}; - -/* - * CPU reset handler when booting directly from a loaded kernel - */ +/* CPU reset handler when booting directly from a loaded kernel */ static struct boot_info { uint32_t entry; uint32_t bdloc; @@ -197,6 +96,126 @@ static void main_cpu_reset(void *opaque) env->nip = bi->entry; } +/* Bootinfo as set-up by u-boot */ +typedef struct { + uint32_t bi_memstart; + uint32_t bi_memsize; + uint32_t bi_flashstart; + uint32_t bi_flashsize; + uint32_t bi_flashoffset; /* 0x10 */ + uint32_t bi_sramstart; + uint32_t bi_sramsize; + uint32_t bi_bootflags; + uint32_t bi_ipaddr; /* 0x20 */ + uint8_t bi_enetaddr[6]; + uint16_t bi_ethspeed; + uint32_t bi_intfreq; + uint32_t bi_busfreq; /* 0x30 */ + uint32_t bi_baudrate; + uint8_t bi_s_version[4]; + uint8_t bi_r_version[32]; + uint32_t bi_procfreq; + uint32_t bi_plb_busfreq; + uint32_t bi_pci_busfreq; + uint8_t bi_pci_enetaddr[6]; + uint8_t bi_pci_enetaddr2[6]; /* PPC405EP specific */ + uint32_t bi_opbfreq; + uint32_t bi_iic_fast[2]; +} ppc4xx_bd_info_t; + +static void ppc405_set_default_bootinfo(ppc4xx_bd_info_t *bd, + ram_addr_t ram_size) +{ + memset(bd, 0, sizeof(*bd)); + + bd->bi_memstart = PPC405EP_SDRAM_BASE; + bd->bi_memsize = ram_size; + bd->bi_sramstart = PPC405EP_SRAM_BASE; + bd->bi_sramsize = PPC405EP_SRAM_SIZE; + bd->bi_bootflags = 0; + bd->bi_intfreq = 133333333; + bd->bi_busfreq = 33333333; + bd->bi_baudrate = 115200; + bd->bi_s_version[0] = 'Q'; + bd->bi_s_version[1] = 'M'; + bd->bi_s_version[2] = 'U'; + bd->bi_s_version[3] = '\0'; + bd->bi_r_version[0] = 'Q'; + bd->bi_r_version[1] = 'E'; + bd->bi_r_version[2] = 'M'; + bd->bi_r_version[3] = 'U'; + bd->bi_r_version[4] = '\0'; + bd->bi_procfreq = 133333333; + bd->bi_plb_busfreq = 33333333; + bd->bi_pci_busfreq = 33333333; + bd->bi_opbfreq = 33333333; +} + +static ram_addr_t __ppc405_set_bootinfo(CPUPPCState *env, ppc4xx_bd_info_t *bd) +{ + CPUState *cs = env_cpu(env); + ram_addr_t bdloc; + int i, n; + + /* We put the bd structure at the top of memory */ + if (bd->bi_memsize >= 0x01000000UL) { + bdloc = 0x01000000UL - sizeof(ppc4xx_bd_info_t); + } else { + bdloc = bd->bi_memsize - sizeof(ppc4xx_bd_info_t); + } + stl_be_phys(cs->as, bdloc + 0x00, bd->bi_memstart); + stl_be_phys(cs->as, bdloc + 0x04, bd->bi_memsize); + stl_be_phys(cs->as, bdloc + 0x08, bd->bi_flashstart); + stl_be_phys(cs->as, bdloc + 0x0C, bd->bi_flashsize); + stl_be_phys(cs->as, bdloc + 0x10, bd->bi_flashoffset); + stl_be_phys(cs->as, bdloc + 0x14, bd->bi_sramstart); + stl_be_phys(cs->as, bdloc + 0x18, bd->bi_sramsize); + stl_be_phys(cs->as, bdloc + 0x1C, bd->bi_bootflags); + stl_be_phys(cs->as, bdloc + 0x20, bd->bi_ipaddr); + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + 0x24 + i, bd->bi_enetaddr[i]); + } + stw_be_phys(cs->as, bdloc + 0x2A, bd->bi_ethspeed); + stl_be_phys(cs->as, bdloc + 0x2C, bd->bi_intfreq); + stl_be_phys(cs->as, bdloc + 0x30, bd->bi_busfreq); + stl_be_phys(cs->as, bdloc + 0x34, bd->bi_baudrate); + for (i = 0; i < 4; i++) { + stb_phys(cs->as, bdloc + 0x38 + i, bd->bi_s_version[i]); + } + for (i = 0; i < 32; i++) { + stb_phys(cs->as, bdloc + 0x3C + i, bd->bi_r_version[i]); + } + stl_be_phys(cs->as, bdloc + 0x5C, bd->bi_procfreq); + stl_be_phys(cs->as, bdloc + 0x60, bd->bi_plb_busfreq); + stl_be_phys(cs->as, bdloc + 0x64, bd->bi_pci_busfreq); + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + 0x68 + i, bd->bi_pci_enetaddr[i]); + } + n = 0x70; /* includes 2 bytes hole */ + for (i = 0; i < 6; i++) { + stb_phys(cs->as, bdloc + n++, bd->bi_pci_enetaddr2[i]); + } + stl_be_phys(cs->as, bdloc + n, bd->bi_opbfreq); + n += 4; + for (i = 0; i < 2; i++) { + stl_be_phys(cs->as, bdloc + n, bd->bi_iic_fast[i]); + n += 4; + } + + return bdloc; +} + +static ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size) +{ + ppc4xx_bd_info_t bd; + + memset(&bd, 0, sizeof(bd)); + + ppc405_set_default_bootinfo(&bd, ram_size); + + return __ppc405_set_bootinfo(env, &bd); +} + static void boot_from_kernel(MachineState *machine, PowerPCCPU *cpu) { CPUPPCState *env = &cpu->env; @@ -334,6 +353,132 @@ static void ppc405_init(MachineState *machine) } } +static void ppc405_machine_class_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "PPC405 generic machine"; + mc->init = ppc405_init; + mc->default_ram_size = 128 * MiB; + mc->default_ram_id = "ppc405.ram"; +} + +static const TypeInfo ppc405_machine_type = { + .name = TYPE_PPC405_MACHINE, + .parent = TYPE_MACHINE, + .instance_size = sizeof(Ppc405MachineState), + .class_init = ppc405_machine_class_init, + .abstract = true, +}; + +/*****************************************************************************/ +/* PPC405EP reference board (IBM) */ +/* + * Standalone board with: + * - PowerPC 405EP CPU + * - SDRAM (0x00000000) + * - Flash (0xFFF80000) + * - SRAM (0xFFF00000) + * - NVRAM (0xF0000000) + * - FPGA (0xF0300000) + */ + +#define PPC405EP_NVRAM_BASE 0xF0000000 +#define PPC405EP_FPGA_BASE 0xF0300000 +#define PPC405EP_FLASH_BASE 0xFFF80000 + +#define TYPE_REF405EP_FPGA "ref405ep-fpga" +OBJECT_DECLARE_SIMPLE_TYPE(Ref405epFpgaState, REF405EP_FPGA); +struct Ref405epFpgaState { + SysBusDevice parent_obj; + + MemoryRegion iomem; + + uint8_t reg0; + uint8_t reg1; +}; + +static uint64_t ref405ep_fpga_readb(void *opaque, hwaddr addr, unsigned size) +{ + Ref405epFpgaState *fpga = opaque; + uint32_t ret; + + switch (addr) { + case 0x0: + ret = fpga->reg0; + break; + case 0x1: + ret = fpga->reg1; + break; + default: + ret = 0; + break; + } + + return ret; +} + +static void ref405ep_fpga_writeb(void *opaque, hwaddr addr, uint64_t value, + unsigned size) +{ + Ref405epFpgaState *fpga = opaque; + + switch (addr) { + case 0x0: + /* Read only */ + break; + case 0x1: + fpga->reg1 = value; + break; + default: + break; + } +} + +static const MemoryRegionOps ref405ep_fpga_ops = { + .read = ref405ep_fpga_readb, + .write = ref405ep_fpga_writeb, + .impl.min_access_size = 1, + .impl.max_access_size = 1, + .valid.min_access_size = 1, + .valid.max_access_size = 4, + .endianness = DEVICE_BIG_ENDIAN, +}; + +static void ref405ep_fpga_reset(DeviceState *dev) +{ + Ref405epFpgaState *fpga = REF405EP_FPGA(dev); + + fpga->reg0 = 0x00; + fpga->reg1 = 0x0F; +} + +static void ref405ep_fpga_realize(DeviceState *dev, Error **errp) +{ + Ref405epFpgaState *s = REF405EP_FPGA(dev); + + memory_region_init_io(&s->iomem, OBJECT(s), &ref405ep_fpga_ops, s, + "fpga", 0x00000100); + sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); +} + +static void ref405ep_fpga_class_init(ObjectClass *oc, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(oc); + + dc->realize = ref405ep_fpga_realize; + dc->reset = ref405ep_fpga_reset; + /* Reason: only works as part of a ppc405 board */ + dc->user_creatable = false; +} + +static const TypeInfo ref405ep_fpga_type = { + .name = TYPE_REF405EP_FPGA, + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = sizeof(Ref405epFpgaState), + .class_init = ref405ep_fpga_class_init, +}; + static void ref405ep_init(MachineState *machine) { DeviceState *dev; @@ -375,24 +520,6 @@ static const TypeInfo ref405ep_type = { .class_init = ref405ep_class_init, }; -static void ppc405_machine_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - - mc->desc = "PPC405 generic machine"; - mc->init = ppc405_init; - mc->default_ram_size = 128 * MiB; - mc->default_ram_id = "ppc405.ram"; -} - -static const TypeInfo ppc405_machine_type = { - .name = TYPE_PPC405_MACHINE, - .parent = TYPE_MACHINE, - .instance_size = sizeof(Ppc405MachineState), - .class_init = ppc405_machine_class_init, - .abstract = true, -}; - static void ppc405_machine_init(void) { type_register_static(&ppc405_machine_type); diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 189f49a138..74d27250a7 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -42,98 +42,6 @@ #include "qapi/error.h" #include "trace.h" -static void ppc405_set_default_bootinfo(ppc4xx_bd_info_t *bd, - ram_addr_t ram_size) -{ - memset(bd, 0, sizeof(*bd)); - - bd->bi_memstart = PPC405EP_SDRAM_BASE; - bd->bi_memsize = ram_size; - bd->bi_sramstart = PPC405EP_SRAM_BASE; - bd->bi_sramsize = PPC405EP_SRAM_SIZE; - bd->bi_bootflags = 0; - bd->bi_intfreq = 133333333; - bd->bi_busfreq = 33333333; - bd->bi_baudrate = 115200; - bd->bi_s_version[0] = 'Q'; - bd->bi_s_version[1] = 'M'; - bd->bi_s_version[2] = 'U'; - bd->bi_s_version[3] = '\0'; - bd->bi_r_version[0] = 'Q'; - bd->bi_r_version[1] = 'E'; - bd->bi_r_version[2] = 'M'; - bd->bi_r_version[3] = 'U'; - bd->bi_r_version[4] = '\0'; - bd->bi_procfreq = 133333333; - bd->bi_plb_busfreq = 33333333; - bd->bi_pci_busfreq = 33333333; - bd->bi_opbfreq = 33333333; -} - -static ram_addr_t __ppc405_set_bootinfo(CPUPPCState *env, ppc4xx_bd_info_t *bd) -{ - CPUState *cs = env_cpu(env); - ram_addr_t bdloc; - int i, n; - - /* We put the bd structure at the top of memory */ - if (bd->bi_memsize >= 0x01000000UL) - bdloc = 0x01000000UL - sizeof(struct ppc4xx_bd_info_t); - else - bdloc = bd->bi_memsize - sizeof(struct ppc4xx_bd_info_t); - stl_be_phys(cs->as, bdloc + 0x00, bd->bi_memstart); - stl_be_phys(cs->as, bdloc + 0x04, bd->bi_memsize); - stl_be_phys(cs->as, bdloc + 0x08, bd->bi_flashstart); - stl_be_phys(cs->as, bdloc + 0x0C, bd->bi_flashsize); - stl_be_phys(cs->as, bdloc + 0x10, bd->bi_flashoffset); - stl_be_phys(cs->as, bdloc + 0x14, bd->bi_sramstart); - stl_be_phys(cs->as, bdloc + 0x18, bd->bi_sramsize); - stl_be_phys(cs->as, bdloc + 0x1C, bd->bi_bootflags); - stl_be_phys(cs->as, bdloc + 0x20, bd->bi_ipaddr); - for (i = 0; i < 6; i++) { - stb_phys(cs->as, bdloc + 0x24 + i, bd->bi_enetaddr[i]); - } - stw_be_phys(cs->as, bdloc + 0x2A, bd->bi_ethspeed); - stl_be_phys(cs->as, bdloc + 0x2C, bd->bi_intfreq); - stl_be_phys(cs->as, bdloc + 0x30, bd->bi_busfreq); - stl_be_phys(cs->as, bdloc + 0x34, bd->bi_baudrate); - for (i = 0; i < 4; i++) { - stb_phys(cs->as, bdloc + 0x38 + i, bd->bi_s_version[i]); - } - for (i = 0; i < 32; i++) { - stb_phys(cs->as, bdloc + 0x3C + i, bd->bi_r_version[i]); - } - stl_be_phys(cs->as, bdloc + 0x5C, bd->bi_procfreq); - stl_be_phys(cs->as, bdloc + 0x60, bd->bi_plb_busfreq); - stl_be_phys(cs->as, bdloc + 0x64, bd->bi_pci_busfreq); - for (i = 0; i < 6; i++) { - stb_phys(cs->as, bdloc + 0x68 + i, bd->bi_pci_enetaddr[i]); - } - n = 0x70; /* includes 2 bytes hole */ - for (i = 0; i < 6; i++) { - stb_phys(cs->as, bdloc + n++, bd->bi_pci_enetaddr2[i]); - } - stl_be_phys(cs->as, bdloc + n, bd->bi_opbfreq); - n += 4; - for (i = 0; i < 2; i++) { - stl_be_phys(cs->as, bdloc + n, bd->bi_iic_fast[i]); - n += 4; - } - - return bdloc; -} - -ram_addr_t ppc405_set_bootinfo(CPUPPCState *env, ram_addr_t ram_size) -{ - ppc4xx_bd_info_t bd; - - memset(&bd, 0, sizeof(bd)); - - ppc405_set_default_bootinfo(&bd, ram_size); - - return __ppc405_set_bootinfo(env, &bd); -} - /*****************************************************************************/ /* Shared peripherals */ From adb566d371141d403a8e55b8728d7ab20389d248 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 20:59:14 +0200 Subject: [PATCH 0258/1020] hw/ppc/sam460ex: Remove PPC405 dependency from sam460ex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that shared PPC4xx devices are separated from PPC405 ones we can drop this depencency. Signed-off-by: BALATON Zoltan Reviewed-by: Cédric Le Goater Message-Id: Signed-off-by: Daniel Henrique Barboza --- hw/ppc/Kconfig | 1 - hw/ppc/sam460ex.c | 1 - 2 files changed, 2 deletions(-) diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 400511c6b7..205f9f98d7 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -58,7 +58,6 @@ config PPC4XX config SAM460EX bool - select PPC405 select PFLASH_CFI01 select IDE_SII3112 select M41T80 diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c index 348ed27211..850bb3b817 100644 --- a/hw/ppc/sam460ex.c +++ b/hw/ppc/sam460ex.c @@ -25,7 +25,6 @@ #include "elf.h" #include "exec/memory.h" #include "ppc440.h" -#include "ppc405.h" #include "hw/block/flash.h" #include "sysemu/sysemu.h" #include "sysemu/reset.h" From 56a5b199e4dd3043eb8f0954bdd71988f063366a Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 17:08:40 +0200 Subject: [PATCH 0259/1020] hw/ppc/Kconfig: Move imply before select MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In pegasos2 section move imply before select to match other sections. Signed-off-by: BALATON Zoltan Reviewed-by: Cédric Le Goater Message-Id: <4d46dde64c2e5df6db3f92426fb3ae885939c2b0.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/Kconfig b/hw/ppc/Kconfig index 205f9f98d7..3a4418a69e 100644 --- a/hw/ppc/Kconfig +++ b/hw/ppc/Kconfig @@ -71,6 +71,7 @@ config SAM460EX config PEGASOS2 bool + imply ATI_VGA select MV64361 select VT82C686 select IDE_VIA @@ -78,7 +79,6 @@ config PEGASOS2 select VOF # This should come with VT82C686 select ACPI_X86 - imply ATI_VGA config PREP bool From 1b46bc17f49a48c8156a82bb8b66b716d1d45d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Le=20Goater?= Date: Wed, 17 Aug 2022 17:08:42 +0200 Subject: [PATCH 0260/1020] ppc/ppc4xx: Fix sdram trace events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Daniel Henrique Barboza Signed-off-by: Cédric Le Goater Signed-off-by: BALATON Zoltan Message-Id: <0a3e454eb7fd5f2b807a9c752c28693f27829f1d.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc4xx_devs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 37e3b87c2e..27ebbb2ffc 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -142,7 +142,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, } sdram->bcr[i] = bcr & 0xFFDEE001; if (enabled && (bcr & 0x00000001)) { - trace_ppc4xx_sdram_unmap(sdram_base(bcr), sdram_size(bcr)); + trace_ppc4xx_sdram_map(sdram_base(bcr), sdram_size(bcr)); memory_region_init(&sdram->containers[i], NULL, "sdram-containers", sdram_size(bcr)); memory_region_add_subregion(&sdram->containers[i], 0, From 95e22932870f523765910b01c2dc5b845b8bec85 Mon Sep 17 00:00:00 2001 From: BALATON Zoltan Date: Wed, 17 Aug 2022 17:08:43 +0200 Subject: [PATCH 0261/1020] ppc4xx: Fix code style problems reported by checkpatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: BALATON Zoltan Reviewed-by: Cédric Le Goater Message-Id: <62798fbe9c200da3e0c870601ed9162b1c3a50a5.1660746880.git.balaton@eik.bme.hu> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/ppc405_uc.c | 5 +++-- hw/ppc/ppc440_bamboo.c | 27 ++++++++++++++---------- hw/ppc/ppc440_uc.c | 3 ++- hw/ppc/ppc4xx_devs.c | 48 +++++++++++++++++++++++------------------- hw/ppc/ppc4xx_pci.c | 31 +++++++++++++++++---------- 5 files changed, 67 insertions(+), 47 deletions(-) diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c index 74d27250a7..2ca42fdef6 100644 --- a/hw/ppc/ppc405_uc.c +++ b/hw/ppc/ppc405_uc.c @@ -540,10 +540,11 @@ static void ppc4xx_gpt_set_irqs(Ppc405GptState *gpt) mask = 0x00008000; for (i = 0; i < 5; i++) { - if (gpt->is & gpt->im & mask) + if (gpt->is & gpt->im & mask) { qemu_irq_raise(gpt->irqs[i]); - else + } else { qemu_irq_lower(gpt->irqs[i]); + } mask = mask >> 1; } } diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c index b14a9ef776..ea945a1c99 100644 --- a/hw/ppc/ppc440_bamboo.c +++ b/hw/ppc/ppc440_bamboo.c @@ -84,27 +84,30 @@ static int bamboo_load_device_tree(hwaddr addr, ret = qemu_fdt_setprop(fdt, "/memory", "reg", mem_reg_property, sizeof(mem_reg_property)); - if (ret < 0) + if (ret < 0) { fprintf(stderr, "couldn't set /memory/reg\n"); - + } ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-start", initrd_base); - if (ret < 0) + if (ret < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-start\n"); - + } ret = qemu_fdt_setprop_cell(fdt, "/chosen", "linux,initrd-end", (initrd_base + initrd_size)); - if (ret < 0) + if (ret < 0) { fprintf(stderr, "couldn't set /chosen/linux,initrd-end\n"); - + } ret = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); - if (ret < 0) + if (ret < 0) { fprintf(stderr, "couldn't set /chosen/bootargs\n"); + } - /* Copy data from the host device tree into the guest. Since the guest can + /* + * Copy data from the host device tree into the guest. Since the guest can * directly access the timebase without host involvement, we must expose - * the correct frequencies. */ + * the correct frequencies. + */ if (kvm_enabled()) { tb_freq = kvmppc_get_tbfreq(); clock_freq = kvmppc_get_clockfreq(); @@ -246,8 +249,10 @@ static void bamboo_init(MachineState *machine) if (pcibus) { /* Register network interfaces. */ for (i = 0; i < nb_nics; i++) { - /* There are no PCI NICs on the Bamboo board, but there are - * PCI slots, so we can pick whatever default model we want. */ + /* + * There are no PCI NICs on the Bamboo board, but there are + * PCI slots, so we can pick whatever default model we want. + */ pci_nic_init_nofail(&nd_table[i], pcibus, "e1000", NULL); } } diff --git a/hw/ppc/ppc440_uc.c b/hw/ppc/ppc440_uc.c index 11fdb88c22..53e981ddf4 100644 --- a/hw/ppc/ppc440_uc.c +++ b/hw/ppc/ppc440_uc.c @@ -1028,7 +1028,8 @@ void ppc4xx_dma_init(CPUPPCState *env, int dcr_base) /*****************************************************************************/ /* PCI Express controller */ -/* FIXME: This is not complete and does not work, only implemented partially +/* + * FIXME: This is not complete and does not work, only implemented partially * to allow firmware and guests to find an empty bus. Cards should use PCI. */ #include "hw/pci/pcie_host.h" diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c index 27ebbb2ffc..ce38ae65e6 100644 --- a/hw/ppc/ppc4xx_devs.c +++ b/hw/ppc/ppc4xx_devs.c @@ -65,12 +65,12 @@ enum { SDRAM0_CFGDATA = 0x011, }; -/* XXX: TOFIX: some patches have made this code become inconsistent: +/* + * XXX: TOFIX: some patches have made this code become inconsistent: * there are type inconsistencies, mixing hwaddr, target_ulong * and uint32_t */ -static uint32_t sdram_bcr (hwaddr ram_base, - hwaddr ram_size) +static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size) { uint32_t bcr; @@ -113,16 +113,17 @@ static inline hwaddr sdram_base(uint32_t bcr) return bcr & 0xFF800000; } -static target_ulong sdram_size (uint32_t bcr) +static target_ulong sdram_size(uint32_t bcr) { target_ulong size; int sh; sh = (bcr >> 17) & 0x7; - if (sh == 7) + if (sh == 7) { size = -1; - else + } else { size = (4 * MiB) << sh; + } return size; } @@ -153,7 +154,7 @@ static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i, } } -static void sdram_map_bcr (ppc4xx_sdram_t *sdram) +static void sdram_map_bcr(ppc4xx_sdram_t *sdram) { int i; @@ -167,7 +168,7 @@ static void sdram_map_bcr (ppc4xx_sdram_t *sdram) } } -static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram) +static void sdram_unmap_bcr(ppc4xx_sdram_t *sdram) { int i; @@ -179,7 +180,7 @@ static void sdram_unmap_bcr (ppc4xx_sdram_t *sdram) } } -static uint32_t dcr_read_sdram (void *opaque, int dcrn) +static uint32_t dcr_read_sdram(void *opaque, int dcrn) { ppc4xx_sdram_t *sdram; uint32_t ret; @@ -247,7 +248,7 @@ static uint32_t dcr_read_sdram (void *opaque, int dcrn) return ret; } -static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) +static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val) { ppc4xx_sdram_t *sdram; @@ -280,10 +281,11 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) sdram_unmap_bcr(sdram); sdram->status |= 0x80000000; } - if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) + if (!(sdram->cfg & 0x40000000) && (val & 0x40000000)) { sdram->status |= 0x40000000; - else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000)) + } else if ((sdram->cfg & 0x40000000) && !(val & 0x40000000)) { sdram->status &= ~0x40000000; + } sdram->cfg = val; break; case 0x24: /* SDRAM_STATUS */ @@ -315,10 +317,11 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) break; case 0x98: /* SDRAM_ECCESR */ val &= 0xFFF0F000; - if (sdram->eccesr == 0 && val != 0) + if (sdram->eccesr == 0 && val != 0) { qemu_irq_raise(sdram->irq); - else if (sdram->eccesr != 0 && val == 0) + } else if (sdram->eccesr != 0 && val == 0) { qemu_irq_lower(sdram->irq); + } sdram->eccesr = val; break; default: /* Error */ @@ -328,7 +331,7 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val) } } -static void sdram_reset (void *opaque) +static void sdram_reset(void *opaque) { ppc4xx_sdram_t *sdram; @@ -348,11 +351,11 @@ static void sdram_reset (void *opaque) sdram->cfg = 0x00800000; } -void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, - MemoryRegion *ram_memories, - hwaddr *ram_bases, - hwaddr *ram_sizes, - int do_init) +void ppc4xx_sdram_init(CPUPPCState *env, qemu_irq irq, int nbanks, + MemoryRegion *ram_memories, + hwaddr *ram_bases, + hwaddr *ram_sizes, + int do_init) { ppc4xx_sdram_t *sdram; @@ -371,8 +374,9 @@ void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, sdram, &dcr_read_sdram, &dcr_write_sdram); ppc_dcr_register(env, SDRAM0_CFGDATA, sdram, &dcr_read_sdram, &dcr_write_sdram); - if (do_init) + if (do_init) { sdram_map_bcr(sdram); + } } /* @@ -429,7 +433,7 @@ void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks, } error_report("at most %d bank%s of %s MiB each supported", nr_banks, nr_banks == 1 ? "" : "s", s->str); - error_printf("Possible valid RAM size: %" PRIi64 " MiB \n", + error_printf("Possible valid RAM size: %" PRIi64 " MiB\n", used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB); g_string_free(s, true); diff --git a/hw/ppc/ppc4xx_pci.c b/hw/ppc/ppc4xx_pci.c index 5df97e6d15..8642b96455 100644 --- a/hw/ppc/ppc4xx_pci.c +++ b/hw/ppc/ppc4xx_pci.c @@ -16,8 +16,10 @@ * Authors: Hollis Blanchard */ -/* This file implements emulation of the 32-bit PCI controller found in some - * 4xx SoCs, such as the 440EP. */ +/* + * This file implements emulation of the 32-bit PCI controller found in some + * 4xx SoCs, such as the 440EP. + */ #include "qemu/osdep.h" #include "qemu/log.h" @@ -65,8 +67,10 @@ struct PPC4xxPCIState { #define PCIC0_CFGADDR 0x0 #define PCIC0_CFGDATA 0x4 -/* PLB Memory Map (PMM) registers specify which PLB addresses are translated to - * PCI accesses. */ +/* + * PLB Memory Map (PMM) registers specify which PLB addresses are translated to + * PCI accesses. + */ #define PCIL0_PMM0LA 0x0 #define PCIL0_PMM0MA 0x4 #define PCIL0_PMM0PCILA 0x8 @@ -80,8 +84,10 @@ struct PPC4xxPCIState { #define PCIL0_PMM2PCILA 0x28 #define PCIL0_PMM2PCIHA 0x2c -/* PCI Target Map (PTM) registers specify which PCI addresses are translated to - * PLB accesses. */ +/* + * PCI Target Map (PTM) registers specify which PCI addresses are translated to + * PLB accesses. + */ #define PCIL0_PTM1MS 0x30 #define PCIL0_PTM1LA 0x34 #define PCIL0_PTM2MS 0x38 @@ -96,9 +102,10 @@ static void ppc4xx_pci_reg_write4(void *opaque, hwaddr offset, { struct PPC4xxPCIState *pci = opaque; - /* We ignore all target attempts at PCI configuration, effectively - * assuming a bidirectional 1:1 mapping of PLB and PCI space. */ - + /* + * We ignore all target attempts at PCI configuration, effectively + * assuming a bidirectional 1:1 mapping of PLB and PCI space. + */ switch (offset) { case PCIL0_PMM0LA: pci->pmm[0].la = value; @@ -243,8 +250,10 @@ static void ppc4xx_pci_reset(void *opaque) memset(pci->ptm, 0, sizeof(pci->ptm)); } -/* On Bamboo, all pins from each slot are tied to a single board IRQ. This - * may need further refactoring for other boards. */ +/* + * On Bamboo, all pins from each slot are tied to a single board IRQ. + * This may need further refactoring for other boards. + */ static int ppc4xx_pci_map_irq(PCIDevice *pci_dev, int irq_num) { int slot = PCI_SLOT(pci_dev->devfn); From 7bccb9e3222024470073568d05c2121386564ca3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 21:57:20 -0700 Subject: [PATCH 0262/1020] target/avr: Support probe argument to tlb_fill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While there are no target-specific nonfaulting probes, generic code may grow some uses at some point. Note that the attrs argument was incorrect -- it should have been MEMTXATTRS_UNSPECIFIED. Just use the simpler interface. Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/avr/helper.c | 46 ++++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/target/avr/helper.c b/target/avr/helper.c index db76452f9a..82284f8997 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -102,38 +102,50 @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) { - int prot = 0; - MemTxAttrs attrs = {}; + int prot, page_size = TARGET_PAGE_SIZE; uint32_t paddr; address &= TARGET_PAGE_MASK; if (mmu_idx == MMU_CODE_IDX) { - /* access to code in flash */ + /* Access to code in flash. */ paddr = OFFSET_CODE + address; prot = PAGE_READ | PAGE_EXEC; - if (paddr + TARGET_PAGE_SIZE > OFFSET_DATA) { + if (paddr >= OFFSET_DATA) { + /* + * This should not be possible via any architectural operations. + * There is certainly not an exception that we can deliver. + * Accept probing that might come from generic code. + */ + if (probe) { + return false; + } error_report("execution left flash memory"); abort(); } - } else if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { - /* - * access to CPU registers, exit and rebuilt this TB to use full access - * incase it touches specially handled registers like SREG or SP - */ - AVRCPU *cpu = AVR_CPU(cs); - CPUAVRState *env = &cpu->env; - env->fullacc = 1; - cpu_loop_exit_restore(cs, retaddr); } else { - /* access to memory. nothing special */ + /* Access to memory. */ paddr = OFFSET_DATA + address; prot = PAGE_READ | PAGE_WRITE; + if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) { + /* + * Access to CPU registers, exit and rebuilt this TB to use + * full access in case it touches specially handled registers + * like SREG or SP. For probing, set page_size = 1, in order + * to force tlb_fill to be called for the next access. + */ + if (probe) { + page_size = 1; + } else { + AVRCPU *cpu = AVR_CPU(cs); + CPUAVRState *env = &cpu->env; + env->fullacc = 1; + cpu_loop_exit_restore(cs, retaddr); + } + } } - tlb_set_page_with_attrs(cs, address, paddr, attrs, prot, - mmu_idx, TARGET_PAGE_SIZE); - + tlb_set_page(cs, address, paddr, prot, mmu_idx, page_size); return true; } From 9e1b2375daabc4d133baf08766676c5d301bade5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 26 Aug 2022 13:32:56 -0700 Subject: [PATCH 0263/1020] target/avr: Call avr_cpu_do_interrupt directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to go through cc->tcg_ops when we know what value that must have. Reviewed-by: Michael Rolnik Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/avr/helper.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/target/avr/helper.c b/target/avr/helper.c index 82284f8997..9614ccf3e4 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -29,14 +29,13 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { bool ret = false; - CPUClass *cc = CPU_GET_CLASS(cs); AVRCPU *cpu = AVR_CPU(cs); CPUAVRState *env = &cpu->env; if (interrupt_request & CPU_INTERRUPT_RESET) { if (cpu_interrupts_enabled(env)) { cs->exception_index = EXCP_RESET; - cc->tcg_ops->do_interrupt(cs); + avr_cpu_do_interrupt(cs); cs->interrupt_request &= ~CPU_INTERRUPT_RESET; @@ -47,7 +46,7 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) if (cpu_interrupts_enabled(env) && env->intsrc != 0) { int index = ctz32(env->intsrc); cs->exception_index = EXCP_INT(index); - cc->tcg_ops->do_interrupt(cs); + avr_cpu_do_interrupt(cs); env->intsrc &= env->intsrc - 1; /* clear the interrupt */ if (!env->intsrc) { From cecaad540155927f2faf1b6897c72cc59074cb45 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 26 Aug 2022 13:35:52 -0700 Subject: [PATCH 0264/1020] target/avr: Only execute one interrupt at a time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We cannot deliver two interrupts simultaneously; the first interrupt handler must execute first. Reviewed-by: Michael Rolnik Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/avr/helper.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/target/avr/helper.c b/target/avr/helper.c index 9614ccf3e4..34f1cbffb2 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -28,7 +28,6 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) { - bool ret = false; AVRCPU *cpu = AVR_CPU(cs); CPUAVRState *env = &cpu->env; @@ -38,8 +37,7 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) avr_cpu_do_interrupt(cs); cs->interrupt_request &= ~CPU_INTERRUPT_RESET; - - ret = true; + return true; } } if (interrupt_request & CPU_INTERRUPT_HARD) { @@ -52,11 +50,10 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) if (!env->intsrc) { cs->interrupt_request &= ~CPU_INTERRUPT_HARD; } - - ret = true; + return true; } } - return ret; + return false; } void avr_cpu_do_interrupt(CPUState *cs) From 36027c70974fef1392e6c73dfb94c3f94f0930bc Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 26 Aug 2022 13:53:32 -0700 Subject: [PATCH 0265/1020] target/avr: Disable interrupts when env->skip set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bit is not saved across interrupts, so we must delay delivering the interrupt until the skip has been processed. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1118 Reviewed-by: Michael Rolnik Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- target/avr/helper.c | 9 +++++++++ target/avr/translate.c | 26 ++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/target/avr/helper.c b/target/avr/helper.c index 34f1cbffb2..156dde4e92 100644 --- a/target/avr/helper.c +++ b/target/avr/helper.c @@ -31,6 +31,15 @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request) AVRCPU *cpu = AVR_CPU(cs); CPUAVRState *env = &cpu->env; + /* + * We cannot separate a skip from the next instruction, + * as the skip would not be preserved across the interrupt. + * Separating the two insn normally only happens at page boundaries. + */ + if (env->skip) { + return false; + } + if (interrupt_request & CPU_INTERRUPT_RESET) { if (cpu_interrupts_enabled(env)) { cs->exception_index = EXCP_RESET; diff --git a/target/avr/translate.c b/target/avr/translate.c index dc9c3d6bcc..026753c963 100644 --- a/target/avr/translate.c +++ b/target/avr/translate.c @@ -2971,8 +2971,18 @@ static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (skip_label) { canonicalize_skip(ctx); gen_set_label(skip_label); - if (ctx->base.is_jmp == DISAS_NORETURN) { + + switch (ctx->base.is_jmp) { + case DISAS_NORETURN: ctx->base.is_jmp = DISAS_CHAIN; + break; + case DISAS_NEXT: + if (ctx->base.tb->flags & TB_FLAGS_SKIP) { + ctx->base.is_jmp = DISAS_TOO_MANY; + } + break; + default: + break; } } @@ -2989,6 +2999,11 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); bool nonconst_skip = canonicalize_skip(ctx); + /* + * Because we disable interrupts while env->skip is set, + * we must return to the main loop to re-evaluate afterward. + */ + bool force_exit = ctx->base.tb->flags & TB_FLAGS_SKIP; switch (ctx->base.is_jmp) { case DISAS_NORETURN: @@ -2997,7 +3012,7 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) case DISAS_NEXT: case DISAS_TOO_MANY: case DISAS_CHAIN: - if (!nonconst_skip) { + if (!nonconst_skip && !force_exit) { /* Note gen_goto_tb checks singlestep. */ gen_goto_tb(ctx, 1, ctx->npc); break; @@ -3005,8 +3020,11 @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) tcg_gen_movi_tl(cpu_pc, ctx->npc); /* fall through */ case DISAS_LOOKUP: - tcg_gen_lookup_and_goto_ptr(); - break; + if (!force_exit) { + tcg_gen_lookup_and_goto_ptr(); + break; + } + /* fall through */ case DISAS_EXIT: tcg_gen_exit_tb(NULL, 0); break; From c6e51f1bb28ed762d2039c063cbb71a8ad29762d Mon Sep 17 00:00:00 2001 From: John Millikin Date: Wed, 17 Aug 2022 14:38:47 +0900 Subject: [PATCH 0266/1020] esp: Handle CMD_BUSRESET by resetting the SCSI bus Per investigation on the linked ticket, SunOS issues a SCSI bus reset to the ESP as part of its boot sequence. If this ESP command doesn't cause devices to assert sense flag UNIT ATTENTION, SunOS will consider the CD-ROM device to be non-compliant with Common Command Set (CCS). In this condition, the SunOS installer's early userspace doesn't set the installation source location to sr0 and the miniroot copy fails. Signed-off-by: John Millikin Suggested-by: Bill Paul Buglink: https://gitlab.com/qemu-project/qemu/-/issues/1127 Message-Id: <20220817053846.699310-1-john@john-millikin.com> Signed-off-by: Paolo Bonzini --- hw/scsi/esp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 2d3c649567..c799c19bd4 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -939,6 +939,11 @@ static void esp_soft_reset(ESPState *s) esp_hard_reset(s); } +static void esp_bus_reset(ESPState *s) +{ + qbus_reset_all(BUS(&s->bus)); +} + static void parent_esp_reset(ESPState *s, int irq, int level) { if (level) { @@ -1067,6 +1072,7 @@ void esp_reg_write(ESPState *s, uint32_t saddr, uint64_t val) break; case CMD_BUSRESET: trace_esp_mem_writeb_cmd_bus_reset(val); + esp_bus_reset(s); if (!(s->wregs[ESP_CFG1] & CFG1_RESREPT)) { s->rregs[ESP_RINTR] |= INTR_RST; esp_raise_irq(s); From fe9d8927e265fd723a6dc87cd6d220f4677dbe1f Mon Sep 17 00:00:00 2001 From: John Millikin Date: Wed, 17 Aug 2022 14:34:58 +0900 Subject: [PATCH 0267/1020] scsi: Add buf_len parameter to scsi_req_new() When a SCSI command is received from the guest, the CDB length implied by the first byte might exceed the number of bytes the guest sent. In this case scsi_req_new() will read uninitialized data, causing unpredictable behavior. Adds the buf_len parameter to scsi_req_new() and plumbs it through the call stack. Signed-off-by: John Millikin Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1127 Message-Id: <20220817053458.698416-1-john@john-millikin.com> [Fill in correct length for adapters other than ESP. - Paolo] Signed-off-by: Paolo Bonzini --- hw/scsi/esp.c | 2 +- hw/scsi/lsi53c895a.c | 2 +- hw/scsi/megasas.c | 10 +++++----- hw/scsi/mptsas.c | 3 ++- hw/scsi/scsi-bus.c | 21 +++++++++++++-------- hw/scsi/scsi-disk.c | 7 ++++--- hw/scsi/scsi-generic.c | 5 +++-- hw/scsi/spapr_vscsi.c | 3 ++- hw/scsi/virtio-scsi.c | 5 +++-- hw/scsi/vmw_pvscsi.c | 2 +- hw/usb/dev-storage.c | 2 +- hw/usb/dev-uas.c | 5 +++-- include/hw/scsi/scsi.h | 11 ++++++----- 13 files changed, 45 insertions(+), 33 deletions(-) diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index c799c19bd4..2ff18ce500 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -292,7 +292,7 @@ static void do_command_phase(ESPState *s) esp_fifo_pop_buf(&s->cmdfifo, buf, cmdlen); current_lun = scsi_device_find(&s->bus, 0, s->current_dev->id, s->lun); - s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, s); + s->current_req = scsi_req_new(current_lun, 0, s->lun, buf, cmdlen, s); datalen = scsi_req_enqueue(s->current_req); s->ti_size = datalen; fifo8_reset(&s->cmdfifo); diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index ad5f5e5f39..05a43ec807 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -864,7 +864,7 @@ static void lsi_do_command(LSIState *s) s->current = g_new0(lsi_request, 1); s->current->tag = s->select_tag; s->current->req = scsi_req_new(dev, s->current->tag, s->current_lun, buf, - s->current); + s->dbc, s->current); n = scsi_req_enqueue(s->current->req); if (n) { diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index d5dfb412ba..7082456d65 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -1062,7 +1062,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, info->inquiry_data[0] = 0x7f; /* Force PQual 0x3, PType 0x1f */ info->vpd_page83[0] = 0x7f; megasas_setup_inquiry(cmdbuf, 0, sizeof(info->inquiry_data)); - cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd); + cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, sizeof(cmdbuf), cmd); if (!cmd->req) { trace_megasas_dcmd_req_alloc_failed(cmd->index, "PD get info std inquiry"); @@ -1080,7 +1080,7 @@ static int megasas_pd_get_info_submit(SCSIDevice *sdev, int lun, return MFI_STAT_INVALID_STATUS; } else if (info->inquiry_data[0] != 0x7f && info->vpd_page83[0] == 0x7f) { megasas_setup_inquiry(cmdbuf, 0x83, sizeof(info->vpd_page83)); - cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, cmd); + cmd->req = scsi_req_new(sdev, cmd->index, lun, cmdbuf, sizeof(cmdbuf), cmd); if (!cmd->req) { trace_megasas_dcmd_req_alloc_failed(cmd->index, "PD get info vpd inquiry"); @@ -1268,7 +1268,7 @@ static int megasas_ld_get_info_submit(SCSIDevice *sdev, int lun, cmd->iov_buf = g_malloc0(dcmd_size); info = cmd->iov_buf; megasas_setup_inquiry(cdb, 0x83, sizeof(info->vpd_page83)); - cmd->req = scsi_req_new(sdev, cmd->index, lun, cdb, cmd); + cmd->req = scsi_req_new(sdev, cmd->index, lun, cdb, sizeof(cdb), cmd); if (!cmd->req) { trace_megasas_dcmd_req_alloc_failed(cmd->index, "LD get info vpd inquiry"); @@ -1748,7 +1748,7 @@ static int megasas_handle_scsi(MegasasState *s, MegasasCmd *cmd, return MFI_STAT_SCSI_DONE_WITH_ERROR; } - cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cmd); + cmd->req = scsi_req_new(sdev, cmd->index, lun_id, cdb, cdb_len, cmd); if (!cmd->req) { trace_megasas_scsi_req_alloc_failed( mfi_frame_desc(frame_cmd), target_id, lun_id); @@ -1823,7 +1823,7 @@ static int megasas_handle_io(MegasasState *s, MegasasCmd *cmd, int frame_cmd) megasas_encode_lba(cdb, lba_start, lba_count, is_write); cmd->req = scsi_req_new(sdev, cmd->index, - lun_id, cdb, cmd); + lun_id, cdb, cdb_len, cmd); if (!cmd->req) { trace_megasas_scsi_req_alloc_failed( mfi_frame_desc(frame_cmd), target_id, lun_id); diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c index 706cf0df3a..a90c2546f1 100644 --- a/hw/scsi/mptsas.c +++ b/hw/scsi/mptsas.c @@ -324,7 +324,8 @@ static int mptsas_process_scsi_io_request(MPTSASState *s, } req->sreq = scsi_req_new(sdev, scsi_io->MsgContext, - scsi_io->LUN[1], scsi_io->CDB, req); + scsi_io->LUN[1], scsi_io->CDB, + scsi_io->CDBLength, req); if (req->sreq->cmd.xfer > scsi_io->DataLength) { goto overrun; diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index b2e2bc3c96..cc71524024 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -102,15 +102,15 @@ static void scsi_device_unrealize(SCSIDevice *s) } int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, - void *hba_private) + size_t buf_len, void *hba_private) { SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, dev->qdev.parent_bus); int rc; assert(cmd->len == 0); - rc = scsi_req_parse_cdb(dev, cmd, buf); + rc = scsi_req_parse_cdb(dev, cmd, buf, buf_len); if (bus->info->parse_cdb) { - rc = bus->info->parse_cdb(dev, cmd, buf, hba_private); + rc = bus->info->parse_cdb(dev, cmd, buf, buf_len, hba_private); } return rc; } @@ -703,7 +703,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, } SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, - uint8_t *buf, void *hba_private) + uint8_t *buf, size_t buf_len, void *hba_private) { SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, d->qdev.parent_bus); const SCSIReqOps *ops; @@ -734,9 +734,9 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, } if (ops != NULL || !sc->parse_cdb) { - ret = scsi_req_parse_cdb(d, &cmd, buf); + ret = scsi_req_parse_cdb(d, &cmd, buf, buf_len); } else { - ret = sc->parse_cdb(d, &cmd, buf, hba_private); + ret = sc->parse_cdb(d, &cmd, buf, buf_len, hba_private); } if (ret != 0) { @@ -1308,7 +1308,8 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd) } } -int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf) +int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, + size_t buf_len) { int rc; int len; @@ -1713,7 +1714,11 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size, qemu_get_buffer(f, buf, sizeof(buf)); qemu_get_be32s(f, &tag); qemu_get_be32s(f, &lun); - req = scsi_req_new(s, tag, lun, buf, NULL); + /* + * A too-short CDB would have been rejected by scsi_req_new, so just use + * SCSI_CMD_BUF_SIZE as the CDB length. + */ + req = scsi_req_new(s, tag, lun, buf, sizeof(buf), NULL); req->retry = (sbyte == 1); if (bus->info->load_request) { req->hba_private = bus->info->load_request(f, req); diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index efee6739f9..399e1787ea 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -3030,14 +3030,15 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag, } static int scsi_block_parse_cdb(SCSIDevice *d, SCSICommand *cmd, - uint8_t *buf, void *hba_private) + uint8_t *buf, size_t buf_len, + void *hba_private) { SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, d); if (scsi_block_is_passthrough(s, buf)) { - return scsi_bus_parse_cdb(&s->qdev, cmd, buf, hba_private); + return scsi_bus_parse_cdb(&s->qdev, cmd, buf, buf_len, hba_private); } else { - return scsi_req_parse_cdb(&s->qdev, cmd, buf); + return scsi_req_parse_cdb(&s->qdev, cmd, buf, buf_len); } } diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index 3d35d307e1..92cce20a4d 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -791,9 +791,10 @@ static Property scsi_generic_properties[] = { }; static int scsi_generic_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, - uint8_t *buf, void *hba_private) + uint8_t *buf, size_t buf_len, + void *hba_private) { - return scsi_bus_parse_cdb(dev, cmd, buf, hba_private); + return scsi_bus_parse_cdb(dev, cmd, buf, buf_len, hba_private); } static void scsi_generic_class_initfn(ObjectClass *klass, void *data) diff --git a/hw/scsi/spapr_vscsi.c b/hw/scsi/spapr_vscsi.c index e320ccaa23..0a8cbf5a4b 100644 --- a/hw/scsi/spapr_vscsi.c +++ b/hw/scsi/spapr_vscsi.c @@ -783,6 +783,7 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req) union srp_iu *srp = &req_iu(req)->srp; SCSIDevice *sdev; int n, lun; + size_t cdb_len = sizeof (srp->cmd.cdb) + (srp->cmd.add_cdb_len & ~3); if ((srp->cmd.lun == 0 || be64_to_cpu(srp->cmd.lun) == SRP_REPORT_LUNS_WLUN) && srp->cmd.cdb[0] == REPORT_LUNS) { @@ -801,7 +802,7 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req) } return 1; } - req->sreq = scsi_req_new(sdev, req->qtag, lun, srp->cmd.cdb, req); + req->sreq = scsi_req_new(sdev, req->qtag, lun, srp->cmd.cdb, cdb_len, req); n = scsi_req_enqueue(req->sreq); trace_spapr_vscsi_queue_cmd(req->qtag, srp->cmd.cdb[0], diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 4141dddd51..41f2a56301 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -622,7 +622,8 @@ static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid) } static int virtio_scsi_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, - uint8_t *buf, void *hba_private) + uint8_t *buf, size_t buf_len, + void *hba_private) { VirtIOSCSIReq *req = hba_private; @@ -696,7 +697,7 @@ static int virtio_scsi_handle_cmd_req_prepare(VirtIOSCSI *s, VirtIOSCSIReq *req) virtio_scsi_ctx_check(s, d); req->sreq = scsi_req_new(d, req->req.cmd.tag, virtio_scsi_get_lun(req->req.cmd.lun), - req->req.cmd.cdb, req); + req->req.cmd.cdb, vs->cdb_size, req); if (req->sreq->cmd.mode != SCSI_XFER_NONE && (req->sreq->cmd.mode != req->mode || diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c index 4d9969f3b1..91e2f858ab 100644 --- a/hw/scsi/vmw_pvscsi.c +++ b/hw/scsi/vmw_pvscsi.c @@ -730,7 +730,7 @@ pvscsi_process_request_descriptor(PVSCSIState *s, r->sg.elemAddr = descr->dataAddr; } - r->sreq = scsi_req_new(d, descr->context, r->lun, descr->cdb, r); + r->sreq = scsi_req_new(d, descr->context, r->lun, descr->cdb, descr->cdbLen, r); if (r->sreq->cmd.mode == SCSI_XFER_FROM_DEV && (descr->flags & PVSCSI_FLAG_CMD_DIR_TODEVICE)) { r->cmp.hostStatus = BTSTAT_BADMSG; diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index dca62d544f..98639696e6 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -415,7 +415,7 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) cbw.cmd_len, s->data_len); assert(le32_to_cpu(s->csw.residue) == 0); s->scsi_len = 0; - s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, NULL); + s->req = scsi_req_new(scsi_dev, tag, cbw.lun, cbw.cmd, cbw.cmd_len, NULL); if (s->commandlog) { scsi_req_print(s->req); } diff --git a/hw/usb/dev-uas.c b/hw/usb/dev-uas.c index c9f295e7e4..5192b062d6 100644 --- a/hw/usb/dev-uas.c +++ b/hw/usb/dev-uas.c @@ -71,7 +71,7 @@ typedef struct { uint8_t reserved_2; uint64_t lun; uint8_t cdb[16]; - uint8_t add_cdb[1]; /* not supported by QEMU */ + uint8_t add_cdb[1]; } QEMU_PACKED uas_iu_command; typedef struct { @@ -699,6 +699,7 @@ static void usb_uas_command(UASDevice *uas, uas_iu *iu) UASRequest *req; uint32_t len; uint16_t tag = be16_to_cpu(iu->hdr.tag); + size_t cdb_len = sizeof(iu->command.cdb) + iu->command.add_cdb_length; if (iu->command.add_cdb_length > 0) { qemu_log_mask(LOG_UNIMP, "additional adb length not yet supported\n"); @@ -729,7 +730,7 @@ static void usb_uas_command(UASDevice *uas, uas_iu *iu) req->req = scsi_req_new(req->dev, req->tag, usb_uas_get_lun(req->lun), - iu->command.cdb, req); + iu->command.cdb, cdb_len, req); if (uas->requestlog) { scsi_req_print(req->req); } diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index e284e3a4ec..001103488c 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -59,7 +59,7 @@ struct SCSIDeviceClass { void (*realize)(SCSIDevice *dev, Error **errp); void (*unrealize)(SCSIDevice *dev); int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, - void *hba_private); + size_t buf_len, void *hba_private); SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun, uint8_t *buf, void *hba_private); void (*unit_attention_reported)(SCSIDevice *s); @@ -122,7 +122,7 @@ struct SCSIBusInfo { int tcq; int max_channel, max_target, max_lun; int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, - void *hba_private); + size_t buf_len, void *hba_private); void (*transfer_data)(SCSIRequest *req, uint32_t arg); void (*fail)(SCSIRequest *req); void (*complete)(SCSIRequest *req, size_t residual); @@ -192,14 +192,15 @@ void scsi_legacy_handle_cmdline(void); SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d, uint32_t tag, uint32_t lun, void *hba_private); SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, - uint8_t *buf, void *hba_private); + uint8_t *buf, size_t buf_len, void *hba_private); int32_t scsi_req_enqueue(SCSIRequest *req); SCSIRequest *scsi_req_ref(SCSIRequest *req); void scsi_req_unref(SCSIRequest *req); int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, - void *hba_private); -int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf); + size_t buf_len, void *hba_private); +int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, + size_t buf_len); void scsi_req_build_sense(SCSIRequest *req, SCSISense sense); void scsi_req_print(SCSIRequest *req); void scsi_req_continue(SCSIRequest *req); From 6d1511cea0fb536f2df7b6c31bb745d80b98d82e Mon Sep 17 00:00:00 2001 From: John Millikin Date: Wed, 17 Aug 2022 14:35:00 +0900 Subject: [PATCH 0268/1020] scsi: Reject commands if the CDB length exceeds buf_len In scsi_req_parse_cdb(), if the CDB length implied by the command type exceeds the initialized portion of the command buffer, reject the request. Rejected requests are recorded by the `scsi_req_parse_bad` trace event. On example of a bug detected by this check is SunOS's use of interleaved DMA and non-DMA commands. This guest behavior currently causes QEMU to parse uninitialized memory as a SCSI command, with unpredictable outcomes. With the new check in place: * QEMU consistently creates a trace event and rejects the request. * SunOS retries the request(s) and is able to successfully boot from disk. Signed-off-by: John Millikin Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1127 Message-Id: <20220817053458.698416-2-john@john-millikin.com> Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-bus.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index cc71524024..4403717c4a 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -712,6 +712,11 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, SCSICommand cmd = { .len = 0 }; int ret; + if (buf_len == 0) { + trace_scsi_req_parse_bad(d->id, lun, tag, 0); + goto invalid_opcode; + } + if ((d->unit_attention.key == UNIT_ATTENTION || bus->unit_attention.key == UNIT_ATTENTION) && (buf[0] != INQUIRY && @@ -741,6 +746,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun, if (ret != 0) { trace_scsi_req_parse_bad(d->id, lun, tag, buf[0]); +invalid_opcode: req = scsi_req_alloc(&reqops_invalid_opcode, d, tag, lun, hba_private); } else { assert(cmd.len != 0); @@ -1316,7 +1322,7 @@ int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf, cmd->lba = -1; len = scsi_cdb_length(buf); - if (len < 0) { + if (len < 0 || len > buf_len) { return -1; } From 3cafdb67504a34a0305260f0c86a73d5a3fb000b Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Thu, 18 Aug 2022 17:01:12 +0200 Subject: [PATCH 0269/1020] i386: reset KVM nested state upon CPU reset Make sure env->nested_state is cleaned up when a vCPU is reset, it may be stale after an incoming migration, kvm_arch_put_registers() may end up failing or putting vCPU in a weird state. Reviewed-by: Maxim Levitsky Signed-off-by: Vitaly Kuznetsov Message-Id: <20220818150113.479917-2-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini --- target/i386/kvm/kvm.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index f148a6d52f..4f8dacc1d4 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -1695,6 +1695,30 @@ static void kvm_init_xsave(CPUX86State *env) env->xsave_buf_len); } +static void kvm_init_nested_state(CPUX86State *env) +{ + struct kvm_vmx_nested_state_hdr *vmx_hdr; + uint32_t size; + + if (!env->nested_state) { + return; + } + + size = env->nested_state->size; + + memset(env->nested_state, 0, size); + env->nested_state->size = size; + + if (cpu_has_vmx(env)) { + env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; + vmx_hdr = &env->nested_state->hdr.vmx; + vmx_hdr->vmxon_pa = -1ull; + vmx_hdr->vmcs12_pa = -1ull; + } else if (cpu_has_svm(env)) { + env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM; + } +} + int kvm_arch_init_vcpu(CPUState *cs) { struct { @@ -2122,19 +2146,10 @@ int kvm_arch_init_vcpu(CPUState *cs) assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); if (cpu_has_vmx(env) || cpu_has_svm(env)) { - struct kvm_vmx_nested_state_hdr *vmx_hdr; - env->nested_state = g_malloc0(max_nested_state_len); env->nested_state->size = max_nested_state_len; - if (cpu_has_vmx(env)) { - env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; - vmx_hdr = &env->nested_state->hdr.vmx; - vmx_hdr->vmxon_pa = -1ull; - vmx_hdr->vmcs12_pa = -1ull; - } else { - env->nested_state->format = KVM_STATE_NESTED_FORMAT_SVM; - } + kvm_init_nested_state(env); } } @@ -2199,6 +2214,8 @@ void kvm_arch_reset_vcpu(X86CPU *cpu) /* enabled by default */ env->poll_control_msr = 1; + kvm_init_nested_state(env); + sev_es_set_reset_vector(CPU(cpu)); } From 45ed68a1a3a19754ade954d75a3c9d13ff560e5c Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Thu, 18 Aug 2022 17:01:13 +0200 Subject: [PATCH 0270/1020] i386: do kvm_put_msr_feature_control() first thing when vCPU is reset kvm_put_sregs2() fails to reset 'locked' CR4/CR0 bits upon vCPU reset when it is in VMX root operation. Do kvm_put_msr_feature_control() before kvm_put_sregs2() to (possibly) kick vCPU out of VMX root operation. It also seems logical to do kvm_put_msr_feature_control() before kvm_put_nested_state() and not after it, especially when 'real' nested state is set. Signed-off-by: Vitaly Kuznetsov Message-Id: <20220818150113.479917-3-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini --- target/i386/kvm/kvm.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index 4f8dacc1d4..a1fd1f5379 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -4529,6 +4529,18 @@ int kvm_arch_put_registers(CPUState *cpu, int level) assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + /* + * Put MSR_IA32_FEATURE_CONTROL first, this ensures the VM gets out of VMX + * root operation upon vCPU reset. kvm_put_msr_feature_control() should also + * preceed kvm_put_nested_state() when 'real' nested state is set. + */ + if (level >= KVM_PUT_RESET_STATE) { + ret = kvm_put_msr_feature_control(x86_cpu); + if (ret < 0) { + return ret; + } + } + /* must be before kvm_put_nested_state so that EFER.SVME is set */ ret = has_sregs2 ? kvm_put_sregs2(x86_cpu) : kvm_put_sregs(x86_cpu); if (ret < 0) { @@ -4540,11 +4552,6 @@ int kvm_arch_put_registers(CPUState *cpu, int level) if (ret < 0) { return ret; } - - ret = kvm_put_msr_feature_control(x86_cpu); - if (ret < 0) { - return ret; - } } if (level == KVM_PUT_FULL_STATE) { From 7cb5844808f092306a5a764fe8427a653ac05358 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 19 Aug 2022 18:40:46 +0200 Subject: [PATCH 0271/1020] configure: improve error for ucontext coroutine backend Instead of using feature_not_found(), which is not a good match because there is no "remedy" to fix the lack of makecontext(), just print a custom error. This happens to remove the last use of feature_not_found(), so remove the definition and the documentation. Signed-off-by: Paolo Bonzini --- configure | 11 +---------- docs/devel/build-system.rst | 5 ----- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/configure b/configure index 72ab03f11a..575dde1c1f 100755 --- a/configure +++ b/configure @@ -1468,15 +1468,6 @@ if test "$tcg" = "enabled"; then git_submodules="$git_submodules tests/fp/berkeley-softfloat-3" fi -feature_not_found() { - feature=$1 - remedy=$2 - - error_exit "User requested feature $feature" \ - "configure was not able to find it." \ - "$remedy" -} - # --- # big/little endian test cat > $TMPC << EOF @@ -1639,7 +1630,7 @@ else ;; ucontext) if test "$ucontext_works" != "yes"; then - feature_not_found "ucontext" + error_exit "'ucontext' backend requested but makecontext not available" fi ;; sigaltstack) diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst index 431caba7aa..1894721743 100644 --- a/docs/devel/build-system.rst +++ b/docs/devel/build-system.rst @@ -99,11 +99,6 @@ developers in checking for system features: Write a minimal C program main() function to the temporary file indicated by $TMPC -``feature_not_found $NAME $REMEDY`` - Print a message to stderr that the feature $NAME was not available - on the system, suggesting the user try $REMEDY to address the - problem. - ``error_exit $MESSAGE $MORE...`` Print $MESSAGE to stderr, followed by $MORE... and then exit from the configure script with non-zero status From 0169815b47bffe4361ac2370a4ad584277a62a96 Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Wed, 17 Aug 2022 14:37:23 +0000 Subject: [PATCH 0272/1020] meson: be strict for boolean options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While Meson buildsystem accepts the 'false' as a value for boolean options, it's not covered by the specification and in general invalid. Some alternative Meson implementations, like Muon, do not accept 'false' or 'true' as a valid value for the boolean options. See https://mesonbuild.com/Build-options.html Signed-off-by: Anton Kochkov Reviewed-by: Philippe Mathieu-Daudé Message-Id: <20220817143538.2107779-1-anton.kochkov@proton.me> Signed-off-by: Paolo Bonzini --- meson_options.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/meson_options.txt b/meson_options.txt index e58e158396..63f0725174 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -82,9 +82,9 @@ option('tcg', type: 'feature', value: 'enabled', description: 'TCG support') option('tcg_interpreter', type: 'boolean', value: false, description: 'TCG with bytecode interpreter (slow)') -option('cfi', type: 'boolean', value: 'false', +option('cfi', type: 'boolean', value: false, description: 'Control-Flow Integrity (CFI)') -option('cfi_debug', type: 'boolean', value: 'false', +option('cfi_debug', type: 'boolean', value: false, description: 'Verbose errors in case of CFI violation') option('multiprocess', type: 'feature', value: 'auto', description: 'Out of process device emulation support') From eccae02d99dfcf32d5c5db76f59c8f6ba25b5cb0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 14 Jul 2022 10:43:46 +0200 Subject: [PATCH 0273/1020] meson: remove dead code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found with "muon analyze". Reviewed-by: Marc-André Lureau Signed-off-by: Paolo Bonzini --- meson.build | 2 -- pc-bios/keymaps/meson.build | 1 - qapi/meson.build | 15 --------------- target/riscv/meson.build | 2 -- 4 files changed, 20 deletions(-) diff --git a/meson.build b/meson.build index 20fddbd707..ca1ba46928 100644 --- a/meson.build +++ b/meson.build @@ -3405,7 +3405,6 @@ foreach target : target_dirs target_inc += include_directories('linux-headers', is_system: true) endif if target.endswith('-softmmu') - qemu_target_name = 'qemu-system-' + target_name target_type='system' t = target_softmmu_arch[target_base_arch].apply(config_target, strict: false) arch_srcs += t.sources() @@ -3422,7 +3421,6 @@ foreach target : target_dirs abi = config_target['TARGET_ABI_DIR'] target_type='user' target_inc += common_user_inc - qemu_target_name = 'qemu-' + target_name if target_base_arch in target_user_arch t = target_user_arch[target_base_arch].apply(config_target, strict: false) arch_srcs += t.sources() diff --git a/pc-bios/keymaps/meson.build b/pc-bios/keymaps/meson.build index 2837eb34f4..06c75e646b 100644 --- a/pc-bios/keymaps/meson.build +++ b/pc-bios/keymaps/meson.build @@ -38,7 +38,6 @@ if meson.is_cross_build() or 'CONFIG_XKBCOMMON' not in config_host else native_qemu_keymap = qemu_keymap endif -cp = find_program('cp') if native_qemu_keymap.found() t = [] diff --git a/qapi/meson.build b/qapi/meson.build index fd5c93d643..840f1b0e19 100644 --- a/qapi/meson.build +++ b/qapi/meson.build @@ -68,21 +68,6 @@ if have_system or have_tools ] endif -qapi_storage_daemon_modules = [ - 'block-core', - 'block-export', - 'char', - 'common', - 'control', - 'crypto', - 'introspect', - 'job', - 'qom', - 'sockets', - 'pragma', - 'transaction', -] - qapi_nonmodule_outputs = [ 'qapi-introspect.c', 'qapi-introspect.h', 'qapi-types.c', 'qapi-types.h', diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 2c1975e72c..6b9435d69a 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -1,6 +1,4 @@ # FIXME extra_args should accept files() -dir = meson.current_source_dir() - gen = [ decodetree.process('insn16.decode', extra_args: ['--static-decode=decode_insn16', '--insnwidth=16']), decodetree.process('insn32.decode', extra_args: '--static-decode=decode_insn32'), From e3af71e9009de156665df67b9bdf5bc192aae215 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 14 Jul 2022 10:43:57 +0200 Subject: [PATCH 0274/1020] meson: remove dead assignments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found with "muon analyze". Reviewed-by: Marc-André Lureau Signed-off-by: Paolo Bonzini --- plugins/meson.build | 2 +- tests/fp/meson.build | 2 +- tests/qapi-schema/meson.build | 24 ++++++++++++------------ 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/meson.build b/plugins/meson.build index fa12047327..752377c66d 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -2,7 +2,7 @@ plugin_ldflags = [] # Modules need more symbols than just those in plugins/qemu-plugins.symbols if not enable_modules if targetos == 'darwin' - qemu_plugins_symbols_list = configure_file( + configure_file( input: files('qemu-plugins.symbols'), output: 'qemu-plugins-ld64.symbols', capture: true, diff --git a/tests/fp/meson.build b/tests/fp/meson.build index 2b4f00b916..6258e2bd7d 100644 --- a/tests/fp/meson.build +++ b/tests/fp/meson.build @@ -632,7 +632,7 @@ test('fp-test-mulAdd', fptest, ['f16_mulAdd', 'f32_mulAdd', 'f64_mulAdd', 'f128_mulAdd'], suite: ['softfloat-slow', 'softfloat-ops-slow', 'slow'], timeout: 90) -fpbench = executable( +executable( 'fp-bench', ['fp-bench.c', '../../fpu/softfloat.c'], link_with: [libtestfloat, libsoftfloat], diff --git a/tests/qapi-schema/meson.build b/tests/qapi-schema/meson.build index c18dd7d02f..406bc7255d 100644 --- a/tests/qapi-schema/meson.build +++ b/tests/qapi-schema/meson.build @@ -215,18 +215,18 @@ test('QAPI schema regression tests', python, diff = find_program('diff') -qapi_doc = custom_target('QAPI doc', - output: ['doc-good-qapi-commands.c', 'doc-good-qapi-commands.h', - 'doc-good-qapi-emit-events.c', 'doc-good-qapi-emit-events.h', - 'doc-good-qapi-events.c', 'doc-good-qapi-events.h', - 'doc-good-qapi-init-commands.c', 'doc-good-qapi-init-commands.h', - 'doc-good-qapi-introspect.c', 'doc-good-qapi-introspect.h', - 'doc-good-qapi-types.c', 'doc-good-qapi-types.h', - 'doc-good-qapi-visit.c', 'doc-good-qapi-visit.h' ], - input: files('doc-good.json'), - command: [ qapi_gen, '-o', meson.current_build_dir(), - '-p', 'doc-good-', '@INPUT0@' ], - depend_files: qapi_gen_depends) +custom_target('QAPI doc', + output: ['doc-good-qapi-commands.c', 'doc-good-qapi-commands.h', + 'doc-good-qapi-emit-events.c', 'doc-good-qapi-emit-events.h', + 'doc-good-qapi-events.c', 'doc-good-qapi-events.h', + 'doc-good-qapi-init-commands.c', 'doc-good-qapi-init-commands.h', + 'doc-good-qapi-introspect.c', 'doc-good-qapi-introspect.h', + 'doc-good-qapi-types.c', 'doc-good-qapi-types.h', + 'doc-good-qapi-visit.c', 'doc-good-qapi-visit.h' ], + input: files('doc-good.json'), + command: [ qapi_gen, '-o', meson.current_build_dir(), + '-p', 'doc-good-', '@INPUT0@' ], + depend_files: qapi_gen_depends) if build_docs # Test the document-comment document generation code by running a test schema From 4802bf910eee98312c4a9777ac2567e6a0445c46 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 26 Aug 2022 13:00:00 +0200 Subject: [PATCH 0275/1020] KVM: dirty ring: add missing memory barrier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The KVM_DIRTY_GFN_F_DIRTY flag ensures that the entry is valid. If the read of the fields are not ordered after the read of the flag, QEMU might see stale values. Cc: Gavin Shan Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Xu Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 8d81ab74de..136c8eaed3 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -719,7 +719,11 @@ static void kvm_dirty_ring_mark_page(KVMState *s, uint32_t as_id, static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn) { - return gfn->flags == KVM_DIRTY_GFN_F_DIRTY; + /* + * Read the flags before the value. Pairs with barrier in + * KVM's kvm_dirty_ring_push() function. + */ + return qatomic_load_acquire(&gfn->flags) == KVM_DIRTY_GFN_F_DIRTY; } static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn) From 9e8504c0572de7a6d91e95738beaf18ffada1cf2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 25 Aug 2022 14:27:00 +0200 Subject: [PATCH 0276/1020] tests/tcg: x86_64: improve consistency with i386 Include test-i386-bmi2, and specify manually the tests (only one for now) that need -cpu max. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- tests/tcg/i386/Makefile.target | 2 +- tests/tcg/x86_64/Makefile.target | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index bd73c96d0d..5614838ffc 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -8,7 +8,7 @@ VPATH += $(I386_SRC) I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c)) ALL_X86_TESTS=$(I386_SRCS:.c=) SKIP_I386_TESTS=test-i386-ssse3 -X86_64_TESTS:=$(filter test-i386-ssse3, $(ALL_X86_TESTS)) +X86_64_TESTS:=$(filter test-i386-bmi2 test-i386-ssse3, $(ALL_X86_TESTS)) test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target index b71a6bcd5e..61d9bb426e 100644 --- a/tests/tcg/x86_64/Makefile.target +++ b/tests/tcg/x86_64/Makefile.target @@ -14,7 +14,9 @@ TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64 else TESTS=$(MULTIARCH_TESTS) endif -QEMU_OPTS += -cpu max + +run-test-i386-ssse3: QEMU_OPTS += -cpu max +run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max test-x86_64: LDFLAGS+=-lm -lc test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h From 7b764d41733075624bf7d93b3e1ff9aa8f66f563 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 25 Aug 2022 12:58:18 +0200 Subject: [PATCH 0277/1020] tests/tcg: i386: extend BMI test Cover all BMI1 and BMI2 instructions, both 32- and 64-bit. Due to the use of inlines, the test now has to be compiled with -O2. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- tests/tcg/i386/Makefile.target | 1 + tests/tcg/i386/test-i386-bmi2.c | 169 ++++++++++++++++++++++++++++++-- 2 files changed, 162 insertions(+), 8 deletions(-) diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index 5614838ffc..646b4ac13e 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -18,6 +18,7 @@ test-i386-pcmpistri: CFLAGS += -msse4.2 run-test-i386-pcmpistri: QEMU_OPTS += -cpu max run-plugin-test-i386-pcmpistri-%: QEMU_OPTS += -cpu max +test-i386-bmi2: CFLAGS=-O2 run-test-i386-bmi2: QEMU_OPTS += -cpu max run-plugin-test-i386-bmi2-%: QEMU_OPTS += -cpu max diff --git a/tests/tcg/i386/test-i386-bmi2.c b/tests/tcg/i386/test-i386-bmi2.c index 935a4d2a73..5fadf47510 100644 --- a/tests/tcg/i386/test-i386-bmi2.c +++ b/tests/tcg/i386/test-i386-bmi2.c @@ -1,6 +1,66 @@ /* See if various BMI2 instructions give expected results */ #include #include +#include + +#define insn1q(name, arg0) \ +static inline uint64_t name##q(uint64_t arg0) \ +{ \ + uint64_t result64; \ + asm volatile (#name "q %1, %0" : "=r"(result64) : "rm"(arg0)); \ + return result64; \ +} + +#define insn1l(name, arg0) \ +static inline uint32_t name##l(uint32_t arg0) \ +{ \ + uint32_t result32; \ + asm volatile (#name "l %k1, %k0" : "=r"(result32) : "rm"(arg0)); \ + return result32; \ +} + +#define insn2q(name, arg0, c0, arg1, c1) \ +static inline uint64_t name##q(uint64_t arg0, uint64_t arg1) \ +{ \ + uint64_t result64; \ + asm volatile (#name "q %2, %1, %0" : "=r"(result64) : c0(arg0), c1(arg1)); \ + return result64; \ +} + +#define insn2l(name, arg0, c0, arg1, c1) \ +static inline uint32_t name##l(uint32_t arg0, uint32_t arg1) \ +{ \ + uint32_t result32; \ + asm volatile (#name "l %k2, %k1, %k0" : "=r"(result32) : c0(arg0), c1(arg1)); \ + return result32; \ +} + +#ifdef __x86_64 +insn2q(pext, src, "r", mask, "rm") +insn2q(pdep, src, "r", mask, "rm") +insn2q(andn, clear, "rm", val, "r") +insn2q(bextr, range, "rm", val, "r") +insn2q(bzhi, pos, "rm", val, "r") +insn2q(rorx, val, "r", n, "i") +insn2q(sarx, val, "rm", n, "r") +insn2q(shlx, val, "rm", n, "r") +insn2q(shrx, val, "rm", n, "r") +insn1q(blsi, src) +insn1q(blsmsk, src) +insn1q(blsr, src) +#endif +insn2l(pext, src, "r", mask, "rm") +insn2l(pdep, src, "r", mask, "rm") +insn2l(andn, clear, "rm", val, "r") +insn2l(bextr, range, "rm", val, "r") +insn2l(bzhi, pos, "rm", val, "r") +insn2l(rorx, val, "r", n, "i") +insn2l(sarx, val, "rm", n, "r") +insn2l(shlx, val, "rm", n, "r") +insn2l(shrx, val, "rm", n, "r") +insn1l(blsi, src) +insn1l(blsmsk, src) +insn1l(blsr, src) int main(int argc, char *argv[]) { uint64_t ehlo = 0x202020204f4c4845ull; @@ -11,32 +71,125 @@ int main(int argc, char *argv[]) { uint64_t result64; /* 64 bits */ - asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(ehlo), "m"(mask)); + result64 = andnq(mask, ehlo); + assert(result64 == 0x002020204d4c4844); + + result64 = pextq(ehlo, mask); assert(result64 == 133); - asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(result64), "m"(mask)); + result64 = pdepq(result64, mask); assert(result64 == (ehlo & mask)); - asm volatile ("pextq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask)); + result64 = pextq(-1ull, mask); assert(result64 == 511); /* mask has 9 bits set */ - asm volatile ("pdepq %2, %1, %0" : "=r"(result64) : "r"(-1ull), "m"(mask)); + result64 = pdepq(-1ull, mask); assert(result64 == mask); + + result64 = bextrq(mask, 0x3f00); + assert(result64 == (mask & ~INT64_MIN)); + + result64 = bextrq(mask, 0x1038); + assert(result64 == 0xa0); + + result64 = bextrq(mask, 0x10f8); + assert(result64 == 0); + + result64 = blsiq(0x30); + assert(result64 == 0x10); + + result64 = blsiq(0x30ull << 32); + assert(result64 == 0x10ull << 32); + + result64 = blsmskq(0x30); + assert(result64 == 0x1f); + + result64 = blsrq(0x30); + assert(result64 == 0x20); + + result64 = blsrq(0x30ull << 32); + assert(result64 == 0x20ull << 32); + + result64 = bzhiq(mask, 0x3f); + assert(result64 == (mask & ~INT64_MIN)); + + result64 = bzhiq(mask, 0x1f); + assert(result64 == (mask & ~(-1 << 30))); + + result64 = rorxq(0x2132435465768798, 8); + assert(result64 == 0x9821324354657687); + + result64 = sarxq(0xffeeddccbbaa9988, 8); + assert(result64 == 0xffffeeddccbbaa99); + + result64 = sarxq(0x77eeddccbbaa9988, 8 | 64); + assert(result64 == 0x0077eeddccbbaa99); + + result64 = shrxq(0xffeeddccbbaa9988, 8); + assert(result64 == 0x00ffeeddccbbaa99); + + result64 = shrxq(0x77eeddccbbaa9988, 8 | 192); + assert(result64 == 0x0077eeddccbbaa99); + + result64 = shlxq(0xffeeddccbbaa9988, 8); + assert(result64 == 0xeeddccbbaa998800); #endif /* 32 bits */ - asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"((uint32_t) ehlo), "m"(mask)); + result32 = andnl(mask, ehlo); + assert(result32 == 0x04d4c4844); + + result32 = pextl((uint32_t) ehlo, mask); assert(result32 == 5); - asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(result32), "m"(mask)); + result32 = pdepl(result32, mask); assert(result32 == (uint32_t)(ehlo & mask)); - asm volatile ("pextl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask)); + result32 = pextl(-1u, mask); assert(result32 == 7); /* mask has 3 bits set */ - asm volatile ("pdepl %2, %k1, %k0" : "=r"(result32) : "r"(-1ull), "m"(mask)); + result32 = pdepl(-1u, mask); assert(result32 == (uint32_t)mask); + result32 = bextrl(mask, 0x1f00); + assert(result32 == (mask & ~INT32_MIN)); + + result32 = bextrl(ehlo, 0x1018); + assert(result32 == 0x4f); + + result32 = bextrl(mask, 0x1038); + assert(result32 == 0); + + result32 = blsil(0xffff); + assert(result32 == 1); + + result32 = blsmskl(0x300); + assert(result32 == 0x1ff); + + result32 = blsrl(0xffc); + assert(result32 == 0xff8); + + result32 = bzhil(mask, 0xf); + assert(result32 == 1); + + result32 = rorxl(0x65768798, 8); + assert(result32 == 0x98657687); + + result32 = sarxl(0xffeeddcc, 8); + assert(result32 == 0xffffeedd); + + result32 = sarxl(0x77eeddcc, 8 | 32); + assert(result32 == 0x0077eedd); + + result32 = shrxl(0xffeeddcc, 8); + assert(result32 == 0x00ffeedd); + + result32 = shrxl(0x77eeddcc, 8 | 128); + assert(result32 == 0x0077eedd); + + result32 = shlxl(0xffeeddcc, 8); + assert(result32 == 0xeeddcc00); + return 0; } From 75046ad72eaaae954849e2b793b6f629befb4ebc Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 25 Aug 2022 17:46:36 +0200 Subject: [PATCH 0278/1020] target/i386: fix PHSUB* instructions with dest=src The computation must not overwrite neither the destination nor the source before the last element has been computed. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 49 +++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 535440f882..2524db4c25 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -1528,34 +1528,43 @@ void glue(helper_pmaddubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) void glue(helper_phsubw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->W(0) = (int16_t)d->W(0) - (int16_t)d->W(1); - d->W(1) = (int16_t)d->W(2) - (int16_t)d->W(3); - XMM_ONLY(d->W(2) = (int16_t)d->W(4) - (int16_t)d->W(5)); - XMM_ONLY(d->W(3) = (int16_t)d->W(6) - (int16_t)d->W(7)); - d->W((2 << SHIFT) + 0) = (int16_t)s->W(0) - (int16_t)s->W(1); - d->W((2 << SHIFT) + 1) = (int16_t)s->W(2) - (int16_t)s->W(3); - XMM_ONLY(d->W(6) = (int16_t)s->W(4) - (int16_t)s->W(5)); - XMM_ONLY(d->W(7) = (int16_t)s->W(6) - (int16_t)s->W(7)); + Reg r; + + r.W(0) = (int16_t)d->W(0) - (int16_t)d->W(1); + r.W(1) = (int16_t)d->W(2) - (int16_t)d->W(3); + XMM_ONLY(r.W(2) = (int16_t)d->W(4) - (int16_t)d->W(5)); + XMM_ONLY(r.W(3) = (int16_t)d->W(6) - (int16_t)d->W(7)); + r.W((2 << SHIFT) + 0) = (int16_t)s->W(0) - (int16_t)s->W(1); + r.W((2 << SHIFT) + 1) = (int16_t)s->W(2) - (int16_t)s->W(3); + XMM_ONLY(r.W(6) = (int16_t)s->W(4) - (int16_t)s->W(5)); + XMM_ONLY(r.W(7) = (int16_t)s->W(6) - (int16_t)s->W(7)); + MOVE(*d, r); } void glue(helper_phsubd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->L(0) = (int32_t)d->L(0) - (int32_t)d->L(1); - XMM_ONLY(d->L(1) = (int32_t)d->L(2) - (int32_t)d->L(3)); - d->L((1 << SHIFT) + 0) = (int32_t)s->L(0) - (int32_t)s->L(1); - XMM_ONLY(d->L(3) = (int32_t)s->L(2) - (int32_t)s->L(3)); + Reg r; + + r.L(0) = (int32_t)d->L(0) - (int32_t)d->L(1); + XMM_ONLY(r.L(1) = (int32_t)d->L(2) - (int32_t)d->L(3)); + r.L((1 << SHIFT) + 0) = (int32_t)s->L(0) - (int32_t)s->L(1); + XMM_ONLY(r.L(3) = (int32_t)s->L(2) - (int32_t)s->L(3)); + MOVE(*d, r); } void glue(helper_phsubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->W(0) = satsw((int16_t)d->W(0) - (int16_t)d->W(1)); - d->W(1) = satsw((int16_t)d->W(2) - (int16_t)d->W(3)); - XMM_ONLY(d->W(2) = satsw((int16_t)d->W(4) - (int16_t)d->W(5))); - XMM_ONLY(d->W(3) = satsw((int16_t)d->W(6) - (int16_t)d->W(7))); - d->W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) - (int16_t)s->W(1)); - d->W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) - (int16_t)s->W(3)); - XMM_ONLY(d->W(6) = satsw((int16_t)s->W(4) - (int16_t)s->W(5))); - XMM_ONLY(d->W(7) = satsw((int16_t)s->W(6) - (int16_t)s->W(7))); + Reg r; + + r.W(0) = satsw((int16_t)d->W(0) - (int16_t)d->W(1)); + r.W(1) = satsw((int16_t)d->W(2) - (int16_t)d->W(3)); + XMM_ONLY(r.W(2) = satsw((int16_t)d->W(4) - (int16_t)d->W(5))); + XMM_ONLY(r.W(3) = satsw((int16_t)d->W(6) - (int16_t)d->W(7))); + r.W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) - (int16_t)s->W(1)); + r.W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) - (int16_t)s->W(3)); + XMM_ONLY(r.W(6) = satsw((int16_t)s->W(4) - (int16_t)s->W(5))); + XMM_ONLY(r.W(7) = satsw((int16_t)s->W(6) - (int16_t)s->W(7))); + MOVE(*d, r); } #define FABSB(_, x) (x > INT8_MAX ? -(int8_t)x : x) From bf30ad8cefeb3b199f5485c5d78f2801cd248264 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 25 Aug 2022 18:47:50 +0200 Subject: [PATCH 0279/1020] target/i386: DPPS rounding fix The DPPS (Dot Product) instruction is defined to first sum pairs of intermediate results, then sum those values to get the final result. i.e. (A+B)+(C+D) We incrementally sum the results, i.e. ((A+B)+C)+D, which can result in incorrect rouding. For consistency, also change the variable names to the ones used in the Intel SDM and implement DPPD following the manual. Based on a patch by Paul Brook . Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 67 ++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 2524db4c25..b12b271fcd 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -1943,56 +1943,59 @@ SSE_HELPER_I(helper_pblendw, W, 8, FBLENDP) void glue(helper_dpps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) { - float32 iresult = float32_zero; + float32 prod1, prod2, temp2, temp3, temp4; + /* + * We must evaluate (A+B)+(C+D), not ((A+B)+C)+D + * to correctly round the intermediate results + */ if (mask & (1 << 4)) { - iresult = float32_add(iresult, - float32_mul(d->ZMM_S(0), s->ZMM_S(0), - &env->sse_status), - &env->sse_status); + prod1 = float32_mul(d->ZMM_S(0), s->ZMM_S(0), &env->sse_status); + } else { + prod1 = float32_zero; } if (mask & (1 << 5)) { - iresult = float32_add(iresult, - float32_mul(d->ZMM_S(1), s->ZMM_S(1), - &env->sse_status), - &env->sse_status); + prod2 = float32_mul(d->ZMM_S(1), s->ZMM_S(1), &env->sse_status); + } else { + prod2 = float32_zero; } + temp2 = float32_add(prod1, prod2, &env->sse_status); if (mask & (1 << 6)) { - iresult = float32_add(iresult, - float32_mul(d->ZMM_S(2), s->ZMM_S(2), - &env->sse_status), - &env->sse_status); + prod1 = float32_mul(d->ZMM_S(2), s->ZMM_S(2), &env->sse_status); + } else { + prod1 = float32_zero; } if (mask & (1 << 7)) { - iresult = float32_add(iresult, - float32_mul(d->ZMM_S(3), s->ZMM_S(3), - &env->sse_status), - &env->sse_status); + prod2 = float32_mul(d->ZMM_S(3), s->ZMM_S(3), &env->sse_status); + } else { + prod2 = float32_zero; } - d->ZMM_S(0) = (mask & (1 << 0)) ? iresult : float32_zero; - d->ZMM_S(1) = (mask & (1 << 1)) ? iresult : float32_zero; - d->ZMM_S(2) = (mask & (1 << 2)) ? iresult : float32_zero; - d->ZMM_S(3) = (mask & (1 << 3)) ? iresult : float32_zero; + temp3 = float32_add(prod1, prod2, &env->sse_status); + temp4 = float32_add(temp2, temp3, &env->sse_status); + + d->ZMM_S(0) = (mask & (1 << 0)) ? temp4 : float32_zero; + d->ZMM_S(1) = (mask & (1 << 1)) ? temp4 : float32_zero; + d->ZMM_S(2) = (mask & (1 << 2)) ? temp4 : float32_zero; + d->ZMM_S(3) = (mask & (1 << 3)) ? temp4 : float32_zero; } void glue(helper_dppd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) { - float64 iresult = float64_zero; + float64 prod1, prod2, temp2; if (mask & (1 << 4)) { - iresult = float64_add(iresult, - float64_mul(d->ZMM_D(0), s->ZMM_D(0), - &env->sse_status), - &env->sse_status); + prod1 = float64_mul(d->ZMM_D(0), s->ZMM_D(0), &env->sse_status); + } else { + prod1 = float64_zero; } if (mask & (1 << 5)) { - iresult = float64_add(iresult, - float64_mul(d->ZMM_D(1), s->ZMM_D(1), - &env->sse_status), - &env->sse_status); + prod2 = float64_mul(d->ZMM_D(1), s->ZMM_D(1), &env->sse_status); + } else { + prod2 = float64_zero; } - d->ZMM_D(0) = (mask & (1 << 0)) ? iresult : float64_zero; - d->ZMM_D(1) = (mask & (1 << 1)) ? iresult : float64_zero; + temp2 = float64_add(prod1, prod2, &env->sse_status); + d->ZMM_D(0) = (mask & (1 << 0)) ? temp2 : float64_zero; + d->ZMM_D(1) = (mask & (1 << 1)) ? temp2 : float64_zero; } void glue(helper_mpsadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, From 91117bc546b10aeefd6d78502d82df5729f5f780 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:02:03 +0100 Subject: [PATCH 0280/1020] tests/tcg: i386: add SSE tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tests for correct operation of most x86-64 SSE instructions. It should cover all combinations of overlapping register and memory operands on a set of random-ish data. Results are bit-identical to an Intel i5-8500, with the exception of the RCPSS and RSQRT approximations where the real CPU gives less accurate results (the Intel spec allows relative errors up to 1.5 * 2^-12) Signed-off-by: Paul Brook Acked-by: Alex Bennée Message-Id: <20220424220204.2493824-42-paul@nowt.org> Signed-off-by: Paolo Bonzini --- tests/tcg/Makefile.target | 2 +- tests/tcg/i386/Makefile.target | 11 +- tests/tcg/i386/README | 9 + tests/tcg/i386/test-avx.c | 330 +++ tests/tcg/i386/test-avx.py | 351 +++ tests/tcg/i386/x86.csv | 4658 ++++++++++++++++++++++++++++++ tests/tcg/x86_64/Makefile.target | 1 + 7 files changed, 5359 insertions(+), 3 deletions(-) create mode 100644 tests/tcg/i386/test-avx.c create mode 100755 tests/tcg/i386/test-avx.py create mode 100644 tests/tcg/i386/x86.csv diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index e68830af15..c896d1033e 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -188,4 +188,4 @@ gdb-%: % run: $(RUN_TESTS) clean: - rm -f $(TESTS) *.o + rm -f $(TESTS) *.o $(CLEANFILES) diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index 646b4ac13e..be21b81b96 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -7,8 +7,8 @@ VPATH += $(I386_SRC) I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c)) ALL_X86_TESTS=$(I386_SRCS:.c=) -SKIP_I386_TESTS=test-i386-ssse3 -X86_64_TESTS:=$(filter test-i386-bmi2 test-i386-ssse3, $(ALL_X86_TESTS)) +SKIP_I386_TESTS=test-i386-ssse3 test-avx +X86_64_TESTS:=$(filter test-i386-bmi2 test-i386-ssse3 test-avx, $(ALL_X86_TESTS)) test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max @@ -81,3 +81,10 @@ run-sha512-sse: QEMU_OPTS+=-cpu max run-plugin-sha512-sse-with-%: QEMU_OPTS+=-cpu max TESTS+=sha512-sse + +CLEANFILES += test-avx.h +test-avx.h: test-avx.py x86.csv + $(PYTHON) $(I386_SRC)/test-avx.py $(I386_SRC)/x86.csv $@ + +test-avx: CFLAGS += -masm=intel -O -I. +test-avx: test-avx.h diff --git a/tests/tcg/i386/README b/tests/tcg/i386/README index 09e88f30dc..403d10dad8 100644 --- a/tests/tcg/i386/README +++ b/tests/tcg/i386/README @@ -15,6 +15,15 @@ The Linux system call vm86() is used to test vm86 emulation. Various exceptions are raised to test most of the x86 user space exception reporting. +test-avx +-------- + +This program executes most SSE/AVX instructions and generates a text output, +for comparison with the output obtained with a real CPU or another emulator. + +test-avx.h is generate from x86.csv by test-avx.py +x86.csv comes from https://github.com/quasilyte/avx512test + linux-test ---------- diff --git a/tests/tcg/i386/test-avx.c b/tests/tcg/i386/test-avx.c new file mode 100644 index 0000000000..23c170dd79 --- /dev/null +++ b/tests/tcg/i386/test-avx.c @@ -0,0 +1,330 @@ +#include +#include +#include +#include + +typedef void (*testfn)(void); + +typedef struct { + uint64_t q0, q1; +} __attribute__((aligned(16))) v2di; + +typedef struct { + uint64_t mm[8]; + v2di xmm[16]; + uint64_t r[16]; + uint64_t flags; + uint32_t ff; + uint64_t pad; + v2di mem[4]; + v2di mem0[4]; +} reg_state; + +typedef struct { + int n; + testfn fn; + const char *s; + reg_state *init; +} TestDef; + +reg_state initI; +reg_state initF32; +reg_state initF64; + +static void dump_xmm(const char *name, int n, const v2di *r, int ff) +{ + printf("%s%d = %016lx %016lx\n", + name, n, r->q1, r->q0); + if (ff == 64) { + double v[2]; + memcpy(v, r, sizeof(v)); + printf(" %16g %16g\n", + v[1], v[0]); + } else if (ff == 32) { + float v[4]; + memcpy(v, r, sizeof(v)); + printf(" %8g %8g %8g %8g\n", + v[3], v[2], v[1], v[0]); + } +} + +static void dump_regs(reg_state *s) +{ + int i; + + for (i = 0; i < 16; i++) { + dump_xmm("xmm", i, &s->xmm[i], 0); + } + for (i = 0; i < 4; i++) { + dump_xmm("mem", i, &s->mem0[i], 0); + } +} + +static void compare_state(const reg_state *a, const reg_state *b) +{ + int i; + for (i = 0; i < 8; i++) { + if (a->mm[i] != b->mm[i]) { + printf("MM%d = %016lx\n", i, b->mm[i]); + } + } + for (i = 0; i < 16; i++) { + if (a->r[i] != b->r[i]) { + printf("r%d = %016lx\n", i, b->r[i]); + } + } + for (i = 0; i < 16; i++) { + if (memcmp(&a->xmm[i], &b->xmm[i], 16)) { + dump_xmm("xmm", i, &b->xmm[i], a->ff); + } + } + for (i = 0; i < 4; i++) { + if (memcmp(&a->mem0[i], &a->mem[i], 16)) { + dump_xmm("mem", i, &a->mem[i], a->ff); + } + } + if (a->flags != b->flags) { + printf("FLAGS = %016lx\n", b->flags); + } +} + +#define LOADMM(r, o) "movq " #r ", " #o "[%0]\n\t" +#define LOADXMM(r, o) "movdqa " #r ", " #o "[%0]\n\t" +#define STOREMM(r, o) "movq " #o "[%1], " #r "\n\t" +#define STOREXMM(r, o) "movdqa " #o "[%1], " #r "\n\t" +#define MMREG(F) \ + F(mm0, 0x00) \ + F(mm1, 0x08) \ + F(mm2, 0x10) \ + F(mm3, 0x18) \ + F(mm4, 0x20) \ + F(mm5, 0x28) \ + F(mm6, 0x30) \ + F(mm7, 0x38) +#define XMMREG(F) \ + F(xmm0, 0x040) \ + F(xmm1, 0x050) \ + F(xmm2, 0x060) \ + F(xmm3, 0x070) \ + F(xmm4, 0x080) \ + F(xmm5, 0x090) \ + F(xmm6, 0x0a0) \ + F(xmm7, 0x0b0) \ + F(xmm8, 0x0c0) \ + F(xmm9, 0x0d0) \ + F(xmm10, 0x0e0) \ + F(xmm11, 0x0f0) \ + F(xmm12, 0x100) \ + F(xmm13, 0x110) \ + F(xmm14, 0x120) \ + F(xmm15, 0x130) +#define LOADREG(r, o) "mov " #r ", " #o "[rax]\n\t" +#define STOREREG(r, o) "mov " #o "[rax], " #r "\n\t" +#define REG(F) \ + F(rbx, 0x148) \ + F(rcx, 0x150) \ + F(rdx, 0x158) \ + F(rsi, 0x160) \ + F(rdi, 0x168) \ + F(r8, 0x180) \ + F(r9, 0x188) \ + F(r10, 0x190) \ + F(r11, 0x198) \ + F(r12, 0x1a0) \ + F(r13, 0x1a8) \ + F(r14, 0x1b0) \ + F(r15, 0x1b8) \ + +static void run_test(const TestDef *t) +{ + reg_state result; + reg_state *init = t->init; + memcpy(init->mem, init->mem0, sizeof(init->mem)); + printf("%5d %s\n", t->n, t->s); + asm volatile( + MMREG(LOADMM) + XMMREG(LOADXMM) + "sub rsp, 128\n\t" + "push rax\n\t" + "push rbx\n\t" + "push rcx\n\t" + "push rdx\n\t" + "push %1\n\t" + "push %2\n\t" + "mov rax, %0\n\t" + "pushf\n\t" + "pop rbx\n\t" + "shr rbx, 8\n\t" + "shl rbx, 8\n\t" + "mov rcx, 0x1c0[rax]\n\t" + "and rcx, 0xff\n\t" + "or rbx, rcx\n\t" + "push rbx\n\t" + "popf\n\t" + REG(LOADREG) + "mov rax, 0x140[rax]\n\t" + "call [rsp]\n\t" + "mov [rsp], rax\n\t" + "mov rax, 8[rsp]\n\t" + REG(STOREREG) + "mov rbx, [rsp]\n\t" + "mov 0x140[rax], rbx\n\t" + "mov rbx, 0\n\t" + "mov 0x170[rax], rbx\n\t" + "mov 0x178[rax], rbx\n\t" + "pushf\n\t" + "pop rbx\n\t" + "and rbx, 0xff\n\t" + "mov 0x1c0[rax], rbx\n\t" + "add rsp, 16\n\t" + "pop rdx\n\t" + "pop rcx\n\t" + "pop rbx\n\t" + "pop rax\n\t" + "add rsp, 128\n\t" + MMREG(STOREMM) + XMMREG(STOREXMM) + : : "r"(init), "r"(&result), "r"(t->fn) + : "memory", "cc", + "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", + "xmm12", "xmm13", "xmm14", "xmm15" + ); + compare_state(init, &result); +} + +#define TEST(n, cmd, type) \ +static void __attribute__((naked)) test_##n(void) \ +{ \ + asm volatile(cmd); \ + asm volatile("ret"); \ +} +#include "test-avx.h" + + +static const TestDef test_table[] = { +#define TEST(n, cmd, type) {n, test_##n, cmd, &init##type}, +#include "test-avx.h" + {-1, NULL, "", NULL} +}; + +static void run_all(void) +{ + const TestDef *t; + for (t = test_table; t->fn; t++) { + run_test(t); + } +} + +#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0])) + +float val_f32[] = {2.0, -1.0, 4.8, 0.8, 3, -42.0, 5e6, 7.5, 8.3}; +double val_f64[] = {2.0, -1.0, 4.8, 0.8, 3, -42.0, 5e6, 7.5}; +v2di val_i64[] = { + {0x3d6b3b6a9e4118f2lu, 0x355ae76d2774d78clu}, + {0xd851c54a56bf1f29lu, 0x4a84d1d50bf4c4fflu}, + {0x5826475e2c5fd799lu, 0xfd32edc01243f5e9lu}, +}; + +v2di deadbeef = {0xa5a5a5a5deadbeefull, 0xa5a5a5a5deadbeefull}; +v2di indexq = {0x000000000000001full, 0x000000000000008full}; +v2di indexd = {0x00000002000000efull, 0xfffffff500000010ull}; + +void init_f32reg(v2di *r) +{ + static int n; + float v[4]; + int i; + for (i = 0; i < 4; i++) { + v[i] = val_f32[n++]; + if (n == ARRAY_LEN(val_f32)) { + n = 0; + } + } + memcpy(r, v, sizeof(*r)); +} + +void init_f64reg(v2di *r) +{ + static int n; + double v[2]; + int i; + for (i = 0; i < 2; i++) { + v[i] = val_f64[n++]; + if (n == ARRAY_LEN(val_f64)) { + n = 0; + } + } + memcpy(r, v, sizeof(*r)); +} + +void init_intreg(v2di *r) +{ + static uint64_t mask; + static int n; + + r->q0 = val_i64[n].q0 ^ mask; + r->q1 = val_i64[n].q1 ^ mask; + n++; + if (n == ARRAY_LEN(val_i64)) { + n = 0; + mask *= 0x104C11DB7; + } +} + +static void init_all(reg_state *s) +{ + int i; + + s->r[3] = (uint64_t)&s->mem[0]; /* rdx */ + s->r[5] = (uint64_t)&s->mem[2]; /* rdi */ + s->flags = 2; + for (i = 0; i < 8; i++) { + s->xmm[i] = deadbeef; + } + s->xmm[13] = indexd; + s->xmm[14] = indexq; + for (i = 0; i < 2; i++) { + s->mem0[i] = deadbeef; + } +} + +int main(int argc, char *argv[]) +{ + init_all(&initI); + init_intreg(&initI.xmm[10]); + init_intreg(&initI.xmm[11]); + init_intreg(&initI.xmm[12]); + init_intreg(&initI.mem0[1]); + printf("Int:\n"); + dump_regs(&initI); + + init_all(&initF32); + init_f32reg(&initF32.xmm[10]); + init_f32reg(&initF32.xmm[11]); + init_f32reg(&initF32.xmm[12]); + init_f32reg(&initF32.mem0[1]); + initF32.ff = 32; + printf("F32:\n"); + dump_regs(&initF32); + + init_all(&initF64); + init_f64reg(&initF64.xmm[10]); + init_f64reg(&initF64.xmm[11]); + init_f64reg(&initF64.xmm[12]); + init_f64reg(&initF64.mem0[1]); + initF64.ff = 64; + printf("F64:\n"); + dump_regs(&initF64); + + if (argc > 1) { + int n = atoi(argv[1]); + run_test(&test_table[n]); + } else { + run_all(); + } + return 0; +} diff --git a/tests/tcg/i386/test-avx.py b/tests/tcg/i386/test-avx.py new file mode 100755 index 0000000000..6eb455a8b4 --- /dev/null +++ b/tests/tcg/i386/test-avx.py @@ -0,0 +1,351 @@ +#! /usr/bin/env python3 + +# Generate test-avx.h from x86.csv + +import csv +import sys +from fnmatch import fnmatch + +archs = [ + # TODO: MMX? + "SSE", "SSE2", "SSE3", "SSSE3", "SSE4_1", "SSE4_2", +] + +ignore = set(["FISTTP", + "LDMXCSR", "VLDMXCSR", "STMXCSR", "VSTMXCSR"]) + +imask = { + 'vBLENDPD': 0xff, + 'vBLENDPS': 0x0f, + 'CMP[PS][SD]': 0x07, + 'VCMP[PS][SD]': 0x1f, + 'vDPPD': 0x33, + 'vDPPS': 0xff, + 'vEXTRACTPS': 0x03, + 'vINSERTPS': 0xff, + 'MPSADBW': 0x7, + 'VMPSADBW': 0x3f, + 'vPALIGNR': 0x3f, + 'vPBLENDW': 0xff, + 'vPCMP[EI]STR*': 0x0f, + 'vPEXTRB': 0x0f, + 'vPEXTRW': 0x07, + 'vPEXTRD': 0x03, + 'vPEXTRQ': 0x01, + 'vPINSRB': 0x0f, + 'vPINSRW': 0x07, + 'vPINSRD': 0x03, + 'vPINSRQ': 0x01, + 'vPSHUF[DW]': 0xff, + 'vPSHUF[LH]W': 0xff, + 'vPS[LR][AL][WDQ]': 0x3f, + 'vPS[RL]LDQ': 0x1f, + 'vROUND[PS][SD]': 0x7, + 'vSHUFPD': 0x0f, + 'vSHUFPS': 0xff, + 'vAESKEYGENASSIST': 0, + 'VEXTRACT[FI]128': 0x01, + 'VINSERT[FI]128': 0x01, + 'VPBLENDD': 0xff, + 'VPERM2[FI]128': 0x33, + 'VPERMPD': 0xff, + 'VPERMQ': 0xff, + 'VPERMILPS': 0xff, + 'VPERMILPD': 0x0f, + } + +def strip_comments(x): + for l in x: + if l != '' and l[0] != '#': + yield l + +def reg_w(w): + if w == 8: + return 'al' + elif w == 16: + return 'ax' + elif w == 32: + return 'eax' + elif w == 64: + return 'rax' + raise Exception("bad reg_w %d" % w) + +def mem_w(w): + if w == 8: + t = "BYTE" + elif w == 16: + t = "WORD" + elif w == 32: + t = "DWORD" + elif w == 64: + t = "QWORD" + elif w == 128: + t = "XMMWORD" + elif w == 256: + t = "YMMWORD" + else: + raise Exception() + + return t + " PTR 16[rdx]" + +class XMMArg(): + isxmm = True + def __init__(self, reg, mw): + if mw not in [0, 8, 16, 32, 64, 128, 256]: + raise Exception("Bad /m width: %s" % w) + self.reg = reg + self.mw = mw + self.ismem = mw != 0 + def regstr(self, n): + if n < 0: + return mem_w(self.mw) + else: + return "%smm%d" % (self.reg, n) + +class MMArg(): + isxmm = True + ismem = False # TODO + def regstr(self, n): + return "mm%d" % (n & 7) + +def match(op, pattern): + if pattern[0] == 'v': + return fnmatch(op, pattern[1:]) or fnmatch(op, 'V'+pattern[1:]) + return fnmatch(op, pattern) + +class ArgVSIB(): + isxmm = True + ismem = False + def __init__(self, reg, w): + if w not in [32, 64]: + raise Exception("Bad vsib width: %s" % w) + self.w = w + self.reg = reg + def regstr(self, n): + reg = "%smm%d" % (self.reg, n >> 2) + return "[rsi + %s * %d]" % (reg, 1 << (n & 3)) + +class ArgImm8u(): + isxmm = False + ismem = False + def __init__(self, op): + for k, v in imask.items(): + if match(op, k): + self.mask = imask[k]; + return + raise Exception("Unknown immediate") + def vals(self): + mask = self.mask + yield 0 + n = 0 + while n != mask: + n += 1 + while (n & ~mask) != 0: + n += (n & ~mask) + yield n + +class ArgRM(): + isxmm = False + def __init__(self, rw, mw): + if rw not in [8, 16, 32, 64]: + raise Exception("Bad r/w width: %s" % w) + if mw not in [0, 8, 16, 32, 64]: + raise Exception("Bad r/w width: %s" % w) + self.rw = rw + self.mw = mw + self.ismem = mw != 0 + def regstr(self, n): + if n < 0: + return mem_w(self.mw) + else: + return reg_w(self.rw) + +class ArgMem(): + isxmm = False + ismem = True + def __init__(self, w): + if w not in [8, 16, 32, 64, 128, 256]: + raise Exception("Bad mem width: %s" % w) + self.w = w + def regstr(self, n): + return mem_w(self.w) + +def ArgGenerator(arg, op): + if arg[:3] == 'xmm' or arg[:3] == "ymm": + if "/" in arg: + r, m = arg.split('/') + if (m[0] != 'm'): + raise Exception("Expected /m: %s", arg) + return XMMArg(arg[0], int(m[1:])); + else: + return XMMArg(arg[0], 0); + elif arg[:2] == 'mm': + return MMArg(); + elif arg[:4] == 'imm8': + return ArgImm8u(op); + elif arg == '': + return None + elif arg[0] == 'r': + if '/m' in arg: + r, m = arg.split('/') + if (m[0] != 'm'): + raise Exception("Expected /m: %s", arg) + mw = int(m[1:]) + if r == 'r': + rw = mw + else: + rw = int(r[1:]) + return ArgRM(rw, mw) + + return ArgRM(int(arg[1:]), 0); + elif arg[0] == 'm': + return ArgMem(int(arg[1:])) + elif arg[:2] == 'vm': + return ArgVSIB(arg[-1], int(arg[2:-1])) + else: + raise Exception("Unrecognised arg: %s", arg) + +class InsnGenerator: + def __init__(self, op, args): + self.op = op + if op[-2:] in ["PS", "PD", "SS", "SD"]: + if op[-1] == 'S': + self.optype = 'F32' + else: + self.optype = 'F64' + else: + self.optype = 'I' + + try: + self.args = list(ArgGenerator(a, op) for a in args) + if len(self.args) > 0 and self.args[-1] is None: + self.args = self.args[:-1] + except Exception as e: + raise Exception("Bad arg %s: %s" % (op, e)) + + def gen(self): + regs = (10, 11, 12) + dest = 9 + + nreg = len(self.args) + if nreg == 0: + yield self.op + return + if isinstance(self.args[-1], ArgImm8u): + nreg -= 1 + immarg = self.args[-1] + else: + immarg = None + memarg = -1 + for n, arg in enumerate(self.args): + if arg.ismem: + memarg = n + + if (self.op.startswith("VGATHER") or self.op.startswith("VPGATHER")): + if "GATHERD" in self.op: + ireg = 13 << 2 + else: + ireg = 14 << 2 + regset = [ + (dest, ireg | 0, regs[0]), + (dest, ireg | 1, regs[0]), + (dest, ireg | 2, regs[0]), + (dest, ireg | 3, regs[0]), + ] + if memarg >= 0: + raise Exception("vsib with memory: %s" % self.op) + elif nreg == 1: + regset = [(regs[0],)] + if memarg == 0: + regset += [(-1,)] + elif nreg == 2: + regset = [ + (regs[0], regs[1]), + (regs[0], regs[0]), + ] + if memarg == 0: + regset += [(-1, regs[0])] + elif memarg == 1: + regset += [(dest, -1)] + elif nreg == 3: + regset = [ + (dest, regs[0], regs[1]), + (dest, regs[0], regs[0]), + (regs[0], regs[0], regs[1]), + (regs[0], regs[1], regs[0]), + (regs[0], regs[0], regs[0]), + ] + if memarg == 2: + regset += [ + (dest, regs[0], -1), + (regs[0], regs[0], -1), + ] + elif memarg > 0: + raise Exception("Memarg %d" % memarg) + elif nreg == 4: + regset = [ + (dest, regs[0], regs[1], regs[2]), + (dest, regs[0], regs[0], regs[1]), + (dest, regs[0], regs[1], regs[0]), + (dest, regs[1], regs[0], regs[0]), + (dest, regs[0], regs[0], regs[0]), + (regs[0], regs[0], regs[1], regs[2]), + (regs[0], regs[1], regs[0], regs[2]), + (regs[0], regs[1], regs[2], regs[0]), + (regs[0], regs[0], regs[0], regs[1]), + (regs[0], regs[0], regs[1], regs[0]), + (regs[0], regs[1], regs[0], regs[0]), + (regs[0], regs[0], regs[0], regs[0]), + ] + if memarg == 2: + regset += [ + (dest, regs[0], -1, regs[1]), + (dest, regs[0], -1, regs[0]), + (regs[0], regs[0], -1, regs[1]), + (regs[0], regs[1], -1, regs[0]), + (regs[0], regs[0], -1, regs[0]), + ] + elif memarg > 0: + raise Exception("Memarg4 %d" % memarg) + else: + raise Exception("Too many regs: %s(%d)" % (self.op, nreg)) + + for regv in regset: + argstr = [] + for i in range(nreg): + arg = self.args[i] + argstr.append(arg.regstr(regv[i])) + if immarg is None: + yield self.op + ' ' + ','.join(argstr) + else: + for immval in immarg.vals(): + yield self.op + ' ' + ','.join(argstr) + ',' + str(immval) + +def split0(s): + if s == '': + return [] + return s.split(',') + +def main(): + n = 0 + if len(sys.argv) != 3: + print("Usage: test-avx.py x86.csv test-avx.h") + exit(1) + csvfile = open(sys.argv[1], 'r', newline='') + with open(sys.argv[2], "w") as outf: + outf.write("// Generated by test-avx.py. Do not edit.\n") + for row in csv.reader(strip_comments(csvfile)): + insn = row[0].replace(',', '').split() + if insn[0] in ignore: + continue + cpuid = row[6] + if cpuid in archs: + g = InsnGenerator(insn[0], insn[1:]) + for insn in g.gen(): + outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype)) + n += 1 + outf.write("#undef TEST\n") + csvfile.close() + +if __name__ == "__main__": + main() diff --git a/tests/tcg/i386/x86.csv b/tests/tcg/i386/x86.csv new file mode 100644 index 0000000000..d5d0c17f1b --- /dev/null +++ b/tests/tcg/i386/x86.csv @@ -0,0 +1,4658 @@ +# x86 instruction set description version 0.2x, 2018-05-08 +# +# https://golang.org/x/arch/x86 +# +# The latest version of the CSV file is +# available online at https://golang.org/s/x86.csv. +# +# This file contains a block of comment lines, each beginning with #, +# followed by entries in CSV format. All the # comments are at the top +# of the file, so a reader can skip past the comments and hand the +# rest of the file to a standard CSV reader. +# Each CSV line contains these fields: +# +# 1. The Intel manual instruction mnemonic. For example, "SHR r/m32, imm8". +# +# 2. The Go assembler instruction mnemonic. For example, "SHRL imm8, r/m32". +# +# 3. The GNU binutils instruction mnemonic. For example, "shrl imm8, r/m32". +# +# 4. The instruction encoding. For example, "C1 /4 ib". +# +# 5. The validity of the instruction in 32-bit (aka compatiblity, legacy) mode. +# +# 6. The validity of the instruction in 64-bit mode. +# +# 7. The CPUID feature flags that signal support for the instruction. +# +# 8. Additional comma-separated tags containing hints about the instruction. +# +# 9. The read/write actions of the instruction on the arguments used in +# the Intel mnemonic. For example, "rw,r" to denote that "SHR r/m32, imm8" +# reads and writes its first argument but only reads its second argument. +# +# 10. Whether the opcode used in the Intel mnemonic has encoding forms +# distinguished only by operand size, like most arithmetic instructions. +# The string "Y" indicates yes, the string "" indicates no. +# +# 11. The data size of the operation in bits. In general this is the size corresponding +# to the Go and GNU assembler opcode suffix. +# Mnemonics (the opcode string) +# +# The instruction mnemonics are as used in the Intel manual, with a few exceptions. +# +# Mnemonics claiming general memory forms but that really require fixed addressing modes +# are omitted in favor of their equivalents with implicit arguments.. +# For example, "CMPS m16, m16" (really CMPS [SI], [DI]) is omitted in favor of "CMPSW". +# +# Instruction forms with an explicit REP, REPE, or REPNE prefix are also omitted. +# Encoders and decoders are expected to handle those prefixes separately. +# +# Perhaps most significantly, the argument syntaxes used in the mnemonic indicate +# exactly how to derive the argument from the instruction encoding, or vice versa. +# +# Immediate values: imm8, imm8u, imm16, imm16u, imm32, imm64. +# Immediates are signed by default; the u suffixes indicates an unsigned value. +# Immediates may have bitfield-like modifier that specifies how much bits +# are used. For example, imm8u:4 is encoded like 8bit immediate, +# but only 4bits are meaningful while the others are ignored or must be 0. +# +# Memory operands. The forms m, m128, m14/28byte, m16, m16&16, m16&32, m16&64, m16:16, m16:32, +# m16:64, m16int, m256, m2byte, m32, m32&32, m32fp, m32int, m512byte, m64, m64fp, m64int, +# m8, m80bcd, m80dec, m80fp, m94/108byte. These operands always correspond to the +# memory address specified by the r/m half of the modrm encoding. +# +# Integer registers. +# The forms r8, r16, r32, r64 indicate a register selected by the modrm reg encoding. +# The forms rmr16, rmr32, rmr64 indicate a register (never memory) selected by the modrm r/m encoding. +# The forms r/m8, r/m16, r/m32, and r/m64 indicate a register or memory selected by the modrm r/m encoding. +# Forms with two sizes, like r32/m16 also indicate a register or memory selected by the modrm r/m encodng, +# but the size for a register argument differs from the size of a memory argument. +# The forms r8V, r16V, r32V, r64V indicate a register selected by the VEX.vvvv bits. +# +# Multimedia registers. +# The forms mm1, xmm1, and ymm1 indicate a multimedia register selected by the +# modrm reg encoding. +# The forms mm2, xmm2, and ymm2 indicate a register (never memory) selected by +# the modrm r/m encoding. +# The forms mm2/m64, xmm2/m128, and so on indicate a register or memory +# selected by the modrm r/m encoding. +# The forms xmmV and ymmV indicate a register selected by the VEX.vvvv bits. +# The forms xmmI and ymmI indicate a register selected by the top four bits of an /is4 immediate byte. +# +# Bound registers. +# The form bnd1 indicates a bound register selected by the modrm reg encoding. +# The form bnd2 indicates a bound register (never memory) selected by the modrm r/m encoding. +# The forms bnd2/m64 and bnd2/m128 indicate a register or memorys selected by the modrm r/m encoding. +# TODO: Describe mib. +# +# One-of-a-kind operands: rel8, rel16, rel32, ptr16:16, ptr16:32, +# moffs8, moffs16, moffs32, moffs64, vm32x, vm32y, vm64x, and vm64y +# are all as in the Intel manual. +# +# Encodings +# +# The encodings are also as used in the Intel manual, with automated corrections. +# For example, the Intel manual sometimes omits the modrm /r indicator or other trailing bytes, +# and it also contains typographical errors. +# These problems are corrected so that the CSV data may be used to generate +# tools for processing x86 machine code. +# See https://golang.org/x/arch/x86/x86map for one such generator. +# +# Valid32 and Valid64 +# +# These columns hold validity abbreviations as defined in the Intel manual: +# V, I, N.E., N.P., N.S., or N.I. +# Tools processing the data are typically only concerned with whether the +# column is "V" (valid) or not. +# This data is also corrected compared to the manual. +# For example, the manual lists many instruction forms using REX bytes +# with an incorrect "V" in the Valid32 column. +# +# CPUID Feature Flags +# +# This column specifies CPUID feature flags that must be present in order +# to use the instruction. If multiple flags are required, +# they are listed separated by plus signs, as in PCLMULQDQ+AVX. +# The column can also list one of the values 486, Pentium, PentiumII, and P6, +# indicating that the instruction was introduced on that architecture version. +# +# Tags +# +# The tag column does not correspond to a traditional column in the Intel manual tables. +# Instead, it is itself a comma-separated list of tags or hints derived by analysis +# of the instruction set or the instruction encodings. +# +# The tags address16, address32, and address64 indicate that the instruction form +# applies when using the specified addressing size. It may therefore be necessary to use an +# address size prefix byte to access the instruction. +# If two address tags are listed, the instruction can be used with either of those +# address sizes. An instruction will never list all three address sizes. +# (In fact, today, no instruction lists two address sizes, but that may change.) +# +# The tags operand16, operand32, and operand64 indicate that the instruction form +# applies when using the specified operand size. It may therefore be necessary to use an +# operand size prefix byte to access the instruction. +# If two operand tags are listed, the instruction can be used with either of those +# operand sizes. An instruction will never list all three operand sizes. +# For some instructions, default64 is used instead of operand64, +# which specifies data promotion to 64-bit. +# For instructions with different possible data sizes, +# it also describes that default data size is 64-bit instead of 32-bit. +# Using refining prefix like 0x66 will lead to 32-bit operation (if supported). +# +# The tags modrm_regonly or modrm_memonly indicate that the modrm byte's +# r/m encoding must specify a register or memory, respectively. +# Especially in newer instructions, the modrm constraint may be the only way +# to distinguish two instruction forms. For example the MOVHLPS and MOVLPS +# instructions share the same encoding, except that the former requires the +# modrm byte's r/m to indicate a register, while the latter requires it to indicate memory. +# +# The tags pseudo and pseudo64 indicate that this instruction form is redundant +# with others listed in the table and should be ignored when generating disassembly +# or instruction scanning programs. The pseudo64 tag is reserved for the case where +# the manual lists an instruction twice, once with the optional 64-bit mode REX byte. +# Since most decoders will handle the REX byte separately, the form with the +# unnecessary REX is tagged pseudo64. +# +# The amd tag marks AMD-specific instructions. +# As an example, all instructions of SSE4a have such tag. +# +# The AVX512-specific tags: scaleX and bscaleX. +# scale1, scale2, scale4, scale8, scale16, scale32, scale64 specify +# the compressed displacement multiplier (scaling). +# For example, if displacement is 128 and scale32 is set, +# disp8 value should be calculated as 128/32. +# bscale4 and bscale8 have the same meaning, but are used +# when instruction uses embedded broadcast feature. +# If instruction does not have bscaleX tag, it does not support EVEX broadcasting. +# +# Related packages (can be a good source of additional documentation): +# x86csv - read and manipulate x86.csv +# x86spec - x86.csv generator +# x86map - x86asm table generator based on x86.csv +# x86avxgen - cmd/internal/obj/x86 optab generator based x86.csv +# All listed packages are located at golang.org/x/arch/x86/. +"PUSH imm32","-/PUSHL/PUSHQ imm32","-/pushl/pushq imm32","68 id","V","N.S.","","operand32","r","Y","" +"PUSH imm32","-/PUSHL/PUSHQ imm32","-/pushl/pushq imm32","68 id","N.S.","V","","default64","r","Y","" +"AAA","AAA","aaa","37","V","N.S.","","","","","" +"AAD","AAD","aad","D5 0A","V","I","","pseudo","","","" +"AAD imm8u","AAD imm8u","aad imm8u","D5 ib","V","N.S.","","","r","","" +"AAM","AAM","aam","D4 0A","V","I","","pseudo","","","" +"AAM imm8u","AAM imm8u","aam imm8u","D4 ib","V","N.S.","","","r","","" +"AAS","AAS","aas","3F","V","N.S.","","","","","" +"ADC AL, imm8","ADCB imm8, AL","adcb imm8, AL","14 ib","V","V","","","rw,r","Y","8" +"ADC r/m8, imm8","ADCB imm8, r/m8","adcb imm8, r/m8","80 /2 ib","V","V","","","rw,r","Y","8" +"ADC r/m8, imm8","ADCB imm8, r/m8","adcb imm8, r/m8","82 /2 ib","V","N.S.","","","rw,r","Y","8" +"ADC r/m8, imm8","ADCB imm8, r/m8","adcb imm8, r/m8","REX 80 /2 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"ADC r8, r/m8","ADCB r/m8, r8","adcb r/m8, r8","12 /r","V","V","","","rw,r","Y","8" +"ADC r8, r/m8","ADCB r/m8, r8","adcb r/m8, r8","REX 12 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"ADC r/m8, r8","ADCB r8, r/m8","adcb r8, r/m8","10 /r","V","V","","","rw,r","Y","8" +"ADC r/m8, r8","ADCB r8, r/m8","adcb r8, r/m8","REX 10 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"ADC EAX, imm32","ADCL imm32, EAX","adcl imm32, EAX","15 id","V","V","","operand32","rw,r","Y","32" +"ADC r/m32, imm32","ADCL imm32, r/m32","adcl imm32, r/m32","81 /2 id","V","V","","operand32","rw,r","Y","32" +"ADC r/m32, imm8","ADCL imm8, r/m32","adcl imm8, r/m32","83 /2 ib","V","V","","operand32","rw,r","Y","32" +"ADC r32, r/m32","ADCL r/m32, r32","adcl r/m32, r32","13 /r","V","V","","operand32","rw,r","Y","32" +"ADC r/m32, r32","ADCL r32, r/m32","adcl r32, r/m32","11 /r","V","V","","operand32","rw,r","Y","32" +"ADC RAX, imm32","ADCQ imm32, RAX","adcq imm32, RAX","REX.W 15 id","N.S.","V","","","rw,r","Y","64" +"ADC r/m64, imm32","ADCQ imm32, r/m64","adcq imm32, r/m64","REX.W 81 /2 id","N.S.","V","","","rw,r","Y","64" +"ADC r/m64, imm8","ADCQ imm8, r/m64","adcq imm8, r/m64","REX.W 83 /2 ib","N.S.","V","","","rw,r","Y","64" +"ADC r64, r/m64","ADCQ r/m64, r64","adcq r/m64, r64","REX.W 13 /r","N.S.","V","","","rw,r","Y","64" +"ADC r/m64, r64","ADCQ r64, r/m64","adcq r64, r/m64","REX.W 11 /r","N.S.","V","","","rw,r","Y","64" +"ADC AX, imm16","ADCW imm16, AX","adcw imm16, AX","15 iw","V","V","","operand16","rw,r","Y","16" +"ADC r/m16, imm16","ADCW imm16, r/m16","adcw imm16, r/m16","81 /2 iw","V","V","","operand16","rw,r","Y","16" +"ADC r/m16, imm8","ADCW imm8, r/m16","adcw imm8, r/m16","83 /2 ib","V","V","","operand16","rw,r","Y","16" +"ADC r16, r/m16","ADCW r/m16, r16","adcw r/m16, r16","13 /r","V","V","","operand16","rw,r","Y","16" +"ADC r/m16, r16","ADCW r16, r/m16","adcw r16, r/m16","11 /r","V","V","","operand16","rw,r","Y","16" +"ADCX r32, r/m32","ADCXL r/m32, r32","adcxl r/m32, r32","66 0F 38 F6 /r","V","V","ADX","operand16,operand32","rw,r","Y","32" +"ADCX r64, r/m64","ADCXQ r/m64, r64","adcxq r/m64, r64","66 REX.W 0F 38 F6 /r","N.S.","V","ADX","","rw,r","Y","64" +"ADD AL, imm8","ADDB imm8, AL","addb imm8, AL","04 ib","V","V","","","rw,r","Y","8" +"ADD r/m8, imm8","ADDB imm8, r/m8","addb imm8, r/m8","80 /0 ib","V","V","","","rw,r","Y","8" +"ADD r/m8, imm8","ADDB imm8, r/m8","addb imm8, r/m8","82 /0 ib","V","N.S.","","","rw,r","Y","8" +"ADD r/m8, imm8","ADDB imm8, r/m8","addb imm8, r/m8","REX 80 /0 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"ADD r8, r/m8","ADDB r/m8, r8","addb r/m8, r8","02 /r","V","V","","","rw,r","Y","8" +"ADD r8, r/m8","ADDB r/m8, r8","addb r/m8, r8","REX 02 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"ADD r/m8, r8","ADDB r8, r/m8","addb r8, r/m8","00 /r","V","V","","","rw,r","Y","8" +"ADD r/m8, r8","ADDB r8, r/m8","addb r8, r/m8","REX 00 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"ADD EAX, imm32","ADDL imm32, EAX","addl imm32, EAX","05 id","V","V","","operand32","rw,r","Y","32" +"ADD r/m32, imm32","ADDL imm32, r/m32","addl imm32, r/m32","81 /0 id","V","V","","operand32","rw,r","Y","32" +"ADD r/m32, imm8","ADDL imm8, r/m32","addl imm8, r/m32","83 /0 ib","V","V","","operand32","rw,r","Y","32" +"ADD r32, r/m32","ADDL r/m32, r32","addl r/m32, r32","03 /r","V","V","","operand32","rw,r","Y","32" +"ADD r/m32, r32","ADDL r32, r/m32","addl r32, r/m32","01 /r","V","V","","operand32","rw,r","Y","32" +"ADDPD xmm1, xmm2/m128","ADDPD xmm2/m128, xmm1","addpd xmm2/m128, xmm1","66 0F 58 /r","V","V","SSE2","","rw,r","","" +"ADDPS xmm1, xmm2/m128","ADDPS xmm2/m128, xmm1","addps xmm2/m128, xmm1","0F 58 /r","V","V","SSE","","rw,r","","" +"ADD RAX, imm32","ADDQ imm32, RAX","addq imm32, RAX","REX.W 05 id","N.S.","V","","","rw,r","Y","64" +"ADD r/m64, imm32","ADDQ imm32, r/m64","addq imm32, r/m64","REX.W 81 /0 id","N.S.","V","","","rw,r","Y","64" +"ADD r/m64, imm8","ADDQ imm8, r/m64","addq imm8, r/m64","REX.W 83 /0 ib","N.S.","V","","","rw,r","Y","64" +"ADD r64, r/m64","ADDQ r/m64, r64","addq r/m64, r64","REX.W 03 /r","N.S.","V","","","rw,r","Y","64" +"ADD r/m64, r64","ADDQ r64, r/m64","addq r64, r/m64","REX.W 01 /r","N.S.","V","","","rw,r","Y","64" +"ADDSD xmm1, xmm2/m64","ADDSD xmm2/m64, xmm1","addsd xmm2/m64, xmm1","F2 0F 58 /r","V","V","SSE2","","rw,r","","" +"ADDSS xmm1, xmm2/m32","ADDSS xmm2/m32, xmm1","addss xmm2/m32, xmm1","F3 0F 58 /r","V","V","SSE","","rw,r","","" +"ADDSUBPD xmm1, xmm2/m128","ADDSUBPD xmm2/m128, xmm1","addsubpd xmm2/m128, xmm1","66 0F D0 /r","V","V","SSE3","","rw,r","","" +"ADDSUBPS xmm1, xmm2/m128","ADDSUBPS xmm2/m128, xmm1","addsubps xmm2/m128, xmm1","F2 0F D0 /r","V","V","SSE3","","rw,r","","" +"ADD AX, imm16","ADDW imm16, AX","addw imm16, AX","05 iw","V","V","","operand16","rw,r","Y","16" +"ADD r/m16, imm16","ADDW imm16, r/m16","addw imm16, r/m16","81 /0 iw","V","V","","operand16","rw,r","Y","16" +"ADD r/m16, imm8","ADDW imm8, r/m16","addw imm8, r/m16","83 /0 ib","V","V","","operand16","rw,r","Y","16" +"ADD r16, r/m16","ADDW r/m16, r16","addw r/m16, r16","03 /r","V","V","","operand16","rw,r","Y","16" +"ADD r/m16, r16","ADDW r16, r/m16","addw r16, r/m16","01 /r","V","V","","operand16","rw,r","Y","16" +"ADOX r32, r/m32","ADOXL r/m32, r32","adoxl r/m32, r32","F3 0F 38 F6 /r","V","V","ADX","operand16,operand32","rw,r","Y","32" +"ADOX r64, r/m64","ADOXQ r/m64, r64","adoxq r/m64, r64","F3 REX.W 0F 38 F6 /r","N.S.","V","ADX","","rw,r","Y","64" +"AESDEC xmm1, xmm2/m128","AESDEC xmm2/m128, xmm1","aesdec xmm2/m128, xmm1","66 0F 38 DE /r","V","V","AES","","rw,r","","" +"AESDECLAST xmm1, xmm2/m128","AESDECLAST xmm2/m128, xmm1","aesdeclast xmm2/m128, xmm1","66 0F 38 DF /r","V","V","AES","","rw,r","","" +"AESENC xmm1, xmm2/m128","AESENC xmm2/m128, xmm1","aesenc xmm2/m128, xmm1","66 0F 38 DC /r","V","V","AES","","rw,r","","" +"AESENCLAST xmm1, xmm2/m128","AESENCLAST xmm2/m128, xmm1","aesenclast xmm2/m128, xmm1","66 0F 38 DD /r","V","V","AES","","rw,r","","" +"AESIMC xmm1, xmm2/m128","AESIMC xmm2/m128, xmm1","aesimc xmm2/m128, xmm1","66 0F 38 DB /r","V","V","AES","","w,r","","" +"AESKEYGENASSIST xmm1, xmm2/m128, imm8u","AESKEYGENASSIST imm8u, xmm2/m128, xmm1","aeskeygenassist imm8u, xmm2/m128, xmm1","66 0F 3A DF /r ib","V","V","AES","","w,r,r","","" +"AND AL, imm8","ANDB imm8, AL","andb imm8, AL","24 ib","V","V","","","rw,r","Y","8" +"AND r/m8, imm8","ANDB imm8, r/m8","andb imm8, r/m8","REX 80 /4 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"AND r/m8, imm8u","ANDB imm8u, r/m8","andb imm8u, r/m8","80 /4 ib","V","V","","","rw,r","Y","8" +"AND r/m8, imm8u","ANDB imm8u, r/m8","andb imm8u, r/m8","82 /4 ib","V","N.S.","","","rw,r","Y","8" +"AND r8, r/m8","ANDB r/m8, r8","andb r/m8, r8","22 /r","V","V","","","rw,r","Y","8" +"AND r8, r/m8","ANDB r/m8, r8","andb r/m8, r8","REX 22 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"AND r/m8, r8","ANDB r8, r/m8","andb r8, r/m8","20 /r","V","V","","","rw,r","Y","8" +"AND r/m8, r8","ANDB r8, r/m8","andb r8, r/m8","REX 20 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"AND EAX, imm32","ANDL imm32, EAX","andl imm32, EAX","25 id","V","V","","operand32","rw,r","Y","32" +"AND r/m32, imm32","ANDL imm32, r/m32","andl imm32, r/m32","81 /4 id","V","V","","operand32","rw,r","Y","32" +"AND r/m32, imm8","ANDL imm8, r/m32","andl imm8, r/m32","83 /4 ib","V","V","","operand32","rw,r","Y","32" +"AND r32, r/m32","ANDL r/m32, r32","andl r/m32, r32","23 /r","V","V","","operand32","rw,r","Y","32" +"AND r/m32, r32","ANDL r32, r/m32","andl r32, r/m32","21 /r","V","V","","operand32","rw,r","Y","32" +"ANDN r32, r32V, r/m32","ANDNL r/m32, r32V, r32","andnl r/m32, r32V, r32","VEX.DDS.128.0F38.W0 F2 /r","V","V","BMI1","","rw,r,r","Y","32" +"ANDNPD xmm1, xmm2/m128","ANDNPD xmm2/m128, xmm1","andnpd xmm2/m128, xmm1","66 0F 55 /r","V","V","SSE2","","rw,r","","" +"ANDNPS xmm1, xmm2/m128","ANDNPS xmm2/m128, xmm1","andnps xmm2/m128, xmm1","0F 55 /r","V","V","SSE","","rw,r","","" +"ANDN r64, r64V, r/m64","ANDNQ r/m64, r64V, r64","andnq r/m64, r64V, r64","VEX.DDS.128.0F38.W1 F2 /r","N.S.","V","BMI1","","rw,r,r","Y","64" +"ANDPD xmm1, xmm2/m128","ANDPD xmm2/m128, xmm1","andpd xmm2/m128, xmm1","66 0F 54 /r","V","V","SSE2","","rw,r","","" +"ANDPS xmm1, xmm2/m128","ANDPS xmm2/m128, xmm1","andps xmm2/m128, xmm1","0F 54 /r","V","V","SSE","","rw,r","","" +"AND RAX, imm32","ANDQ imm32, RAX","andq imm32, RAX","REX.W 25 id","N.S.","V","","","rw,r","Y","64" +"AND r/m64, imm32","ANDQ imm32, r/m64","andq imm32, r/m64","REX.W 81 /4 id","N.S.","V","","","rw,r","Y","64" +"AND r/m64, imm8","ANDQ imm8, r/m64","andq imm8, r/m64","REX.W 83 /4 ib","N.S.","V","","","rw,r","Y","64" +"AND r64, r/m64","ANDQ r/m64, r64","andq r/m64, r64","REX.W 23 /r","N.S.","V","","","rw,r","Y","64" +"AND r/m64, r64","ANDQ r64, r/m64","andq r64, r/m64","REX.W 21 /r","N.S.","V","","","rw,r","Y","64" +"AND AX, imm16","ANDW imm16, AX","andw imm16, AX","25 iw","V","V","","operand16","rw,r","Y","16" +"AND r/m16, imm16","ANDW imm16, r/m16","andw imm16, r/m16","81 /4 iw","V","V","","operand16","rw,r","Y","16" +"AND r/m16, imm8","ANDW imm8, r/m16","andw imm8, r/m16","83 /4 ib","V","V","","operand16","rw,r","Y","16" +"AND r16, r/m16","ANDW r/m16, r16","andw r/m16, r16","23 /r","V","V","","operand16","rw,r","Y","16" +"AND r/m16, r16","ANDW r16, r/m16","andw r16, r/m16","21 /r","V","V","","operand16","rw,r","Y","16" +"ARPL r/m16, r16","ARPL r16, r/m16","arpl r16, r/m16","63 /r","V","N.S.","","","rw,r","","" +"BEXTR r32, r/m32, r32V","BEXTRL r32V, r/m32, r32","bextrl r32V, r/m32, r32","VEX.NDS.128.0F38.W0 F7 /r","V","V","BMI1","","w,r,r","Y","32" +"BEXTR r64, r/m64, r64V","BEXTRQ r64V, r/m64, r64","bextrq r64V, r/m64, r64","VEX.NDS.128.0F38.W1 F7 /r","N.S.","V","BMI1","","w,r,r","Y","64" +"BEXTR_XOP r32, r/m32, imm32u","BEXTR_XOPL imm32u, r/m32, r32","bextr_xopl imm32u, r/m32, r32","XOP.128.0A.WIG 10 /r","V","V","TBM","amd,operand16,operand32","w,r,r","Y","32" +"BEXTR_XOP r64, r/m64, imm32u","BEXTR_XOPQ imm32u, r/m64, r64","bextr_xopq imm32u, r/m64, r64","XOP.128.0A.WIG 10 /r","N.S.","V","TBM","amd,operand64","w,r,r","Y","64" +"BLCFILL r32V, r/m32","BLCFILLL r/m32, r32V","blcfill r/m32, r32V","XOP.NDD.128.09.WIG 01 /1","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"BLCFILL r64V, r/m64","BLCFILLQ r/m64, r64V","blcfill r/m64, r64V","XOP.NDD.128.09.W1 01 /1","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"BLCIC r32V, r/m32","BLCICL r/m32, r32V","blcicl r/m32, r32V","XOP.NDD.128.09.WIG 01 /5","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"BLCIC r64V, r/m64","BLCICQ r/m64, r64V","blcicq r/m64, r64V","XOP.NDD.128.09.WIG 01 /5","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"BLCI r32V, r/m32","BLCIL r/m32, r32V","blcil r/m32, r32V","XOP.NDD.128.09.WIG 02 /6","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"BLCI r64V, r/m64","BLCIQ r/m64, r64V","blciq r/m64, r64V","XOP.NDD.128.09.WIG 02 /6","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"BLCMSK r32V, r/m32","BLCMSKL r/m32, r32V","blcmskl r/m32, r32V","XOP.NDD.128.09.WIG 02 /1","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"BLCMSK r64V, r/m64","BLCMSKQ r/m64, r64V","blcmskq r/m64, r64V","XOP.NDD.128.09.WIG 02 /1","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"BLCS r32V, r/m32","BLCSL r/m32, r32V","blcsl r/m32, r32V","XOP.NDD.128.09.WIG 01 /3","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"BLCS r64V, r/m64","BLCSQ r/m64, r64V","blcsq r/m64, r64V","XOP.NDD.128.09.WIG 01 /3","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"BLENDPD xmm1, xmm2/m128, imm8u","BLENDPD imm8u, xmm2/m128, xmm1","blendpd imm8u, xmm2/m128, xmm1","66 0F 3A 0D /r ib","V","V","SSE4_1","","rw,r,r","","" +"BLENDPS xmm1, xmm2/m128, imm8u","BLENDPS imm8u, xmm2/m128, xmm1","blendps imm8u, xmm2/m128, xmm1","66 0F 3A 0C /r ib","V","V","SSE4_1","","rw,r,r","","" +"BLENDVPD xmm1, xmm2/m128, ","BLENDVPD , xmm2/m128, xmm1","blendvpd , xmm2/m128, xmm1","66 0F 38 15 /r","V","V","SSE4_1","","rw,r,r","","" +"BLENDVPS xmm1, xmm2/m128, ","BLENDVPS , xmm2/m128, xmm1","blendvps , xmm2/m128, xmm1","66 0F 38 14 /r","V","V","SSE4_1","","rw,r,r","","" +"BLSFILL r32V, r/m32","BLSFILLL r/m32, r32V","blsfill r/m32, r32V","XOP.NDD.128.09.WIG 01 /2","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"BLSFILL r64V, r/m64","BLSFILLQ r/m64, r64V","blsfill r/m64, r64V","XOP.NDD.128.09.W1 01 /2","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"BLSIC r32V, r/m32","BLSICL r/m32, r32V","blsicl r/m32, r32V","XOP.NDD.128.09.WIG 01 /6","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"BLSIC r64V, r/m64","BLSICQ r/m64, r64V","blsicq r/m64, r64V","XOP.NDD.128.09.WIG 01 /6","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"BLSI r32V, r/m32","BLSIL r/m32, r32V","blsil r/m32, r32V","VEX.NDD.128.0F38.W0 F3 /3","V","V","BMI1","","w,r","Y","32" +"BLSI r64V, r/m64","BLSIQ r/m64, r64V","blsiq r/m64, r64V","VEX.NDD.128.0F38.W1 F3 /3","N.S.","V","BMI1","","w,r","Y","64" +"BLSMSK r32V, r/m32","BLSMSKL r/m32, r32V","blsmskl r/m32, r32V","VEX.NDD.128.0F38.W0 F3 /2","V","V","BMI1","","w,r","Y","32" +"BLSMSK r64V, r/m64","BLSMSKQ r/m64, r64V","blsmskq r/m64, r64V","VEX.NDD.128.0F38.W1 F3 /2","N.S.","V","BMI1","","w,r","Y","64" +"BLSR r32V, r/m32","BLSRL r/m32, r32V","blsrl r/m32, r32V","VEX.NDD.128.0F38.W0 F3 /1","V","V","BMI1","","w,r","Y","32" +"BLSR r64V, r/m64","BLSRQ r/m64, r64V","blsrq r/m64, r64V","VEX.NDD.128.0F38.W1 F3 /1","N.S.","V","BMI1","","w,r","Y","64" +"BNDCL bnd1, r/m32","BNDCL r/m32, bnd1","bndcl r/m32, bnd1","F3 0F 1A /r","V","N.S.","MPX","","r,r","","" +"BNDCL bnd1, r/m64","BNDCL r/m64, bnd1","bndcl r/m64, bnd1","F3 0F 1A /r","N.S.","V","MPX","","r,r","","" +"BNDCN bnd1, r/m32","BNDCN r/m32, bnd1","bndcn r/m32, bnd1","F2 0F 1B /r","V","N.S.","MPX","","r,r","","" +"BNDCN bnd1, r/m64","BNDCN r/m64, bnd1","bndcn r/m64, bnd1","F2 0F 1B /r","N.S.","V","MPX","","r,r","","" +"BNDCU bnd1, r/m32","BNDCU r/m32, bnd1","bndcu r/m32, bnd1","F2 0F 1A /r","V","N.S.","MPX","","r,r","","" +"BNDCU bnd1, r/m64","BNDCU r/m64, bnd1","bndcu r/m64, bnd1","F2 0F 1A /r","N.S.","V","MPX","","r,r","","" +"BNDLDX bnd1, mib","BNDLDX mib, bnd1","bndldx mib, bnd1","0F 1A /r","V","V","MPX","modrm_memonly","w,r","","" +"BNDMK bnd1, m32","BNDMK m32, bnd1","bndmk m32, bnd1","F3 0F 1B /r","V","N.S.","MPX","modrm_memonly","w,r","","" +"BNDMK bnd1, m64","BNDMK m64, bnd1","bndmk m64, bnd1","F3 0F 1B /r","N.S.","V","MPX","modrm_memonly","w,r","","" +"BNDMOV bnd2/m128, bnd1","BNDMOV bnd1, bnd2/m128","bndmov bnd1, bnd2/m128","66 0F 1B /r","N.S.","V","MPX","","w,r","","" +"BNDMOV bnd2/m64, bnd1","BNDMOV bnd1, bnd2/m64","bndmov bnd1, bnd2/m64","66 0F 1B /r","V","N.S.","MPX","","w,r","","" +"BNDMOV bnd1, bnd2/m128","BNDMOV bnd2/m128, bnd1","bndmov bnd2/m128, bnd1","66 0F 1A /r","N.S.","V","MPX","","w,r","","" +"BNDMOV bnd1, bnd2/m64","BNDMOV bnd2/m64, bnd1","bndmov bnd2/m64, bnd1","66 0F 1A /r","V","N.S.","MPX","","w,r","","" +"BNDSTX mib, bnd1","BNDSTX bnd1, mib","bndstx bnd1, mib","0F 1B /r","V","V","MPX","modrm_memonly","w,r","","" +"BOUND r32, m32&32","BOUNDL m32&32, r32","boundl r32, m32&32","62 /r","V","N.S.","","modrm_memonly,operand32","r,r","Y","32" +"BOUND r16, m16&16","BOUNDW m16&16, r16","boundw r16, m16&16","62 /r","V","N.S.","","modrm_memonly,operand16","r,r","Y","16" +"BSF r32, r/m32","BSFL r/m32, r32","bsfl r/m32, r32","0F BC /r","V","V","","operand32","rw,r","Y","32" +"BSF r32, r/m32","BSFL r/m32, r32","bsfl r/m32, r32","F3 0F BC /r","V","V","","operand32","rw,r","Y","32" +"BSF r64, r/m64","BSFQ r/m64, r64","bsfq r/m64, r64","F3 REX.W 0F BC /r","N.S.","V","","","rw,r","Y","64" +"BSF r64, r/m64","BSFQ r/m64, r64","bsfq r/m64, r64","REX.W 0F BC /r","N.S.","V","","","rw,r","Y","64" +"BSF r16, r/m16","BSFW r/m16, r16","bsfw r/m16, r16","0F BC /r","V","V","","operand16","rw,r","Y","16" +"BSF r16, r/m16","BSFW r/m16, r16","bsfw r/m16, r16","F3 0F BC /r","V","V","","operand16","rw,r","Y","16" +"BSR r32, r/m32","BSRL r/m32, r32","bsrl r/m32, r32","0F BD /r","V","V","","operand32","rw,r","Y","32" +"BSR r32, r/m32","BSRL r/m32, r32","bsrl r/m32, r32","F3 0F BD /r","V","V","","operand32","rw,r","Y","32" +"BSR r64, r/m64","BSRQ r/m64, r64","bsrq r/m64, r64","F3 REX.W 0F BD /r","N.S.","V","","","rw,r","Y","64" +"BSR r64, r/m64","BSRQ r/m64, r64","bsrq r/m64, r64","REX.W 0F BD /r","N.S.","V","","","rw,r","Y","64" +"BSR r16, r/m16","BSRW r/m16, r16","bsrw r/m16, r16","0F BD /r","V","V","","operand16","rw,r","Y","16" +"BSR r16, r/m16","BSRW r/m16, r16","bsrw r/m16, r16","F3 0F BD /r","V","V","","operand16","rw,r","Y","16" +"BSWAP r32op","BSWAPL r32op","bswap r32op","0F C8+rd","V","V","486","operand32","rw","Y","32" +"BSWAP r64op","BSWAPQ r64op","bswap r64op","REX.W 0F C8+ro","N.S.","V","486","","rw","Y","64" +"BSWAP r16op","BSWAPW r16op","bswap r16op","0F C8+rw","V","V","486","operand16","rw","Y","16" +"BTC r/m32, imm8u","BTCL imm8u, r/m32","btcl imm8u, r/m32","0F BA /7 ib","V","V","","operand32","rw,r","Y","32" +"BTC r/m32, r32","BTCL r32, r/m32","btcl r32, r/m32","0F BB /r","V","V","","operand32","rw,r","Y","32" +"BTC r/m64, imm8u","BTCQ imm8u, r/m64","btcq imm8u, r/m64","REX.W 0F BA /7 ib","N.S.","V","","","rw,r","Y","64" +"BTC r/m64, r64","BTCQ r64, r/m64","btcq r64, r/m64","REX.W 0F BB /r","N.S.","V","","","rw,r","Y","64" +"BTC r/m16, imm8u","BTCW imm8u, r/m16","btcw imm8u, r/m16","0F BA /7 ib","V","V","","operand16","rw,r","Y","16" +"BTC r/m16, r16","BTCW r16, r/m16","btcw r16, r/m16","0F BB /r","V","V","","operand16","rw,r","Y","16" +"BT r/m32, imm8u","BTL imm8u, r/m32","btl imm8u, r/m32","0F BA /4 ib","V","V","","operand32","r,r","Y","32" +"BT r/m32, r32","BTL r32, r/m32","btl r32, r/m32","0F A3 /r","V","V","","operand32","r,r","Y","32" +"BT r/m64, imm8u","BTQ imm8u, r/m64","btq imm8u, r/m64","REX.W 0F BA /4 ib","N.S.","V","","","r,r","Y","64" +"BT r/m64, r64","BTQ r64, r/m64","btq r64, r/m64","REX.W 0F A3 /r","N.S.","V","","","r,r","Y","64" +"BTR r/m32, imm8u","BTRL imm8u, r/m32","btrl imm8u, r/m32","0F BA /6 ib","V","V","","operand32","rw,r","Y","32" +"BTR r/m32, r32","BTRL r32, r/m32","btrl r32, r/m32","0F B3 /r","V","V","","operand32","rw,r","Y","32" +"BTR r/m64, imm8u","BTRQ imm8u, r/m64","btrq imm8u, r/m64","REX.W 0F BA /6 ib","N.S.","V","","","rw,r","Y","64" +"BTR r/m64, r64","BTRQ r64, r/m64","btrq r64, r/m64","REX.W 0F B3 /r","N.S.","V","","","rw,r","Y","64" +"BTR r/m16, imm8u","BTRW imm8u, r/m16","btrw imm8u, r/m16","0F BA /6 ib","V","V","","operand16","rw,r","Y","16" +"BTR r/m16, r16","BTRW r16, r/m16","btrw r16, r/m16","0F B3 /r","V","V","","operand16","rw,r","Y","16" +"BTS r/m32, imm8u","BTSL imm8u, r/m32","btsl imm8u, r/m32","0F BA /5 ib","V","V","","operand32","rw,r","Y","32" +"BTS r/m32, r32","BTSL r32, r/m32","btsl r32, r/m32","0F AB /r","V","V","","operand32","rw,r","Y","32" +"BTS r/m64, imm8u","BTSQ imm8u, r/m64","btsq imm8u, r/m64","REX.W 0F BA /5 ib","N.S.","V","","","rw,r","Y","64" +"BTS r/m64, r64","BTSQ r64, r/m64","btsq r64, r/m64","REX.W 0F AB /r","N.S.","V","","","rw,r","Y","64" +"BTS r/m16, imm8u","BTSW imm8u, r/m16","btsw imm8u, r/m16","0F BA /5 ib","V","V","","operand16","rw,r","Y","16" +"BTS r/m16, r16","BTSW r16, r/m16","btsw r16, r/m16","0F AB /r","V","V","","operand16","rw,r","Y","16" +"BT r/m16, imm8u","BTW imm8u, r/m16","btw imm8u, r/m16","0F BA /4 ib","V","V","","operand16","r,r","Y","16" +"BT r/m16, r16","BTW r16, r/m16","btw r16, r/m16","0F A3 /r","V","V","","operand16","r,r","Y","16" +"BZHI r32, r/m32, r32V","BZHIL r32V, r/m32, r32","bzhil r32V, r/m32, r32","VEX.NDS.128.0F38.W0 F5 /r","V","V","BMI2","","w,r,r","Y","32" +"BZHI r64, r/m64, r64V","BZHIQ r64V, r/m64, r64","bzhiq r64V, r/m64, r64","VEX.NDS.128.0F38.W1 F5 /r","N.S.","V","BMI2","","w,r,r","Y","64" +"CALL rel16","CALL rel16","call rel16","E8 cw","V","N.S.","","operand16","r","Y","" +"CALL rel32","CALL rel32","call rel32","E8 cd","V","N.S.","","operand32","r","Y","" +"CALL rel32","CALL rel32","call rel32","E8 cd","N.S.","V","","default64","r","Y","" +"CALL r/m32","CALLL* r/m32","calll* r/m32","FF /2","V","N.S.","","operand32","r","Y","32" +"CALL r/m64","CALLQ* r/m64","callq* r/m64","FF /2","N.S.","V","","default64","r","Y","64" +"CALL r/m16","CALLW* r/m16","callw* r/m16","FF /2","V","N.S.","","operand16","r","Y","16" +"CBW","CBW","cbtw","98","V","V","","operand16","","","" +"CDQ","CDQ","cltd","99","V","V","","operand32","","","" +"CDQE","CDQE","cltq","REX.W 98","N.S.","V","","","","","" +"CLAC","CLAC","clac","0F 01 CA","V","V","","","","","" +"CLC","CLC","clc","F8","V","V","","","","","" +"CLD","CLD","cld","FC","V","V","","","","","" +"CLFLUSH m8","CLFLUSH m8","clflush m8","0F AE /7","V","V","","modrm_memonly","r","","" +"CLFLUSHOPT m8","CLFLUSHOPT m8","clflushopt m8","66 0F AE /7","V","V","","modrm_memonly","r","","" +"CLGI","CLGI","clgi","0F 01 DD","V","V","SVM","amd","","","" +"CLI","CLI","cli","FA","V","V","","","","","" +"CLRSSBSY m64","CLRSSBSY m64","clrssbsy m64","F3 0F AE /6","V","V","CET","modrm_memonly","w","","" +"CLTS","CLTS","clts","0F 06","V","V","","","","","" +"CLWB m8","CLWB m8","clwb m8","66 0F AE /6","V","V","CLWB","modrm_memonly","r","","" +"CLZERO EAX","CLZEROL EAX","clzerol EAX","0F 01 FC","V","V","CLZERO","amd,modrm_regonly,operand32","r","Y","32" +"CLZERO RAX","CLZEROQ RAX","clzeroq RAX","REX.W 0F 01 FC","N.S.","V","CLZERO","amd,modrm_regonly","r","Y","64" +"CLZERO AX","CLZEROW AX","clzerow AX","0F 01 FC","V","V","CLZERO","amd,modrm_regonly,operand16","r","Y","16" +"CMC","CMC","cmc","F5","V","V","","","","","" +"CMOVC r16, r/m16","CMOVC r/m16, r16","cmovc r/m16, r16","0F 42 /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVC r32, r/m32","CMOVC r/m32, r32","cmovc r/m32, r32","0F 42 /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVC r64, r/m64","CMOVC r/m64, r64","cmovc r/m64, r64","REX.W 0F 42 /r","N.E.","V","","pseudo","rw,r","","" +"CMOVAE r32, r/m32","CMOVLCC r/m32, r32","cmovael r/m32, r32","0F 43 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVB r32, r/m32","CMOVLCS r/m32, r32","cmovbl r/m32, r32","0F 42 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVE r32, r/m32","CMOVLEQ r/m32, r32","cmovel r/m32, r32","0F 44 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVGE r32, r/m32","CMOVLGE r/m32, r32","cmovgel r/m32, r32","0F 4D /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVG r32, r/m32","CMOVLGT r/m32, r32","cmovgl r/m32, r32","0F 4F /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVA r32, r/m32","CMOVLHI r/m32, r32","cmoval r/m32, r32","0F 47 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVLE r32, r/m32","CMOVLLE r/m32, r32","cmovlel r/m32, r32","0F 4E /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVBE r32, r/m32","CMOVLLS r/m32, r32","cmovbel r/m32, r32","0F 46 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVL r32, r/m32","CMOVLLT r/m32, r32","cmovll r/m32, r32","0F 4C /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVS r32, r/m32","CMOVLMI r/m32, r32","cmovsl r/m32, r32","0F 48 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVNE r32, r/m32","CMOVLNE r/m32, r32","cmovnel r/m32, r32","0F 45 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVNO r32, r/m32","CMOVLOC r/m32, r32","cmovnol r/m32, r32","0F 41 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVO r32, r/m32","CMOVLOS r/m32, r32","cmovol r/m32, r32","0F 40 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVNP r32, r/m32","CMOVLPC r/m32, r32","cmovnpl r/m32, r32","0F 4B /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVNS r32, r/m32","CMOVLPL r/m32, r32","cmovnsl r/m32, r32","0F 49 /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVP r32, r/m32","CMOVLPS r/m32, r32","cmovpl r/m32, r32","0F 4A /r","V","V","","P6,operand32","rw,r","Y","32" +"CMOVNA r16, r/m16","CMOVNA r/m16, r16","cmovna r/m16, r16","0F 46 /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNA r32, r/m32","CMOVNA r/m32, r32","cmovna r/m32, r32","0F 46 /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNA r64, r/m64","CMOVNA r/m64, r64","cmovna r/m64, r64","REX.W 0F 46 /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNAE r16, r/m16","CMOVNAE r/m16, r16","cmovnae r/m16, r16","0F 42 /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNAE r32, r/m32","CMOVNAE r/m32, r32","cmovnae r/m32, r32","0F 42 /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNAE r64, r/m64","CMOVNAE r/m64, r64","cmovnae r/m64, r64","REX.W 0F 42 /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNB r16, r/m16","CMOVNB r/m16, r16","cmovnb r/m16, r16","0F 43 /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNB r32, r/m32","CMOVNB r/m32, r32","cmovnb r/m32, r32","0F 43 /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNB r64, r/m64","CMOVNB r/m64, r64","cmovnb r/m64, r64","REX.W 0F 43 /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNBE r16, r/m16","CMOVNBE r/m16, r16","cmovnbe r/m16, r16","0F 47 /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNBE r32, r/m32","CMOVNBE r/m32, r32","cmovnbe r/m32, r32","0F 47 /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNBE r64, r/m64","CMOVNBE r/m64, r64","cmovnbe r/m64, r64","REX.W 0F 47 /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNC r16, r/m16","CMOVNC r/m16, r16","cmovnc r/m16, r16","0F 43 /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNC r32, r/m32","CMOVNC r/m32, r32","cmovnc r/m32, r32","0F 43 /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNC r64, r/m64","CMOVNC r/m64, r64","cmovnc r/m64, r64","REX.W 0F 43 /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNG r16, r/m16","CMOVNG r/m16, r16","cmovng r/m16, r16","0F 4E /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNG r32, r/m32","CMOVNG r/m32, r32","cmovng r/m32, r32","0F 4E /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNG r64, r/m64","CMOVNG r/m64, r64","cmovng r/m64, r64","REX.W 0F 4E /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNGE r16, r/m16","CMOVNGE r/m16, r16","cmovnge r/m16, r16","0F 4C /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNGE r32, r/m32","CMOVNGE r/m32, r32","cmovnge r/m32, r32","0F 4C /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNGE r64, r/m64","CMOVNGE r/m64, r64","cmovnge r/m64, r64","REX.W 0F 4C /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNL r16, r/m16","CMOVNL r/m16, r16","cmovnl r/m16, r16","0F 4D /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNL r32, r/m32","CMOVNL r/m32, r32","cmovnl r/m32, r32","0F 4D /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNL r64, r/m64","CMOVNL r/m64, r64","cmovnl r/m64, r64","REX.W 0F 4D /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNLE r16, r/m16","CMOVNLE r/m16, r16","cmovnle r/m16, r16","0F 4F /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNLE r32, r/m32","CMOVNLE r/m32, r32","cmovnle r/m32, r32","0F 4F /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNLE r64, r/m64","CMOVNLE r/m64, r64","cmovnle r/m64, r64","REX.W 0F 4F /r","N.E.","V","","pseudo","rw,r","","" +"CMOVNZ r16, r/m16","CMOVNZ r/m16, r16","cmovnz r/m16, r16","0F 45 /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVNZ r32, r/m32","CMOVNZ r/m32, r32","cmovnz r/m32, r32","0F 45 /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVNZ r64, r/m64","CMOVNZ r/m64, r64","cmovnz r/m64, r64","REX.W 0F 45 /r","N.E.","V","","pseudo","rw,r","","" +"CMOVPE r16, r/m16","CMOVPE r/m16, r16","cmovpe r/m16, r16","0F 4A /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVPE r32, r/m32","CMOVPE r/m32, r32","cmovpe r/m32, r32","0F 4A /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVPE r64, r/m64","CMOVPE r/m64, r64","cmovpe r/m64, r64","REX.W 0F 4A /r","N.E.","V","","pseudo","rw,r","","" +"CMOVPO r16, r/m16","CMOVPO r/m16, r16","cmovpo r/m16, r16","0F 4B /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVPO r32, r/m32","CMOVPO r/m32, r32","cmovpo r/m32, r32","0F 4B /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVPO r64, r/m64","CMOVPO r/m64, r64","cmovpo r/m64, r64","REX.W 0F 4B /r","N.E.","V","","pseudo","rw,r","","" +"CMOVAE r64, r/m64","CMOVQCC r/m64, r64","cmovaeq r/m64, r64","REX.W 0F 43 /r","N.S.","V","","","rw,r","Y","64" +"CMOVB r64, r/m64","CMOVQCS r/m64, r64","cmovbq r/m64, r64","REX.W 0F 42 /r","N.S.","V","","","rw,r","Y","64" +"CMOVE r64, r/m64","CMOVQEQ r/m64, r64","cmoveq r/m64, r64","REX.W 0F 44 /r","N.S.","V","","","rw,r","Y","64" +"CMOVGE r64, r/m64","CMOVQGE r/m64, r64","cmovgeq r/m64, r64","REX.W 0F 4D /r","N.S.","V","","","rw,r","Y","64" +"CMOVG r64, r/m64","CMOVQGT r/m64, r64","cmovgq r/m64, r64","REX.W 0F 4F /r","N.S.","V","","","rw,r","Y","64" +"CMOVA r64, r/m64","CMOVQHI r/m64, r64","cmovaq r/m64, r64","REX.W 0F 47 /r","N.S.","V","","","rw,r","Y","64" +"CMOVLE r64, r/m64","CMOVQLE r/m64, r64","cmovleq r/m64, r64","REX.W 0F 4E /r","N.S.","V","","","rw,r","Y","64" +"CMOVBE r64, r/m64","CMOVQLS r/m64, r64","cmovbeq r/m64, r64","REX.W 0F 46 /r","N.S.","V","","","rw,r","Y","64" +"CMOVL r64, r/m64","CMOVQLT r/m64, r64","cmovlq r/m64, r64","REX.W 0F 4C /r","N.S.","V","","","rw,r","Y","64" +"CMOVS r64, r/m64","CMOVQMI r/m64, r64","cmovsq r/m64, r64","REX.W 0F 48 /r","N.S.","V","","","rw,r","Y","64" +"CMOVNE r64, r/m64","CMOVQNE r/m64, r64","cmovneq r/m64, r64","REX.W 0F 45 /r","N.S.","V","","","rw,r","Y","64" +"CMOVNO r64, r/m64","CMOVQOC r/m64, r64","cmovnoq r/m64, r64","REX.W 0F 41 /r","N.S.","V","","","rw,r","Y","64" +"CMOVO r64, r/m64","CMOVQOS r/m64, r64","cmovoq r/m64, r64","REX.W 0F 40 /r","N.S.","V","","","rw,r","Y","64" +"CMOVNP r64, r/m64","CMOVQPC r/m64, r64","cmovnpq r/m64, r64","REX.W 0F 4B /r","N.S.","V","","","rw,r","Y","64" +"CMOVNS r64, r/m64","CMOVQPL r/m64, r64","cmovnsq r/m64, r64","REX.W 0F 49 /r","N.S.","V","","","rw,r","Y","64" +"CMOVP r64, r/m64","CMOVQPS r/m64, r64","cmovpq r/m64, r64","REX.W 0F 4A /r","N.S.","V","","","rw,r","Y","64" +"CMOVAE r16, r/m16","CMOVWCC r/m16, r16","cmovaew r/m16, r16","0F 43 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVB r16, r/m16","CMOVWCS r/m16, r16","cmovbw r/m16, r16","0F 42 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVE r16, r/m16","CMOVWEQ r/m16, r16","cmovew r/m16, r16","0F 44 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVGE r16, r/m16","CMOVWGE r/m16, r16","cmovgew r/m16, r16","0F 4D /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVG r16, r/m16","CMOVWGT r/m16, r16","cmovgw r/m16, r16","0F 4F /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVA r16, r/m16","CMOVWHI r/m16, r16","cmovaw r/m16, r16","0F 47 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVLE r16, r/m16","CMOVWLE r/m16, r16","cmovlew r/m16, r16","0F 4E /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVBE r16, r/m16","CMOVWLS r/m16, r16","cmovbew r/m16, r16","0F 46 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVL r16, r/m16","CMOVWLT r/m16, r16","cmovlw r/m16, r16","0F 4C /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVS r16, r/m16","CMOVWMI r/m16, r16","cmovsw r/m16, r16","0F 48 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVNE r16, r/m16","CMOVWNE r/m16, r16","cmovnew r/m16, r16","0F 45 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVNO r16, r/m16","CMOVWOC r/m16, r16","cmovnow r/m16, r16","0F 41 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVO r16, r/m16","CMOVWOS r/m16, r16","cmovow r/m16, r16","0F 40 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVNP r16, r/m16","CMOVWPC r/m16, r16","cmovnpw r/m16, r16","0F 4B /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVNS r16, r/m16","CMOVWPL r/m16, r16","cmovnsw r/m16, r16","0F 49 /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVP r16, r/m16","CMOVWPS r/m16, r16","cmovpw r/m16, r16","0F 4A /r","V","V","","P6,operand16","rw,r","Y","16" +"CMOVZ r16, r/m16","CMOVZ r/m16, r16","cmovz r/m16, r16","0F 44 /r","V","V","","P6,operand16,pseudo","rw,r","","" +"CMOVZ r32, r/m32","CMOVZ r/m32, r32","cmovz r/m32, r32","0F 44 /r","V","V","","P6,operand32,pseudo","rw,r","","" +"CMOVZ r64, r/m64","CMOVZ r/m64, r64","cmovz r/m64, r64","REX.W 0F 44 /r","N.E.","V","","pseudo","rw,r","","" +"CMP AL, imm8","CMPB AL, imm8","cmpb imm8, AL","3C ib","V","V","","","r,r","Y","8" +"CMP r/m8, imm8","CMPB r/m8, imm8","cmpb imm8, r/m8","80 /7 ib","V","V","","","r,r","Y","8" +"CMP r/m8, imm8","CMPB r/m8, imm8","cmpb imm8, r/m8","82 /7 ib","V","N.S.","","","r,r","Y","8" +"CMP r/m8, imm8","CMPB r/m8, imm8","cmpb imm8, r/m8","REX 80 /7 ib","N.E.","V","","pseudo64","r,r","Y","8" +"CMP r/m8, r8","CMPB r/m8, r8","cmpb r8, r/m8","38 /r","V","V","","","r,r","Y","8" +"CMP r/m8, r8","CMPB r/m8, r8","cmpb r8, r/m8","REX 38 /r","N.E.","V","","pseudo64","r,r","Y","8" +"CMP r8, r/m8","CMPB r8, r/m8","cmpb r/m8, r8","3A /r","V","V","","","r,r","Y","8" +"CMP r8, r/m8","CMPB r8, r/m8","cmpb r/m8, r8","REX 3A /r","N.E.","V","","pseudo64","r,r","Y","8" +"CMP EAX, imm32","CMPL EAX, imm32","cmpl imm32, EAX","3D id","V","V","","operand32","r,r","Y","32" +"CMP r/m32, imm32","CMPL r/m32, imm32","cmpl imm32, r/m32","81 /7 id","V","V","","operand32","r,r","Y","32" +"CMP r/m32, imm8","CMPL r/m32, imm8","cmpl imm8, r/m32","83 /7 ib","V","V","","operand32","r,r","Y","32" +"CMP r/m32, r32","CMPL r/m32, r32","cmpl r32, r/m32","39 /r","V","V","","operand32","r,r","Y","32" +"CMP r32, r/m32","CMPL r32, r/m32","cmpl r/m32, r32","3B /r","V","V","","operand32","r,r","Y","32" +"CMPPD xmm1, xmm2/m128, imm8u","CMPPD imm8u, xmm1, xmm2/m128","cmppd imm8u, xmm2/m128, xmm1","66 0F C2 /r ib","V","V","SSE2","","rw,r,r","","" +"CMPPS xmm1, xmm2/m128, imm8u","CMPPS imm8u, xmm1, xmm2/m128","cmpps imm8u, xmm2/m128, xmm1","0F C2 /r ib","V","V","SSE","","rw,r,r","","" +"CMP RAX, imm32","CMPQ RAX, imm32","cmpq imm32, RAX","REX.W 3D id","N.S.","V","","","r,r","Y","64" +"CMP r/m64, imm32","CMPQ r/m64, imm32","cmpq imm32, r/m64","REX.W 81 /7 id","N.S.","V","","","r,r","Y","64" +"CMP r/m64, imm8","CMPQ r/m64, imm8","cmpq imm8, r/m64","REX.W 83 /7 ib","N.S.","V","","","r,r","Y","64" +"CMP r/m64, r64","CMPQ r/m64, r64","cmpq r64, r/m64","REX.W 39 /r","N.S.","V","","","r,r","Y","64" +"CMP r64, r/m64","CMPQ r64, r/m64","cmpq r/m64, r64","REX.W 3B /r","N.S.","V","","","r,r","Y","64" +"CMPSB","CMPSB","cmpsb","A6","V","V","","","","","" +"CMPSD xmm1, xmm2/m64, imm8u","CMPSD imm8u, xmm1, xmm2/m64","cmpsd imm8u, xmm2/m64, xmm1","F2 0F C2 /r ib","V","V","SSE2","","rw,r,r","","" +"CMPSD","CMPSL","cmpsl","A7","V","V","","operand32","","","" +"CMPSQ","CMPSQ","cmpsq","REX.W A7","N.S.","V","","","","","" +"CMPSS xmm1, xmm2/m32, imm8u","CMPSS imm8u, xmm1, xmm2/m32","cmpss imm8u, xmm2/m32, xmm1","F3 0F C2 /r ib","V","V","SSE","","rw,r,r","","" +"CMPSW","CMPSW","cmpsw","A7","V","V","","operand16","","","" +"CMP AX, imm16","CMPW AX, imm16","cmpw imm16, AX","3D iw","V","V","","operand16","r,r","Y","16" +"CMP r/m16, imm16","CMPW r/m16, imm16","cmpw imm16, r/m16","81 /7 iw","V","V","","operand16","r,r","Y","16" +"CMP r/m16, imm8","CMPW r/m16, imm8","cmpw imm8, r/m16","83 /7 ib","V","V","","operand16","r,r","Y","16" +"CMP r/m16, r16","CMPW r/m16, r16","cmpw r16, r/m16","39 /r","V","V","","operand16","r,r","Y","16" +"CMP r16, r/m16","CMPW r16, r/m16","cmpw r/m16, r16","3B /r","V","V","","operand16","r,r","Y","16" +"CMPXCHG16B m128","CMPXCHG16B m128","cmpxchg16b m128","REX.W 0F C7 /1","N.S.","V","","modrm_memonly","rw","","" +"CMPXCHG8B m64","CMPXCHG8B m64","cmpxchg8b m64","0F C7 /1","V","V","Pentium","modrm_memonly,operand16,operand32","rw","","" +"CMPXCHG r/m8, r8","CMPXCHGB r8, r/m8","cmpxchgb r8, r/m8","0F B0 /r","V","V","486","","rw,r","Y","8" +"CMPXCHG r/m8, r8","CMPXCHGB r8, r/m8","cmpxchgb r8, r/m8","REX 0F B0 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"CMPXCHG r/m32, r32","CMPXCHGL r32, r/m32","cmpxchgl r32, r/m32","0F B1 /r","V","V","486","operand32","rw,r","Y","32" +"CMPXCHG r/m64, r64","CMPXCHGQ r64, r/m64","cmpxchgq r64, r/m64","REX.W 0F B1 /r","N.S.","V","486","","rw,r","Y","64" +"CMPXCHG r/m16, r16","CMPXCHGW r16, r/m16","cmpxchgw r16, r/m16","0F B1 /r","V","V","486","operand16","rw,r","Y","16" +"COMISD xmm1, xmm2/m64","COMISD xmm2/m64, xmm1","comisd xmm2/m64, xmm1","66 0F 2F /r","V","V","SSE2","","r,r","","" +"COMISS xmm1, xmm2/m32","COMISS xmm2/m32, xmm1","comiss xmm2/m32, xmm1","0F 2F /r","V","V","SSE","","r,r","","" +"CPUID","CPUID","cpuid","0F A2","V","V","486","","","","" +"CQO","CQO","cqto","REX.W 99","N.S.","V","","","","","" +"CRC32 r32, r/m8","CRC32B r/m8, r32","crc32b r/m8, r32","F2 0F 38 F0 /r","V","V","SSE4_2","operand16,operand32","rw,r","Y","8" +"CRC32 r32, r/m8","CRC32B r/m8, r32","crc32b r/m8, r32","F2 REX 0F 38 F0 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"CRC32 r64, r/m8","CRC32B r/m8, r64","crc32b r/m8, r64","F2 REX.W 0F 38 F0 /r","N.S.","V","SSE4_2","","rw,r","Y","8" +"CRC32 r32, r/m32","CRC32L r/m32, r32","crc32l r/m32, r32","F2 0F 38 F1 /r","V","V","SSE4_2","operand32","rw,r","Y","32" +"CRC32 r64, r/m64","CRC32Q r/m64, r64","crc32q r/m64, r64","F2 REX.W 0F 38 F1 /r","N.S.","V","SSE4_2","","rw,r","Y","64" +"CRC32 r32, r/m16","CRC32W r/m16, r32","crc32w r/m16, r32","F2 0F 38 F1 /r","V","V","SSE4_2","operand16","rw,r","Y","16" +"CVTPD2PI mm1, xmm2/m128","CVTPD2PI xmm2/m128, mm1","cvtpd2pi xmm2/m128, mm1","66 0F 2D /r","V","V","SSE2","","w,r","","" +"CVTPD2DQ xmm1, xmm2/m128","CVTPD2PL xmm2/m128, xmm1","cvtpd2dq xmm2/m128, xmm1","F2 0F E6 /r","V","V","SSE2","","w,r","","" +"CVTPD2PS xmm1, xmm2/m128","CVTPD2PS xmm2/m128, xmm1","cvtpd2ps xmm2/m128, xmm1","66 0F 5A /r","V","V","SSE2","","w,r","","" +"CVTPI2PD xmm1, mm2/m64","CVTPI2PD mm2/m64, xmm1","cvtpi2pd mm2/m64, xmm1","66 0F 2A /r","V","V","SSE2","","w,r","","" +"CVTPI2PS xmm1, mm2/m64","CVTPI2PS mm2/m64, xmm1","cvtpi2ps mm2/m64, xmm1","0F 2A /r","V","V","SSE","","w,r","","" +"CVTDQ2PD xmm1, xmm2/m64","CVTPL2PD xmm2/m64, xmm1","cvtdq2pd xmm2/m64, xmm1","F3 0F E6 /r","V","V","SSE2","","w,r","","" +"CVTDQ2PS xmm1, xmm2/m128","CVTPL2PS xmm2/m128, xmm1","cvtdq2ps xmm2/m128, xmm1","0F 5B /r","V","V","SSE2","","w,r","","" +"CVTPS2PD xmm1, xmm2/m64","CVTPS2PD xmm2/m64, xmm1","cvtps2pd xmm2/m64, xmm1","0F 5A /r","V","V","SSE2","","w,r","","" +"CVTPS2PI mm1, xmm2/m64","CVTPS2PI xmm2/m64, mm1","cvtps2pi xmm2/m64, mm1","0F 2D /r","V","V","SSE","","w,r","","" +"CVTPS2DQ xmm1, xmm2/m128","CVTPS2PL xmm2/m128, xmm1","cvtps2dq xmm2/m128, xmm1","66 0F 5B /r","V","V","SSE2","","w,r","","" +"CVTSD2SI r32, xmm2/m64","CVTSD2SL xmm2/m64, r32","cvtsd2si xmm2/m64, r32","F2 0F 2D /r","V","V","SSE2","operand16,operand32","w,r","Y","32" +"CVTSD2SI r64, xmm2/m64","CVTSD2SL xmm2/m64, r64","cvtsd2siq xmm2/m64, r64","F2 REX.W 0F 2D /r","N.S.","V","SSE2","","w,r","Y","64" +"CVTSD2SS xmm1, xmm2/m64","CVTSD2SS xmm2/m64, xmm1","cvtsd2ss xmm2/m64, xmm1","F2 0F 5A /r","V","V","SSE2","","w,r","","" +"CVTSI2SD xmm1, r/m32","CVTSL2SD r/m32, xmm1","cvtsi2sdl r/m32, xmm1","F2 0F 2A /r","V","V","SSE2","operand16,operand32","w,r","Y","32" +"CVTSI2SS xmm1, r/m32","CVTSL2SS r/m32, xmm1","cvtsi2ssl r/m32, xmm1","F3 0F 2A /r","V","V","SSE","operand16,operand32","w,r","Y","32" +"CVTSI2SD xmm1, r/m64","CVTSQ2SD r/m64, xmm1","cvtsi2sdq r/m64, xmm1","F2 REX.W 0F 2A /r","N.S.","V","SSE2","","w,r","Y","64" +"CVTSI2SS xmm1, r/m64","CVTSQ2SS r/m64, xmm1","cvtsi2ssq r/m64, xmm1","F3 REX.W 0F 2A /r","N.S.","V","SSE","","w,r","Y","64" +"CVTSS2SD xmm1, xmm2/m32","CVTSS2SD xmm2/m32, xmm1","cvtss2sd xmm2/m32, xmm1","F3 0F 5A /r","V","V","SSE2","","w,r","","" +"CVTSS2SI r32, xmm2/m32","CVTSS2SL xmm2/m32, r32","cvtss2si xmm2/m32, r32","F3 0F 2D /r","V","V","SSE","operand16,operand32","w,r","Y","32" +"CVTSS2SI r64, xmm2/m32","CVTSS2SL xmm2/m32, r64","cvtss2siq xmm2/m32, r64","F3 REX.W 0F 2D /r","N.S.","V","SSE","","w,r","Y","64" +"CVTTPD2PI mm1, xmm2/m128","CVTTPD2PI xmm2/m128, mm1","cvttpd2pi xmm2/m128, mm1","66 0F 2C /r","V","V","SSE2","","w,r","","" +"CVTTPD2DQ xmm1, xmm2/m128","CVTTPD2PL xmm2/m128, xmm1","cvttpd2dq xmm2/m128, xmm1","66 0F E6 /r","V","V","SSE2","","w,r","","" +"CVTTPS2PI mm1, xmm2/m64","CVTTPS2PI xmm2/m64, mm1","cvttps2pi xmm2/m64, mm1","0F 2C /r","V","V","SSE","","w,r","","" +"CVTTPS2DQ xmm1, xmm2/m128","CVTTPS2PL xmm2/m128, xmm1","cvttps2dq xmm2/m128, xmm1","F3 0F 5B /r","V","V","SSE2","","w,r","","" +"CVTTSD2SI r32, xmm2/m64","CVTTSD2SL xmm2/m64, r32","cvttsd2si xmm2/m64, r32","F2 0F 2C /r","V","V","SSE2","operand16,operand32","w,r","Y","32" +"CVTTSD2SI r64, xmm2/m64","CVTTSD2SL xmm2/m64, r64","cvttsd2siq xmm2/m64, r64","F2 REX.W 0F 2C /r","N.S.","V","SSE2","","w,r","Y","64" +"CVTTSS2SI r32, xmm2/m32","CVTTSS2SL xmm2/m32, r32","cvttss2si xmm2/m32, r32","F3 0F 2C /r","V","V","SSE","operand16,operand32","w,r","Y","32" +"CVTTSS2SI r64, xmm2/m32","CVTTSS2SL xmm2/m32, r64","cvttss2siq xmm2/m32, r64","F3 REX.W 0F 2C /r","N.S.","V","SSE","","w,r","Y","64" +"CWD","CWD","cwtd","99","V","V","","operand16","","","" +"CWDE","CWDE","cwtl","98","V","V","","operand32","","","" +"DAA","DAA","daa","27","V","N.S.","","","","","" +"DAS","DAS","das","2F","V","N.S.","","","","","" +"DEC r/m8","DECB r/m8","decb r/m8","FE /1","V","V","","","rw","Y","8" +"DEC r/m8","DECB r/m8","decb r/m8","REX FE /1","N.E.","V","","pseudo64","rw","Y","8" +"DEC r/m32","DECL r/m32","decl r/m32","FF /1","V","V","","operand32","rw","Y","32" +"DEC r32op","DECL r32op","decl r32op","48+rd","V","N.S.","","operand32","rw","Y","32" +"DEC r/m64","DECQ r/m64","decq r/m64","REX.W FF /1","N.S.","V","","","rw","Y","64" +"DEC r/m16","DECW r/m16","decw r/m16","FF /1","V","V","","operand16","rw","Y","16" +"DEC r16op","DECW r16op","decw r16op","48+rw","V","N.S.","","operand16","rw","Y","16" +"DIV r/m8","DIVB r/m8","divb r/m8","F6 /6","V","V","","","r","Y","8" +"DIV r/m8","DIVB r/m8","divb r/m8","REX F6 /6","N.E.","V","","pseudo64","w","Y","8" +"DIV r/m32","DIVL r/m32","divl r/m32","F7 /6","V","V","","operand32","r","Y","32" +"DIVPD xmm1, xmm2/m128","DIVPD xmm2/m128, xmm1","divpd xmm2/m128, xmm1","66 0F 5E /r","V","V","SSE2","","rw,r","","" +"DIVPS xmm1, xmm2/m128","DIVPS xmm2/m128, xmm1","divps xmm2/m128, xmm1","0F 5E /r","V","V","SSE","","rw,r","","" +"DIV r/m64","DIVQ r/m64","divq r/m64","REX.W F7 /6","N.S.","V","","","r","Y","64" +"DIVSD xmm1, xmm2/m64","DIVSD xmm2/m64, xmm1","divsd xmm2/m64, xmm1","F2 0F 5E /r","V","V","SSE2","","rw,r","","" +"DIVSS xmm1, xmm2/m32","DIVSS xmm2/m32, xmm1","divss xmm2/m32, xmm1","F3 0F 5E /r","V","V","SSE","","rw,r","","" +"DIV r/m16","DIVW r/m16","divw r/m16","F7 /6","V","V","","operand16","r","Y","16" +"DPPD xmm1, xmm2/m128, imm8u","DPPD imm8u, xmm2/m128, xmm1","dppd imm8u, xmm2/m128, xmm1","66 0F 3A 41 /r ib","V","V","SSE4_1","","rw,r,r","","" +"DPPS xmm1, xmm2/m128, imm8u","DPPS imm8u, xmm2/m128, xmm1","dpps imm8u, xmm2/m128, xmm1","66 0F 3A 40 /r ib","V","V","SSE4_1","","rw,r,r","","" +"EMMS","EMMS","emms","0F 77","V","V","MMX","","","","" +"ENCLS","ENCLS","encls","0F 01 CF","V","V","","","","","" +"ENCLU","ENCLU","enclu","0F 01 D7","V","V","","","","","" +"ENDBR32","ENDBR32","endbr32","F3 0F 1E FB","V","V","CET","","","","" +"ENDBR64","ENDBR64","endbr64","F3 0F 1E FA","V","V","CET","","","Y","" +"ENTER imm16, 0","ENTER 0, imm16","enter imm16, 0","C8 iw 00","V","V","","pseudo","r,r","","" +"ENTER imm16, 1","ENTER 1, imm16","enter imm16, 1","C8 iw 01","V","V","","pseudo","r,r","","" +"ENTER imm16, imm8b","ENTERW/ENTERL/ENTERQ imm8b, imm16","enterw/enterl/enterq imm16, imm8b","C8 iw ib","V","V","","","r,r","","" +"EXTRACTPS r/m32, xmm1, imm8u:2","EXTRACTPS imm8u:2, xmm1, r/m32","extractps imm8u:2, xmm1, r/m32","66 0F 3A 17 /r ib","V","V","SSE4_1","","w,r,r","","" +"EXTRQ xmm1, imm8u, imm8u","EXTRQ imm8u, imm8u, xmm1","extrq imm8u, imm8u, xmm1","66 0F 78 /0 ib ib","V","V","SSE4a","amd,modrm_regonly","w,r,r","","" +"EXTRQ xmm1, xmm2","EXTRQ xmm2, xmm1","extrq xmm2, xmm1","66 0F 79 /r","V","V","SSE4a","amd,modrm_regonly","w,r","","" +"F2XM1","F2XM1","f2xm1","D9 F0","V","V","","","","","" +"FABS","FABS","fabs","D9 E1","V","V","","","","","" +"FADD ST(i), ST(0)","FADDD ST(0), ST(i)","fadd ST(0), ST(i)","DC C0+i","V","V","","","rw,r","Y","" +"FADD ST(0), ST(i)","FADDD ST(i), ST(0)","fadd ST(i), ST(0)","D8 C0+i","V","V","","","rw,r","Y","" +"FADD ST(0), m32fp","FADDD m32fp, ST(0)","fadds m32fp, ST(0)","D8 /0","V","V","","","rw,r","Y","32" +"FADD ST(0), m64fp","FADDD m64fp, ST(0)","faddl m64fp, ST(0)","DC /0","V","V","","","rw,r","Y","64" +"FADDP","FADDDP","faddp","DE C1","V","V","","pseudo","","","" +"FADDP ST(i), ST(0)","FADDDP ST(0), ST(i)","faddp ST(0), ST(i)","DE C0+i","V","V","","","rw,r","","" +"FBLD ST(0), m80dec","FBLD m80dec, ST(0)","fbld m80dec, ST(0)","DF /4","V","V","","","w,r","","" +"FBSTP m80dec, ST(0)","FBSTP ST(0), m80dec","fbstp ST(0), m80dec","DF /6","V","V","","","w,r","","" +"FCHS","FCHS","fchs","D9 E0","V","V","","","","","" +"FCLEX","FCLEX","fclex","9B DB E2","V","V","","pseudo","","","" +"FCMOVB ST(0), ST(i)","FCMOVB ST(i), ST(0)","fcmovb ST(i), ST(0)","DA C0+i","V","V","","P6","rw,r","","" +"FCMOVBE ST(0), ST(i)","FCMOVBE ST(i), ST(0)","fcmovbe ST(i), ST(0)","DA D0+i","V","V","","P6","rw,r","","" +"FCMOVE ST(0), ST(i)","FCMOVE ST(i), ST(0)","fcmove ST(i), ST(0)","DA C8+i","V","V","","P6","rw,r","","" +"FCMOVNB ST(0), ST(i)","FCMOVNB ST(i), ST(0)","fcmovnb ST(i), ST(0)","DB C0+i","V","V","","P6","rw,r","","" +"FCMOVNBE ST(0), ST(i)","FCMOVNBE ST(i), ST(0)","fcmovnbe ST(i), ST(0)","DB D0+i","V","V","","P6","rw,r","","" +"FCMOVNE ST(0), ST(i)","FCMOVNE ST(i), ST(0)","fcmovne ST(i), ST(0)","DB C8+i","V","V","","P6","rw,r","","" +"FCMOVNU ST(0), ST(i)","FCMOVNU ST(i), ST(0)","fcmovnu ST(i), ST(0)","DB D8+i","V","V","","P6","rw,r","","" +"FCMOVU ST(0), ST(i)","FCMOVU ST(i), ST(0)","fcmovu ST(i), ST(0)","DA D8+i","V","V","","P6","rw,r","","" +"FCOM","FCOMD","fcom","D8 D1","V","V","","pseudo","","Y","" +"FCOM ST(0), ST(i)","FCOMD ST(i), ST(0)","fcom ST(i), ST(0)","D8 D0+i","V","V","","","r,r","Y","" +"FCOM ST(0), ST(i)","FCOMD ST(i), ST(0)","fcom ST(i), ST(0)","DC D0+i","V","V","","","r,r","Y","" +"FCOM ST(0), m32fp","FCOMD m32fp, ST(0)","fcoms m32fp, ST(0)","D8 /2","V","V","","","r,r","Y","32" +"FCOM ST(0), m64fp","FCOMD m64fp, ST(0)","fcoml m64fp, ST(0)","DC /2","V","V","","","r,r","Y","64" +"FCOMP ST(0), m32fp","FCOMFP m32fp, ST(0)","fcomps m32fp, ST(0)","D8 /3","V","V","","","r,r","Y","32" +"FCOMI ST(0), ST(i)","FCOMI ST(i), ST(0)","fcomi ST(i), ST(0)","DB F0+i","V","V","PPRO","P6","r,r","","" +"FCOMIP ST(0), ST(i)","FCOMIP ST(i), ST(0)","fcomip ST(i), ST(0)","DF F0+i","V","V","PPRO","P6","r,r","","" +"FCOMP","FCOMP","fcomp","D8 D9","V","V","","pseudo","","Y","" +"FCOMP ST(0), ST(i)","FCOMP ST(i), ST(0)","fcomp ST(i), ST(0)","D8 D8+i","V","V","","","r,r","Y","" +"FCOMP ST(0), ST(i)","FCOMP ST(i), ST(0)","fcomp ST(i), ST(0)","DC D8+i","V","V","","","r,r","Y","" +"FCOMP ST(0), ST(i)","FCOMP ST(i), ST(0)","fcomp ST(i), ST(0)","DE D0+i","V","V","","","r,r","Y","" +"FCOMP ST(0), m64fp","FCOMPL m64fp, ST(0)","fcompl m64fp, ST(0)","DC /3","V","V","","","r,r","Y","64" +"FCOMPP","FCOMPP","fcompp","DE D9","V","V","","","","","" +"FCOS","FCOS","fcos","D9 FF","V","V","","","","","" +"FDECSTP","FDECSTP","fdecstp","D9 F6","V","V","","","","","" +"FDISI8087_NOP","FDISI8087_NOP","fdisi8087_nop","DB E1","V","V","","","","","" +"FDIVR ST(i), ST(0)","FDIVD ST(0), ST(i)","fdiv ST(0), ST(i)","DC F0+i","V","V","","","rw,r","Y","" +"FDIV ST(i), ST(0)","FDIVD ST(0), ST(i)","fdivr ST(0), ST(i)","DC F8+i","V","V","","","rw,r","Y","" +"FDIV ST(0), ST(i)","FDIVD ST(i), ST(0)","fdiv ST(i), ST(0)","D8 F0+i","V","V","","","rw,r","Y","" +"FDIV ST(0), m32fp","FDIVD m32fp, ST(0)","fdivs m32fp, ST(0)","D8 /6","V","V","","","rw,r","Y","32" +"FDIV ST(0), m64fp","FDIVD m64fp, ST(0)","fdivl m64fp, ST(0)","DC /6","V","V","","","rw,r","Y","64" +"FDIVR ST(0), m32fp","FDIVFR m32fp, ST(0)","fdivrs m32fp, ST(0)","D8 /7","V","V","","","rw,r","Y","32" +"FDIVP","FDIVP","fdivp","DE F9","V","V","","pseudo","","","" +"FDIVRP ST(i), ST(0)","FDIVP ST(0), ST(i)","fdivp ST(0), ST(i)","DE F0+i","V","V","","","rw,r","","" +"FDIVR ST(0), ST(i)","FDIVR ST(i), ST(0)","fdivr ST(i), ST(0)","D8 F8+i","V","V","","","rw,r","Y","" +"FDIVR ST(0), m64fp","FDIVRL m64fp, ST(0)","fdivrl m64fp, ST(0)","DC /7","V","V","","","rw,r","Y","64" +"FDIVRP","FDIVRP","fdivrp","DE F1","V","V","","pseudo","","","" +"FDIVP ST(i), ST(0)","FDIVRP ST(0), ST(i)","fdivrp ST(0), ST(i)","DE F8+i","V","V","","","rw,r","","" +"FEMMS","FEMMS","femms","0F 0E","V","V","3DNOW","amd","","","" +"FENI8087_NOP","FENI8087_NOP","feni8087_nop","DB E0","V","V","","","","","" +"FFREE ST(i)","FFREE ST(i)","ffree ST(i)","DD C0+i","V","V","","","r","","" +"FFREEP ST(i)","FFREEP ST(i)","ffreep ST(i)","DF C0+i","V","V","","","r","","" +"FIADD ST(0), m16int","FIADD m16int, ST(0)","fiadd m16int, ST(0)","DE /0","V","V","","","rw,r","Y","" +"FIADD ST(0), m32int","FIADDL m32int, ST(0)","fiaddl m32int, ST(0)","DA /0","V","V","","","rw,r","Y","32" +"FICOM ST(0), m16int","FICOM m16int, ST(0)","ficom m16int, ST(0)","DE /2","V","V","","","r,r","Y","" +"FICOM ST(0), m32int","FICOML m32int, ST(0)","ficoml m32int, ST(0)","DA /2","V","V","","","r,r","Y","32" +"FICOMP ST(0), m16int","FICOMP m16int, ST(0)","ficomp m16int, ST(0)","DE /3","V","V","","","r,r","Y","" +"FICOMP ST(0), m32int","FICOMPL m32int, ST(0)","ficompl m32int, ST(0)","DA /3","V","V","","","r,r","Y","32" +"FIDIV ST(0), m16int","FIDIV m16int, ST(0)","fidiv m16int, ST(0)","DE /6","V","V","","","rw,r","Y","" +"FIDIV ST(0), m32int","FIDIVL m32int, ST(0)","fidivl m32int, ST(0)","DA /6","V","V","","","rw,r","Y","32" +"FIDIVR ST(0), m16int","FIDIVR m16int, ST(0)","fidivr m16int, ST(0)","DE /7","V","V","","","rw,r","Y","" +"FIDIVR ST(0), m32int","FIDIVRL m32int, ST(0)","fidivrl m32int, ST(0)","DA /7","V","V","","","rw,r","Y","32" +"FILD ST(0), m16int","FILD m16int, ST(0)","fild m16int, ST(0)","DF /0","V","V","","","w,r","Y","" +"FILD ST(0), m32int","FILDL m32int, ST(0)","fildl m32int, ST(0)","DB /0","V","V","","","w,r","Y","32" +"FILD ST(0), m64int","FILDLL m64int, ST(0)","fildll m64int, ST(0)","DF /5","V","V","","","w,r","Y","64" +"FIMUL ST(0), m16int","FIMUL m16int, ST(0)","fimul m16int, ST(0)","DE /1","V","V","","","rw,r","Y","" +"FIMUL ST(0), m32int","FIMULL m32int, ST(0)","fimull m32int, ST(0)","DA /1","V","V","","","rw,r","Y","32" +"FINCSTP","FINCSTP","fincstp","D9 F7","V","V","","","","","" +"FINIT","FINIT","finit","9B DB E3","V","V","","pseudo","","","" +"FIST m16int, ST(0)","FIST ST(0), m16int","fist ST(0), m16int","DF /2","V","V","","","w,r","Y","" +"FIST m32int, ST(0)","FISTL ST(0), m32int","fistl ST(0), m32int","DB /2","V","V","","","w,r","Y","32" +"FISTP m16int, ST(0)","FISTP ST(0), m16int","fistp ST(0), m16int","DF /3","V","V","","","w,r","Y","" +"FISTP m32int, ST(0)","FISTPL ST(0), m32int","fistpl ST(0), m32int","DB /3","V","V","","","w,r","Y","32" +"FISTP m64int, ST(0)","FISTPLL ST(0), m64int","fistpll ST(0), m64int","DF /7","V","V","","","w,r","Y","64" +"FISTTP m16int, ST(0)","FISTTP ST(0), m16int","fisttp ST(0), m16int","DF /1","V","V","SSE3","modrm_memonly","w,r","Y","" +"FISTTP m32int, ST(0)","FISTTPL ST(0), m32int","fisttpl ST(0), m32int","DB /1","V","V","SSE3","modrm_memonly","w,r","Y","32" +"FISTTP m64int, ST(0)","FISTTPLL ST(0), m64int","fisttpll ST(0), m64int","DD /1","V","V","SSE3","modrm_memonly","w,r","Y","64" +"FISUB ST(0), m16int","FISUB m16int, ST(0)","fisub m16int, ST(0)","DE /4","V","V","","","rw,r","Y","" +"FISUB ST(0), m32int","FISUBL m32int, ST(0)","fisubl m32int, ST(0)","DA /4","V","V","","","rw,r","Y","32" +"FISUBR ST(0), m16int","FISUBR m16int, ST(0)","fisubr m16int, ST(0)","DE /5","V","V","","","rw,r","Y","" +"FISUBR ST(0), m32int","FISUBRL m32int, ST(0)","fisubrl m32int, ST(0)","DA /5","V","V","","","rw,r","Y","32" +"FLD ST(0), ST(i)","FLD ST(i), ST(0)","fld ST(i), ST(0)","D9 C0+i","V","V","","","w,r","Y","" +"FLD1","FLD1","fld1","D9 E8","V","V","","","","","" +"FLDCW m2byte","FLDCW m2byte","fldcw m2byte","D9 /5","V","V","","","r","","" +"FLDENV m28byte","FLDENV m28byte","fldenv m28byte","D9 /4","V","V","","operand32,operand64","r","","" +"FLDENV m14byte","FLDENVS m14byte","fldenv m14byte","D9 /4","V","V","","operand16","r","","" +"FLD ST(0), m64fp","FLDL m64fp, ST(0)","fldl m64fp, ST(0)","DD /0","V","V","","","w,r","Y","64" +"FLDL2E","FLDL2E","fldl2e","D9 EA","V","V","","","","","" +"FLDL2T","FLDL2T","fldl2t","D9 E9","V","V","","","","","" +"FLDLG2","FLDLG2","fldlg2","D9 EC","V","V","","","","","" +"FLDLN2","FLDLN2","fldln2","D9 ED","V","V","","","","","" +"FLDPI","FLDPI","fldpi","D9 EB","V","V","","","","","" +"FLD ST(0), m32fp","FLDS m32fp, ST(0)","flds m32fp, ST(0)","D9 /0","V","V","","","w,r","Y","32" +"FLD ST(0), m80fp","FLDT m80fp, ST(0)","fldt m80fp, ST(0)","DB /5","V","V","","","w,r","Y","80" +"FLDZ","FLDZ","fldz","D9 EE","V","V","","","","","" +"FMUL ST(i), ST(0)","FMUL ST(0), ST(i)","fmul ST(0), ST(i)","DC C8+i","V","V","","","rw,r","Y","" +"FMUL ST(0), ST(i)","FMUL ST(i), ST(0)","fmul ST(i), ST(0)","D8 C8+i","V","V","","","rw,r","Y","" +"FMUL ST(0), m64fp","FMULL m64fp, ST(0)","fmull m64fp, ST(0)","DC /1","V","V","","","rw,r","Y","64" +"FMULP","FMULP","fmulp","DE C9","V","V","","pseudo","","","" +"FMULP ST(i), ST(0)","FMULP ST(0), ST(i)","fmulp ST(0), ST(i)","DE C8+i","V","V","","","rw,r","","" +"FMUL ST(0), m32fp","FMULS m32fp, ST(0)","fmuls m32fp, ST(0)","D8 /1","V","V","","","rw,r","Y","32" +"FNCLEX","FNCLEX","fnclex","DB E2","V","V","","","","","" +"FNINIT","FNINIT","fninit","DB E3","V","V","","","","","" +"FNOP","FNOP","fnop","D9 D0","V","V","","","","","" +"FNSAVE m108byte","FNSAVE m108byte","fnsave m108byte","DD /6","V","V","","operand32,operand64","w","","" +"FNSAVE m94byte","FNSAVES m94byte","fnsave m94byte","DD /6","V","V","","operand16","w","","" +"FNSTCW m2byte","FNSTCW m2byte","fnstcw m2byte","D9 /7","V","V","","","w","","" +"FNSTENV m28byte","FNSTENV m28byte","fnstenv m28byte","D9 /6","V","V","","operand32,operand64","w","","" +"FNSTENV m14byte","FNSTENVS m14byte","fnstenv m14byte","D9 /6","V","V","","operand16","w","","" +"FNSTSW AX","FNSTSW AX","fnstsw AX","DF E0","V","V","","","w","","" +"FNSTSW m2byte","FNSTSW m2byte","fnstsw m2byte","DD /7","V","V","","","w","","" +"FPATAN","FPATAN","fpatan","D9 F3","V","V","","","","","" +"FPREM","FPREM","fprem","D9 F8","V","V","","","","","" +"FPREM1","FPREM1","fprem1","D9 F5","V","V","","","","","" +"FPTAN","FPTAN","fptan","D9 F2","V","V","","","","","" +"FRNDINT","FRNDINT","frndint","D9 FC","V","V","","","","","" +"FRSTOR m108byte","FRSTOR m108byte","frstor m108byte","DD /4","V","V","","operand32,operand64","r","","" +"FRSTOR m94byte","FRSTORS m94byte","frstor m94byte","DD /4","V","V","","operand16","r","","" +"FSAVE m94/108byte","FSAVE m94/108byte","fsave m94/108byte","9B DD /6","V","V","","pseudo","w","","" +"FSCALE","FSCALE","fscale","D9 FD","V","V","","","","","" +"FSETPM287_NOP","FSETPM287_NOP","fsetpm287_nop","DB E4","V","V","","","","","" +"FSIN","FSIN","fsin","D9 FE","V","V","","","","","" +"FSINCOS","FSINCOS","fsincos","D9 FB","V","V","","","","","" +"FSQRT","FSQRT","fsqrt","D9 FA","V","V","","","","","" +"FST ST(i), ST(0)","FST ST(0), ST(i)","fst ST(0), ST(i)","DD D0+i","V","V","","","w,r","Y","" +"FSTCW m2byte","FSTCW m2byte","fstcw m2byte","9B D9 /7","V","V","","pseudo","w","","" +"FSTENV m14/28byte","FSTENV m14/28byte","fstenv m14/28byte","9B D9 /6","V","V","","pseudo","w","","" +"FST m64fp, ST(0)","FSTL ST(0), m64fp","fstl ST(0), m64fp","DD /2","V","V","","","w,r","Y","64" +"FSTP ST(i), ST(0)","FSTP ST(0), ST(i)","fstp ST(0), ST(i)","DD D8+i","V","V","","","w,r","Y","" +"FSTP ST(i), ST(0)","FSTP ST(0), ST(i)","fstp ST(0), ST(i)","DF D0+i","V","V","","","w,r","Y","" +"FSTP ST(i), ST(0)","FSTP ST(0), ST(i)","fstp ST(0), ST(i)","DF D8+i","V","V","","","w,r","Y","" +"FSTP m64fp, ST(0)","FSTPL ST(0), m64fp","fstpl ST(0), m64fp","DD /3","V","V","","","w,r","Y","64" +"FSTPNCE ST(i), ST(0)","FSTPNCE ST(0), ST(i)","fstpnce ST(0), ST(i)","D9 D8+i","V","V","","","w,r","","" +"FSTP m32fp, ST(0)","FSTPS ST(0), m32fp","fstps ST(0), m32fp","D9 /3","V","V","","","w,r","Y","32" +"FSTP m80fp, ST(0)","FSTPT ST(0), m80fp","fstpt ST(0), m80fp","DB /7","V","V","","","w,r","Y","80" +"FST m32fp, ST(0)","FSTS ST(0), m32fp","fsts ST(0), m32fp","D9 /2","V","V","","","w,r","Y","32" +"FSTSW AX","FSTSW AX","fstsw AX","9B DF E0","V","V","","pseudo","w","","" +"FSTSW m2byte","FSTSW m2byte","fstsw m2byte","9B DD /7","V","V","","pseudo","w","","" +"FSUBR ST(i), ST(0)","FSUB ST(0), ST(i)","fsub ST(0), ST(i)","DC E0+i","V","V","","","rw,r","Y","" +"FSUB ST(0), ST(i)","FSUB ST(i), ST(0)","fsub ST(i), ST(0)","D8 E0+i","V","V","","","rw,r","Y","" +"FSUB ST(0), m64fp","FSUBL m64fp, ST(0)","fsubl m64fp, ST(0)","DC /4","V","V","","","rw,r","Y","64" +"FSUBP","FSUBP","fsubp","DE E9","V","V","","pseudo","","","" +"FSUBRP ST(i), ST(0)","FSUBP ST(0), ST(i)","fsubp ST(0), ST(i)","DE E0+i","V","V","","","rw,r","","" +"FSUB ST(i), ST(0)","FSUBR ST(0), ST(i)","fsubr ST(0), ST(i)","DC E8+i","V","V","","","rw,r","Y","" +"FSUBR ST(0), ST(i)","FSUBR ST(i), ST(0)","fsubr ST(i), ST(0)","D8 E8+i","V","V","","","rw,r","Y","" +"FSUBR ST(0), m64fp","FSUBRL m64fp, ST(0)","fsubrl m64fp, ST(0)","DC /5","V","V","","","rw,r","Y","64" +"FSUBRP","FSUBRP","fsubrp","DE E1","V","V","","pseudo","","","" +"FSUBP ST(i), ST(0)","FSUBRP ST(0), ST(i)","fsubrp ST(0), ST(i)","DE E8+i","V","V","","","rw,r","","" +"FSUBR ST(0), m32fp","FSUBRS m32fp, ST(0)","fsubrs m32fp, ST(0)","D8 /5","V","V","","","rw,r","Y","32" +"FSUB ST(0), m32fp","FSUBS m32fp, ST(0)","fsubs m32fp, ST(0)","D8 /4","V","V","","","rw,r","Y","32" +"FTST","FTST","ftst","D9 E4","V","V","","","","","" +"FUCOM","FUCOM","fucom","DD E1","V","V","","pseudo","","","" +"FUCOM ST(0), ST(i)","FUCOM ST(i), ST(0)","fucom ST(i), ST(0)","DD E0+i","V","V","","","r,r","","" +"FUCOMI ST(0), ST(i)","FUCOMI ST(i), ST(0)","fucomi ST(i), ST(0)","DB E8+i","V","V","PPRO","P6","r,r","","" +"FUCOMIP ST(0), ST(i)","FUCOMIP ST(i), ST(0)","fucomip ST(i), ST(0)","DF E8+i","V","V","PPRO","P6","r,r","","" +"FUCOMP","FUCOMP","fucomp","DD E9","V","V","","pseudo","","","" +"FUCOMP ST(0), ST(i)","FUCOMP ST(i), ST(0)","fucomp ST(i), ST(0)","DD E8+i","V","V","","","r,r","","" +"FUCOMPP","FUCOMPP","fucompp","DA E9","V","V","","","","","" +"FWAIT","FWAIT","fwait","9B","V","V","","","","","" +"FXAM","FXAM","fxam","D9 E5","V","V","","","","","" +"FXCH","FXCH","fxch","D9 C9","V","V","","pseudo","","","" +"FXCH ST(0), ST(i)","FXCH ST(i), ST(0)","fxch ST(i), ST(0)","D9 C8+i","V","V","","","rw,rw","","" +"FXCH_ALIAS1 ST(0), ST(i)","FXCH_ALIAS1 ST(i), ST(0)","fxch_alias1 ST(i), ST(0)","DD C8+i","V","V","","","rw,rw","","" +"FXCH_ALIAS2 ST(0), ST(i)","FXCH_ALIAS2 ST(i), ST(0)","fxch_alias2 ST(i), ST(0)","DF C8+i","V","V","","","rw,rw","","" +"FXRSTOR m512byte","FXRSTOR m512byte","fxrstor m512byte","0F AE /1","V","V","","modrm_memonly,operand16,operand32","r","","" +"FXRSTOR64 m512byte","FXRSTOR64 m512byte","fxrstor64 m512byte","REX.W 0F AE /1","N.S.","V","","modrm_memonly","r","","" +"FXSAVE m512byte","FXSAVE m512byte","fxsave m512byte","0F AE /0","V","V","","modrm_memonly,operand16,operand32","w","","" +"FXSAVE64 m512byte","FXSAVE64 m512byte","fxsave64 m512byte","REX.W 0F AE /0","N.S.","V","","modrm_memonly","w","","" +"FXTRACT","FXTRACT","fxtract","D9 F4","V","V","","","","","" +"FYL2X","FYL2X","fyl2x","D9 F1","V","V","","","","","" +"FYL2XP1","FYL2XP1","fyl2xp1","D9 F9","V","V","","","","","" +"GETSEC","GETSEC","getsec","0F 37","V","V","SMX","","","","" +"GF2P8AFFINEINVQB xmm1, xmm2/m128, imm8u","GF2P8AFFINEINVQB imm8u, xmm2/m128, xmm1","gf2p8affineinvqb imm8u, xmm2/m128, xmm1","66 0F 3A CF /r ib","V","V","GFNI","","rw,r,r","","" +"GF2P8AFFINEQB xmm1, xmm2/m128, imm8u","GF2P8AFFINEQB imm8u, xmm2/m128, xmm1","gf2p8affineqb imm8u, xmm2/m128, xmm1","66 0F 3A CE /r ib","V","V","GFNI","","rw,r,r","","" +"GF2P8MULB xmm1, xmm2/m128","GF2P8MULB xmm2/m128, xmm1","gf2p8mulb xmm2/m128, xmm1","66 0F 38 CF /r","V","V","GFNI","","rw,r","","" +"HADDPD xmm1, xmm2/m128","HADDPD xmm2/m128, xmm1","haddpd xmm2/m128, xmm1","66 0F 7C /r","V","V","SSE3","","rw,r","","" +"HADDPS xmm1, xmm2/m128","HADDPS xmm2/m128, xmm1","haddps xmm2/m128, xmm1","F2 0F 7C /r","V","V","SSE3","","rw,r","","" +"HLT","HLT","hlt","F4","V","V","","","","","" +"HSUBPD xmm1, xmm2/m128","HSUBPD xmm2/m128, xmm1","hsubpd xmm2/m128, xmm1","66 0F 7D /r","V","V","SSE3","","rw,r","","" +"HSUBPS xmm1, xmm2/m128","HSUBPS xmm2/m128, xmm1","hsubps xmm2/m128, xmm1","F2 0F 7D /r","V","V","SSE3","","rw,r","","" +"ICEBP","ICEBP","icebp","F1","V","V","","","","","" +"IDIV r/m8","IDIVB r/m8","idivb r/m8","F6 /7","V","V","","","r","Y","8" +"IDIV r/m8","IDIVB r/m8","idivb r/m8","REX F6 /7","N.E.","V","","pseudo64","r","Y","8" +"IDIV r/m32","IDIVL r/m32","idivl r/m32","F7 /7","V","V","","operand32","r","Y","32" +"IDIV r/m64","IDIVQ r/m64","idivq r/m64","REX.W F7 /7","N.S.","V","","","r","Y","64" +"IDIV r/m16","IDIVW r/m16","idivw r/m16","F7 /7","V","V","","operand16","r","Y","16" +"IMUL r32, r/m32, imm32","IMUL3 imm32, r/m32, r32","imull imm32, r/m32, r32","69 /r id","V","V","","operand32","w,r,r","Y","32" +"IMUL r64, r/m64, imm32","IMUL3 imm32, r/m64, r64","imulq imm32, r/m64, r64","REX.W 69 /r id","N.S.","V","","","w,r,r","Y","64" +"IMUL r16, r/m16, imm8","IMUL3 imm8, r/m16, r16","imulw imm8, r/m16, r16","6B /r ib","V","V","","operand16","w,r,r","Y","16" +"IMUL r32, r/m32, imm8","IMUL3 imm8, r/m32, r32","imull imm8, r/m32, r32","6B /r ib","V","V","","operand32","w,r,r","Y","32" +"IMUL r64, r/m64, imm8","IMUL3 imm8, r/m64, r64","imulq imm8, r/m64, r64","REX.W 6B /r ib","N.S.","V","","","w,r,r","Y","64" +"IMUL r/m8","IMULB r/m8","imulb r/m8","F6 /5","V","V","","","r","Y","8" +"IMUL r/m32","IMULL r/m32","imull r/m32","F7 /5","V","V","","operand32","r","Y","32" +"IMUL r32, r/m32","IMULL r/m32, r32","imull r/m32, r32","0F AF /r","V","V","","operand32","rw,r","Y","32" +"IMUL r/m64","IMULQ r/m64","imulq r/m64","REX.W F7 /5","N.S.","V","","","r","Y","64" +"IMUL r64, r/m64","IMULQ r/m64, r64","imulq r/m64, r64","REX.W 0F AF /r","N.S.","V","","","rw,r","Y","64" +"IMUL r16, r/m16, imm16","IMULW imm16, r/m16, r16","imulw imm16, r/m16, r16","69 /r iw","V","V","","operand16","w,r,r","Y","16" +"IMUL r/m16","IMULW r/m16","imulw r/m16","F7 /5","V","V","","operand16","r","Y","16" +"IMUL r16, r/m16","IMULW r/m16, r16","imulw r/m16, r16","0F AF /r","V","V","","operand16","rw,r","Y","16" +"IN AL, DX","INB DX, AL","inb DX, AL","EC","V","V","","","w,r","Y","8" +"IN AL, imm8u","INB imm8u, AL","inb imm8u, AL","E4 ib","V","V","","","w,r","Y","8" +"INC r/m8","INCB r/m8","incb r/m8","FE /0","V","V","","","rw","Y","8" +"INC r/m8","INCB r/m8","incb r/m8","REX FE /0","N.E.","V","","pseudo64","rw","Y","8" +"INC r/m32","INCL r/m32","incl r/m32","FF /0","V","V","","operand32","rw","Y","32" +"INC r32op","INCL r32op","incl r32op","40+rd","V","N.S.","","operand32","rw","Y","32" +"INC r/m64","INCQ r/m64","incq r/m64","REX.W FF /0","N.S.","V","","","rw","Y","64" +"INCSSPD rmr32","INCSSPD rmr32","incsspd rmr32","F3 0F AE /5","V","V","CET","modrm_regonly,operand16,operand32","r","","" +"INCSSPQ rmr64","INCSSPQ rmr64","incsspq rmr64","F3 REX.W 0F AE /5","N.S.","V","CET","modrm_regonly","r","","" +"INC r/m16","INCW r/m16","incw r/m16","FF /0","V","V","","operand16","rw","Y","16" +"INC r16op","INCW r16op","incw r16op","40+rw","V","N.S.","","operand16","rw","Y","16" +"IN EAX, DX","INL DX, EAX","inl DX, EAX","ED","V","V","","operand32,operand64","w,r","Y","32" +"IN EAX, imm8u","INL imm8u, EAX","inl imm8u, EAX","E5 ib","V","V","","operand32,operand64","w,r","Y","32" +"INSB","INSB","insb","6C","V","V","","","","","" +"INSERTPS xmm1, xmm2/m32, imm8u","INSERTPS imm8u, xmm2/m32, xmm1","insertps imm8u, xmm2/m32, xmm1","66 0F 3A 21 /r ib","V","V","SSE4_1","","rw,r,r","","" +"INSERTQ xmm1, xmm2, imm8u, imm8u","INSERTQ imm8u, imm8u, xmm2, xmm1","insertq imm8u, imm8u, xmm2, xmm1","F2 0F 78 /r ib ib","V","V","SSE4a","amd,modrm_regonly","w,r,r,r","","" +"INSERTQ xmm1, xmm2","INSERTQ xmm2, xmm1","insertq xmm2, xmm1","F2 0F 79 /r","V","V","SSE4a","amd,modrm_regonly","w,r","","" +"INSD","INSL","insl","6D","V","V","","operand32,operand64","","","" +"INSW","INSW","insw","6D","V","V","","operand16","","","" +"INT 3","INT 3","int 3","CC","V","V","","","r","","" +"INT imm8u","INT imm8u","int imm8u","CD ib","V","V","","","r","","" +"INTO","INTO","into","CE","V","N.S.","","","","","" +"INVD","INVD","invd","0F 08","V","V","486","","","","" +"INVEPT r32, m128","INVEPT m128, r32","invept m128, r32","66 0F 38 80 /r","V","N.S.","VTX","modrm_memonly","r,r","","" +"INVEPT r64, m128","INVEPT m128, r64","invept m128, r64","66 0F 38 80 /r","N.S.","V","VTX","default64,modrm_memonly","r,r","","" +"INVLPG m","INVLPG m","invlpg m","0F 01 /7","V","V","486","modrm_memonly","r","","" +"INVLPGA EAX, ECX","INVLPGAL ECX, EAX","invlpgal ECX, EAX","0F 01 DF","V","V","SVM","amd,modrm_regonly,operand32","r,r","Y","32" +"INVLPGA RAX, ECX","INVLPGAQ ECX, RAX","invlpgaq ECX, RAX","REX.W 0F 01 DF","N.S.","V","SVM","amd,modrm_regonly","r,r","Y","64" +"INVLPGA AX, ECX","INVLPGAW ECX, AX","invlpgaw ECX, AX","0F 01 DF","V","V","SVM","amd,modrm_regonly,operand16","r,r","Y","16" +"INVPCID r32, m128","INVPCID m128, r32","invpcid m128, r32","66 0F 38 82 /r","V","N.S.","INVPCID","modrm_memonly","r,r","","" +"INVPCID r64, m128","INVPCID m128, r64","invpcid m128, r64","66 0F 38 82 /r","N.S.","V","INVPCID","default64,modrm_memonly","r,r","","" +"INVVPID r32, m128","INVVPID m128, r32","invvpid m128, r32","66 0F 38 81 /r","V","N.S.","VTX","modrm_memonly","r,r","","" +"INVVPID r64, m128","INVVPID m128, r64","invvpid m128, r64","66 0F 38 81 /r","N.S.","V","VTX","default64,modrm_memonly","r,r","","" +"IN AX, DX","INW DX, AX","inw DX, AX","ED","V","V","","operand16","w,r","Y","16" +"IN AX, imm8u","INW imm8u, AX","inw imm8u, AX","E5 ib","V","V","","operand16","w,r","Y","16" +"IRETD","IRETL","iretl","CF","V","V","","operand32","","","" +"IRETQ","IRETQ","iretq","REX.W CF","N.S.","V","","","","","" +"IRET","IRETW","iretw","CF","V","V","","operand16","","","" +"JA rel16","JA rel16","ja rel16","0F 87 cw","V","N.S.","","operand16","r","","" +"JA rel32","JA rel32","ja rel32","0F 87 cd","V","N.S.","","operand32","r","","" +"JA rel32","JA rel32","ja rel32","0F 87 cd","N.S.","V","","default64","r","","" +"JA rel8","JA rel8","ja rel8","77 cb","N.S.","V","","default64","r","","" +"JA rel8","JA rel8","ja rel8","77 cb","V","N.S.","","","r","","" +"JAE rel16","JAE rel16","jae rel16","0F 83 cw","V","N.S.","","operand16","r","","" +"JAE rel32","JAE rel32","jae rel32","0F 83 cd","N.S.","V","","default64","r","","" +"JAE rel32","JAE rel32","jae rel32","0F 83 cd","V","N.S.","","operand32","r","","" +"JAE rel8","JAE rel8","jae rel8","73 cb","V","N.S.","","","r","","" +"JAE rel8","JAE rel8","jae rel8","73 cb","N.S.","V","","default64","r","","" +"JB rel16","JB rel16","jb rel16","0F 82 cw","V","N.S.","","operand16","r","","" +"JB rel32","JB rel32","jb rel32","0F 82 cd","V","N.S.","","operand32","r","","" +"JB rel32","JB rel32","jb rel32","0F 82 cd","N.S.","V","","default64","r","","" +"JB rel8","JB rel8","jb rel8","72 cb","N.S.","V","","default64","r","","" +"JB rel8","JB rel8","jb rel8","72 cb","V","N.S.","","","r","","" +"JBE rel16","JBE rel16","jbe rel16","0F 86 cw","V","N.S.","","operand16","r","","" +"JBE rel32","JBE rel32","jbe rel32","0F 86 cd","V","N.S.","","operand32","r","","" +"JBE rel32","JBE rel32","jbe rel32","0F 86 cd","N.S.","V","","default64","r","","" +"JBE rel8","JBE rel8","jbe rel8","76 cb","V","N.S.","","","r","","" +"JBE rel8","JBE rel8","jbe rel8","76 cb","N.S.","V","","default64","r","","" +"JC rel16","JC rel16","jc rel16","0F 82 cw","V","N.S.","","pseudo","r","","" +"JC rel32","JC rel32","jc rel32","0F 82 cd","V","V","","pseudo","r","","" +"JC rel8","JC rel8","jc rel8","72 cb","V","V","","pseudo","r","","" +"JCXZ rel8","JCXZ rel8","jcxz rel8","E3 cb","V","N.S.","","address16","r","","" +"JE rel16","JE rel16","je rel16","0F 84 cw","V","N.S.","","operand16","r","","" +"JE rel32","JE rel32","je rel32","0F 84 cd","V","N.S.","","operand32","r","","" +"JE rel32","JE rel32","je rel32","0F 84 cd","N.S.","V","","default64","r","","" +"JE rel8","JE rel8","je rel8","74 cb","N.S.","V","","default64","r","","" +"JE rel8","JE rel8","je rel8","74 cb","V","N.S.","","","r","","" +"JECXZ rel8","JECXZ rel8","jecxz rel8","E3 cb","V","V","","address32","r","","" +"JG rel16","JG rel16","jg rel16","0F 8F cw","V","N.S.","","operand16","r","","" +"JG rel32","JG rel32","jg rel32","0F 8F cd","N.S.","V","","default64","r","","" +"JG rel32","JG rel32","jg rel32","0F 8F cd","V","N.S.","","operand32","r","","" +"JG rel8","JG rel8","jg rel8","7F cb","V","N.S.","","","r","","" +"JG rel8","JG rel8","jg rel8","7F cb","N.S.","V","","default64","r","","" +"JGE rel16","JGE rel16","jge rel16","0F 8D cw","V","N.S.","","operand16","r","","" +"JGE rel32","JGE rel32","jge rel32","0F 8D cd","V","N.S.","","operand32","r","","" +"JGE rel32","JGE rel32","jge rel32","0F 8D cd","N.S.","V","","default64","r","","" +"JGE rel8","JGE rel8","jge rel8","7D cb","N.S.","V","","default64","r","","" +"JGE rel8","JGE rel8","jge rel8","7D cb","V","N.S.","","","r","","" +"JL rel16","JL rel16","jl rel16","0F 8C cw","V","N.S.","","operand16","r","","" +"JL rel32","JL rel32","jl rel32","0F 8C cd","V","N.S.","","operand32","r","","" +"JL rel32","JL rel32","jl rel32","0F 8C cd","N.S.","V","","default64","r","","" +"JL rel8","JL rel8","jl rel8","7C cb","V","N.S.","","","r","","" +"JL rel8","JL rel8","jl rel8","7C cb","N.S.","V","","default64","r","","" +"JLE rel16","JLE rel16","jle rel16","0F 8E cw","V","N.S.","","operand16","r","","" +"JLE rel32","JLE rel32","jle rel32","0F 8E cd","V","N.S.","","operand32","r","","" +"JLE rel32","JLE rel32","jle rel32","0F 8E cd","N.S.","V","","default64","r","","" +"JLE rel8","JLE rel8","jle rel8","7E cb","N.S.","V","","default64","r","","" +"JLE rel8","JLE rel8","jle rel8","7E cb","V","N.S.","","","r","","" +"JMP rel16","JMP rel16","jmp rel16","E9 cw","V","N.S.","","operand16","r","Y","" +"JMP rel32","JMP rel32","jmp rel32","E9 cd","N.S.","V","","default64","r","Y","" +"JMP rel32","JMP rel32","jmp rel32","E9 cd","V","N.S.","","operand32","r","Y","" +"JMP rel8","JMP rel8","jmp rel8","EB cb","N.S.","V","","default64","r","Y","" +"JMP rel8","JMP rel8","jmp rel8","EB cb","V","N.S.","","","r","Y","" +"JMP r/m32","JMPL* r/m32","jmpl* r/m32","FF /4","V","N.S.","","operand32","r","Y","32" +"JMP r/m64","JMPQ* r/m64","jmpq* r/m64","FF /4","N.S.","V","","","r","Y","64" +"JMP r/m16","JMPW* r/m16","jmpw* r/m16","FF /4","V","N.S.","","operand16","r","Y","16" +"JNA rel16","JNA rel16","jna rel16","0F 86 cw","V","N.S.","","pseudo","r","","" +"JNA rel32","JNA rel32","jna rel32","0F 86 cd","V","V","","pseudo","r","","" +"JNA rel8","JNA rel8","jna rel8","76 cb","V","V","","pseudo","r","","" +"JNAE rel16","JNAE rel16","jnae rel16","0F 82 cw","V","N.S.","","pseudo","r","","" +"JNAE rel32","JNAE rel32","jnae rel32","0F 82 cd","V","V","","pseudo","r","","" +"JNAE rel8","JNAE rel8","jnae rel8","72 cb","V","V","","pseudo","r","","" +"JNB rel16","JNB rel16","jnb rel16","0F 83 cw","V","N.S.","","pseudo","r","","" +"JNB rel32","JNB rel32","jnb rel32","0F 83 cd","V","V","","pseudo","r","","" +"JNB rel8","JNB rel8","jnb rel8","73 cb","V","V","","pseudo","r","","" +"JNBE rel16","JNBE rel16","jnbe rel16","0F 87 cw","V","N.S.","","pseudo","r","","" +"JNBE rel32","JNBE rel32","jnbe rel32","0F 87 cd","V","V","","pseudo","r","","" +"JNBE rel8","JNBE rel8","jnbe rel8","77 cb","V","V","","pseudo","r","","" +"JNC rel16","JNC rel16","jnc rel16","0F 83 cw","V","N.S.","","pseudo","r","","" +"JNC rel32","JNC rel32","jnc rel32","0F 83 cd","V","V","","pseudo","r","","" +"JNC rel8","JNC rel8","jnc rel8","73 cb","V","V","","pseudo","r","","" +"JNE rel16","JNE rel16","jne rel16","0F 85 cw","V","N.S.","","operand16","r","","" +"JNE rel32","JNE rel32","jne rel32","0F 85 cd","N.S.","V","","default64","r","","" +"JNE rel32","JNE rel32","jne rel32","0F 85 cd","V","N.S.","","operand32","r","","" +"JNE rel8","JNE rel8","jne rel8","75 cb","V","N.S.","","","r","","" +"JNE rel8","JNE rel8","jne rel8","75 cb","N.S.","V","","default64","r","","" +"JNG rel16","JNG rel16","jng rel16","0F 8E cw","V","N.S.","","pseudo","r","","" +"JNG rel32","JNG rel32","jng rel32","0F 8E cd","V","V","","pseudo","r","","" +"JNG rel8","JNG rel8","jng rel8","7E cb","V","V","","pseudo","r","","" +"JNGE rel16","JNGE rel16","jnge rel16","0F 8C cw","V","N.S.","","pseudo","r","","" +"JNGE rel32","JNGE rel32","jnge rel32","0F 8C cd","V","V","","pseudo","r","","" +"JNGE rel8","JNGE rel8","jnge rel8","7C cb","V","V","","pseudo","r","","" +"JNL rel16","JNL rel16","jnl rel16","0F 8D cw","V","N.S.","","pseudo","r","","" +"JNL rel32","JNL rel32","jnl rel32","0F 8D cd","V","V","","pseudo","r","","" +"JNL rel8","JNL rel8","jnl rel8","7D cb","V","V","","pseudo","r","","" +"JNLE rel16","JNLE rel16","jnle rel16","0F 8F cw","V","N.S.","","pseudo","r","","" +"JNLE rel32","JNLE rel32","jnle rel32","0F 8F cd","V","V","","pseudo","r","","" +"JNLE rel8","JNLE rel8","jnle rel8","7F cb","V","V","","pseudo","r","","" +"JNO rel16","JNO rel16","jno rel16","0F 81 cw","V","N.S.","","operand16","r","","" +"JNO rel32","JNO rel32","jno rel32","0F 81 cd","V","N.S.","","operand32","r","","" +"JNO rel32","JNO rel32","jno rel32","0F 81 cd","N.S.","V","","default64","r","","" +"JNO rel8","JNO rel8","jno rel8","71 cb","V","N.S.","","","r","","" +"JNO rel8","JNO rel8","jno rel8","71 cb","N.S.","V","","default64","r","","" +"JNP rel16","JNP rel16","jnp rel16","0F 8B cw","V","N.S.","","operand16","r","","" +"JNP rel32","JNP rel32","jnp rel32","0F 8B cd","V","N.S.","","operand32","r","","" +"JNP rel32","JNP rel32","jnp rel32","0F 8B cd","N.S.","V","","default64","r","","" +"JNP rel8","JNP rel8","jnp rel8","7B cb","N.S.","V","","default64","r","","" +"JNP rel8","JNP rel8","jnp rel8","7B cb","V","N.S.","","","r","","" +"JNS rel16","JNS rel16","jns rel16","0F 89 cw","V","N.S.","","operand16","r","","" +"JNS rel32","JNS rel32","jns rel32","0F 89 cd","N.S.","V","","default64","r","","" +"JNS rel32","JNS rel32","jns rel32","0F 89 cd","V","N.S.","","operand32","r","","" +"JNS rel8","JNS rel8","jns rel8","79 cb","V","N.S.","","","r","","" +"JNS rel8","JNS rel8","jns rel8","79 cb","N.S.","V","","default64","r","","" +"JNZ rel16","JNZ rel16","jnz rel16","0F 85 cw","V","N.S.","","pseudo","r","","" +"JNZ rel32","JNZ rel32","jnz rel32","0F 85 cd","V","V","","pseudo","r","","" +"JNZ rel8","JNZ rel8","jnz rel8","75 cb","V","V","","pseudo","r","","" +"JO rel16","JO rel16","jo rel16","0F 80 cw","V","N.S.","","operand16","r","","" +"JO rel32","JO rel32","jo rel32","0F 80 cd","V","N.S.","","operand32","r","","" +"JO rel32","JO rel32","jo rel32","0F 80 cd","N.S.","V","","default64","r","","" +"JO rel8","JO rel8","jo rel8","70 cb","V","N.S.","","","r","","" +"JO rel8","JO rel8","jo rel8","70 cb","N.S.","V","","default64","r","","" +"JP rel16","JP rel16","jp rel16","0F 8A cw","V","N.S.","","operand16","r","","" +"JP rel32","JP rel32","jp rel32","0F 8A cd","N.S.","V","","default64","r","","" +"JP rel32","JP rel32","jp rel32","0F 8A cd","V","N.S.","","operand32","r","","" +"JP rel8","JP rel8","jp rel8","7A cb","N.S.","V","","default64","r","","" +"JP rel8","JP rel8","jp rel8","7A cb","V","N.S.","","","r","","" +"JPE rel16","JPE rel16","jpe rel16","0F 8A cw","V","N.S.","","pseudo","r","","" +"JPE rel32","JPE rel32","jpe rel32","0F 8A cd","V","V","","pseudo","r","","" +"JPE rel8","JPE rel8","jpe rel8","7A cb","V","V","","pseudo","r","","" +"JPO rel16","JPO rel16","jpo rel16","0F 8B cw","V","N.S.","","pseudo","r","","" +"JPO rel32","JPO rel32","jpo rel32","0F 8B cd","V","V","","pseudo","r","","" +"JPO rel8","JPO rel8","jpo rel8","7B cb","V","V","","pseudo","r","","" +"JRCXZ rel8","JRCXZ rel8","jrcxz rel8","E3 cb","N.S.","V","","address64","r","","" +"JS rel16","JS rel16","js rel16","0F 88 cw","V","N.S.","","operand16","r","","" +"JS rel32","JS rel32","js rel32","0F 88 cd","V","N.S.","","operand32","r","","" +"JS rel32","JS rel32","js rel32","0F 88 cd","N.S.","V","","default64","r","","" +"JS rel8","JS rel8","js rel8","78 cb","V","N.S.","","","r","","" +"JS rel8","JS rel8","js rel8","78 cb","N.S.","V","","default64","r","","" +"JZ rel16","JZ rel16","jz rel16","0F 84 cw","V","N.S.","","operand16,pseudo","r","","" +"JZ rel32","JZ rel32","jz rel32","0F 84 cd","V","V","","operand32,pseudo","r","","" +"JZ rel8","JZ rel8","jz rel8","74 cb","V","V","","pseudo","r","","" +"KADDB k1, kV, k2","KADDB k2, kV, k1","kaddb k2, kV, k1","VEX.NDS.256.66.0F.W0 4A /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KADDD k1, kV, k2","KADDD k2, kV, k1","kaddd k2, kV, k1","VEX.NDS.256.66.0F.W1 4A /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KADDQ k1, kV, k2","KADDQ k2, kV, k1","kaddq k2, kV, k1","VEX.NDS.256.0F.W1 4A /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KADDW k1, kV, k2","KADDW k2, kV, k1","kaddw k2, kV, k1","VEX.NDS.256.0F.W0 4A /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KANDB k1, kV, k2","KANDB k2, kV, k1","kandb k2, kV, k1","VEX.NDS.256.66.0F.W0 41 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KANDD k1, kV, k2","KANDD k2, kV, k1","kandd k2, kV, k1","VEX.NDS.256.66.0F.W1 41 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KANDNB k1, kV, k2","KANDNB k2, kV, k1","kandnb k2, kV, k1","VEX.NDS.256.66.0F.W0 42 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KANDND k1, kV, k2","KANDND k2, kV, k1","kandnd k2, kV, k1","VEX.NDS.256.66.0F.W1 42 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KANDNQ k1, kV, k2","KANDNQ k2, kV, k1","kandnq k2, kV, k1","VEX.NDS.256.0F.W1 42 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KANDNW k1, kV, k2","KANDNW k2, kV, k1","kandnw k2, kV, k1","VEX.NDS.256.0F.W0 42 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"KANDQ k1, kV, k2","KANDQ k2, kV, k1","kandq k2, kV, k1","VEX.NDS.256.0F.W1 41 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KANDW k1, kV, k2","KANDW k2, kV, k1","kandw k2, kV, k1","VEX.NDS.256.0F.W0 41 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"KMOVB m8, k1","KMOVB k1, m8","kmovb k1, m8","VEX.128.66.0F.W0 91 /r","V","V","AVX512DQ","modrm_memonly","w,r","","" +"KMOVB r32, k2","KMOVB k2, r32","kmovb k2, r32","VEX.128.66.0F.W0 93 /r","V","V","AVX512DQ","modrm_regonly","w,r","","" +"KMOVB k1, k2/m8","KMOVB k2/m8, k1","kmovb k2/m8, k1","VEX.128.66.0F.W0 90 /r","V","V","AVX512DQ","","w,r","","" +"KMOVB k1, rmr32","KMOVB rmr32, k1","kmovb rmr32, k1","VEX.128.66.0F.W0 92 /r","V","V","AVX512DQ","modrm_regonly","w,r","","" +"KMOVD m32, k1","KMOVD k1, m32","kmovd k1, m32","VEX.128.66.0F.W1 91 /r","V","V","AVX512BW","modrm_memonly","w,r","","" +"KMOVD r32, k2","KMOVD k2, r32","kmovd k2, r32","VEX.128.F2.0F.W0 93 /r","V","V","AVX512BW","modrm_regonly","w,r","","" +"KMOVD k1, k2/m32","KMOVD k2/m32, k1","kmovd k2/m32, k1","VEX.128.66.0F.W1 90 /r","V","V","AVX512BW","","w,r","","" +"KMOVD k1, rmr32","KMOVD rmr32, k1","kmovd rmr32, k1","VEX.128.F2.0F.W0 92 /r","V","V","AVX512BW","modrm_regonly","w,r","","" +"KMOVQ m64, k1","KMOVQ k1, m64","kmovq k1, m64","VEX.128.0F.W1 91 /r","V","V","AVX512BW","modrm_memonly","w,r","","" +"KMOVQ r64, k2","KMOVQ k2, r64","kmovq k2, r64","VEX.128.F2.0F.W1 93 /r","N.S.","V","AVX512BW","modrm_regonly","w,r","","" +"KMOVQ k1, k2/m64","KMOVQ k2/m64, k1","kmovq k2/m64, k1","VEX.128.0F.W1 90 /r","V","V","AVX512BW","","w,r","","" +"KMOVQ k1, rmr64","KMOVQ rmr64, k1","kmovq rmr64, k1","VEX.128.F2.0F.W1 92 /r","N.S.","V","AVX512BW","modrm_regonly","w,r","","" +"KMOVW m16, k1","KMOVW k1, m16","kmovw k1, m16","VEX.128.0F.W0 91 /r","V","V","AVX512F","modrm_memonly","w,r","","" +"KMOVW r32, k2","KMOVW k2, r32","kmovw k2, r32","VEX.128.0F.W0 93 /r","V","V","AVX512F","modrm_regonly","w,r","","" +"KMOVW k1, k2/m16","KMOVW k2/m16, k1","kmovw k2/m16, k1","VEX.128.0F.W0 90 /r","V","V","AVX512F","","w,r","","" +"KMOVW k1, rmr32","KMOVW rmr32, k1","kmovw rmr32, k1","VEX.128.0F.W0 92 /r","V","V","AVX512F","modrm_regonly","w,r","","" +"KNOTB k1, k2","KNOTB k2, k1","knotb k2, k1","VEX.128.66.0F.W0 44 /r","V","V","AVX512DQ","modrm_regonly","w,r","","" +"KNOTD k1, k2","KNOTD k2, k1","knotd k2, k1","VEX.128.66.0F.W1 44 /r","V","V","AVX512BW","modrm_regonly","w,r","","" +"KNOTQ k1, k2","KNOTQ k2, k1","knotq k2, k1","VEX.128.0F.W1 44 /r","V","V","AVX512BW","modrm_regonly","w,r","","" +"KNOTW k1, k2","KNOTW k2, k1","knotw k2, k1","VEX.128.0F.W0 44 /r","V","V","AVX512F","modrm_regonly","w,r","","" +"KORB k1, kV, k2","KORB k2, kV, k1","korb k2, kV, k1","VEX.NDS.256.66.0F.W0 45 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KORD k1, kV, k2","KORD k2, kV, k1","kord k2, kV, k1","VEX.NDS.256.66.0F.W1 45 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KORQ k1, kV, k2","KORQ k2, kV, k1","korq k2, kV, k1","VEX.NDS.256.0F.W1 45 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KORTESTB k1, k2","KORTESTB k2, k1","kortestb k2, k1","VEX.128.66.0F.W0 98 /r","V","V","AVX512DQ","modrm_regonly","r,r","","" +"KORTESTD k1, k2","KORTESTD k2, k1","kortestd k2, k1","VEX.128.66.0F.W1 98 /r","V","V","AVX512BW","modrm_regonly","r,r","","" +"KORTESTQ k1, k2","KORTESTQ k2, k1","kortestq k2, k1","VEX.128.0F.W1 98 /r","V","V","AVX512BW","modrm_regonly","r,r","","" +"KORTESTW k1, k2","KORTESTW k2, k1","kortestw k2, k1","VEX.128.0F.W0 98 /r","V","V","AVX512F","modrm_regonly","r,r","","" +"KORW k1, kV, k2","KORW k2, kV, k1","korw k2, kV, k1","VEX.NDS.256.0F.W0 45 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"KSHIFTLB k1, k2, imm8u","KSHIFTLB imm8u, k2, k1","kshiftlb imm8u, k2, k1","VEX.128.66.0F3A.W0 32 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KSHIFTLD k1, k2, imm8u","KSHIFTLD imm8u, k2, k1","kshiftld imm8u, k2, k1","VEX.128.66.0F3A.W0 33 /r ib","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KSHIFTLQ k1, k2, imm8u","KSHIFTLQ imm8u, k2, k1","kshiftlq imm8u, k2, k1","VEX.128.66.0F3A.W1 33 /r ib","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KSHIFTLW k1, k2, imm8u","KSHIFTLW imm8u, k2, k1","kshiftlw imm8u, k2, k1","VEX.128.66.0F3A.W1 32 /r ib","V","V","AVX512F","modrm_regonly","w,r,r","","" +"KSHIFTRB k1, k2, imm8u","KSHIFTRB imm8u, k2, k1","kshiftrb imm8u, k2, k1","VEX.128.66.0F3A.W0 30 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KSHIFTRD k1, k2, imm8u","KSHIFTRD imm8u, k2, k1","kshiftrd imm8u, k2, k1","VEX.128.66.0F3A.W0 31 /r ib","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KSHIFTRQ k1, k2, imm8u","KSHIFTRQ imm8u, k2, k1","kshiftrq imm8u, k2, k1","VEX.128.66.0F3A.W1 31 /r ib","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KSHIFTRW k1, k2, imm8u","KSHIFTRW imm8u, k2, k1","kshiftrw imm8u, k2, k1","VEX.128.66.0F3A.W1 30 /r ib","V","V","AVX512F","modrm_regonly","w,r,r","","" +"KTESTB k1, k2","KTESTB k2, k1","ktestb k2, k1","VEX.128.66.0F.W0 99 /r","V","V","AVX512DQ","modrm_regonly","r,r","","" +"KTESTD k1, k2","KTESTD k2, k1","ktestd k2, k1","VEX.128.66.0F.W1 99 /r","V","V","AVX512BW","modrm_regonly","r,r","","" +"KTESTQ k1, k2","KTESTQ k2, k1","ktestq k2, k1","VEX.128.0F.W1 99 /r","V","V","AVX512BW","modrm_regonly","r,r","","" +"KTESTW k1, k2","KTESTW k2, k1","ktestw k2, k1","VEX.128.0F.W0 99 /r","V","V","AVX512DQ","modrm_regonly","r,r","","" +"KUNPCKBW k1, kV, k2","KUNPCKBW k2, kV, k1","kunpckbw k2, kV, k1","VEX.NDS.256.66.0F.W0 4B /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"KUNPCKDQ k1, kV, k2","KUNPCKDQ k2, kV, k1","kunpckdq k2, kV, k1","VEX.NDS.256.0F.W1 4B /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KUNPCKWD k1, kV, k2","KUNPCKWD k2, kV, k1","kunpckwd k2, kV, k1","VEX.NDS.256.0F.W0 4B /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KXNORB k1, kV, k2","KXNORB k2, kV, k1","kxnorb k2, kV, k1","VEX.NDS.256.66.0F.W0 46 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KXNORD k1, kV, k2","KXNORD k2, kV, k1","kxnord k2, kV, k1","VEX.NDS.256.66.0F.W1 46 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KXNORQ k1, kV, k2","KXNORQ k2, kV, k1","kxnorq k2, kV, k1","VEX.NDS.256.0F.W1 46 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KXNORW k1, kV, k2","KXNORW k2, kV, k1","kxnorw k2, kV, k1","VEX.NDS.256.0F.W0 46 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"KXORB k1, kV, k2","KXORB k2, kV, k1","kxorb k2, kV, k1","VEX.NDS.256.66.0F.W0 47 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"KXORD k1, kV, k2","KXORD k2, kV, k1","kxord k2, kV, k1","VEX.NDS.256.66.0F.W1 47 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KXORQ k1, kV, k2","KXORQ k2, kV, k1","kxorq k2, kV, k1","VEX.NDS.256.0F.W1 47 /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"KXORW k1, kV, k2","KXORW k2, kV, k1","kxorw k2, kV, k1","VEX.NDS.256.0F.W0 47 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"LAHF","LAHF","lahf","9F","V","V","LAHFSAHF","","","","" +"LAR r32, r32/m16","LARL r32/m16, r32","larl r32/m16, r32","0F 02 /r","V","V","","operand32","rw,r","Y","32" +"LAR r64, r64/m16","LARQ r64/m16, r64","larq r64/m16, r64","REX.W 0F 02 /r","N.S.","V","","","rw,r","Y","64" +"LAR r16, r/m16","LARW r/m16, r16","larw r/m16, r16","0F 02 /r","V","V","","operand16","rw,r","Y","16" +"CALL_FAR ptr16:32","LCALLL ptr16:32","lcalll ptr16:32","9A cd iw","V","N.S.","","operand32","r","Y","" +"CALL_FAR m16:32","LCALLL* m16:32","lcalll* m16:32","FF /3","V","V","","modrm_memonly,operand32","r","Y","" +"CALL_FAR m16:64","LCALLQ* m16:64","lcallq* m16:64","REX.W FF /3","N.S.","V","","modrm_memonly","r","Y","" +"CALL_FAR ptr16:16","LCALLW ptr16:16","lcallw ptr16:16","9A cw iw","V","N.S.","","operand16","r","Y","" +"CALL_FAR m16:16","LCALLW* m16:16","lcallw* m16:16","FF /3","V","V","","modrm_memonly,operand16","r","Y","" +"LDDQU xmm1, m128","LDDQU m128, xmm1","lddqu m128, xmm1","F2 0F F0 /r","V","V","SSE3","modrm_memonly","w,r","","" +"LDMXCSR m32","LDMXCSR m32","ldmxcsr m32","0F AE /2","V","V","SSE","modrm_memonly","r","","" +"LDS r32, m16:32","LDSL m16:32, r32","ldsl m16:32, r32","C5 /r","V","N.S.","","modrm_memonly,operand32","w,r","Y","32" +"LDS r16, m16:16","LDSW m16:16, r16","ldsw m16:16, r16","C5 /r","V","N.S.","","modrm_memonly,operand16","w,r","Y","16" +"LEA r32, m","LEAL m, r32","leal m, r32","8D /r","V","V","","modrm_memonly,operand32","w,r","Y","32" +"LEA r64, m","LEAQ m, r64","leaq m, r64","REX.W 8D /r","N.S.","V","","modrm_memonly","w,r","Y","64" +"LEAVE","LEAVEW/LEAVEL/LEAVEQ","leavew/leavel/leaveq","C9","N.S.","V","","default64","","Y","" +"LEAVE","LEAVEW/LEAVEL/LEAVEQ","leavew/leavel/leaveq","C9","V","N.S.","","operand32","","Y","" +"LEAVE","LEAVEW/LEAVEL/LEAVEQ","leavew/leavel/leaveq","C9","V","V","","operand16","","Y","" +"LEA r16, m","LEAW m, r16","leaw m, r16","8D /r","V","V","","modrm_memonly,operand16","w,r","Y","16" +"LES r32, m16:32","LESL m16:32, r32","lesl m16:32, r32","C4 /r","V","N.S.","","modrm_memonly,operand32","w,r","Y","32" +"LES r16, m16:16","LESW m16:16, r16","lesw m16:16, r16","C4 /r","V","N.S.","","modrm_memonly,operand16","w,r","Y","16" +"LFENCE","LFENCE","lfence","0F AE /5","V","V","SSE2","","","","" +"LFS r32, m16:32","LFSL m16:32, r32","lfsl m16:32, r32","0F B4 /r","V","V","","modrm_memonly,operand32","w,r","Y","32" +"LFS r64, m16:64","LFSQ m16:64, r64","lfsq m16:64, r64","REX.W 0F B4 /r","N.S.","V","","modrm_memonly","w,r","Y","64" +"LFS r16, m16:16","LFSW m16:16, r16","lfsw m16:16, r16","0F B4 /r","V","V","","modrm_memonly,operand16","w,r","Y","16" +"LGDT m16&64","LGDT m16&64","lgdt m16&64","0F 01 /2","N.S.","V","","default64,modrm_memonly","r","","" +"LGDT m16&32","LGDTW/LGDTL m16&32","lgdtw/lgdtl m16&32","0F 01 /2","V","N.S.","","modrm_memonly","r","","" +"LGS r32, m16:32","LGSL m16:32, r32","lgsl m16:32, r32","0F B5 /r","V","V","","modrm_memonly,operand32","w,r","Y","32" +"LGS r64, m16:64","LGSQ m16:64, r64","lgsq m16:64, r64","REX.W 0F B5 /r","N.S.","V","","modrm_memonly","w,r","Y","64" +"LGS r16, m16:16","LGSW m16:16, r16","lgsw m16:16, r16","0F B5 /r","V","V","","modrm_memonly,operand16","w,r","Y","16" +"LIDT m16&64","LIDT m16&64","lidt m16&64","0F 01 /3","N.S.","V","","default64,modrm_memonly","r","","" +"LIDT m16&32","LIDTW/LIDTL m16&32","lidtw/lidtl m16&32","0F 01 /3","V","N.S.","","modrm_memonly","r","","" +"JMP_FAR ptr16:32","LJMPL ptr16:32","ljmpl ptr16:32","EA cd iw","V","N.S.","","operand32","r","Y","" +"JMP_FAR m16:32","LJMPL* m16:32","ljmpl* m16:32","FF /5","V","V","","modrm_memonly,operand32","r","Y","" +"JMP_FAR m16:64","LJMPQ* m16:64","ljmpq* m16:64","REX.W FF /5","N.S.","V","","modrm_memonly","r","Y","" +"JMP_FAR ptr16:16","LJMPW ptr16:16","ljmpw ptr16:16","EA cw iw","V","N.S.","","operand16","r","Y","" +"JMP_FAR m16:16","LJMPW* m16:16","ljmpw* m16:16","FF /5","V","V","","modrm_memonly,operand16","r","Y","" +"LLDT r/m16","LLDT r/m16","lldt r/m16","0F 00 /2","V","V","","","r","","" +"LLWPCB rmr32","LLWPCBL rmr32","llwpcbl rmr32","XOP.128.09.W0 12 /0","V","V","XOP","amd,modrm_regonly,operand16,operand32","w","Y","32" +"LLWPCB rmr64","LLWPCBQ rmr64","llwpcbq rmr64","XOP.128.09.W0 12 /0","N.S.","V","XOP","amd,modrm_regonly,operand64","w","Y","64" +"LMSW r/m16","LMSW r/m16","lmsw r/m16","0F 01 /6","V","V","","","r","","" +"LOCK","LOCK","lock","F0","V","V","","pseudo","","","" +"LODSB","LODSB","lodsb","AC","V","V","","","","","" +"LODSD","LODSL","lodsl","AD","V","V","","operand32","","","" +"LODSQ","LODSQ","lodsq","REX.W AD","N.S.","V","","","","","" +"LODSW","LODSW","lodsw","AD","V","V","","operand16","","","" +"LOOP rel8","LOOP rel8","loop rel8","E2 cb","V","V","","","r","","" +"LOOPE rel8","LOOPEQ rel8","loope rel8","E1 cb","V","V","","","r","","" +"LOOPNE rel8","LOOPNE rel8","loopne rel8","E0 cb","V","V","","","r","","" +"LSL r32, r32/m16","LSLL r32/m16, r32","lsll r32/m16, r32","0F 03 /r","V","V","","operand32","rw,r","Y","32" +"LSL r64, r32/m16","LSLQ r32/m16, r64","lslq r32/m16, r64","REX.W 0F 03 /r","N.S.","V","","","rw,r","Y","64" +"LSL r16, r/m16","LSLW r/m16, r16","lslw r/m16, r16","0F 03 /r","V","V","","operand16","rw,r","Y","16" +"LSS r32, m16:32","LSSL m16:32, r32","lssl m16:32, r32","0F B2 /r","V","V","","modrm_memonly,operand32","w,r","Y","32" +"LSS r64, m16:64","LSSQ m16:64, r64","lssq m16:64, r64","REX.W 0F B2 /r","N.S.","V","","modrm_memonly","w,r","Y","64" +"LSS r16, m16:16","LSSW m16:16, r16","lssw m16:16, r16","0F B2 /r","V","V","","modrm_memonly,operand16","w,r","Y","16" +"LTR r/m16","LTR r/m16","ltr r/m16","0F 00 /3","V","V","","","r","","" +"LWPINS r32V, r/m32, imm32u","LWPINS imm32u, r/m32, r32V","lwpins imm32u, r/m32, r32V","XOP.NDD.128.0A.W0 12 /0","V","V","XOP","amd,operand16,operand32","w,r,r","","" +"LWPINS r64V, r64/m32, imm32u","LWPINS imm32u, r64/m32, r64V","lwpins imm32u, r64/m32, r64V","XOP.NDD.128.0A.W0 12 /0","N.S.","V","XOP","amd,operand64","w,r,r","","" +"LWPVAL r32V, r/m32, imm32u","LWPVAL imm32u, r/m32, r32V","lwpval imm32u, r/m32, r32V","XOP.NDD.128.0A.W0 12 /1","V","V","XOP","amd,operand16,operand32","w,r,r","","" +"LWPVAL r64V, r64/m32, imm32u","LWPVAL imm32u, r64/m32, r64V","lwpval imm32u, r64/m32, r64V","XOP.NDD.128.0A.W0 12 /1","N.S.","V","XOP","amd,operand64","w,r,r","","" +"LZCNT r32, r/m32","LZCNTL r/m32, r32","lzcntl r/m32, r32","F3 0F BD /r","V","V","LZCNT","operand32","w,r","Y","32" +"LZCNT r32, r/m32","LZCNTL r/m32, r32","lzcntl r/m32, r32","F3 0F BD /r","V","V","AMD","amd,operand32","w,r","Y","32" +"LZCNT r64, r/m64","LZCNTQ r/m64, r64","lzcntq r/m64, r64","F3 REX.W 0F BD /r","N.S.","V","AMD","amd","w,r","Y","64" +"LZCNT r64, r/m64","LZCNTQ r/m64, r64","lzcntq r/m64, r64","F3 REX.W 0F BD /r","N.S.","V","LZCNT","","w,r","Y","64" +"LZCNT r16, r/m16","LZCNTW r/m16, r16","lzcntw r/m16, r16","F3 0F BD /r","V","V","AMD","amd,operand16","w,r","Y","16" +"LZCNT r16, r/m16","LZCNTW r/m16, r16","lzcntw r/m16, r16","F3 0F BD /r","V","V","LZCNT","operand16","w,r","Y","16" +"MASKMOVDQU xmm1, xmm2","MASKMOVOU xmm2, xmm1","maskmovdqu xmm2, xmm1","66 0F F7 /r","V","V","SSE2","modrm_regonly","r,r","","" +"MASKMOVQ mm1, mm2","MASKMOVQ mm2, mm1","maskmovq mm2, mm1","0F F7 /r","V","V","MMX","modrm_regonly","r,r","","" +"MAXPD xmm1, xmm2/m128","MAXPD xmm2/m128, xmm1","maxpd xmm2/m128, xmm1","66 0F 5F /r","V","V","SSE2","","rw,r","","" +"MAXPS xmm1, xmm2/m128","MAXPS xmm2/m128, xmm1","maxps xmm2/m128, xmm1","0F 5F /r","V","V","SSE","","rw,r","","" +"MAXSD xmm1, xmm2/m64","MAXSD xmm2/m64, xmm1","maxsd xmm2/m64, xmm1","F2 0F 5F /r","V","V","SSE2","","rw,r","","" +"MAXSS xmm1, xmm2/m32","MAXSS xmm2/m32, xmm1","maxss xmm2/m32, xmm1","F3 0F 5F /r","V","V","SSE","","rw,r","","" +"MFENCE","MFENCE","mfence","0F AE /6","V","V","SSE2","","","","" +"MINPD xmm1, xmm2/m128","MINPD xmm2/m128, xmm1","minpd xmm2/m128, xmm1","66 0F 5D /r","V","V","SSE2","","rw,r","","" +"MINPS xmm1, xmm2/m128","MINPS xmm2/m128, xmm1","minps xmm2/m128, xmm1","0F 5D /r","V","V","SSE","","rw,r","","" +"MINSD xmm1, xmm2/m64","MINSD xmm2/m64, xmm1","minsd xmm2/m64, xmm1","F2 0F 5D /r","V","V","SSE2","","rw,r","","" +"MINSS xmm1, xmm2/m32","MINSS xmm2/m32, xmm1","minss xmm2/m32, xmm1","F3 0F 5D /r","V","V","SSE","","rw,r","","" +"MONITOR","MONITOR","monitor","0F 01 C8","V","V","MONITOR","","","","" +"MOVAPD xmm2/m128, xmm1","MOVAPD xmm1, xmm2/m128","movapd xmm1, xmm2/m128","66 0F 29 /r","V","V","SSE2","","w,r","","" +"MOVAPD xmm1, xmm2/m128","MOVAPD xmm2/m128, xmm1","movapd xmm2/m128, xmm1","66 0F 28 /r","V","V","SSE2","","w,r","","" +"MOVAPS xmm2/m128, xmm1","MOVAPS xmm1, xmm2/m128","movaps xmm1, xmm2/m128","0F 29 /r","V","V","SSE","","w,r","","" +"MOVAPS xmm1, xmm2/m128","MOVAPS xmm2/m128, xmm1","movaps xmm2/m128, xmm1","0F 28 /r","V","V","SSE","","w,r","","" +"MOV r/m8, imm8u","MOVB imm8u, r/m8","movb imm8u, r/m8","C6 /0 ib","V","V","","","w,r","Y","8" +"MOV r/m8, imm8u","MOVB imm8u, r/m8","movb imm8u, r/m8","REX C6 /0 ib","N.E.","V","","pseudo64","w,r","Y","8" +"MOV r8op, imm8u","MOVB imm8u, r8op","movb imm8u, r8op","B0+rb ib","V","V","","","w,r","Y","8" +"MOV r8op, imm8u","MOVB imm8u, r8op","movb imm8u, r8op","REX B0+rb ib","N.E.","V","","pseudo64","w,r","Y","8" +"MOV r8, r/m8","MOVB r/m8, r8","movb r/m8, r8","8A /r","V","V","","","w,r","Y","8" +"MOV r8, r/m8","MOVB r/m8, r8","movb r/m8, r8","REX 8A /r","N.E.","V","","pseudo64","w,r","Y","8" +"MOV r/m8, r8","MOVB r8, r/m8","movb r8, r/m8","88 /r","V","V","","","w,r","Y","8" +"MOV r/m8, r8","MOVB r8, r/m8","movb r8, r/m8","REX 88 /r","N.E.","V","","pseudo64","w,r","Y","8" +"MOV moffs8, AL","MOVB/MOVB/MOVABSB AL, moffs8","movb/movb/movabsb AL, moffs8","A2 cm","V","V","","","w,r","Y","8" +"MOV moffs8, AL","MOVB/MOVB/MOVABSB AL, moffs8","movb/movb/movabsb AL, moffs8","REX.W A2 cm","N.E.","V","","pseudo","w,r","Y","8" +"MOV AL, moffs8","MOVB/MOVB/MOVABSB moffs8, AL","movb/movb/movabsb moffs8, AL","A0 cm","V","V","","","w,r","Y","8" +"MOV AL, moffs8","MOVB/MOVB/MOVABSB moffs8, AL","movb/movb/movabsb moffs8, AL","REX.W A0 cm","N.E.","V","","pseudo","w,r","Y","8" +"MOVBE r32, m32","MOVBELL m32, r32","movbell m32, r32","0F 38 F0 /r","V","V","MOVBE","modrm_memonly,operand32","w,r","Y","32" +"MOVBE m32, r32","MOVBELL r32, m32","movbell r32, m32","0F 38 F1 /r","V","V","MOVBE","modrm_memonly,operand32","w,r","Y","32" +"MOVBE r64, m64","MOVBEQQ m64, r64","movbeqq m64, r64","REX.W 0F 38 F0 /r","N.S.","V","MOVBE","modrm_memonly","w,r","Y","64" +"MOVBE m64, r64","MOVBEQQ r64, m64","movbeqq r64, m64","REX.W 0F 38 F1 /r","N.S.","V","MOVBE","modrm_memonly","w,r","Y","64" +"MOVBE r16, m16","MOVBEWW m16, r16","movbeww m16, r16","0F 38 F0 /r","V","V","MOVBE","modrm_memonly,operand16","w,r","Y","16" +"MOVBE m16, r16","MOVBEWW r16, m16","movbeww r16, m16","0F 38 F1 /r","V","V","MOVBE","modrm_memonly,operand16","w,r","Y","16" +"MOVSX r32, r/m8","MOVBLSX r/m8, r32","movsbl r/m8, r32","0F BE /r","V","V","","operand32","w,r","Y","32" +"MOVZX r32, r/m8","MOVBLZX r/m8, r32","movzbl r/m8, r32","0F B6 /r","V","V","","operand32","w,r","Y","32" +"MOVSX r64, r/m8","MOVBQSX r/m8, r64","movsbq r/m8, r64","REX.W 0F BE /r","N.S.","V","","","w,r","Y","64" +"MOVZX r64, r/m8","MOVBQZX r/m8, r64","movzbq r/m8, r64","REX.W 0F B6 /r","N.S.","V","","","w,r","Y","64" +"MOVSX r16, r/m8","MOVBWSX r/m8, r16","movsbw r/m8, r16","0F BE /r","V","V","","operand16","w,r","Y","16" +"MOVZX r16, r/m8","MOVBWZX r/m8, r16","movzbw r/m8, r16","0F B6 /r","V","V","","operand16","w,r","Y","16" +"MOVD r/m32, mm1","MOVD mm1, r/m32","movd mm1, r/m32","0F 7E /r","V","V","MMX","operand16,operand32","w,r","","" +"MOVD mm1, r/m32","MOVD r/m32, mm1","movd r/m32, mm1","0F 6E /r","V","V","MMX","operand16,operand32","w,r","","" +"MOVD xmm1, r/m32","MOVD r/m32, xmm1","movd r/m32, xmm1","66 0F 6E /r","V","V","SSE2","operand16,operand32","w,r","","" +"MOVD r/m32, xmm1","MOVD xmm1, r/m32","movd xmm1, r/m32","66 0F 7E /r","V","V","SSE2","operand16,operand32","w,r","","" +"MOVDDUP xmm1, xmm2/m64","MOVDDUP xmm2/m64, xmm1","movddup xmm2/m64, xmm1","F2 0F 12 /r","V","V","SSE3","","w,r","","" +"MOVHLPS xmm1, xmm2","MOVHLPS xmm2, xmm1","movhlps xmm2, xmm1","0F 12 /r","V","V","SSE","modrm_regonly","w,r","","" +"MOVHPD xmm1, m64","MOVHPD m64, xmm1","movhpd m64, xmm1","66 0F 16 /r","V","V","SSE2","modrm_memonly","w,r","","" +"MOVHPD m64, xmm1","MOVHPD xmm1, m64","movhpd xmm1, m64","66 0F 17 /r","V","V","SSE2","modrm_memonly","w,r","","" +"MOVHPS xmm1, m64","MOVHPS m64, xmm1","movhps m64, xmm1","0F 16 /r","V","V","SSE","modrm_memonly","w,r","","" +"MOVHPS m64, xmm1","MOVHPS xmm1, m64","movhps xmm1, m64","0F 17 /r","V","V","SSE","modrm_memonly","w,r","","" +"MOV rmr32, CR0-CR7","MOVL CR0-CR7, rmr32","movl CR0-CR7, rmr32","0F 20 /r","V","N.S.","","","w,r","Y","32" +"MOV rmr32, DR0-DR7","MOVL DR0-DR7, rmr32","movl DR0-DR7, rmr32","0F 21 /r","V","N.S.","","","w,r","Y","32" +"MOV moffs32, EAX","MOVL EAX, moffs32","movl EAX, moffs32","A3 cm","V","V","","operand32","w,r","Y","32" +"MOV r/m32, imm32","MOVL imm32, r/m32","movl imm32, r/m32","C7 /0 id","V","V","","operand32","w,r","Y","32" +"MOV r32op, imm32u","MOVL imm32u, r32op","movl imm32u, r32op","B8+rd id","V","V","","operand32","w,r","Y","32" +"MOV EAX, moffs32","MOVL moffs32, EAX","movl moffs32, EAX","A1 cm","V","V","","operand32","w,r","Y","32" +"MOV r32, r/m32","MOVL r/m32, r32","movl r/m32, r32","8B /r","V","V","","operand32","w,r","Y","32" +"MOV r/m32, r32","MOVL r32, r/m32","movl r32, r/m32","89 /r","V","V","","operand32","w,r","Y","32" +"MOV CR0-CR7, rmr32","MOVL rmr32, CR0-CR7","movl rmr32, CR0-CR7","0F 22 /r","V","N.S.","","","w,r","Y","32" +"MOV DR0-DR7, rmr32","MOVL rmr32, DR0-DR7","movl rmr32, DR0-DR7","0F 23 /r","V","N.S.","","","w,r","Y","32" +"MOVLHPS xmm1, xmm2","MOVLHPS xmm2, xmm1","movlhps xmm2, xmm1","0F 16 /r","V","V","SSE","modrm_regonly","w,r","","" +"MOVLPD xmm1, m64","MOVLPD m64, xmm1","movlpd m64, xmm1","66 0F 12 /r","V","V","SSE2","modrm_memonly","w,r","","" +"MOVLPD m64, xmm1","MOVLPD xmm1, m64","movlpd xmm1, m64","66 0F 13 /r","V","V","SSE2","modrm_memonly","w,r","","" +"MOVLPS xmm1, m64","MOVLPS m64, xmm1","movlps m64, xmm1","0F 12 /r","V","V","SSE","modrm_memonly","w,r","","" +"MOVLPS m64, xmm1","MOVLPS xmm1, m64","movlps xmm1, m64","0F 13 /r","V","V","SSE","modrm_memonly","w,r","","" +"MOVSXD r32, r/m32","MOVLQSX r/m32, r32","movsxdl r/m32, r32","63 /r","N.S.","V","","operand32","w,r","Y","32" +"MOVSXD r64, r/m32","MOVLQSX r/m32, r64","movslq r/m32, r64","REX.W 63 /r","N.S.","V","","","w,r","Y","64" +"MOVMSKPD r32, xmm2","MOVMSKPD xmm2, r32","movmskpd xmm2, r32","66 0F 50 /r","V","V","SSE2","modrm_regonly","w,r","","" +"MOVMSKPS r32, xmm2","MOVMSKPS xmm2, r32","movmskps xmm2, r32","0F 50 /r","V","V","SSE","modrm_regonly","w,r","","" +"MOVNTDQA xmm1, m128","MOVNTDQA m128, xmm1","movntdqa m128, xmm1","66 0F 38 2A /r","V","V","SSE4_1","modrm_memonly","w,r","","" +"MOVNTI m32, r32","MOVNTIL r32, m32","movntil r32, m32","0F C3 /r","V","V","SSE2","modrm_memonly,operand16,operand32","w,r","Y","32" +"MOVNTI m64, r64","MOVNTIQ r64, m64","movntiq r64, m64","REX.W 0F C3 /r","N.S.","V","SSE2","modrm_memonly","w,r","Y","64" +"MOVNTDQ m128, xmm1","MOVNTO xmm1, m128","movntdq xmm1, m128","66 0F E7 /r","V","V","SSE2","modrm_memonly","w,r","","" +"MOVNTPD m128, xmm1","MOVNTPD xmm1, m128","movntpd xmm1, m128","66 0F 2B /r","V","V","SSE2","modrm_memonly","w,r","","" +"MOVNTPS m128, xmm1","MOVNTPS xmm1, m128","movntps xmm1, m128","0F 2B /r","V","V","SSE","modrm_memonly","w,r","","" +"MOVNTQ m64, mm1","MOVNTQ mm1, m64","movntq mm1, m64","0F E7 /r","V","V","MMX","modrm_memonly","w,r","","" +"MOVNTSD m64, xmm1","MOVNTSD xmm1, m64","movntsd xmm1, m64","F2 0F 2B /r","V","V","SSE4a","amd,modrm_memonly","w,r","","" +"MOVNTSS m32, xmm1","MOVNTSS xmm1, m32","movntss xmm1, m32","F3 0F 2B /r","V","V","SSE4a","amd,modrm_memonly","w,r","","" +"MOVDQA xmm2/m128, xmm1","MOVO xmm1, xmm2/m128","movdqa xmm1, xmm2/m128","66 0F 7F /r","V","V","SSE2","","w,r","","" +"MOVDQA xmm1, xmm2/m128","MOVO xmm2/m128, xmm1","movdqa xmm2/m128, xmm1","66 0F 6F /r","V","V","SSE2","","w,r","","" +"MOVDQU xmm2/m128, xmm1","MOVOU xmm1, xmm2/m128","movdqu xmm1, xmm2/m128","F3 0F 7F /r","V","V","SSE2","","w,r","","" +"MOVDQU xmm1, xmm2/m128","MOVOU xmm2/m128, xmm1","movdqu xmm2/m128, xmm1","F3 0F 6F /r","V","V","SSE2","","w,r","","" +"MOV rmr64, CR0-CR7","MOVQ CR0-CR7, rmr64","movq CR0-CR7, rmr64","0F 20 /r","N.S.","V","","default64","w,r","Y","64" +"MOV rmr64, CR8","MOVQ CR8, rmr64","movq CR8, rmr64","REX.R + 0F 20 /0","N.E.","V","","modrm_regonly,pseudo","w,r","Y","64" +"MOV rmr64, DR0-DR7","MOVQ DR0-DR7, rmr64","movq DR0-DR7, rmr64","0F 21 /r","N.S.","V","","default64","w,r","Y","64" +"MOV moffs64, RAX","MOVQ RAX, moffs64","movabsq RAX, moffs64","REX.W A3 cm","N.S.","V","","","w,r","Y","64" +"MOV r/m64, imm32","MOVQ imm32, r/m64","movq imm32, r/m64","REX.W C7 /0 id","N.S.","V","","","w,r","Y","64" +"MOV r64op, imm64u","MOVQ imm64u, r64op","movq imm64u, r64op","REX.W B8+ro io","N.S.","V","","","w,r","Y","64" +"MOVQ mm2/m64, mm1","MOVQ mm1, mm2/m64","movq mm1, mm2/m64","0F 7F /r","V","V","MMX","","w,r","","" +"MOVQ r/m64, mm1","MOVQ mm1, r/m64","movq mm1, r/m64","REX.W 0F 7E /r","N.S.","V","MMX","","w,r","","" +"MOVQ mm1, mm2/m64","MOVQ mm2/m64, mm1","movq mm2/m64, mm1","0F 6F /r","V","V","MMX","","w,r","","" +"MOV RAX, moffs64","MOVQ moffs64, RAX","movabsq moffs64, RAX","REX.W A1 cm","N.S.","V","","","w,r","Y","64" +"MOVQ mm1, r/m64","MOVQ r/m64, mm1","movq r/m64, mm1","REX.W 0F 6E /r","N.S.","V","MMX","","w,r","","" +"MOV r64, r/m64","MOVQ r/m64, r64","movq r/m64, r64","REX.W 8B /r","N.S.","V","","","w,r","Y","64" +"MOVQ xmm1, r/m64","MOVQ r/m64, xmm1","movq r/m64, xmm1","66 REX.W 0F 6E /r","N.S.","V","SSE2","","w,r","","" +"MOV r/m64, r64","MOVQ r64, r/m64","movq r64, r/m64","REX.W 89 /r","N.S.","V","","","w,r","Y","64" +"MOV CR0-CR7, rmr64","MOVQ rmr64, CR0-CR7","movq rmr64, CR0-CR7","0F 22 /r","N.S.","V","","default64","w,r","Y","64" +"MOV CR8, rmr64","MOVQ rmr64, CR8","movq rmr64, CR8","REX.R + 0F 22 /0","N.E.","V","","modrm_regonly,pseudo","w,r","Y","64" +"MOV DR0-DR7, rmr64","MOVQ rmr64, DR0-DR7","movq rmr64, DR0-DR7","0F 23 /r","N.S.","V","","default64","w,r","Y","64" +"MOVQ r/m64, xmm1","MOVQ xmm1, r/m64","movq xmm1, r/m64","66 REX.W 0F 7E /r","N.S.","V","SSE2","","w,r","","" +"MOVQ xmm2/m64, xmm1","MOVQ xmm1, xmm2/m64","movq xmm1, xmm2/m64","66 0F D6 /r","V","V","SSE2","","w,r","","" +"MOVDQ2Q mm1, xmm2","MOVQ xmm2, mm1","movdq2q xmm2, mm1","F2 0F D6 /r","V","V","SSE2","modrm_regonly","w,r","","" +"MOVQ xmm1, xmm2/m64","MOVQ xmm2/m64, xmm1","movq xmm2/m64, xmm1","F3 0F 7E /r","V","V","SSE2","","w,r","","" +"MOVQ2DQ xmm1, mm2","MOVQOZX mm2, xmm1","movq2dq mm2, xmm1","F3 0F D6 /r","V","V","SSE2","modrm_regonly","w,r","","" +"MOVSB","MOVSB","movsb","A4","V","V","","","","","" +"MOVSD xmm2/m64, xmm1","MOVSD xmm1, xmm2/m64","movsd xmm1, xmm2/m64","F2 0F 11 /r","V","V","SSE2","","w,r","","" +"MOVSD xmm1, xmm2/m64","MOVSD xmm2/m64, xmm1","movsd xmm2/m64, xmm1","F2 0F 10 /r","V","V","SSE2","","w,r","","" +"MOVSHDUP xmm1, xmm2/m128","MOVSHDUP xmm2/m128, xmm1","movshdup xmm2/m128, xmm1","F3 0F 16 /r","V","V","SSE3","","w,r","","" +"MOVSD","MOVSL","movsl","A5","V","V","","operand32","","","" +"MOVSLDUP xmm1, xmm2/m128","MOVSLDUP xmm2/m128, xmm1","movsldup xmm2/m128, xmm1","F3 0F 12 /r","V","V","SSE3","","w,r","","" +"MOVSQ","MOVSQ","movsq","REX.W A5","N.S.","V","","","","","" +"MOVSS xmm2/m32, xmm1","MOVSS xmm1, xmm2/m32","movss xmm1, xmm2/m32","F3 0F 11 /r","V","V","SSE","","w,r","","" +"MOVSS xmm1, xmm2/m32","MOVSS xmm2/m32, xmm1","movss xmm2/m32, xmm1","F3 0F 10 /r","V","V","SSE","","w,r","","" +"MOVSW","MOVSW","movsw","A5","V","V","","operand16","","","" +"MOVSX r16, r/m16","MOVSWW r/m16, r16","movsww r/m16, r16","0F BF /r","V","V","","operand16","w,r","Y","16" +"MOVUPD xmm2/m128, xmm1","MOVUPD xmm1, xmm2/m128","movupd xmm1, xmm2/m128","66 0F 11 /r","V","V","SSE2","","w,r","","" +"MOVUPD xmm1, xmm2/m128","MOVUPD xmm2/m128, xmm1","movupd xmm2/m128, xmm1","66 0F 10 /r","V","V","SSE2","","w,r","","" +"MOVUPS xmm2/m128, xmm1","MOVUPS xmm1, xmm2/m128","movups xmm1, xmm2/m128","0F 11 /r","V","V","SSE","","w,r","","" +"MOVUPS xmm1, xmm2/m128","MOVUPS xmm2/m128, xmm1","movups xmm2/m128, xmm1","0F 10 /r","V","V","SSE","","w,r","","" +"MOV moffs16, AX","MOVW AX, moffs16","movw AX, moffs16","A3 cm","V","V","","operand16","w,r","Y","16" +"MOV r/m16, Sreg","MOVW Sreg, r/m16","movw Sreg, r/m16","8C /r","V","V","","operand16","w,r","Y","16" +"MOV r/m16, imm16","MOVW imm16, r/m16","movw imm16, r/m16","C7 /0 iw","V","V","","operand16","w,r","Y","16" +"MOV r16op, imm16u","MOVW imm16u, r16op","movw imm16u, r16op","B8+rw iw","V","V","","operand16","w,r","Y","16" +"MOV AX, moffs16","MOVW moffs16, AX","movw moffs16, AX","A1 cm","V","V","","operand16","w,r","Y","16" +"MOV Sreg, r/m16","MOVW r/m16, Sreg","movw r/m16, Sreg","8E /r","V","V","","","w,r","Y","16" +"MOV r16, r/m16","MOVW r/m16, r16","movw r/m16, r16","8B /r","V","V","","operand16","w,r","Y","16" +"MOV r/m16, r16","MOVW r16, r/m16","movw r16, r/m16","89 /r","V","V","","operand16","w,r","Y","16" +"MOVSX r32, r/m16","MOVWLSX r/m16, r32","movswl r/m16, r32","0F BF /r","V","V","","operand32","w,r","Y","32" +"MOVZX r32, r/m16","MOVWLZX r/m16, r32","movzwl r/m16, r32","0F B7 /r","V","V","","operand32","w,r","Y","32" +"MOVSX r64, r/m16","MOVWQSX r/m16, r64","movswq r/m16, r64","REX.W 0F BF /r","N.S.","V","","","w,r","Y","64" +"MOVSXD r16, r/m32","MOVWQSX r/m32, r16","movsxdw r/m32, r16","63 /r","N.S.","V","","operand16","w,r","Y","16" +"MOVZX r64, r/m16","MOVWQZX r/m16, r64","movzwq r/m16, r64","REX.W 0F B7 /r","N.S.","V","","","w,r","Y","64" +"MOVZX r16, r/m16","MOVZWW r/m16, r16","movzww r/m16, r16","0F B7 /r","V","V","","operand16","w,r","Y","16" +"MOV r32/m16, Sreg","MOV{L/W} Sreg, r32/m16","mov{l/w} Sreg, r32/m16","8C /r","V","V","","operand32","w,r","Y","" +"MOV r64/m16, Sreg","MOV{Q/W} Sreg, r64/m16","mov{q/w} Sreg, r64/m16","REX.W 8C /r","N.S.","V","","","w,r","Y","" +"MPSADBW xmm1, xmm2/m128, imm8u","MPSADBW imm8u, xmm2/m128, xmm1","mpsadbw imm8u, xmm2/m128, xmm1","66 0F 3A 42 /r ib","V","V","SSE4_1","","rw,r,r","","" +"MUL r/m8","MULB r/m8","mulb r/m8","F6 /4","V","V","","","r","Y","8" +"MUL r/m8","MULB r/m8","mulb r/m8","REX F6 /4","N.E.","V","","pseudo64","r","Y","8" +"MUL r/m32","MULL r/m32","mull r/m32","F7 /4","V","V","","operand32","r","Y","32" +"MULPD xmm1, xmm2/m128","MULPD xmm2/m128, xmm1","mulpd xmm2/m128, xmm1","66 0F 59 /r","V","V","SSE2","","rw,r","","" +"MULPS xmm1, xmm2/m128","MULPS xmm2/m128, xmm1","mulps xmm2/m128, xmm1","0F 59 /r","V","V","SSE","","rw,r","","" +"MUL r/m64","MULQ r/m64","mulq r/m64","REX.W F7 /4","N.S.","V","","","r","Y","64" +"MULSD xmm1, xmm2/m64","MULSD xmm2/m64, xmm1","mulsd xmm2/m64, xmm1","F2 0F 59 /r","V","V","SSE2","","rw,r","","" +"MULSS xmm1, xmm2/m32","MULSS xmm2/m32, xmm1","mulss xmm2/m32, xmm1","F3 0F 59 /r","V","V","SSE","","rw,r","","" +"MUL r/m16","MULW r/m16","mulw r/m16","F7 /4","V","V","","operand16","r","Y","16" +"MULX r32, r32V, r/m32","MULXL r/m32, r32V, r32","mulxl r/m32, r32V, r32","VEX.NDD.128.F2.0F38.W0 F6 /r","V","V","BMI2","","w,w,r","Y","32" +"MULX r64, r64V, r/m64","MULXQ r/m64, r64V, r64","mulxq r/m64, r64V, r64","VEX.NDD.128.F2.0F38.W1 F6 /r","N.S.","V","BMI2","","w,w,r","Y","64" +"MWAIT","MWAIT","mwait","0F 01 C9","V","V","MONITOR","","","","" +"NEG r/m8","NEGB r/m8","negb r/m8","F6 /3","V","V","","","rw","Y","8" +"NEG r/m8","NEGB r/m8","negb r/m8","REX F6 /3","N.E.","V","","pseudo64","rw","Y","8" +"NEG r/m32","NEGL r/m32","negl r/m32","F7 /3","V","V","","operand32","rw","Y","32" +"NEG r/m64","NEGQ r/m64","negq r/m64","REX.W F7 /3","N.S.","V","","","rw","Y","64" +"NEG r/m16","NEGW r/m16","negw r/m16","F7 /3","V","V","","operand16","rw","Y","16" +"NOP","NOP","nop","90","V","V","","pseudo","","Y","" +"NOP","NOP","nop","90+rd","V","V","","operand32,operand64","","Y","" +"NOP","NOP","nop","90+rw","V","V","","operand16,operand64","","Y","" +"NOP","NOP","nop","F3 90+rd","V","V","","operand32","","Y","" +"NOP","NOP","nop","F3 90+rw","V","V","","operand16","","Y","" +"NOP r/m32","NOPL r/m32","nopl r/m32","0F 18 /4","V","V","","operand32","r","Y","32" +"NOP r/m32","NOPL r/m32","nopl r/m32","0F 18 /5","V","V","","operand32","r","Y","32" +"NOP r/m32","NOPL r/m32","nopl r/m32","0F 18 /6","V","V","","operand32","r","Y","32" +"NOP r/m32","NOPL r/m32","nopl r/m32","0F 18 /7","V","V","","operand32","r","Y","32" +"NOP r/m32, r32","NOPL r32, r/m32","nopl r32, r/m32","0F 19 /r","V","V","","operand32","r,r","Y","32" +"NOP r/m32, r32","NOPL r32, r/m32","nopl r32, r/m32","0F 1A /r","V","V","","operand32","r,r","Y","32" +"NOP r/m32, r32","NOPL r32, r/m32","nopl r32, r/m32","0F 1B /r","V","V","","operand32","r,r","Y","32" +"NOP r/m32, r32","NOPL r32, r/m32","nopl r32, r/m32","0F 1C /r","V","V","","operand32","r,r","Y","32" +"NOP r/m32, r32","NOPL r32, r/m32","nopl r32, r/m32","0F 1D /r","V","V","","operand32","r,r","Y","32" +"NOP r/m32, r32","NOPL r32, r/m32","nopl r32, r/m32","0F 1E /r","V","V","PPRO","operand32","r,r","Y","32" +"NOP r/m32, r32","NOPL r32, r/m32","nopl r32, r/m32","0F 1E /r","V","V","","operand32","r,r","Y","32" +"NOP r/m32, r32","NOPL r32, r/m32","nopl r32, r/m32","0F 1F /r","V","V","","operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","0F 0D /r","V","V","PRFCHW","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","0F 1A /r","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","0F 1B /r","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","66 0F 1E /r","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F2 0F 1E /r","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1B /r","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E /0","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E /1","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E /2","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E /3","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E /4","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E /5","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E /6","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E F8","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E F9","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E FA","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E FB","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E FC","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E FD","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E FE","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32, r32","NOPL r32, rmr32","nopl r32, rmr32","F3 0F 1E FF","V","V","PPRO","modrm_regonly,operand32","r,r","Y","32" +"NOP rmr32","NOPL rmr32","nopl rmr32","0F 18 /0","V","V","","modrm_regonly,operand32","r","Y","32" +"NOP rmr32","NOPL rmr32","nopl rmr32","0F 18 /1","V","V","","modrm_regonly,operand32","r","Y","32" +"NOP rmr32","NOPL rmr32","nopl rmr32","0F 18 /2","V","V","","modrm_regonly,operand32","r","Y","32" +"NOP rmr32","NOPL rmr32","nopl rmr32","0F 18 /3","V","V","","modrm_regonly,operand32","r","Y","32" +"NOP r/m64","NOPQ r/m64","nopq r/m64","REX.W 0F 18 /4","N.S.","V","","","r","Y","64" +"NOP r/m64","NOPQ r/m64","nopq r/m64","REX.W 0F 18 /5","N.S.","V","","","r","Y","64" +"NOP r/m64","NOPQ r/m64","nopq r/m64","REX.W 0F 18 /6","N.S.","V","","","r","Y","64" +"NOP r/m64","NOPQ r/m64","nopq r/m64","REX.W 0F 18 /7","N.S.","V","","","r","Y","64" +"NOP r/m64, r64","NOPQ r64, r/m64","nopq r64, r/m64","REX.W 0F 19 /r","N.S.","V","","","r,r","Y","64" +"NOP r/m64, r64","NOPQ r64, r/m64","nopq r64, r/m64","REX.W 0F 1A /r","N.S.","V","","","r,r","Y","64" +"NOP r/m64, r64","NOPQ r64, r/m64","nopq r64, r/m64","REX.W 0F 1B /r","N.S.","V","","","r,r","Y","64" +"NOP r/m64, r64","NOPQ r64, r/m64","nopq r64, r/m64","REX.W 0F 1C /r","N.S.","V","","","r,r","Y","64" +"NOP r/m64, r64","NOPQ r64, r/m64","nopq r64, r/m64","REX.W 0F 1D /r","N.S.","V","","","r,r","Y","64" +"NOP r/m64, r64","NOPQ r64, r/m64","nopq r64, r/m64","REX.W 0F 1E /r","N.S.","V","","","r,r","Y","64" +"NOP r/m64, r64","NOPQ r64, r/m64","nopq r64, r/m64","REX.W 0F 1E /r","N.S.","V","PPRO","","r,r","Y","64" +"NOP r/m64, r64","NOPQ r64, r/m64","nopq r64, r/m64","REX.W 0F 1F /r","N.S.","V","","","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","66 REX.W 0F 1E /r","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F2 REX.W 0F 1E /r","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1B /r","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E /0","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E /1","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E /2","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E /3","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E /4","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E /5","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E /6","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E F8","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E F9","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E FA","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E FB","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E FC","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E FD","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E FE","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","F3 REX.W 0F 1E FF","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","REX.W 0F 0D /r","N.S.","V","PRFCHW","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","REX.W 0F 1A /r","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64, r64","NOPQ r64, rmr64","nopq r64, rmr64","REX.W 0F 1B /r","N.S.","V","PPRO","modrm_regonly","r,r","Y","64" +"NOP rmr64","NOPQ rmr64","nopq rmr64","REX.W 0F 18 /0","N.S.","V","","modrm_regonly","r","Y","64" +"NOP rmr64","NOPQ rmr64","nopq rmr64","REX.W 0F 18 /1","N.S.","V","","modrm_regonly","r","Y","64" +"NOP rmr64","NOPQ rmr64","nopq rmr64","REX.W 0F 18 /2","N.S.","V","","modrm_regonly","r","Y","64" +"NOP rmr64","NOPQ rmr64","nopq rmr64","REX.W 0F 18 /3","N.S.","V","","modrm_regonly","r","Y","64" +"NOP r/m16","NOPW r/m16","nopw r/m16","0F 18 /4","V","V","","operand16","r","Y","16" +"NOP r/m16","NOPW r/m16","nopw r/m16","0F 18 /5","V","V","","operand16","r","Y","16" +"NOP r/m16","NOPW r/m16","nopw r/m16","0F 18 /6","V","V","","operand16","r","Y","16" +"NOP r/m16","NOPW r/m16","nopw r/m16","0F 18 /7","V","V","","operand16","r","Y","16" +"NOP r/m16, r16","NOPW r16, r/m16","nopw r16, r/m16","0F 19 /r","V","V","","operand16","r,r","Y","16" +"NOP r/m16, r16","NOPW r16, r/m16","nopw r16, r/m16","0F 1A /r","V","V","","operand16","r,r","Y","16" +"NOP r/m16, r16","NOPW r16, r/m16","nopw r16, r/m16","0F 1B /r","V","V","","operand16","r,r","Y","16" +"NOP r/m16, r16","NOPW r16, r/m16","nopw r16, r/m16","0F 1C /r","V","V","","operand16","r,r","Y","16" +"NOP r/m16, r16","NOPW r16, r/m16","nopw r16, r/m16","0F 1D /r","V","V","","operand16","r,r","Y","16" +"NOP r/m16, r16","NOPW r16, r/m16","nopw r16, r/m16","0F 1E /r","V","V","","operand16","r,r","Y","16" +"NOP r/m16, r16","NOPW r16, r/m16","nopw r16, r/m16","0F 1E /r","V","V","PPRO","operand16","r,r","Y","16" +"NOP r/m16, r16","NOPW r16, r/m16","nopw r16, r/m16","0F 1F /r","V","V","","operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","0F 0D /r","V","V","PRFCHW","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","0F 1A /r","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","0F 1B /r","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","66 0F 1E /r","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F2 0F 1E /r","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1B /r","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E /0","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E /1","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E /2","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E /3","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E /4","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E /5","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E /6","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E F8","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E F9","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E FA","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E FB","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E FC","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E FD","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E FE","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16, r16","NOPW r16, rmr16","nopw r16, rmr16","F3 0F 1E FF","V","V","PPRO","modrm_regonly,operand16","r,r","Y","16" +"NOP rmr16","NOPW rmr16","nopw rmr16","0F 18 /0","V","V","","modrm_regonly,operand16","r","Y","16" +"NOP rmr16","NOPW rmr16","nopw rmr16","0F 18 /1","V","V","","modrm_regonly,operand16","r","Y","16" +"NOP rmr16","NOPW rmr16","nopw rmr16","0F 18 /2","V","V","","modrm_regonly,operand16","r","Y","16" +"NOP rmr16","NOPW rmr16","nopw rmr16","0F 18 /3","V","V","","modrm_regonly,operand16","r","Y","16" +"NOT r/m8","NOTB r/m8","notb r/m8","F6 /2","V","V","","","rw","Y","8" +"NOT r/m8","NOTB r/m8","notb r/m8","REX F6 /2","N.E.","V","","pseudo64","rw","Y","8" +"NOT r/m32","NOTL r/m32","notl r/m32","F7 /2","V","V","","operand32","rw","Y","32" +"NOT r/m64","NOTQ r/m64","notq r/m64","REX.W F7 /2","N.S.","V","","","rw","Y","64" +"NOT r/m16","NOTW r/m16","notw r/m16","F7 /2","V","V","","operand16","rw","Y","16" +"OR r/m8, imm8","ORB imm8, r/m8","orb imm8, r/m8","80 /1 ib","V","V","","","rw,r","Y","8" +"OR r/m8, imm8","ORB imm8, r/m8","orb imm8, r/m8","82 /1 ib","V","N.S.","","","rw,r","Y","8" +"OR r/m8, imm8","ORB imm8, r/m8","orb imm8, r/m8","REX 80 /1 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"OR AL, imm8u","ORB imm8u, AL","orb imm8u, AL","0C ib","V","V","","","rw,r","Y","8" +"OR r8, r/m8","ORB r/m8, r8","orb r/m8, r8","0A /r","V","V","","","rw,r","Y","8" +"OR r8, r/m8","ORB r/m8, r8","orb r/m8, r8","REX 0A /r","N.E.","V","","pseudo64","rw,r","Y","8" +"OR r/m8, r8","ORB r8, r/m8","orb r8, r/m8","08 /r","V","V","","","rw,r","Y","8" +"OR r/m8, r8","ORB r8, r/m8","orb r8, r/m8","REX 08 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"OR EAX, imm32","ORL imm32, EAX","orl imm32, EAX","0D id","V","V","","operand32","rw,r","Y","32" +"OR r/m32, imm32","ORL imm32, r/m32","orl imm32, r/m32","81 /1 id","V","V","","operand32","rw,r","Y","32" +"OR r/m32, imm8","ORL imm8, r/m32","orl imm8, r/m32","83 /1 ib","V","V","","operand32","rw,r","Y","32" +"OR r32, r/m32","ORL r/m32, r32","orl r/m32, r32","0B /r","V","V","","operand32","rw,r","Y","32" +"OR r/m32, r32","ORL r32, r/m32","orl r32, r/m32","09 /r","V","V","","operand32","rw,r","Y","32" +"ORPD xmm1, xmm2/m128","ORPD xmm2/m128, xmm1","orpd xmm2/m128, xmm1","66 0F 56 /r","V","V","SSE2","","rw,r","","" +"ORPS xmm1, xmm2/m128","ORPS xmm2/m128, xmm1","orps xmm2/m128, xmm1","0F 56 /r","V","V","SSE","","rw,r","","" +"OR RAX, imm32","ORQ imm32, RAX","orq imm32, RAX","REX.W 0D id","N.S.","V","","","rw,r","Y","64" +"OR r/m64, imm32","ORQ imm32, r/m64","orq imm32, r/m64","REX.W 81 /1 id","N.S.","V","","","rw,r","Y","64" +"OR r/m64, imm8","ORQ imm8, r/m64","orq imm8, r/m64","REX.W 83 /1 ib","N.S.","V","","","rw,r","Y","64" +"OR r64, r/m64","ORQ r/m64, r64","orq r/m64, r64","REX.W 0B /r","N.S.","V","","","rw,r","Y","64" +"OR r/m64, r64","ORQ r64, r/m64","orq r64, r/m64","REX.W 09 /r","N.S.","V","","","rw,r","Y","64" +"OR AX, imm16","ORW imm16, AX","orw imm16, AX","0D iw","V","V","","operand16","rw,r","Y","16" +"OR r/m16, imm16","ORW imm16, r/m16","orw imm16, r/m16","81 /1 iw","V","V","","operand16","rw,r","Y","16" +"OR r/m16, imm8","ORW imm8, r/m16","orw imm8, r/m16","83 /1 ib","V","V","","operand16","rw,r","Y","16" +"OR r16, r/m16","ORW r/m16, r16","orw r/m16, r16","0B /r","V","V","","operand16","rw,r","Y","16" +"OR r/m16, r16","ORW r16, r/m16","orw r16, r/m16","09 /r","V","V","","operand16","rw,r","Y","16" +"OUT DX, AL","OUTB AL, DX","outb AL, DX","EE","V","V","","","r,r","Y","8" +"OUT imm8u, AL","OUTB AL, imm8u","outb AL, imm8u","E6 ib","V","V","","","r,r","Y","8" +"OUT DX, EAX","OUTL EAX, DX","outl EAX, DX","EF","V","V","","operand32,operand64","r,r","Y","32" +"OUT imm8u, EAX","OUTL EAX, imm8u","outl EAX, imm8u","E7 ib","V","V","","operand32,operand64","r,r","Y","32" +"OUTSB","OUTSB","outsb","6E","V","V","","","","","" +"OUTSD","OUTSL","outsl","6F","V","V","","operand32,operand64","","","" +"OUTSW","OUTSW","outsw","6F","V","V","","operand16","","","" +"OUT DX, AX","OUTW AX, DX","outw AX, DX","EF","V","V","","operand16","r,r","Y","16" +"OUT imm8u, AX","OUTW AX, imm8u","outw AX, imm8u","E7 ib","V","V","","operand16","r,r","Y","16" +"PABSB mm1, mm2/m64","PABSB mm2/m64, mm1","pabsb mm2/m64, mm1","0F 38 1C /r","V","V","SSSE3","","w,r","","" +"PABSB xmm1, xmm2/m128","PABSB xmm2/m128, xmm1","pabsb xmm2/m128, xmm1","66 0F 38 1C /r","V","V","SSSE3","","w,r","","" +"PABSD mm1, mm2/m64","PABSD mm2/m64, mm1","pabsd mm2/m64, mm1","0F 38 1E /r","V","V","SSSE3","","w,r","","" +"PABSD xmm1, xmm2/m128","PABSD xmm2/m128, xmm1","pabsd xmm2/m128, xmm1","66 0F 38 1E /r","V","V","SSSE3","","w,r","","" +"PABSW mm1, mm2/m64","PABSW mm2/m64, mm1","pabsw mm2/m64, mm1","0F 38 1D /r","V","V","SSSE3","","w,r","","" +"PABSW xmm1, xmm2/m128","PABSW xmm2/m128, xmm1","pabsw xmm2/m128, xmm1","66 0F 38 1D /r","V","V","SSSE3","","w,r","","" +"PACKSSDW mm1, mm2/m64","PACKSSLW mm2/m64, mm1","packssdw mm2/m64, mm1","0F 6B /r","V","V","MMX","","rw,r","","" +"PACKSSDW xmm1, xmm2/m128","PACKSSLW xmm2/m128, xmm1","packssdw xmm2/m128, xmm1","66 0F 6B /r","V","V","SSE2","","rw,r","","" +"PACKSSWB mm1, mm2/m64","PACKSSWB mm2/m64, mm1","packsswb mm2/m64, mm1","0F 63 /r","V","V","MMX","","rw,r","","" +"PACKSSWB xmm1, xmm2/m128","PACKSSWB xmm2/m128, xmm1","packsswb xmm2/m128, xmm1","66 0F 63 /r","V","V","SSE2","","rw,r","","" +"PACKUSDW xmm1, xmm2/m128","PACKUSDW xmm2/m128, xmm1","packusdw xmm2/m128, xmm1","66 0F 38 2B /r","V","V","SSE4_1","","rw,r","","" +"PACKUSWB mm1, mm2/m64","PACKUSWB mm2/m64, mm1","packuswb mm2/m64, mm1","0F 67 /r","V","V","MMX","","rw,r","","" +"PACKUSWB xmm1, xmm2/m128","PACKUSWB xmm2/m128, xmm1","packuswb xmm2/m128, xmm1","66 0F 67 /r","V","V","SSE2","","rw,r","","" +"PADDB mm1, mm2/m64","PADDB mm2/m64, mm1","paddb mm2/m64, mm1","0F FC /r","V","V","MMX","","rw,r","","" +"PADDB xmm1, xmm2/m128","PADDB xmm2/m128, xmm1","paddb xmm2/m128, xmm1","66 0F FC /r","V","V","SSE2","","rw,r","","" +"PADDD mm1, mm2/m64","PADDL mm2/m64, mm1","paddd mm2/m64, mm1","0F FE /r","V","V","MMX","","rw,r","","" +"PADDD xmm1, xmm2/m128","PADDL xmm2/m128, xmm1","paddd xmm2/m128, xmm1","66 0F FE /r","V","V","SSE2","","rw,r","","" +"PADDQ mm1, mm2/m64","PADDQ mm2/m64, mm1","paddq mm2/m64, mm1","0F D4 /r","V","V","SSE2","","rw,r","","" +"PADDQ xmm1, xmm2/m128","PADDQ xmm2/m128, xmm1","paddq xmm2/m128, xmm1","66 0F D4 /r","V","V","SSE2","","rw,r","","" +"PADDSB mm1, mm2/m64","PADDSB mm2/m64, mm1","paddsb mm2/m64, mm1","0F EC /r","V","V","MMX","","rw,r","","" +"PADDSB xmm1, xmm2/m128","PADDSB xmm2/m128, xmm1","paddsb xmm2/m128, xmm1","66 0F EC /r","V","V","SSE2","","rw,r","","" +"PADDSW mm1, mm2/m64","PADDSW mm2/m64, mm1","paddsw mm2/m64, mm1","0F ED /r","V","V","MMX","","rw,r","","" +"PADDSW xmm1, xmm2/m128","PADDSW xmm2/m128, xmm1","paddsw xmm2/m128, xmm1","66 0F ED /r","V","V","SSE2","","rw,r","","" +"PADDUSB mm1, mm2/m64","PADDUSB mm2/m64, mm1","paddusb mm2/m64, mm1","0F DC /r","V","V","MMX","","rw,r","","" +"PADDUSB xmm1, xmm2/m128","PADDUSB xmm2/m128, xmm1","paddusb xmm2/m128, xmm1","66 0F DC /r","V","V","SSE2","","rw,r","","" +"PADDUSW mm1, mm2/m64","PADDUSW mm2/m64, mm1","paddusw mm2/m64, mm1","0F DD /r","V","V","MMX","","rw,r","","" +"PADDUSW xmm1, xmm2/m128","PADDUSW xmm2/m128, xmm1","paddusw xmm2/m128, xmm1","66 0F DD /r","V","V","SSE2","","rw,r","","" +"PADDW mm1, mm2/m64","PADDW mm2/m64, mm1","paddw mm2/m64, mm1","0F FD /r","V","V","MMX","","rw,r","","" +"PADDW xmm1, xmm2/m128","PADDW xmm2/m128, xmm1","paddw xmm2/m128, xmm1","66 0F FD /r","V","V","SSE2","","rw,r","","" +"PALIGNR mm1, mm2/m64, imm8u","PALIGNR imm8u, mm2/m64, mm1","palignr imm8u, mm2/m64, mm1","0F 3A 0F /r ib","V","V","SSSE3","","rw,r,r","","" +"PALIGNR xmm1, xmm2/m128, imm8u","PALIGNR imm8u, xmm2/m128, xmm1","palignr imm8u, xmm2/m128, xmm1","66 0F 3A 0F /r ib","V","V","SSSE3","","rw,r,r","","" +"PAND mm1, mm2/m64","PAND mm2/m64, mm1","pand mm2/m64, mm1","0F DB /r","V","V","MMX","","rw,r","","" +"PAND xmm1, xmm2/m128","PAND xmm2/m128, xmm1","pand xmm2/m128, xmm1","66 0F DB /r","V","V","SSE2","","rw,r","","" +"PANDN mm1, mm2/m64","PANDN mm2/m64, mm1","pandn mm2/m64, mm1","0F DF /r","V","V","MMX","","rw,r","","" +"PANDN xmm1, xmm2/m128","PANDN xmm2/m128, xmm1","pandn xmm2/m128, xmm1","66 0F DF /r","V","V","SSE2","","rw,r","","" +"PAUSE","PAUSE","pause","F3 90","V","V","","pseudo","","","" +"PAUSE","PAUSE","pause","F3 90+rd","V","V","","operand32","","Y","" +"PAUSE","PAUSE","pause","F3 90+rw","V","V","","operand16,operand64","","Y","" +"PAVGB mm1, mm2/m64","PAVGB mm2/m64, mm1","pavgb mm2/m64, mm1","0F E0 /r","V","V","MMX","","rw,r","","" +"PAVGB xmm1, xmm2/m128","PAVGB xmm2/m128, xmm1","pavgb xmm2/m128, xmm1","66 0F E0 /r","V","V","SSE2","","rw,r","","" +"PAVGUSB mm1, mm2/m64","PAVGUSB mm2/m64, mm1","pavgusb mm2/m64, mm1","0F 0F BF /r","V","V","3DNOW","amd","rw,r","","" +"PAVGW mm1, mm2/m64","PAVGW mm2/m64, mm1","pavgw mm2/m64, mm1","0F E3 /r","V","V","MMX","","rw,r","","" +"PAVGW xmm1, xmm2/m128","PAVGW xmm2/m128, xmm1","pavgw xmm2/m128, xmm1","66 0F E3 /r","V","V","SSE2","","rw,r","","" +"PBLENDVB xmm1, xmm2/m128, ","PBLENDVB , xmm2/m128, xmm1","pblendvb , xmm2/m128, xmm1","66 0F 38 10 /r","V","V","SSE4_1","","rw,r,r","","" +"PBLENDW xmm1, xmm2/m128, imm8u","PBLENDW imm8u, xmm2/m128, xmm1","pblendw imm8u, xmm2/m128, xmm1","66 0F 3A 0E /r ib","V","V","SSE4_1","","rw,r,r","","" +"PCLMULQDQ xmm1, xmm2/m128, imm8u","PCLMULQDQ imm8u, xmm2/m128, xmm1","pclmulqdq imm8u, xmm2/m128, xmm1","66 0F 3A 44 /r ib","V","V","PCLMULQDQ","","rw,r,r","","" +"PCMPEQB mm1, mm2/m64","PCMPEQB mm2/m64, mm1","pcmpeqb mm2/m64, mm1","0F 74 /r","V","V","MMX","","rw,r","","" +"PCMPEQB xmm1, xmm2/m128","PCMPEQB xmm2/m128, xmm1","pcmpeqb xmm2/m128, xmm1","66 0F 74 /r","V","V","SSE2","","rw,r","","" +"PCMPEQD mm1, mm2/m64","PCMPEQL mm2/m64, mm1","pcmpeqd mm2/m64, mm1","0F 76 /r","V","V","MMX","","rw,r","","" +"PCMPEQD xmm1, xmm2/m128","PCMPEQL xmm2/m128, xmm1","pcmpeqd xmm2/m128, xmm1","66 0F 76 /r","V","V","SSE2","","rw,r","","" +"PCMPEQQ xmm1, xmm2/m128","PCMPEQQ xmm2/m128, xmm1","pcmpeqq xmm2/m128, xmm1","66 0F 38 29 /r","V","V","SSE4_1","","rw,r","","" +"PCMPEQW mm1, mm2/m64","PCMPEQW mm2/m64, mm1","pcmpeqw mm2/m64, mm1","0F 75 /r","V","V","MMX","","rw,r","","" +"PCMPEQW xmm1, xmm2/m128","PCMPEQW xmm2/m128, xmm1","pcmpeqw xmm2/m128, xmm1","66 0F 75 /r","V","V","SSE2","","rw,r","","" +"PCMPESTRI xmm1, xmm2/m128, imm8u","PCMPESTRI imm8u, xmm2/m128, xmm1","pcmpestri imm8u, xmm2/m128, xmm1","66 0F 3A 61 /r ib","V","V","SSE4_2","","r,r,r","","" +"PCMPESTRM xmm1, xmm2/m128, imm8u","PCMPESTRM imm8u, xmm2/m128, xmm1","pcmpestrm imm8u, xmm2/m128, xmm1","66 0F 3A 60 /r ib","V","V","SSE4_2","","r,r,r","","" +"PCMPGTB mm1, mm2/m64","PCMPGTB mm2/m64, mm1","pcmpgtb mm2/m64, mm1","0F 64 /r","V","V","MMX","","rw,r","","" +"PCMPGTB xmm1, xmm2/m128","PCMPGTB xmm2/m128, xmm1","pcmpgtb xmm2/m128, xmm1","66 0F 64 /r","V","V","SSE2","","rw,r","","" +"PCMPGTD mm1, mm2/m64","PCMPGTL mm2/m64, mm1","pcmpgtd mm2/m64, mm1","0F 66 /r","V","V","MMX","","rw,r","","" +"PCMPGTD xmm1, xmm2/m128","PCMPGTL xmm2/m128, xmm1","pcmpgtd xmm2/m128, xmm1","66 0F 66 /r","V","V","SSE2","","rw,r","","" +"PCMPGTQ xmm1, xmm2/m128","PCMPGTQ xmm2/m128, xmm1","pcmpgtq xmm2/m128, xmm1","66 0F 38 37 /r","V","V","SSE4_2","","rw,r","","" +"PCMPGTW mm1, mm2/m64","PCMPGTW mm2/m64, mm1","pcmpgtw mm2/m64, mm1","0F 65 /r","V","V","MMX","","rw,r","","" +"PCMPGTW xmm1, xmm2/m128","PCMPGTW xmm2/m128, xmm1","pcmpgtw xmm2/m128, xmm1","66 0F 65 /r","V","V","SSE2","","rw,r","","" +"PCMPISTRI xmm1, xmm2/m128, imm8u","PCMPISTRI imm8u, xmm2/m128, xmm1","pcmpistri imm8u, xmm2/m128, xmm1","66 0F 3A 63 /r ib","V","V","SSE4_2","","r,r,r","","" +"PCMPISTRM xmm1, xmm2/m128, imm8u","PCMPISTRM imm8u, xmm2/m128, xmm1","pcmpistrm imm8u, xmm2/m128, xmm1","66 0F 3A 62 /r ib","V","V","SSE4_2","","r,r,r","","" +"PDEP r32, r32V, r/m32","PDEPL r/m32, r32V, r32","pdepl r/m32, r32V, r32","VEX.DDS.128.F2.0F38.W0 F5 /r","V","V","BMI2","","rw,r,r","Y","32" +"PDEP r64, r64V, r/m64","PDEPQ r/m64, r64V, r64","pdepq r/m64, r64V, r64","VEX.DDS.128.F2.0F38.W1 F5 /r","N.S.","V","BMI2","","rw,r,r","Y","64" +"PEXT r32, r32V, r/m32","PEXTL r/m32, r32V, r32","pextl r/m32, r32V, r32","VEX.DDS.128.F3.0F38.W0 F5 /r","V","V","BMI2","","rw,r,r","Y","32" +"PEXT r64, r64V, r/m64","PEXTQ r/m64, r64V, r64","pextq r/m64, r64V, r64","VEX.DDS.128.F3.0F38.W1 F5 /r","N.S.","V","BMI2","","rw,r,r","Y","64" +"PEXTRB r32/m8, xmm1, imm8u","PEXTRB imm8u, xmm1, r32/m8","pextrb imm8u, xmm1, r32/m8","66 0F 3A 14 /r ib","V","V","SSE4_1","","w,r,r","","" +"PEXTRD r/m32, xmm1, imm8u","PEXTRD imm8u, xmm1, r/m32","pextrd imm8u, xmm1, r/m32","66 0F 3A 16 /r ib","V","V","SSE4_1","operand16,operand32","w,r,r","","" +"PEXTRQ r/m64, xmm1, imm8u","PEXTRQ imm8u, xmm1, r/m64","pextrq imm8u, xmm1, r/m64","66 REX.W 0F 3A 16 /r ib","N.S.","V","SSE4_1","","w,r,r","","" +"PEXTRW r32, mm2, imm8u","PEXTRW imm8u, mm2, r32","pextrw imm8u, mm2, r32","0F C5 /r ib","V","V","MMX","modrm_regonly","w,r,r","","" +"PEXTRW r32/m16, xmm1, imm8u","PEXTRW imm8u, xmm1, r32/m16","pextrw imm8u, xmm1, r32/m16","66 0F 3A 15 /r ib","V","V","SSE4_1","","w,r,r","","" +"PEXTRW r32, xmm2, imm8u","PEXTRW imm8u, xmm2, r32","pextrw imm8u, xmm2, r32","66 0F C5 /r ib","V","V","SSE2","modrm_regonly","w,r,r","","" +"PF2ID mm1, mm2/m64","PF2ID mm2/m64, mm1","pf2id mm2/m64, mm1","0F 0F 1D /r","V","V","3DNOW","amd","rw,r","","" +"PF2IW mm1, mm2/m64","PF2IW mm2/m64, mm1","pf2iw mm2/m64, mm1","0F 0F 1C /r","V","V","3DNOW","amd","rw,r","","" +"PFACC mm1, mm2/m64","PFACC mm2/m64, mm1","pfacc mm2/m64, mm1","0F 0F AE /r","V","V","3DNOW","amd","rw,r","","" +"PFADD mm1, mm2/m64","PFADD mm2/m64, mm1","pfadd mm2/m64, mm1","0F 0F 9E /r","V","V","3DNOW","amd","rw,r","","" +"PFCMPEQ mm1, mm2/m64","PFCMPEQ mm2/m64, mm1","pfcmpeq mm2/m64, mm1","0F 0F B0 /r","V","V","3DNOW","amd","rw,r","","" +"PFCMPGE mm1, mm2/m64","PFCMPGE mm2/m64, mm1","pfcmpge mm2/m64, mm1","0F 0F 90 /r","V","V","3DNOW","amd","rw,r","","" +"PFCMPGT mm1, mm2/m64","PFCMPGT mm2/m64, mm1","pfcmpgt mm2/m64, mm1","0F 0F A0 /r","V","V","3DNOW","amd","rw,r","","" +"PFCPIT1 mm1, mm2/m64","PFCPIT1 mm2/m64, mm1","pfcpit1 mm2/m64, mm1","0F 0F A6 /r","V","V","3DNOW","amd","rw,r","","" +"PFMAX mm1, mm2/m64","PFMAX mm2/m64, mm1","pfmax mm2/m64, mm1","0F 0F A4 /r","V","V","3DNOW","amd","rw,r","","" +"PFMIN mm1, mm2/m64","PFMIN mm2/m64, mm1","pfmin mm2/m64, mm1","0F 0F 94 /r","V","V","3DNOW","amd","rw,r","","" +"PFMUL mm1, mm2/m64","PFMUL mm2/m64, mm1","pfmul mm2/m64, mm1","0F 0F B4 /r","V","V","3DNOW","amd","rw,r","","" +"PFNACC mm1, mm2/m64","PFNACC mm2/m64, mm1","pfnacc mm2/m64, mm1","0F 0F 8A /r","V","V","3DNOW","amd","rw,r","","" +"PFPNACC mm1, mm2/m64","PFPNACC mm2/m64, mm1","pfpnacc mm2/m64, mm1","0F 0F 8E /r","V","V","3DNOW","amd","rw,r","","" +"PFRCP mm1, mm2/m64","PFRCP mm2/m64, mm1","pfrcp mm2/m64, mm1","0F 0F 96 /r","V","V","3DNOW","amd","rw,r","","" +"PFRCPIT2 mm1, mm2/m64","PFRCPIT2 mm2/m64, mm1","pfrcpit2 mm2/m64, mm1","0F 0F B6 /r","V","V","3DNOW","amd","rw,r","","" +"PFRSQIT1 mm1, mm2/m64","PFRSQIT1 mm2/m64, mm1","pfrsqit1 mm2/m64, mm1","0F 0F A7 /r","V","V","3DNOW","amd","rw,r","","" +"PFSQRT mm1, mm2/m64","PFSQRT mm2/m64, mm1","pfsqrt mm2/m64, mm1","0F 0F 97 /r","V","V","3DNOW","amd","rw,r","","" +"PFSUB mm1, mm2/m64","PFSUB mm2/m64, mm1","pfsub mm2/m64, mm1","0F 0F 9A /r","V","V","3DNOW","amd","rw,r","","" +"PFSUBR mm1, mm2/m64","PFSUBR mm2/m64, mm1","pfsubr mm2/m64, mm1","0F 0F AA /r","V","V","3DNOW","amd","rw,r","","" +"PHADDD mm1, mm2/m64","PHADDD mm2/m64, mm1","phaddd mm2/m64, mm1","0F 38 02 /r","V","V","SSSE3","","rw,r","","" +"PHADDD xmm1, xmm2/m128","PHADDD xmm2/m128, xmm1","phaddd xmm2/m128, xmm1","66 0F 38 02 /r","V","V","SSSE3","","rw,r","","" +"PHADDSW mm1, mm2/m64","PHADDSW mm2/m64, mm1","phaddsw mm2/m64, mm1","0F 38 03 /r","V","V","SSSE3","","rw,r","","" +"PHADDSW xmm1, xmm2/m128","PHADDSW xmm2/m128, xmm1","phaddsw xmm2/m128, xmm1","66 0F 38 03 /r","V","V","SSSE3","","rw,r","","" +"PHADDW mm1, mm2/m64","PHADDW mm2/m64, mm1","phaddw mm2/m64, mm1","0F 38 01 /r","V","V","SSSE3","","rw,r","","" +"PHADDW xmm1, xmm2/m128","PHADDW xmm2/m128, xmm1","phaddw xmm2/m128, xmm1","66 0F 38 01 /r","V","V","SSSE3","","rw,r","","" +"PHMINPOSUW xmm1, xmm2/m128","PHMINPOSUW xmm2/m128, xmm1","phminposuw xmm2/m128, xmm1","66 0F 38 41 /r","V","V","SSE4_1","","w,r","","" +"PHSUBD mm1, mm2/m64","PHSUBD mm2/m64, mm1","phsubd mm2/m64, mm1","0F 38 06 /r","V","V","SSSE3","","rw,r","","" +"PHSUBD xmm1, xmm2/m128","PHSUBD xmm2/m128, xmm1","phsubd xmm2/m128, xmm1","66 0F 38 06 /r","V","V","SSSE3","","rw,r","","" +"PHSUBSW mm1, mm2/m64","PHSUBSW mm2/m64, mm1","phsubsw mm2/m64, mm1","0F 38 07 /r","V","V","SSSE3","","rw,r","","" +"PHSUBSW xmm1, xmm2/m128","PHSUBSW xmm2/m128, xmm1","phsubsw xmm2/m128, xmm1","66 0F 38 07 /r","V","V","SSSE3","","rw,r","","" +"PHSUBW mm1, mm2/m64","PHSUBW mm2/m64, mm1","phsubw mm2/m64, mm1","0F 38 05 /r","V","V","SSSE3","","rw,r","","" +"PHSUBW xmm1, xmm2/m128","PHSUBW xmm2/m128, xmm1","phsubw xmm2/m128, xmm1","66 0F 38 05 /r","V","V","SSSE3","","rw,r","","" +"PI2FD mm1, mm2/m64","PI2FD mm2/m64, mm1","pi2fd mm2/m64, mm1","0F 0F 0D /r","V","V","3DNOW","amd","rw,r","","" +"PI2FW mm1, mm2/m64","PI2FW mm2/m64, mm1","pi2fw mm2/m64, mm1","0F 0F 0C /r","V","V","3DNOW","amd","rw,r","","" +"PINSRB xmm1, r32/m8, imm8u","PINSRB imm8u, r32/m8, xmm1","pinsrb imm8u, r32/m8, xmm1","66 0F 3A 20 /r ib","V","V","SSE4_1","","rw,r,r","","" +"PINSRD xmm1, r/m32, imm8u","PINSRD imm8u, r/m32, xmm1","pinsrd imm8u, r/m32, xmm1","66 0F 3A 22 /r ib","V","V","SSE4_1","operand16,operand32","rw,r,r","","" +"PINSRQ xmm1, r/m64, imm8u","PINSRQ imm8u, r/m64, xmm1","pinsrq imm8u, r/m64, xmm1","66 REX.W 0F 3A 22 /r ib","N.S.","V","SSE4_1","","rw,r,r","","" +"PINSRW mm1, r32/m16, imm8u","PINSRW imm8u, r32/m16, mm1","pinsrw imm8u, r32/m16, mm1","0F C4 /r ib","V","V","MMX","","rw,r,r","","" +"PINSRW xmm1, r32/m16, imm8u","PINSRW imm8u, r32/m16, xmm1","pinsrw imm8u, r32/m16, xmm1","66 0F C4 /r ib","V","V","SSE2","","rw,r,r","","" +"PMADDUBSW mm1, mm2/m64","PMADDUBSW mm2/m64, mm1","pmaddubsw mm2/m64, mm1","0F 38 04 /r","V","V","SSSE3","","rw,r","","" +"PMADDUBSW xmm1, xmm2/m128","PMADDUBSW xmm2/m128, xmm1","pmaddubsw xmm2/m128, xmm1","66 0F 38 04 /r","V","V","SSSE3","","rw,r","","" +"PMADDWD mm1, mm2/m64","PMADDWL mm2/m64, mm1","pmaddwd mm2/m64, mm1","0F F5 /r","V","V","MMX","","rw,r","","" +"PMADDWD xmm1, xmm2/m128","PMADDWL xmm2/m128, xmm1","pmaddwd xmm2/m128, xmm1","66 0F F5 /r","V","V","SSE2","","rw,r","","" +"PMAXSB xmm1, xmm2/m128","PMAXSB xmm2/m128, xmm1","pmaxsb xmm2/m128, xmm1","66 0F 38 3C /r","V","V","SSE4_1","","rw,r","","" +"PMAXSD xmm1, xmm2/m128","PMAXSD xmm2/m128, xmm1","pmaxsd xmm2/m128, xmm1","66 0F 38 3D /r","V","V","SSE4_1","","rw,r","","" +"PMAXSW mm1, mm2/m64","PMAXSW mm2/m64, mm1","pmaxsw mm2/m64, mm1","0F EE /r","V","V","MMX","","rw,r","","" +"PMAXSW xmm1, xmm2/m128","PMAXSW xmm2/m128, xmm1","pmaxsw xmm2/m128, xmm1","66 0F EE /r","V","V","SSE2","","rw,r","","" +"PMAXUB mm1, mm2/m64","PMAXUB mm2/m64, mm1","pmaxub mm2/m64, mm1","0F DE /r","V","V","MMX","","rw,r","","" +"PMAXUB xmm1, xmm2/m128","PMAXUB xmm2/m128, xmm1","pmaxub xmm2/m128, xmm1","66 0F DE /r","V","V","SSE2","","rw,r","","" +"PMAXUD xmm1, xmm2/m128","PMAXUD xmm2/m128, xmm1","pmaxud xmm2/m128, xmm1","66 0F 38 3F /r","V","V","SSE4_1","","rw,r","","" +"PMAXUW xmm1, xmm2/m128","PMAXUW xmm2/m128, xmm1","pmaxuw xmm2/m128, xmm1","66 0F 38 3E /r","V","V","SSE4_1","","rw,r","","" +"PMINSB xmm1, xmm2/m128","PMINSB xmm2/m128, xmm1","pminsb xmm2/m128, xmm1","66 0F 38 38 /r","V","V","SSE4_1","","rw,r","","" +"PMINSD xmm1, xmm2/m128","PMINSD xmm2/m128, xmm1","pminsd xmm2/m128, xmm1","66 0F 38 39 /r","V","V","SSE4_1","","rw,r","","" +"PMINSW mm1, mm2/m64","PMINSW mm2/m64, mm1","pminsw mm2/m64, mm1","0F EA /r","V","V","MMX","","rw,r","","" +"PMINSW xmm1, xmm2/m128","PMINSW xmm2/m128, xmm1","pminsw xmm2/m128, xmm1","66 0F EA /r","V","V","SSE2","","rw,r","","" +"PMINUB mm1, mm2/m64","PMINUB mm2/m64, mm1","pminub mm2/m64, mm1","0F DA /r","V","V","MMX","","rw,r","","" +"PMINUB xmm1, xmm2/m128","PMINUB xmm2/m128, xmm1","pminub xmm2/m128, xmm1","66 0F DA /r","V","V","SSE2","","rw,r","","" +"PMINUD xmm1, xmm2/m128","PMINUD xmm2/m128, xmm1","pminud xmm2/m128, xmm1","66 0F 38 3B /r","V","V","SSE4_1","","rw,r","","" +"PMINUW xmm1, xmm2/m128","PMINUW xmm2/m128, xmm1","pminuw xmm2/m128, xmm1","66 0F 38 3A /r","V","V","SSE4_1","","rw,r","","" +"PMOVMSKB r32, mm2","PMOVMSKB mm2, r32","pmovmskb mm2, r32","0F D7 /r","V","V","SSE","modrm_regonly","w,r","","" +"PMOVMSKB r32, xmm2","PMOVMSKB xmm2, r32","pmovmskb xmm2, r32","66 0F D7 /r","V","V","SSE2","modrm_regonly","w,r","","" +"PMOVSXBD xmm1, xmm2/m32","PMOVSXBD xmm2/m32, xmm1","pmovsxbd xmm2/m32, xmm1","66 0F 38 21 /r","V","V","SSE4_1","","w,r","","" +"PMOVSXBQ xmm1, xmm2/m16","PMOVSXBQ xmm2/m16, xmm1","pmovsxbq xmm2/m16, xmm1","66 0F 38 22 /r","V","V","SSE4_1","","w,r","","" +"PMOVSXBW xmm1, xmm2/m64","PMOVSXBW xmm2/m64, xmm1","pmovsxbw xmm2/m64, xmm1","66 0F 38 20 /r","V","V","SSE4_1","","w,r","","" +"PMOVSXDQ xmm1, xmm2/m64","PMOVSXDQ xmm2/m64, xmm1","pmovsxdq xmm2/m64, xmm1","66 0F 38 25 /r","V","V","SSE4_1","","w,r","","" +"PMOVSXWD xmm1, xmm2/m64","PMOVSXWD xmm2/m64, xmm1","pmovsxwd xmm2/m64, xmm1","66 0F 38 23 /r","V","V","SSE4_1","","w,r","","" +"PMOVSXWQ xmm1, xmm2/m32","PMOVSXWQ xmm2/m32, xmm1","pmovsxwq xmm2/m32, xmm1","66 0F 38 24 /r","V","V","SSE4_1","","w,r","","" +"PMOVZXBD xmm1, xmm2/m32","PMOVZXBD xmm2/m32, xmm1","pmovzxbd xmm2/m32, xmm1","66 0F 38 31 /r","V","V","SSE4_1","","w,r","","" +"PMOVZXBQ xmm1, xmm2/m16","PMOVZXBQ xmm2/m16, xmm1","pmovzxbq xmm2/m16, xmm1","66 0F 38 32 /r","V","V","SSE4_1","","w,r","","" +"PMOVZXBW xmm1, xmm2/m64","PMOVZXBW xmm2/m64, xmm1","pmovzxbw xmm2/m64, xmm1","66 0F 38 30 /r","V","V","SSE4_1","","w,r","","" +"PMOVZXDQ xmm1, xmm2/m64","PMOVZXDQ xmm2/m64, xmm1","pmovzxdq xmm2/m64, xmm1","66 0F 38 35 /r","V","V","SSE4_1","","w,r","","" +"PMOVZXWD xmm1, xmm2/m64","PMOVZXWD xmm2/m64, xmm1","pmovzxwd xmm2/m64, xmm1","66 0F 38 33 /r","V","V","SSE4_1","","w,r","","" +"PMOVZXWQ xmm1, xmm2/m32","PMOVZXWQ xmm2/m32, xmm1","pmovzxwq xmm2/m32, xmm1","66 0F 38 34 /r","V","V","SSE4_1","","w,r","","" +"PMULDQ xmm1, xmm2/m128","PMULDQ xmm2/m128, xmm1","pmuldq xmm2/m128, xmm1","66 0F 38 28 /r","V","V","SSE4_1","","rw,r","","" +"PMULHRSW mm1, mm2/m64","PMULHRSW mm2/m64, mm1","pmulhrsw mm2/m64, mm1","0F 38 0B /r","V","V","SSSE3","","rw,r","","" +"PMULHRSW xmm1, xmm2/m128","PMULHRSW xmm2/m128, xmm1","pmulhrsw xmm2/m128, xmm1","66 0F 38 0B /r","V","V","SSSE3","","rw,r","","" +"PMULHRW mm1, mm2/m64","PMULHRW mm2/m64, mm1","pmulhrw mm2/m64, mm1","0F 0F B7 /r","V","V","3DNOW","amd","rw,r","","" +"PMULHUW mm1, mm2/m64","PMULHUW mm2/m64, mm1","pmulhuw mm2/m64, mm1","0F E4 /r","V","V","MMX","","rw,r","","" +"PMULHUW xmm1, xmm2/m128","PMULHUW xmm2/m128, xmm1","pmulhuw xmm2/m128, xmm1","66 0F E4 /r","V","V","SSE2","","rw,r","","" +"PMULHW mm1, mm2/m64","PMULHW mm2/m64, mm1","pmulhw mm2/m64, mm1","0F E5 /r","V","V","MMX","","rw,r","","" +"PMULHW xmm1, xmm2/m128","PMULHW xmm2/m128, xmm1","pmulhw xmm2/m128, xmm1","66 0F E5 /r","V","V","SSE2","","rw,r","","" +"PMULLD xmm1, xmm2/m128","PMULLD xmm2/m128, xmm1","pmulld xmm2/m128, xmm1","66 0F 38 40 /r","V","V","SSE4_1","","rw,r","","" +"PMULLW mm1, mm2/m64","PMULLW mm2/m64, mm1","pmullw mm2/m64, mm1","0F D5 /r","V","V","MMX","","rw,r","","" +"PMULLW xmm1, xmm2/m128","PMULLW xmm2/m128, xmm1","pmullw xmm2/m128, xmm1","66 0F D5 /r","V","V","SSE2","","rw,r","","" +"PMULUDQ mm1, mm2/m64","PMULULQ mm2/m64, mm1","pmuludq mm2/m64, mm1","0F F4 /r","V","V","SSE2","","rw,r","","" +"PMULUDQ xmm1, xmm2/m128","PMULULQ xmm2/m128, xmm1","pmuludq xmm2/m128, xmm1","66 0F F4 /r","V","V","SSE2","","rw,r","","" +"POPAD","POPAL","popal","61","V","N.S.","","operand32","","","" +"POPA","POPAW","popaw","61","V","N.S.","","operand16","","","" +"POPCNT r32, r/m32","POPCNTL r/m32, r32","popcntl r/m32, r32","F3 0F B8 /r","V","V","POPCNT","operand32","w,r","Y","32" +"POPCNT r64, r/m64","POPCNTQ r/m64, r64","popcntq r/m64, r64","F3 REX.W 0F B8 /r","N.S.","V","POPCNT","","w,r","Y","64" +"POPCNT r16, r/m16","POPCNTW r/m16, r16","popcntw r/m16, r16","F3 0F B8 /r","V","V","POPCNT","operand16","w,r","Y","16" +"POPFD","POPFL","popfl","9D","V","N.S.","","operand32","","","" +"POPFQ","POPFQ","popfq","9D","N.S.","V","","default64","","","" +"POPF","POPFW","popfw","9D","V","V","","operand16","","","" +"POP r/m32","POPL r/m32","popl r/m32","8F /0","V","N.S.","","operand32","w","Y","32" +"POP r32op","POPL r32op","popl r32op","58+rd","V","N.S.","","operand32","w","Y","32" +"POP r/m64","POPQ r/m64","popq r/m64","8F /0","N.S.","V","","default64","w","Y","64" +"POP r64op","POPQ r64op","popq r64op","58+ro","N.S.","V","","default64","w","Y","64" +"POP r/m16","POPW r/m16","popw r/m16","8F /0","V","V","","operand16","w","Y","16" +"POP r16op","POPW r16op","popw r16op","58+rw","V","V","","operand16","w","Y","16" +"POP DS","POPW/POPL/POPQ DS","popw/popl/popq DS","1F","V","N.S.","","","w","Y","" +"POP ES","POPW/POPL/POPQ ES","popw/popl/popq ES","07","V","N.S.","","","w","Y","" +"POP FS","POPW/POPL/POPQ FS","popw/popl/popq FS","0F A1","N.S.","V","","default64","w","Y","" +"POP FS","POPW/POPL/POPQ FS","popw/popl/popq FS","0F A1","V","N.S.","","operand32","w","Y","" +"POP FS","POPW/POPL/POPQ FS","popw/popl/popq FS","0F A1","V","V","","operand16","w","Y","" +"POP GS","POPW/POPL/POPQ GS","popw/popl/popq GS","0F A9","N.S.","V","","default64","w","Y","" +"POP GS","POPW/POPL/POPQ GS","popw/popl/popq GS","0F A9","V","V","","operand16","w","Y","" +"POP GS","POPW/POPL/POPQ GS","popw/popl/popq GS","0F A9","V","N.S.","","operand32","w","Y","" +"POP SS","POPW/POPL/POPQ SS","popw/popl/popq SS","17","V","N.S.","","","w","Y","" +"POR mm1, mm2/m64","POR mm2/m64, mm1","por mm2/m64, mm1","0F EB /r","V","V","MMX","","rw,r","","" +"POR xmm1, xmm2/m128","POR xmm2/m128, xmm1","por xmm2/m128, xmm1","66 0F EB /r","V","V","SSE2","","rw,r","","" +"PREFETCHNTA m8","PREFETCHNTA m8","prefetchnta m8","0F 18 /0","V","V","","modrm_memonly","r","","" +"PREFETCHT0 m8","PREFETCHT0 m8","prefetcht0 m8","0F 18 /1","V","V","","modrm_memonly","r","","" +"PREFETCHT1 m8","PREFETCHT1 m8","prefetcht1 m8","0F 18 /2","V","V","","modrm_memonly","r","","" +"PREFETCHT2 m8","PREFETCHT2 m8","prefetcht2 m8","0F 18 /3","V","V","","modrm_memonly","r","","" +"PREFETCHW m8","PREFETCHW m8","prefetchw m8","0F 0D /1","V","V","PRFCHW","modrm_memonly","r","","" +"PREFETCHWT1 m8","PREFETCHWT1 m8","prefetchwt1 m8","0F 0D /2","V","V","PREFETCHWT1","modrm_memonly","r","","" +"PREFETCHW_ALIAS m8","PREFETCHW_ALIAS m8","prefetchw_alias m8","0F 0D /3","V","V","PRFCHW","modrm_memonly","r","","" +"PREFETCH_EXCLUSIVE m8","PREFETCH_EXCLUSIVE m8","prefetch_exclusive m8","0F 0D /0","V","V","PRFCHW","modrm_memonly","r","","" +"PREFETCH_RESERVED m8","PREFETCH_RESERVED m8","prefetch_reserved m8","0F 0D /2","V","V","PRFCHW","modrm_memonly","r","Y","" +"PREFETCH_RESERVED m8","PREFETCH_RESERVED m8","prefetch_reserved m8","0F 0D /4","V","V","PRFCHW","modrm_memonly","r","Y","" +"PREFETCH_RESERVED m8","PREFETCH_RESERVED m8","prefetch_reserved m8","0F 0D /5","V","V","PRFCHW","modrm_memonly","r","Y","" +"PREFETCH_RESERVED m8","PREFETCH_RESERVED m8","prefetch_reserved m8","0F 0D /6","V","V","PRFCHW","modrm_memonly","r","Y","" +"PREFETCH_RESERVED m8","PREFETCH_RESERVED m8","prefetch_reserved m8","0F 0D /7","V","V","PRFCHW","modrm_memonly","r","Y","" +"PSADBW mm1, mm2/m64","PSADBW mm2/m64, mm1","psadbw mm2/m64, mm1","0F F6 /r","V","V","MMX","","rw,r","","" +"PSADBW xmm1, xmm2/m128","PSADBW xmm2/m128, xmm1","psadbw xmm2/m128, xmm1","66 0F F6 /r","V","V","SSE2","","rw,r","","" +"PSHUFB mm1, mm2/m64","PSHUFB mm2/m64, mm1","pshufb mm2/m64, mm1","0F 38 00 /r","V","V","SSSE3","","rw,r","","" +"PSHUFB xmm1, xmm2/m128","PSHUFB xmm2/m128, xmm1","pshufb xmm2/m128, xmm1","66 0F 38 00 /r","V","V","SSSE3","","rw,r","","" +"PSHUFD xmm1, xmm2/m128, imm8u","PSHUFD imm8u, xmm2/m128, xmm1","pshufd imm8u, xmm2/m128, xmm1","66 0F 70 /r ib","V","V","SSE2","","w,r,r","","" +"PSHUFHW xmm1, xmm2/m128, imm8u","PSHUFHW imm8u, xmm2/m128, xmm1","pshufhw imm8u, xmm2/m128, xmm1","F3 0F 70 /r ib","V","V","SSE2","","w,r,r","","" +"PSHUFLW xmm1, xmm2/m128, imm8u","PSHUFLW imm8u, xmm2/m128, xmm1","pshuflw imm8u, xmm2/m128, xmm1","F2 0F 70 /r ib","V","V","SSE2","","w,r,r","","" +"PSHUFW mm1, mm2/m64, imm8u","PSHUFW imm8u, mm2/m64, mm1","pshufw imm8u, mm2/m64, mm1","0F 70 /r ib","V","V","MMX","","w,r,r","","" +"PSIGNB mm1, mm2/m64","PSIGNB mm2/m64, mm1","psignb mm2/m64, mm1","0F 38 08 /r","V","V","SSSE3","","rw,r","","" +"PSIGNB xmm1, xmm2/m128","PSIGNB xmm2/m128, xmm1","psignb xmm2/m128, xmm1","66 0F 38 08 /r","V","V","SSSE3","","rw,r","","" +"PSIGND mm1, mm2/m64","PSIGND mm2/m64, mm1","psignd mm2/m64, mm1","0F 38 0A /r","V","V","SSSE3","","rw,r","","" +"PSIGND xmm1, xmm2/m128","PSIGND xmm2/m128, xmm1","psignd xmm2/m128, xmm1","66 0F 38 0A /r","V","V","SSSE3","","rw,r","","" +"PSIGNW mm1, mm2/m64","PSIGNW mm2/m64, mm1","psignw mm2/m64, mm1","0F 38 09 /r","V","V","SSSE3","","rw,r","","" +"PSIGNW xmm1, xmm2/m128","PSIGNW xmm2/m128, xmm1","psignw xmm2/m128, xmm1","66 0F 38 09 /r","V","V","SSSE3","","rw,r","","" +"PSLLD mm2, imm8u","PSLLL imm8u, mm2","pslld imm8u, mm2","0F 72 /6 ib","V","V","MMX","modrm_regonly","rw,r","","" +"PSLLD xmm2, imm8u","PSLLL imm8u, xmm2","pslld imm8u, xmm2","66 0F 72 /6 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSLLD mm1, mm2/m64","PSLLL mm2/m64, mm1","pslld mm2/m64, mm1","0F F2 /r","V","V","MMX","","rw,r","","" +"PSLLD xmm1, xmm2/m128","PSLLL xmm2/m128, xmm1","pslld xmm2/m128, xmm1","66 0F F2 /r","V","V","SSE2","","rw,r","","" +"PSLLDQ xmm2, imm8u","PSLLO imm8u, xmm2","pslldq imm8u, xmm2","66 0F 73 /7 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSLLQ mm2, imm8u","PSLLQ imm8u, mm2","psllq imm8u, mm2","0F 73 /6 ib","V","V","MMX","modrm_regonly","rw,r","","" +"PSLLQ xmm2, imm8u","PSLLQ imm8u, xmm2","psllq imm8u, xmm2","66 0F 73 /6 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSLLQ mm1, mm2/m64","PSLLQ mm2/m64, mm1","psllq mm2/m64, mm1","0F F3 /r","V","V","MMX","","rw,r","","" +"PSLLQ xmm1, xmm2/m128","PSLLQ xmm2/m128, xmm1","psllq xmm2/m128, xmm1","66 0F F3 /r","V","V","SSE2","","rw,r","","" +"PSLLW mm2, imm8u","PSLLW imm8u, mm2","psllw imm8u, mm2","0F 71 /6 ib","V","V","MMX","modrm_regonly","rw,r","","" +"PSLLW xmm2, imm8u","PSLLW imm8u, xmm2","psllw imm8u, xmm2","66 0F 71 /6 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSLLW mm1, mm2/m64","PSLLW mm2/m64, mm1","psllw mm2/m64, mm1","0F F1 /r","V","V","MMX","","rw,r","","" +"PSLLW xmm1, xmm2/m128","PSLLW xmm2/m128, xmm1","psllw xmm2/m128, xmm1","66 0F F1 /r","V","V","SSE2","","rw,r","","" +"PSRAD mm2, imm8u","PSRAL imm8u, mm2","psrad imm8u, mm2","0F 72 /4 ib","V","V","MMX","modrm_regonly","rw,r","","" +"PSRAD xmm2, imm8u","PSRAL imm8u, xmm2","psrad imm8u, xmm2","66 0F 72 /4 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSRAD mm1, mm2/m64","PSRAL mm2/m64, mm1","psrad mm2/m64, mm1","0F E2 /r","V","V","MMX","","rw,r","","" +"PSRAD xmm1, xmm2/m128","PSRAL xmm2/m128, xmm1","psrad xmm2/m128, xmm1","66 0F E2 /r","V","V","SSE2","","rw,r","","" +"PSRAW mm2, imm8u","PSRAW imm8u, mm2","psraw imm8u, mm2","0F 71 /4 ib","V","V","MMX","modrm_regonly","rw,r","","" +"PSRAW xmm2, imm8u","PSRAW imm8u, xmm2","psraw imm8u, xmm2","66 0F 71 /4 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSRAW mm1, mm2/m64","PSRAW mm2/m64, mm1","psraw mm2/m64, mm1","0F E1 /r","V","V","MMX","","rw,r","","" +"PSRAW xmm1, xmm2/m128","PSRAW xmm2/m128, xmm1","psraw xmm2/m128, xmm1","66 0F E1 /r","V","V","SSE2","","rw,r","","" +"PSRLD mm2, imm8u","PSRLL imm8u, mm2","psrld imm8u, mm2","0F 72 /2 ib","V","V","MMX","modrm_regonly","rw,r","","" +"PSRLD xmm2, imm8u","PSRLL imm8u, xmm2","psrld imm8u, xmm2","66 0F 72 /2 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSRLD mm1, mm2/m64","PSRLL mm2/m64, mm1","psrld mm2/m64, mm1","0F D2 /r","V","V","MMX","","rw,r","","" +"PSRLD xmm1, xmm2/m128","PSRLL xmm2/m128, xmm1","psrld xmm2/m128, xmm1","66 0F D2 /r","V","V","SSE2","","rw,r","","" +"PSRLDQ xmm2, imm8u","PSRLO imm8u, xmm2","psrldq imm8u, xmm2","66 0F 73 /3 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSRLQ mm2, imm8u","PSRLQ imm8u, mm2","psrlq imm8u, mm2","0F 73 /2 ib","V","V","MMX","modrm_regonly","rw,r","","" +"PSRLQ xmm2, imm8u","PSRLQ imm8u, xmm2","psrlq imm8u, xmm2","66 0F 73 /2 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSRLQ mm1, mm2/m64","PSRLQ mm2/m64, mm1","psrlq mm2/m64, mm1","0F D3 /r","V","V","MMX","","rw,r","","" +"PSRLQ xmm1, xmm2/m128","PSRLQ xmm2/m128, xmm1","psrlq xmm2/m128, xmm1","66 0F D3 /r","V","V","SSE2","","rw,r","","" +"PSRLW mm2, imm8u","PSRLW imm8u, mm2","psrlw imm8u, mm2","0F 71 /2 ib","V","V","MMX","modrm_regonly","rw,r","","" +"PSRLW xmm2, imm8u","PSRLW imm8u, xmm2","psrlw imm8u, xmm2","66 0F 71 /2 ib","V","V","SSE2","modrm_regonly","rw,r","","" +"PSRLW mm1, mm2/m64","PSRLW mm2/m64, mm1","psrlw mm2/m64, mm1","0F D1 /r","V","V","MMX","","rw,r","","" +"PSRLW xmm1, xmm2/m128","PSRLW xmm2/m128, xmm1","psrlw xmm2/m128, xmm1","66 0F D1 /r","V","V","SSE2","","rw,r","","" +"PSUBB mm1, mm2/m64","PSUBB mm2/m64, mm1","psubb mm2/m64, mm1","0F F8 /r","V","V","MMX","","rw,r","","" +"PSUBB xmm1, xmm2/m128","PSUBB xmm2/m128, xmm1","psubb xmm2/m128, xmm1","66 0F F8 /r","V","V","SSE2","","rw,r","","" +"PSUBD mm1, mm2/m64","PSUBL mm2/m64, mm1","psubd mm2/m64, mm1","0F FA /r","V","V","MMX","","rw,r","","" +"PSUBD xmm1, xmm2/m128","PSUBL xmm2/m128, xmm1","psubd xmm2/m128, xmm1","66 0F FA /r","V","V","SSE2","","rw,r","","" +"PSUBQ mm1, mm2/m64","PSUBQ mm2/m64, mm1","psubq mm2/m64, mm1","0F FB /r","V","V","SSE2","","rw,r","","" +"PSUBQ xmm1, xmm2/m128","PSUBQ xmm2/m128, xmm1","psubq xmm2/m128, xmm1","66 0F FB /r","V","V","SSE2","","rw,r","","" +"PSUBSB mm1, mm2/m64","PSUBSB mm2/m64, mm1","psubsb mm2/m64, mm1","0F E8 /r","V","V","MMX","","rw,r","","" +"PSUBSB xmm1, xmm2/m128","PSUBSB xmm2/m128, xmm1","psubsb xmm2/m128, xmm1","66 0F E8 /r","V","V","SSE2","","rw,r","","" +"PSUBSW mm1, mm2/m64","PSUBSW mm2/m64, mm1","psubsw mm2/m64, mm1","0F E9 /r","V","V","MMX","","rw,r","","" +"PSUBSW xmm1, xmm2/m128","PSUBSW xmm2/m128, xmm1","psubsw xmm2/m128, xmm1","66 0F E9 /r","V","V","SSE2","","rw,r","","" +"PSUBUSB mm1, mm2/m64","PSUBUSB mm2/m64, mm1","psubusb mm2/m64, mm1","0F D8 /r","V","V","MMX","","rw,r","","" +"PSUBUSB xmm1, xmm2/m128","PSUBUSB xmm2/m128, xmm1","psubusb xmm2/m128, xmm1","66 0F D8 /r","V","V","SSE2","","rw,r","","" +"PSUBUSW mm1, mm2/m64","PSUBUSW mm2/m64, mm1","psubusw mm2/m64, mm1","0F D9 /r","V","V","MMX","","rw,r","","" +"PSUBUSW xmm1, xmm2/m128","PSUBUSW xmm2/m128, xmm1","psubusw xmm2/m128, xmm1","66 0F D9 /r","V","V","SSE2","","rw,r","","" +"PSUBW mm1, mm2/m64","PSUBW mm2/m64, mm1","psubw mm2/m64, mm1","0F F9 /r","V","V","MMX","","rw,r","","" +"PSUBW xmm1, xmm2/m128","PSUBW xmm2/m128, xmm1","psubw xmm2/m128, xmm1","66 0F F9 /r","V","V","SSE2","","rw,r","","" +"PSWAPD mm1, mm2/m64","PSWAPD mm2/m64, mm1","pswapd mm2/m64, mm1","0F 0F BB /r","V","V","3DNOW","amd","rw,r","","" +"PTEST xmm1, xmm2/m128","PTEST xmm2/m128, xmm1","ptest xmm2/m128, xmm1","66 0F 38 17 /r","V","V","SSE4_1","","r,r","","" +"PTWRITE r/m32","PTWRITEL r/m32","ptwritel r/m32","F3 0F AE /4","V","V","","operand16,operand32","r","Y","32" +"PTWRITE r/m64","PTWRITEQ r/m64","ptwriteq r/m64","F3 REX.W 0F AE /4","N.S.","V","","","r","Y","64" +"PUNPCKHBW mm1, mm2/m64","PUNPCKHBW mm2/m64, mm1","punpckhbw mm2/m64, mm1","0F 68 /r","V","V","MMX","","rw,r","","" +"PUNPCKHBW xmm1, xmm2/m128","PUNPCKHBW xmm2/m128, xmm1","punpckhbw xmm2/m128, xmm1","66 0F 68 /r","V","V","SSE2","","rw,r","","" +"PUNPCKHDQ mm1, mm2/m64","PUNPCKHLQ mm2/m64, mm1","punpckhdq mm2/m64, mm1","0F 6A /r","V","V","MMX","","rw,r","","" +"PUNPCKHDQ xmm1, xmm2/m128","PUNPCKHLQ xmm2/m128, xmm1","punpckhdq xmm2/m128, xmm1","66 0F 6A /r","V","V","SSE2","","rw,r","","" +"PUNPCKHQDQ xmm1, xmm2/m128","PUNPCKHQDQ xmm2/m128, xmm1","punpckhqdq xmm2/m128, xmm1","66 0F 6D /r","V","V","SSE2","","rw,r","","" +"PUNPCKHWD mm1, mm2/m64","PUNPCKHWL mm2/m64, mm1","punpckhwd mm2/m64, mm1","0F 69 /r","V","V","MMX","","rw,r","","" +"PUNPCKHWD xmm1, xmm2/m128","PUNPCKHWL xmm2/m128, xmm1","punpckhwd xmm2/m128, xmm1","66 0F 69 /r","V","V","SSE2","","rw,r","","" +"PUNPCKLBW mm1, mm2/m32","PUNPCKLBW mm2/m32, mm1","punpcklbw mm2/m32, mm1","0F 60 /r","V","V","MMX","","rw,r","","" +"PUNPCKLBW xmm1, xmm2/m128","PUNPCKLBW xmm2/m128, xmm1","punpcklbw xmm2/m128, xmm1","66 0F 60 /r","V","V","SSE2","","rw,r","","" +"PUNPCKLDQ mm1, mm2/m32","PUNPCKLLQ mm2/m32, mm1","punpckldq mm2/m32, mm1","0F 62 /r","V","V","MMX","","rw,r","","" +"PUNPCKLDQ xmm1, xmm2/m128","PUNPCKLLQ xmm2/m128, xmm1","punpckldq xmm2/m128, xmm1","66 0F 62 /r","V","V","SSE2","","rw,r","","" +"PUNPCKLQDQ xmm1, xmm2/m128","PUNPCKLQDQ xmm2/m128, xmm1","punpcklqdq xmm2/m128, xmm1","66 0F 6C /r","V","V","SSE2","","rw,r","","" +"PUNPCKLWD mm1, mm2/m32","PUNPCKLWL mm2/m32, mm1","punpcklwd mm2/m32, mm1","0F 61 /r","V","V","MMX","","rw,r","","" +"PUNPCKLWD xmm1, xmm2/m128","PUNPCKLWL xmm2/m128, xmm1","punpcklwd xmm2/m128, xmm1","66 0F 61 /r","V","V","SSE2","","rw,r","","" +"PUSHAD","PUSHAL","pushal","60","V","N.S.","","operand32","","","" +"PUSHA","PUSHAW","pushaw","60","V","N.S.","","operand16","","","" +"PUSHFD","PUSHFL","pushfl","9C","V","N.S.","","operand32","","","" +"PUSHFQ","PUSHFQ","pushfq","9C","N.S.","V","","default64","","","" +"PUSHF","PUSHFW","pushfw","9C","V","V","","operand16","","","" +"PUSH r/m32","PUSHL r/m32","pushl r/m32","FF /6","V","N.S.","","operand32","r","Y","32" +"PUSH r32op","PUSHL r32op","pushl r32op","50+rd","V","N.S.","","operand32","r","Y","32" +"PUSH r/m64","PUSHQ r/m64","pushq r/m64","FF /6","N.S.","V","","default64","r","Y","64" +"PUSH r64op","PUSHQ r64op","pushq r64op","50+ro","N.S.","V","","default64","r","Y","64" +"PUSH imm16","PUSHW imm16","pushw imm16","68 iw","V","V","","operand16","r","Y","" +"PUSH r/m16","PUSHW r/m16","pushw r/m16","FF /6","V","V","","operand16","r","Y","16" +"PUSH r16op","PUSHW r16op","pushw r16op","50+rw","V","V","","operand16","r","Y","16" +"PUSH CS","PUSHW/PUSHL/PUSHQ CS","pushw/pushl/pushq CS","0E","V","N.S.","","","r","Y","" +"PUSH DS","PUSHW/PUSHL/PUSHQ DS","pushw/pushl/pushq DS","1E","V","N.S.","","","r","Y","" +"PUSH ES","PUSHW/PUSHL/PUSHQ ES","pushw/pushl/pushq ES","06","V","N.S.","","","r","Y","" +"PUSH FS","PUSHW/PUSHL/PUSHQ FS","pushw/pushl/pushq FS","0F A0","V","V","","operand16","r","Y","" +"PUSH FS","PUSHW/PUSHL/PUSHQ FS","pushw/pushl/pushq FS","0F A0","N.S.","V","","default64","r","Y","" +"PUSH FS","PUSHW/PUSHL/PUSHQ FS","pushw/pushl/pushq FS","0F A0","V","N.S.","","operand32","r","Y","" +"PUSH GS","PUSHW/PUSHL/PUSHQ GS","pushw/pushl/pushq GS","0F A8","N.S.","V","","default64","r","Y","" +"PUSH GS","PUSHW/PUSHL/PUSHQ GS","pushw/pushl/pushq GS","0F A8","V","N.S.","","operand32","r","Y","" +"PUSH GS","PUSHW/PUSHL/PUSHQ GS","pushw/pushl/pushq GS","0F A8","V","V","","operand16","r","Y","" +"PUSH SS","PUSHW/PUSHL/PUSHQ SS","pushw/pushl/pushq SS","16","V","N.S.","","","r","Y","" +"PUSH imm8","PUSHW/PUSHL/PUSHQ imm8","pushw/pushl/pushq imm8","6A ib","V","N.S.","","operand32","r","Y","" +"PUSH imm8","PUSHW/PUSHL/PUSHQ imm8","pushw/pushl/pushq imm8","6A ib","N.S.","V","","default64","r","Y","" +"PUSH imm8","PUSHW/PUSHL/PUSHQ imm8","pushw/pushl/pushq imm8","6A ib","V","V","","operand16","r","Y","" +"PXOR mm1, mm2/m64","PXOR mm2/m64, mm1","pxor mm2/m64, mm1","0F EF /r","V","V","MMX","","rw,r","","" +"PXOR xmm1, xmm2/m128","PXOR xmm2/m128, xmm1","pxor xmm2/m128, xmm1","66 0F EF /r","V","V","SSE2","","rw,r","","" +"RCL r/m8, 1","RCLB 1, r/m8","rclb 1, r/m8","D0 /2","V","V","","","rw,r","Y","8" +"RCL r/m8, 1","RCLB 1, r/m8","rclb 1, r/m8","REX D0 /2","N.E.","V","","pseudo64","w,r","Y","8" +"RCL r/m8, CL","RCLB CL, r/m8","rclb CL, r/m8","D2 /2","V","V","","","rw,r","Y","8" +"RCL r/m8, CL","RCLB CL, r/m8","rclb CL, r/m8","REX D2 /2","N.E.","V","","pseudo64","w,r","Y","8" +"RCL r/m8, imm8","RCLB imm8, r/m8","rclb imm8, r/m8","REX C0 /2 ib","N.E.","V","","pseudo64","w,r","Y","8" +"RCL r/m8, imm8u","RCLB imm8u, r/m8","rclb imm8u, r/m8","C0 /2 ib","V","V","","","rw,r","Y","8" +"RCL r/m32, 1","RCLL 1, r/m32","rcll 1, r/m32","D1 /2","V","V","","operand32","rw,r","Y","32" +"RCL r/m32, CL","RCLL CL, r/m32","rcll CL, r/m32","D3 /2","V","V","","operand32","rw,r","Y","32" +"RCL r/m32, imm8u","RCLL imm8u, r/m32","rcll imm8u, r/m32","C1 /2 ib","V","V","","operand32","rw,r","Y","32" +"RCL r/m64, 1","RCLQ 1, r/m64","rclq 1, r/m64","REX.W D1 /2","N.S.","V","","","rw,r","Y","64" +"RCL r/m64, CL","RCLQ CL, r/m64","rclq CL, r/m64","REX.W D3 /2","N.S.","V","","","rw,r","Y","64" +"RCL r/m64, imm8u","RCLQ imm8u, r/m64","rclq imm8u, r/m64","REX.W C1 /2 ib","N.S.","V","","","rw,r","Y","64" +"RCL r/m16, 1","RCLW 1, r/m16","rclw 1, r/m16","D1 /2","V","V","","operand16","rw,r","Y","16" +"RCL r/m16, CL","RCLW CL, r/m16","rclw CL, r/m16","D3 /2","V","V","","operand16","rw,r","Y","16" +"RCL r/m16, imm8u","RCLW imm8u, r/m16","rclw imm8u, r/m16","C1 /2 ib","V","V","","operand16","rw,r","Y","16" +"RCPPS xmm1, xmm2/m128","RCPPS xmm2/m128, xmm1","rcpps xmm2/m128, xmm1","0F 53 /r","V","V","SSE","","w,r","","" +"RCPSS xmm1, xmm2/m32","RCPSS xmm2/m32, xmm1","rcpss xmm2/m32, xmm1","F3 0F 53 /r","V","V","SSE","","w,r","","" +"RCR r/m8, 1","RCRB 1, r/m8","rcrb 1, r/m8","D0 /3","V","V","","","rw,r","Y","8" +"RCR r/m8, 1","RCRB 1, r/m8","rcrb 1, r/m8","REX D0 /3","N.E.","V","","pseudo64","w,r","Y","8" +"RCR r/m8, CL","RCRB CL, r/m8","rcrb CL, r/m8","D2 /3","V","V","","","rw,r","Y","8" +"RCR r/m8, CL","RCRB CL, r/m8","rcrb CL, r/m8","REX D2 /3","N.E.","V","","pseudo64","w,r","Y","8" +"RCR r/m8, imm8","RCRB imm8, r/m8","rcrb imm8, r/m8","REX C0 /3 ib","N.E.","V","","pseudo64","w,r","Y","8" +"RCR r/m8, imm8u","RCRB imm8u, r/m8","rcrb imm8u, r/m8","C0 /3 ib","V","V","","","rw,r","Y","8" +"RCR r/m32, 1","RCRL 1, r/m32","rcrl 1, r/m32","D1 /3","V","V","","operand32","rw,r","Y","32" +"RCR r/m32, CL","RCRL CL, r/m32","rcrl CL, r/m32","D3 /3","V","V","","operand32","rw,r","Y","32" +"RCR r/m32, imm8u","RCRL imm8u, r/m32","rcrl imm8u, r/m32","C1 /3 ib","V","V","","operand32","rw,r","Y","32" +"RCR r/m64, 1","RCRQ 1, r/m64","rcrq 1, r/m64","REX.W D1 /3","N.S.","V","","","rw,r","Y","64" +"RCR r/m64, CL","RCRQ CL, r/m64","rcrq CL, r/m64","REX.W D3 /3","N.S.","V","","","rw,r","Y","64" +"RCR r/m64, imm8u","RCRQ imm8u, r/m64","rcrq imm8u, r/m64","REX.W C1 /3 ib","N.S.","V","","","rw,r","Y","64" +"RCR r/m16, 1","RCRW 1, r/m16","rcrw 1, r/m16","D1 /3","V","V","","operand16","rw,r","Y","16" +"RCR r/m16, CL","RCRW CL, r/m16","rcrw CL, r/m16","D3 /3","V","V","","operand16","rw,r","Y","16" +"RCR r/m16, imm8u","RCRW imm8u, r/m16","rcrw imm8u, r/m16","C1 /3 ib","V","V","","operand16","rw,r","Y","16" +"RDFSBASE rmr32","RDFSBASEL rmr32","rdfsbase rmr32","F3 0F AE /0","N.S.","V","FSGSBASE","modrm_regonly,operand16,operand32","w","Y","32" +"RDFSBASE rmr64","RDFSBASEQ rmr64","rdfsbase rmr64","F3 REX.W 0F AE /0","N.S.","V","FSGSBASE","modrm_regonly","w","Y","64" +"RDGSBASE rmr32","RDGSBASEL rmr32","rdgsbase rmr32","F3 0F AE /1","N.S.","V","FSGSBASE","modrm_regonly,operand16,operand32","w","Y","32" +"RDGSBASE rmr64","RDGSBASEQ rmr64","rdgsbase rmr64","F3 REX.W 0F AE /1","N.S.","V","FSGSBASE","modrm_regonly","w","Y","64" +"RDMSR","RDMSR","rdmsr","0F 32","V","V","Pentium","","","","" +"RDPKRU","RDPKRU","rdpkru","0F 01 EE","V","V","PKU","","","","" +"RDPMC","RDPMC","rdpmc","0F 33","V","V","","","","","" +"RDRAND rmr32","RDRANDL rmr32","rdrand rmr32","0F C7 /6","V","V","RDRAND","modrm_regonly,operand32","w","Y","32" +"RDRAND rmr64","RDRANDQ rmr64","rdrand rmr64","REX.W 0F C7 /6","N.S.","V","RDRAND","modrm_regonly","w","Y","64" +"RDRAND rmr16","RDRANDW rmr16","rdrand rmr16","0F C7 /6","V","V","RDRAND","modrm_regonly,operand16","w","Y","16" +"RDSEED rmr32","RDSEEDL rmr32","rdseed rmr32","0F C7 /7","V","V","RDSEED","modrm_regonly,operand32","w","Y","32" +"RDSEED rmr64","RDSEEDQ rmr64","rdseed rmr64","REX.W 0F C7 /7","N.S.","V","RDSEED","modrm_regonly","w","Y","64" +"RDSEED rmr16","RDSEEDW rmr16","rdseed rmr16","0F C7 /7","V","V","RDSEED","modrm_regonly,operand16","w","Y","16" +"RDSSPD rmr32","RDSSPD rmr32","rdsspd rmr32","F3 0F 1E /1","V","V","CET","modrm_regonly,operand16,operand32","w","","" +"RDSSPQ rmr64","RDSSPQ rmr64","rdsspq rmr64","F3 REX.W 0F 1E /1","N.S.","V","CET","modrm_regonly","w","","" +"RDTSC","RDTSC","rdtsc","0F 31","V","V","Pentium","","","","" +"RDTSCP","RDTSCP","rdtscp","0F 01 F9","V","V","RDTSCP","","","","" +"RET_FAR","RETFW/RETFL/RETFQ","lretw/lretl/lretl","CB","V","V","","","","","" +"RET_FAR imm16u","RETFW/RETFL/RETFQ imm16u","lretw/lretl/lretl imm16u","CA iw","V","V","","","r","","" +"RET","RETW/RETL/RETQ","retw/retl/retq","C3","N.S.","V","","default64","","","" +"RET","RETW/RETL/RETQ","retw/retl/retq","C3","V","N.S.","","","","","" +"RET imm16u","RETW/RETL/RETQ imm16u","retw/retl/retq imm16u","C2 iw","N.S.","V","","default64","r","","" +"RET imm16u","RETW/RETL/RETQ imm16u","retw/retl/retq imm16u","C2 iw","V","N.S.","","","r","","" +"ROL r/m8, 1","ROLB 1, r/m8","rolb 1, r/m8","D0 /0","V","V","","","rw,r","Y","8" +"ROL r/m8, 1","ROLB 1, r/m8","rolb 1, r/m8","REX D0 /0","N.E.","V","","pseudo64","w,r","Y","8" +"ROL r/m8, CL","ROLB CL, r/m8","rolb CL, r/m8","D2 /0","V","V","","","rw,r","Y","8" +"ROL r/m8, CL","ROLB CL, r/m8","rolb CL, r/m8","REX D2 /0","N.E.","V","","pseudo64","w,r","Y","8" +"ROL r/m8, imm8","ROLB imm8, r/m8","rolb imm8, r/m8","REX C0 /0 ib","N.E.","V","","pseudo64","w,r","Y","8" +"ROL r/m8, imm8u","ROLB imm8u, r/m8","rolb imm8u, r/m8","C0 /0 ib","V","V","","","rw,r","Y","8" +"ROL r/m32, 1","ROLL 1, r/m32","roll 1, r/m32","D1 /0","V","V","","operand32","rw,r","Y","32" +"ROL r/m32, CL","ROLL CL, r/m32","roll CL, r/m32","D3 /0","V","V","","operand32","rw,r","Y","32" +"ROL r/m32, imm8u","ROLL imm8u, r/m32","roll imm8u, r/m32","C1 /0 ib","V","V","","operand32","rw,r","Y","32" +"ROL r/m64, 1","ROLQ 1, r/m64","rolq 1, r/m64","REX.W D1 /0","N.S.","V","","","rw,r","Y","64" +"ROL r/m64, CL","ROLQ CL, r/m64","rolq CL, r/m64","REX.W D3 /0","N.S.","V","","","rw,r","Y","64" +"ROL r/m64, imm8u","ROLQ imm8u, r/m64","rolq imm8u, r/m64","REX.W C1 /0 ib","N.S.","V","","","rw,r","Y","64" +"ROL r/m16, 1","ROLW 1, r/m16","rolw 1, r/m16","D1 /0","V","V","","operand16","rw,r","Y","16" +"ROL r/m16, CL","ROLW CL, r/m16","rolw CL, r/m16","D3 /0","V","V","","operand16","rw,r","Y","16" +"ROL r/m16, imm8u","ROLW imm8u, r/m16","rolw imm8u, r/m16","C1 /0 ib","V","V","","operand16","rw,r","Y","16" +"ROR r/m8, 1","RORB 1, r/m8","rorb 1, r/m8","D0 /1","V","V","","","rw,r","Y","8" +"ROR r/m8, 1","RORB 1, r/m8","rorb 1, r/m8","REX D0 /1","N.E.","V","","pseudo64","w,r","Y","8" +"ROR r/m8, CL","RORB CL, r/m8","rorb CL, r/m8","D2 /1","V","V","","","rw,r","Y","8" +"ROR r/m8, CL","RORB CL, r/m8","rorb CL, r/m8","REX D2 /1","N.E.","V","","pseudo64","w,r","Y","8" +"ROR r/m8, imm8","RORB imm8, r/m8","rorb imm8, r/m8","REX C0 /1 ib","N.E.","V","","pseudo64","w,r","Y","8" +"ROR r/m8, imm8u","RORB imm8u, r/m8","rorb imm8u, r/m8","C0 /1 ib","V","V","","","rw,r","Y","8" +"ROR r/m32, 1","RORL 1, r/m32","rorl 1, r/m32","D1 /1","V","V","","operand32","rw,r","Y","32" +"ROR r/m32, CL","RORL CL, r/m32","rorl CL, r/m32","D3 /1","V","V","","operand32","rw,r","Y","32" +"ROR r/m32, imm8u","RORL imm8u, r/m32","rorl imm8u, r/m32","C1 /1 ib","V","V","","operand32","rw,r","Y","32" +"ROR r/m64, 1","RORQ 1, r/m64","rorq 1, r/m64","REX.W D1 /1","N.S.","V","","","rw,r","Y","64" +"ROR r/m64, CL","RORQ CL, r/m64","rorq CL, r/m64","REX.W D3 /1","N.S.","V","","","rw,r","Y","64" +"ROR r/m64, imm8u","RORQ imm8u, r/m64","rorq imm8u, r/m64","REX.W C1 /1 ib","N.S.","V","","","rw,r","Y","64" +"ROR r/m16, 1","RORW 1, r/m16","rorw 1, r/m16","D1 /1","V","V","","operand16","rw,r","Y","16" +"ROR r/m16, CL","RORW CL, r/m16","rorw CL, r/m16","D3 /1","V","V","","operand16","rw,r","Y","16" +"ROR r/m16, imm8u","RORW imm8u, r/m16","rorw imm8u, r/m16","C1 /1 ib","V","V","","operand16","rw,r","Y","16" +"RORX r32, r/m32, imm8u","RORXL imm8u, r/m32, r32","rorxl imm8u, r/m32, r32","VEX.128.F2.0F3A.W0 F0 /r ib","V","V","BMI2","","w,r,r","Y","32" +"RORX r64, r/m64, imm8u","RORXQ imm8u, r/m64, r64","rorxq imm8u, r/m64, r64","VEX.128.F2.0F3A.W1 F0 /r ib","N.S.","V","BMI2","","w,r,r","Y","64" +"ROUNDPD xmm1, xmm2/m128, imm8u","ROUNDPD imm8u, xmm2/m128, xmm1","roundpd imm8u, xmm2/m128, xmm1","66 0F 3A 09 /r ib","V","V","SSE4_1","","w,r,r","","" +"ROUNDPS xmm1, xmm2/m128, imm8u","ROUNDPS imm8u, xmm2/m128, xmm1","roundps imm8u, xmm2/m128, xmm1","66 0F 3A 08 /r ib","V","V","SSE4_1","","w,r,r","","" +"ROUNDSD xmm1, xmm2/m64, imm8u","ROUNDSD imm8u, xmm2/m64, xmm1","roundsd imm8u, xmm2/m64, xmm1","66 0F 3A 0B /r ib","V","V","SSE4_1","","w,r,r","","" +"ROUNDSS xmm1, xmm2/m32, imm8u","ROUNDSS imm8u, xmm2/m32, xmm1","roundss imm8u, xmm2/m32, xmm1","66 0F 3A 0A /r ib","V","V","SSE4_1","","w,r,r","","" +"RSM","RSM","rsm","0F AA","V","V","","","","","" +"RSQRTPS xmm1, xmm2/m128","RSQRTPS xmm2/m128, xmm1","rsqrtps xmm2/m128, xmm1","0F 52 /r","V","V","SSE","","w,r","","" +"RSQRTSS xmm1, xmm2/m32","RSQRTSS xmm2/m32, xmm1","rsqrtss xmm2/m32, xmm1","F3 0F 52 /r","V","V","SSE","","w,r","","" +"RSTORSSP m64","RSTORSSP m64","rstorssp m64","F3 0F 01 /5","V","V","CET","modrm_memonly","rw","","" +"SAHF","SAHF","sahf","9E","V","V","LAHFSAHF","","","","" +"SAL r/m8, 1","SALB 1, r/m8","salb 1, r/m8","D0 /4","V","V","","pseudo","rw,r","Y","8" +"SAL r/m8, 1","SALB 1, r/m8","salb 1, r/m8","REX D0 /4","N.E.","V","","pseudo","rw,r","Y","8" +"SAL r/m8, CL","SALB CL, r/m8","salb CL, r/m8","D2 /4","V","V","","pseudo","rw,r","Y","8" +"SAL r/m8, CL","SALB CL, r/m8","salb CL, r/m8","REX D2 /4","N.E.","V","","pseudo","rw,r","Y","8" +"SAL r/m8, imm8","SALB imm8, r/m8","salb imm8, r/m8","C0 /4 ib","V","V","","pseudo","rw,r","Y","8" +"SAL r/m8, imm8","SALB imm8, r/m8","salb imm8, r/m8","REX C0 /4 ib","N.E.","V","","pseudo","rw,r","Y","8" +"SALC","SALC","salc","D6","V","N.S.","","","","","" +"SAL r/m32, 1","SALL 1, r/m32","sall 1, r/m32","D1 /4","V","V","","operand32,pseudo","rw,r","Y","32" +"SAL r/m32, CL","SALL CL, r/m32","sall CL, r/m32","D3 /4","V","V","","operand32,pseudo","rw,r","Y","32" +"SAL r/m32, imm8","SALL imm8, r/m32","sall imm8, r/m32","C1 /4 ib","V","V","","operand32,pseudo","rw,r","Y","32" +"SAL r/m64, 1","SALQ 1, r/m64","salq 1, r/m64","REX.W D1 /4","N.E.","V","","pseudo","rw,r","Y","64" +"SAL r/m64, CL","SALQ CL, r/m64","salq CL, r/m64","REX.W D3 /4","N.E.","V","","pseudo","rw,r","Y","64" +"SAL r/m64, imm8","SALQ imm8, r/m64","salq imm8, r/m64","REX.W C1 /4 ib","N.E.","V","","pseudo","rw,r","Y","64" +"SAL r/m16, 1","SALW 1, r/m16","salw 1, r/m16","D1 /4","V","V","","operand16,pseudo","rw,r","Y","16" +"SAL r/m16, CL","SALW CL, r/m16","salw CL, r/m16","D3 /4","V","V","","operand16,pseudo","rw,r","Y","16" +"SAL r/m16, imm8","SALW imm8, r/m16","salw imm8, r/m16","C1 /4 ib","V","V","","operand16,pseudo","rw,r","Y","16" +"SAR r/m8, 1","SARB 1, r/m8","sarb 1, r/m8","D0 /7","V","V","","","rw,r","Y","8" +"SAR r/m8, 1","SARB 1, r/m8","sarb 1, r/m8","REX D0 /7","N.E.","V","","pseudo64","rw,r","Y","8" +"SAR r/m8, CL","SARB CL, r/m8","sarb CL, r/m8","D2 /7","V","V","","","rw,r","Y","8" +"SAR r/m8, CL","SARB CL, r/m8","sarb CL, r/m8","REX D2 /7","N.E.","V","","pseudo64","rw,r","Y","8" +"SAR r/m8, imm8","SARB imm8, r/m8","sarb imm8, r/m8","REX C0 /7 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"SAR r/m8, imm8u","SARB imm8u, r/m8","sarb imm8u, r/m8","C0 /7 ib","V","V","","","rw,r","Y","8" +"SAR r/m32, 1","SARL 1, r/m32","sarl 1, r/m32","D1 /7","V","V","","operand32","rw,r","Y","32" +"SAR r/m32, CL","SARL CL, r/m32","sarl CL, r/m32","D3 /7","V","V","","operand32","rw,r","Y","32" +"SAR r/m32, imm8u","SARL imm8u, r/m32","sarl imm8u, r/m32","C1 /7 ib","V","V","","operand32","rw,r","Y","32" +"SAR r/m64, 1","SARQ 1, r/m64","sarq 1, r/m64","REX.W D1 /7","N.S.","V","","","rw,r","Y","64" +"SAR r/m64, CL","SARQ CL, r/m64","sarq CL, r/m64","REX.W D3 /7","N.S.","V","","","rw,r","Y","64" +"SAR r/m64, imm8u","SARQ imm8u, r/m64","sarq imm8u, r/m64","REX.W C1 /7 ib","N.S.","V","","","rw,r","Y","64" +"SAR r/m16, 1","SARW 1, r/m16","sarw 1, r/m16","D1 /7","V","V","","operand16","rw,r","Y","16" +"SAR r/m16, CL","SARW CL, r/m16","sarw CL, r/m16","D3 /7","V","V","","operand16","rw,r","Y","16" +"SAR r/m16, imm8u","SARW imm8u, r/m16","sarw imm8u, r/m16","C1 /7 ib","V","V","","operand16","rw,r","Y","16" +"SARX r32, r/m32, r32V","SARXL r32V, r/m32, r32","sarxl r32V, r/m32, r32","VEX.NDS.128.F3.0F38.W0 F7 /r","V","V","BMI2","","w,r,r","Y","32" +"SARX r64, r/m64, r64V","SARXQ r64V, r/m64, r64","sarxq r64V, r/m64, r64","VEX.NDS.128.F3.0F38.W1 F7 /r","N.S.","V","BMI2","","w,r,r","Y","64" +"SAVESSP","SAVESSP","savessp","F3 0F 01 EA","V","V","CET","","","","" +"SBB AL, imm8","SBBB imm8, AL","sbbb imm8, AL","1C ib","V","V","","","rw,r","Y","8" +"SBB r/m8, imm8","SBBB imm8, r/m8","sbbb imm8, r/m8","80 /3 ib","V","V","","","rw,r","Y","8" +"SBB r/m8, imm8","SBBB imm8, r/m8","sbbb imm8, r/m8","82 /3 ib","V","N.S.","","","rw,r","Y","8" +"SBB r/m8, imm8","SBBB imm8, r/m8","sbbb imm8, r/m8","REX 80 /3 ib","N.E.","V","","pseudo64","w,r","Y","8" +"SBB r8, r/m8","SBBB r/m8, r8","sbbb r/m8, r8","1A /r","V","V","","","rw,r","Y","8" +"SBB r8, r/m8","SBBB r/m8, r8","sbbb r/m8, r8","REX 1A /r","N.E.","V","","pseudo64","w,r","Y","8" +"SBB r/m8, r8","SBBB r8, r/m8","sbbb r8, r/m8","18 /r","V","V","","","rw,r","Y","8" +"SBB r/m8, r8","SBBB r8, r/m8","sbbb r8, r/m8","REX 18 /r","N.E.","V","","pseudo64","w,r","Y","8" +"SBB EAX, imm32","SBBL imm32, EAX","sbbl imm32, EAX","1D id","V","V","","operand32","rw,r","Y","32" +"SBB r/m32, imm32","SBBL imm32, r/m32","sbbl imm32, r/m32","81 /3 id","V","V","","operand32","rw,r","Y","32" +"SBB r/m32, imm8","SBBL imm8, r/m32","sbbl imm8, r/m32","83 /3 ib","V","V","","operand32","rw,r","Y","32" +"SBB r32, r/m32","SBBL r/m32, r32","sbbl r/m32, r32","1B /r","V","V","","operand32","rw,r","Y","32" +"SBB r/m32, r32","SBBL r32, r/m32","sbbl r32, r/m32","19 /r","V","V","","operand32","rw,r","Y","32" +"SBB RAX, imm32","SBBQ imm32, RAX","sbbq imm32, RAX","REX.W 1D id","N.S.","V","","","rw,r","Y","64" +"SBB r/m64, imm32","SBBQ imm32, r/m64","sbbq imm32, r/m64","REX.W 81 /3 id","N.S.","V","","","rw,r","Y","64" +"SBB r/m64, imm8","SBBQ imm8, r/m64","sbbq imm8, r/m64","REX.W 83 /3 ib","N.S.","V","","","rw,r","Y","64" +"SBB r64, r/m64","SBBQ r/m64, r64","sbbq r/m64, r64","REX.W 1B /r","N.S.","V","","","rw,r","Y","64" +"SBB r/m64, r64","SBBQ r64, r/m64","sbbq r64, r/m64","REX.W 19 /r","N.S.","V","","","rw,r","Y","64" +"SBB AX, imm16","SBBW imm16, AX","sbbw imm16, AX","1D iw","V","V","","operand16","rw,r","Y","16" +"SBB r/m16, imm16","SBBW imm16, r/m16","sbbw imm16, r/m16","81 /3 iw","V","V","","operand16","rw,r","Y","16" +"SBB r/m16, imm8","SBBW imm8, r/m16","sbbw imm8, r/m16","83 /3 ib","V","V","","operand16","rw,r","Y","16" +"SBB r16, r/m16","SBBW r/m16, r16","sbbw r/m16, r16","1B /r","V","V","","operand16","rw,r","Y","16" +"SBB r/m16, r16","SBBW r16, r/m16","sbbw r16, r/m16","19 /r","V","V","","operand16","rw,r","Y","16" +"SCASB","SCASB","scasb","AE","V","V","","","","","" +"SCASD","SCASL","scasl","AF","V","V","","operand32","","","" +"SCASQ","SCASQ","scasq","REX.W AF","N.S.","V","","","","","" +"SCASW","SCASW","scasw","AF","V","V","","operand16","","","" +"SETAE r/m8","SETCC r/m8","setae r/m8","0F 93 /r","V","V","","","w","","" +"SETNB r/m8","SETCC r/m8","setnb r/m8","0F 93 /r","V","V","","pseudo","r","","" +"SETNC r/m8","SETCC r/m8","setnc r/m8","0F 93 /r","V","V","","pseudo","r","","" +"SETAE r/m8","SETCC r/m8","setae r/m8","REX 0F 93 /r","N.E.","V","","pseudo64","r","","" +"SETNB r/m8","SETCC r/m8","setnb r/m8","REX 0F 93 /r","N.E.","V","","pseudo","r","","" +"SETNC r/m8","SETCC r/m8","setnc r/m8","REX 0F 93 /r","N.E.","V","","pseudo","r","","" +"SETB r/m8","SETCS r/m8","setb r/m8","0F 92 /r","V","V","","","w","","" +"SETC r/m8","SETCS r/m8","setc r/m8","0F 92 /r","V","V","","pseudo","r","","" +"SETNAE r/m8","SETCS r/m8","setnae r/m8","0F 92 /r","V","V","","pseudo","r","","" +"SETB r/m8","SETCS r/m8","setb r/m8","REX 0F 92 /r","N.E.","V","","pseudo64","r","","" +"SETC r/m8","SETCS r/m8","setc r/m8","REX 0F 92 /r","N.E.","V","","pseudo","r","","" +"SETNAE r/m8","SETCS r/m8","setnae r/m8","REX 0F 92 /r","N.E.","V","","pseudo","r","","" +"SETE r/m8","SETEQ r/m8","sete r/m8","0F 94 /r","V","V","","","w","","" +"SETZ r/m8","SETEQ r/m8","setz r/m8","0F 94 /r","V","V","","pseudo","r","","" +"SETE r/m8","SETEQ r/m8","sete r/m8","REX 0F 94 /r","N.E.","V","","pseudo64","r","","" +"SETZ r/m8","SETEQ r/m8","setz r/m8","REX 0F 94 /r","N.E.","V","","pseudo","r","","" +"SETGE r/m8","SETGE r/m8","setge r/m8","0F 9D /r","V","V","","","w","","" +"SETNL r/m8","SETGE r/m8","setnl r/m8","0F 9D /r","V","V","","pseudo","r","","" +"SETGE r/m8","SETGE r/m8","setge r/m8","REX 0F 9D /r","N.E.","V","","pseudo64","r","","" +"SETNL r/m8","SETGE r/m8","setnl r/m8","REX 0F 9D /r","N.E.","V","","pseudo","r","","" +"SETG r/m8","SETGT r/m8","setg r/m8","0F 9F /r","V","V","","","w","","" +"SETNLE r/m8","SETGT r/m8","setnle r/m8","0F 9F /r","V","V","","pseudo","r","","" +"SETG r/m8","SETGT r/m8","setg r/m8","REX 0F 9F /r","N.E.","V","","pseudo64","r","","" +"SETNLE r/m8","SETGT r/m8","setnle r/m8","REX 0F 9F /r","N.E.","V","","pseudo","r","","" +"SETA r/m8","SETHI r/m8","seta r/m8","0F 97 /r","V","V","","","w","","" +"SETNBE r/m8","SETHI r/m8","setnbe r/m8","0F 97 /r","V","V","","pseudo","r","","" +"SETA r/m8","SETHI r/m8","seta r/m8","REX 0F 97 /r","N.E.","V","","pseudo64","r","","" +"SETNBE r/m8","SETHI r/m8","setnbe r/m8","REX 0F 97 /r","N.E.","V","","pseudo","r","","" +"SETLE r/m8","SETLE r/m8","setle r/m8","0F 9E /r","V","V","","","w","","" +"SETNG r/m8","SETLE r/m8","setng r/m8","0F 9E /r","V","V","","pseudo","r","","" +"SETLE r/m8","SETLE r/m8","setle r/m8","REX 0F 9E /r","N.E.","V","","pseudo64","r","","" +"SETNG r/m8","SETLE r/m8","setng r/m8","REX 0F 9E /r","N.E.","V","","pseudo","r","","" +"SETBE r/m8","SETLS r/m8","setbe r/m8","0F 96 /r","V","V","","","w","","" +"SETNA r/m8","SETLS r/m8","setna r/m8","0F 96 /r","V","V","","pseudo","r","","" +"SETBE r/m8","SETLS r/m8","setbe r/m8","REX 0F 96 /r","N.E.","V","","pseudo64","r","","" +"SETNA r/m8","SETLS r/m8","setna r/m8","REX 0F 96 /r","N.E.","V","","pseudo","r","","" +"SETL r/m8","SETLT r/m8","setl r/m8","0F 9C /r","V","V","","","w","","" +"SETNGE r/m8","SETLT r/m8","setnge r/m8","0F 9C /r","V","V","","pseudo","r","","" +"SETL r/m8","SETLT r/m8","setl r/m8","REX 0F 9C /r","N.E.","V","","pseudo64","r","","" +"SETNGE r/m8","SETLT r/m8","setnge r/m8","REX 0F 9C /r","N.E.","V","","pseudo","r","","" +"SETS r/m8","SETMI r/m8","sets r/m8","0F 98 /r","V","V","","","w","","" +"SETS r/m8","SETMI r/m8","sets r/m8","REX 0F 98 /r","N.E.","V","","pseudo64","r","","" +"SETNE r/m8","SETNE r/m8","setne r/m8","0F 95 /r","V","V","","","w","","" +"SETNZ r/m8","SETNE r/m8","setnz r/m8","0F 95 /r","V","V","","pseudo","r","","" +"SETNE r/m8","SETNE r/m8","setne r/m8","REX 0F 95 /r","N.E.","V","","pseudo64","r","","" +"SETNZ r/m8","SETNE r/m8","setnz r/m8","REX 0F 95 /r","N.E.","V","","pseudo","r","","" +"SETNO r/m8","SETOC r/m8","setno r/m8","0F 91 /r","V","V","","","w","","" +"SETNO r/m8","SETOC r/m8","setno r/m8","REX 0F 91 /r","N.E.","V","","pseudo64","r","","" +"SETO r/m8","SETOS r/m8","seto r/m8","0F 90 /r","V","V","","","w","","" +"SETO r/m8","SETOS r/m8","seto r/m8","REX 0F 90 /r","N.E.","V","","pseudo64","r","","" +"SETNP r/m8","SETPC r/m8","setnp r/m8","0F 9B /r","V","V","","","w","","" +"SETPO r/m8","SETPC r/m8","setpo r/m8","0F 9B /r","V","V","","pseudo","r","","" +"SETNP r/m8","SETPC r/m8","setnp r/m8","REX 0F 9B /r","N.E.","V","","pseudo64","r","","" +"SETPO r/m8","SETPC r/m8","setpo r/m8","REX 0F 9B /r","N.E.","V","","pseudo","r","","" +"SETNS r/m8","SETPL r/m8","setns r/m8","0F 99 /r","V","V","","","w","","" +"SETNS r/m8","SETPL r/m8","setns r/m8","REX 0F 99 /r","N.E.","V","","pseudo64","r","","" +"SETP r/m8","SETPS r/m8","setp r/m8","0F 9A /r","V","V","","","w","","" +"SETPE r/m8","SETPS r/m8","setpe r/m8","0F 9A /r","V","V","","pseudo","r","","" +"SETP r/m8","SETPS r/m8","setp r/m8","REX 0F 9A /r","N.E.","V","","pseudo64","r","","" +"SETPE r/m8","SETPS r/m8","setpe r/m8","REX 0F 9A /r","N.E.","V","","pseudo","r","","" +"SETSSBSY","SETSSBSY","setssbsy","F3 0F 01 E8","V","V","CET","","","","" +"SFENCE","SFENCE","sfence","0F AE /7","V","V","SSE","","","","" +"SGDT m16&32","SGDT m16&32","sgdt m16&32","0F 01 /0","V","N.S.","","modrm_memonly","w","","" +"SGDT m16&64","SGDT m16&64","sgdt m16&64","0F 01 /0","N.S.","V","","default64,modrm_memonly","w","","" +"SHA1MSG1 xmm1, xmm2/m128","SHA1MSG1 xmm2/m128, xmm1","sha1msg1 xmm2/m128, xmm1","0F 38 C9 /r","V","V","SHA","","rw,r","","" +"SHA1MSG2 xmm1, xmm2/m128","SHA1MSG2 xmm2/m128, xmm1","sha1msg2 xmm2/m128, xmm1","0F 38 CA /r","V","V","SHA","","rw,r","","" +"SHA1NEXTE xmm1, xmm2/m128","SHA1NEXTE xmm2/m128, xmm1","sha1nexte xmm2/m128, xmm1","0F 38 C8 /r","V","V","SHA","","rw,r","","" +"SHA1RNDS4 xmm1, xmm2/m128, imm8u:2","SHA1RNDS4 imm8u:2, xmm2/m128, xmm1","sha1rnds4 imm8u:2, xmm2/m128, xmm1","0F 3A CC /r ib","V","V","SHA","","rw,r,r","","" +"SHA256MSG1 xmm1, xmm2/m128","SHA256MSG1 xmm2/m128, xmm1","sha256msg1 xmm2/m128, xmm1","0F 38 CC /r","V","V","SHA","","rw,r","","" +"SHA256MSG2 xmm1, xmm2/m128","SHA256MSG2 xmm2/m128, xmm1","sha256msg2 xmm2/m128, xmm1","0F 38 CD /r","V","V","SHA","","rw,r","","" +"SHA256RNDS2 xmm1, xmm2/m128, ","SHA256RNDS2 , xmm2/m128, xmm1","sha256rnds2 , xmm2/m128, xmm1","0F 38 CB /r","V","V","SHA","","rw,r,r","","" +"SHL r/m8, 1","SHLB 1, r/m8","shlb 1, r/m8","D0 /4","V","V","","","rw,r","Y","8" +"SHL r/m8, 1","SHLB 1, r/m8","shlb 1, r/m8","D0 /6","V","V","","","rw,r","Y","8" +"SHL r/m8, 1","SHLB 1, r/m8","shlb 1, r/m8","REX D0 /4","N.E.","V","","pseudo64","rw,r","Y","8" +"SHL r/m8, CL","SHLB CL, r/m8","shlb CL, r/m8","D2 /4","V","V","","","rw,r","Y","8" +"SHL r/m8, CL","SHLB CL, r/m8","shlb CL, r/m8","D2 /6","V","V","","","rw,r","Y","8" +"SHL r/m8, CL","SHLB CL, r/m8","shlb CL, r/m8","REX D2 /4","N.E.","V","","pseudo64","rw,r","Y","8" +"SHL r/m8, imm8","SHLB imm8, r/m8","shlb imm8, r/m8","REX C0 /4 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"SHL r/m8, imm8u","SHLB imm8u, r/m8","shlb imm8u, r/m8","C0 /4 ib","V","V","","","rw,r","Y","8" +"SHL r/m8, imm8u","SHLB imm8u, r/m8","shlb imm8u, r/m8","C0 /6 ib","V","V","","","rw,r","Y","8" +"SHL r/m32, 1","SHLL 1, r/m32","shll 1, r/m32","D1 /4","V","V","","operand32","rw,r","Y","32" +"SHL r/m32, 1","SHLL 1, r/m32","shll 1, r/m32","D1 /6","V","V","","operand32","rw,r","Y","32" +"SHL r/m32, CL","SHLL CL, r/m32","shll CL, r/m32","D3 /4","V","V","","operand32","rw,r","Y","32" +"SHL r/m32, CL","SHLL CL, r/m32","shll CL, r/m32","D3 /6","V","V","","operand32","rw,r","Y","32" +"SHLD r/m32, r32, CL","SHLL CL, r32, r/m32","shldl CL, r32, r/m32","0F A5 /r","V","V","","operand32","rw,r,r","Y","32" +"SHL r/m32, imm8u","SHLL imm8u, r/m32","shll imm8u, r/m32","C1 /4 ib","V","V","","operand32","rw,r","Y","32" +"SHL r/m32, imm8u","SHLL imm8u, r/m32","shll imm8u, r/m32","C1 /6 ib","V","V","","operand32","rw,r","Y","32" +"SHLD r/m32, r32, imm8u","SHLL imm8u, r32, r/m32","shldl imm8u, r32, r/m32","0F A4 /r ib","V","V","","operand32","rw,r,r","Y","32" +"SHL r/m64, 1","SHLQ 1, r/m64","shlq 1, r/m64","REX.W D1 /4","N.S.","V","","","rw,r","Y","64" +"SHL r/m64, 1","SHLQ 1, r/m64","shlq 1, r/m64","REX.W D1 /6","N.S.","V","","","rw,r","Y","64" +"SHL r/m64, CL","SHLQ CL, r/m64","shlq CL, r/m64","REX.W D3 /4","N.S.","V","","","rw,r","Y","64" +"SHL r/m64, CL","SHLQ CL, r/m64","shlq CL, r/m64","REX.W D3 /6","N.S.","V","","","rw,r","Y","64" +"SHLD r/m64, r64, CL","SHLQ CL, r64, r/m64","shldq CL, r64, r/m64","REX.W 0F A5 /r","N.S.","V","","","rw,r,r","Y","64" +"SHL r/m64, imm8u","SHLQ imm8u, r/m64","shlq imm8u, r/m64","REX.W C1 /4 ib","N.S.","V","","","rw,r","Y","64" +"SHL r/m64, imm8u","SHLQ imm8u, r/m64","shlq imm8u, r/m64","REX.W C1 /6 ib","N.S.","V","","","rw,r","Y","64" +"SHLD r/m64, r64, imm8u","SHLQ imm8u, r64, r/m64","shldq imm8u, r64, r/m64","REX.W 0F A4 /r ib","N.S.","V","","","rw,r,r","Y","64" +"SHL r/m16, 1","SHLW 1, r/m16","shlw 1, r/m16","D1 /4","V","V","","operand16","rw,r","Y","16" +"SHL r/m16, 1","SHLW 1, r/m16","shlw 1, r/m16","D1 /6","V","V","","operand16","rw,r","Y","16" +"SHL r/m16, CL","SHLW CL, r/m16","shlw CL, r/m16","D3 /4","V","V","","operand16","rw,r","Y","16" +"SHL r/m16, CL","SHLW CL, r/m16","shlw CL, r/m16","D3 /6","V","V","","operand16","rw,r","Y","16" +"SHLD r/m16, r16, CL","SHLW CL, r16, r/m16","shldw CL, r16, r/m16","0F A5 /r","V","V","","operand16","rw,r,r","Y","16" +"SHL r/m16, imm8u","SHLW imm8u, r/m16","shlw imm8u, r/m16","C1 /4 ib","V","V","","operand16","rw,r","Y","16" +"SHL r/m16, imm8u","SHLW imm8u, r/m16","shlw imm8u, r/m16","C1 /6 ib","V","V","","operand16","rw,r","Y","16" +"SHLD r/m16, r16, imm8u","SHLW imm8u, r16, r/m16","shldw imm8u, r16, r/m16","0F A4 /r ib","V","V","","operand16","rw,r,r","Y","16" +"SHLX r32, r/m32, r32V","SHLXL r32V, r/m32, r32","shlxl r32V, r/m32, r32","VEX.NDS.128.66.0F38.W0 F7 /r","V","V","BMI2","","w,r,r","Y","32" +"SHLX r64, r/m64, r64V","SHLXQ r64V, r/m64, r64","shlxq r64V, r/m64, r64","VEX.NDS.128.66.0F38.W1 F7 /r","N.S.","V","BMI2","","w,r,r","Y","64" +"SHR r/m8, 1","SHRB 1, r/m8","shrb 1, r/m8","D0 /5","V","V","","","rw,r","Y","8" +"SHR r/m8, 1","SHRB 1, r/m8","shrb 1, r/m8","REX D0 /5","N.E.","V","","pseudo64","rw,r","Y","8" +"SHR r/m8, CL","SHRB CL, r/m8","shrb CL, r/m8","D2 /5","V","V","","","rw,r","Y","8" +"SHR r/m8, CL","SHRB CL, r/m8","shrb CL, r/m8","REX D2 /5","N.E.","V","","pseudo64","rw,r","Y","8" +"SHR r/m8, imm8","SHRB imm8, r/m8","shrb imm8, r/m8","REX C0 /5 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"SHR r/m8, imm8u","SHRB imm8u, r/m8","shrb imm8u, r/m8","C0 /5 ib","V","V","","","rw,r","Y","8" +"SHR r/m32, 1","SHRL 1, r/m32","shrl 1, r/m32","D1 /5","V","V","","operand32","rw,r","Y","32" +"SHR r/m32, CL","SHRL CL, r/m32","shrl CL, r/m32","D3 /5","V","V","","operand32","rw,r","Y","32" +"SHRD r/m32, r32, CL","SHRL CL, r32, r/m32","shrdl CL, r32, r/m32","0F AD /r","V","V","","operand32","rw,r,r","Y","32" +"SHR r/m32, imm8u","SHRL imm8u, r/m32","shrl imm8u, r/m32","C1 /5 ib","V","V","","operand32","rw,r","Y","32" +"SHRD r/m32, r32, imm8u","SHRL imm8u, r32, r/m32","shrdl imm8u, r32, r/m32","0F AC /r ib","V","V","","operand32","rw,r,r","Y","32" +"SHR r/m64, 1","SHRQ 1, r/m64","shrq 1, r/m64","REX.W D1 /5","N.S.","V","","","rw,r","Y","64" +"SHR r/m64, CL","SHRQ CL, r/m64","shrq CL, r/m64","REX.W D3 /5","N.S.","V","","","rw,r","Y","64" +"SHRD r/m64, r64, CL","SHRQ CL, r64, r/m64","shrdq CL, r64, r/m64","REX.W 0F AD /r","N.S.","V","","","rw,r,r","Y","64" +"SHR r/m64, imm8u","SHRQ imm8u, r/m64","shrq imm8u, r/m64","REX.W C1 /5 ib","N.S.","V","","","rw,r","Y","64" +"SHRD r/m64, r64, imm8u","SHRQ imm8u, r64, r/m64","shrdq imm8u, r64, r/m64","REX.W 0F AC /r ib","N.S.","V","","","rw,r,r","Y","64" +"SHR r/m16, 1","SHRW 1, r/m16","shrw 1, r/m16","D1 /5","V","V","","operand16","rw,r","Y","16" +"SHR r/m16, CL","SHRW CL, r/m16","shrw CL, r/m16","D3 /5","V","V","","operand16","rw,r","Y","16" +"SHRD r/m16, r16, CL","SHRW CL, r16, r/m16","shrdw CL, r16, r/m16","0F AD /r","V","V","","operand16","rw,r,r","Y","16" +"SHR r/m16, imm8u","SHRW imm8u, r/m16","shrw imm8u, r/m16","C1 /5 ib","V","V","","operand16","rw,r","Y","16" +"SHRD r/m16, r16, imm8u","SHRW imm8u, r16, r/m16","shrdw imm8u, r16, r/m16","0F AC /r ib","V","V","","operand16","rw,r,r","Y","16" +"SHRX r32, r/m32, r32V","SHRXL r32V, r/m32, r32","shrxl r32V, r/m32, r32","VEX.NDS.128.F2.0F38.W0 F7 /r","V","V","BMI2","","w,r,r","Y","32" +"SHRX r64, r/m64, r64V","SHRXQ r64V, r/m64, r64","shrxq r64V, r/m64, r64","VEX.NDS.128.F2.0F38.W1 F7 /r","N.S.","V","BMI2","","w,r,r","Y","64" +"SHUFPD xmm1, xmm2/m128, imm8u","SHUFPD imm8u, xmm2/m128, xmm1","shufpd imm8u, xmm2/m128, xmm1","66 0F C6 /r ib","V","V","SSE2","","rw,r,r","","" +"SHUFPS xmm1, xmm2/m128, imm8u","SHUFPS imm8u, xmm2/m128, xmm1","shufps imm8u, xmm2/m128, xmm1","0F C6 /r ib","V","V","SSE","","rw,r,r","","" +"SIDT m16&32","SIDT m16&32","sidt m16&32","0F 01 /1","V","N.S.","","modrm_memonly","w","","" +"SIDT m16&64","SIDT m16&64","sidt m16&64","0F 01 /1","N.S.","V","","default64,modrm_memonly","w","","" +"SKINIT EAX","SKINIT EAX","skinit EAX","0F 01 DE","V","V","SVM","amd,modrm_regonly","r","","" +"SLDT r/m16","SLDTW r/m16","sldtw r/m16","0F 00 /0","V","V","","operand16","w","Y","16" +"SLDT r32/m16","SLDT{L/W} r32/m16","sldt{l/w} r32/m16","0F 00 /0","V","V","","operand32","w","Y","" +"SLDT r64/m16","SLDT{Q/W} r64/m16","sldt{q/w} r64/m16","REX.W 0F 00 /0","N.S.","V","","","w","Y","" +"SLWPCB rmr32","SLWPCBL rmr32","slwpcbl rmr32","XOP.128.09.W0 12 /1","V","V","XOP","amd,modrm_regonly,operand16,operand32","w","Y","32" +"SLWPCB rmr64","SLWPCBQ rmr64","slwpcbq rmr64","XOP.128.09.W0 12 /1","N.S.","V","XOP","amd,modrm_regonly,operand64","w","Y","64" +"SMSW r/m16","SMSWW r/m16","smsww r/m16","0F 01 /4","V","V","","operand16","w","Y","16" +"SMSW r32/m16","SMSW{L/W} r32/m16","smsw{l/w} r32/m16","0F 01 /4","V","V","","operand32","w","Y","" +"SMSW r64/m16","SMSW{Q/W} r64/m16","smsw{q/w} r64/m16","REX.W 0F 01 /4","N.S.","V","","","w","Y","" +"SQRTPD xmm1, xmm2/m128","SQRTPD xmm2/m128, xmm1","sqrtpd xmm2/m128, xmm1","66 0F 51 /r","V","V","SSE2","","w,r","","" +"SQRTPS xmm1, xmm2/m128","SQRTPS xmm2/m128, xmm1","sqrtps xmm2/m128, xmm1","0F 51 /r","V","V","SSE","","w,r","","" +"SQRTSD xmm1, xmm2/m64","SQRTSD xmm2/m64, xmm1","sqrtsd xmm2/m64, xmm1","F2 0F 51 /r","V","V","SSE2","","w,r","","" +"SQRTSS xmm1, xmm2/m32","SQRTSS xmm2/m32, xmm1","sqrtss xmm2/m32, xmm1","F3 0F 51 /r","V","V","SSE","","w,r","","" +"STAC","STAC","stac","0F 01 CB","V","V","","","","","" +"STC","STC","stc","F9","V","V","","","","","" +"STD","STD","std","FD","V","V","","","","","" +"STGI","STGI","stgi","0F 01 DC","V","V","SVM","amd","","","" +"STI","STI","sti","FB","V","V","","","","","" +"STMXCSR m32","STMXCSR m32","stmxcsr m32","0F AE /3","V","V","SSE","modrm_memonly","w","","" +"STOSB","STOSB","stosb","AA","V","V","","","","","" +"STOSD","STOSL","stosl","AB","V","V","","operand32","","","" +"STOSQ","STOSQ","stosq","REX.W AB","N.S.","V","","","","","" +"STOSW","STOSW","stosw","AB","V","V","","operand16","","","" +"STR r/m16","STRW r/m16","strw r/m16","0F 00 /1","V","V","","operand16","w","Y","16" +"STR r32/m16","STR{L/W} r32/m16","str{l/w} r32/m16","0F 00 /1","V","V","","operand32","w","Y","" +"STR r64/m16","STR{Q/W} r64/m16","str{q/w} r64/m16","REX.W 0F 00 /1","N.S.","V","","","w","Y","" +"SUB AL, imm8","SUBB imm8, AL","subb imm8, AL","2C ib","V","V","","","rw,r","Y","8" +"SUB r/m8, imm8","SUBB imm8, r/m8","subb imm8, r/m8","80 /5 ib","V","V","","","rw,r","Y","8" +"SUB r/m8, imm8","SUBB imm8, r/m8","subb imm8, r/m8","82 /5 ib","V","N.S.","","","rw,r","Y","8" +"SUB r/m8, imm8","SUBB imm8, r/m8","subb imm8, r/m8","REX 80 /5 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"SUB r8, r/m8","SUBB r/m8, r8","subb r/m8, r8","2A /r","V","V","","","rw,r","Y","8" +"SUB r8, r/m8","SUBB r/m8, r8","subb r/m8, r8","REX 2A /r","N.E.","V","","pseudo64","rw,r","Y","8" +"SUB r/m8, r8","SUBB r8, r/m8","subb r8, r/m8","28 /r","V","V","","","rw,r","Y","8" +"SUB r/m8, r8","SUBB r8, r/m8","subb r8, r/m8","REX 28 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"SUB EAX, imm32","SUBL imm32, EAX","subl imm32, EAX","2D id","V","V","","operand32","rw,r","Y","32" +"SUB r/m32, imm32","SUBL imm32, r/m32","subl imm32, r/m32","81 /5 id","V","V","","operand32","rw,r","Y","32" +"SUB r/m32, imm8","SUBL imm8, r/m32","subl imm8, r/m32","83 /5 ib","V","V","","operand32","rw,r","Y","32" +"SUB r32, r/m32","SUBL r/m32, r32","subl r/m32, r32","2B /r","V","V","","operand32","rw,r","Y","32" +"SUB r/m32, r32","SUBL r32, r/m32","subl r32, r/m32","29 /r","V","V","","operand32","rw,r","Y","32" +"SUBPD xmm1, xmm2/m128","SUBPD xmm2/m128, xmm1","subpd xmm2/m128, xmm1","66 0F 5C /r","V","V","SSE2","","rw,r","","" +"SUBPS xmm1, xmm2/m128","SUBPS xmm2/m128, xmm1","subps xmm2/m128, xmm1","0F 5C /r","V","V","SSE","","rw,r","","" +"SUB RAX, imm32","SUBQ imm32, RAX","subq imm32, RAX","REX.W 2D id","N.S.","V","","","rw,r","Y","64" +"SUB r/m64, imm32","SUBQ imm32, r/m64","subq imm32, r/m64","REX.W 81 /5 id","N.S.","V","","","rw,r","Y","64" +"SUB r/m64, imm8","SUBQ imm8, r/m64","subq imm8, r/m64","REX.W 83 /5 ib","N.S.","V","","","rw,r","Y","64" +"SUB r64, r/m64","SUBQ r/m64, r64","subq r/m64, r64","REX.W 2B /r","N.S.","V","","","rw,r","Y","64" +"SUB r/m64, r64","SUBQ r64, r/m64","subq r64, r/m64","REX.W 29 /r","N.S.","V","","","rw,r","Y","64" +"SUBSD xmm1, xmm2/m64","SUBSD xmm2/m64, xmm1","subsd xmm2/m64, xmm1","F2 0F 5C /r","V","V","SSE2","","rw,r","","" +"SUBSS xmm1, xmm2/m32","SUBSS xmm2/m32, xmm1","subss xmm2/m32, xmm1","F3 0F 5C /r","V","V","SSE","","rw,r","","" +"SUB AX, imm16","SUBW imm16, AX","subw imm16, AX","2D iw","V","V","","operand16","rw,r","Y","16" +"SUB r/m16, imm16","SUBW imm16, r/m16","subw imm16, r/m16","81 /5 iw","V","V","","operand16","rw,r","Y","16" +"SUB r/m16, imm8","SUBW imm8, r/m16","subw imm8, r/m16","83 /5 ib","V","V","","operand16","rw,r","Y","16" +"SUB r16, r/m16","SUBW r/m16, r16","subw r/m16, r16","2B /r","V","V","","operand16","rw,r","Y","16" +"SUB r/m16, r16","SUBW r16, r/m16","subw r16, r/m16","29 /r","V","V","","operand16","rw,r","Y","16" +"SWAPGS","SWAPGS","swapgs","0F 01 F8","N.S.","V","","","","","" +"SYSCALL","SYSCALL","syscall","0F 05","N.S.","V","","default64","","","" +"SYSCALL","SYSCALL","syscall","0F 05","V","N.S.","AMD","amd","","","" +"SYSENTER","SYSENTER","sysenter","0F 34","V","V","PPRO","","","","" +"SYSEXIT","SYSEXIT","sysexit","0F 35","V","V","PPRO","","","","" +"SYSEXIT","SYSEXIT","sysexit","REX.W 0F 35","N.E.","V","","pseudo","","","" +"SYSRET","SYSRET","sysretw/sysretl/sysretl","0F 07","V","N.S.","AMD","amd","","","" +"SYSRET","SYSRET","sysretw/sysretl/sysretl","0F 07","N.S.","V","","operand32,operand64","","","" +"SYSRET","SYSRET","sysretw/sysretl/sysretl","REX.W 0F 07","I","V","","pseudo","","","" +"T1MSKC r32V, r/m32","T1MSKCL r/m32, r32V","t1mskcl r/m32, r32V","XOP.NDD.128.09.WIG 01 /7","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"T1MSKC r64V, r/m64","T1MSKCQ r/m64, r64V","t1mskcq r/m64, r64V","XOP.NDD.128.09.WIG 01 /7","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"TEST AL, imm8","TESTB imm8, AL","testb imm8, AL","A8 ib","V","V","","","r,r","Y","8" +"TEST r/m8, imm8","TESTB imm8, r/m8","testb imm8, r/m8","F6 /0 ib","V","V","","","r,r","Y","8" +"TEST r/m8, imm8","TESTB imm8, r/m8","testb imm8, r/m8","F6 /1 ib","V","V","","","r,r","Y","8" +"TEST r/m8, imm8","TESTB imm8, r/m8","testb imm8, r/m8","REX F6 /0 ib","N.E.","V","","pseudo64","r,r","Y","8" +"TEST r/m8, r8","TESTB r8, r/m8","testb r8, r/m8","84 /r","V","V","","","r,r","Y","8" +"TEST r/m8, r8","TESTB r8, r/m8","testb r8, r/m8","REX 84 /r","N.E.","V","","pseudo64","r,r","Y","8" +"TEST EAX, imm32","TESTL imm32, EAX","testl imm32, EAX","A9 id","V","V","","operand32","r,r","Y","32" +"TEST r/m32, imm32","TESTL imm32, r/m32","testl imm32, r/m32","F7 /0 id","V","V","","operand32","r,r","Y","32" +"TEST r/m32, imm32","TESTL imm32, r/m32","testl imm32, r/m32","F7 /1 id","V","V","","operand32","r,r","Y","32" +"TEST r/m32, r32","TESTL r32, r/m32","testl r32, r/m32","85 /r","V","V","","operand32","r,r","Y","32" +"TEST RAX, imm32","TESTQ imm32, RAX","testq imm32, RAX","REX.W A9 id","N.S.","V","","","r,r","Y","64" +"TEST r/m64, imm32","TESTQ imm32, r/m64","testq imm32, r/m64","REX.W F7 /0 id","N.S.","V","","","r,r","Y","64" +"TEST r/m64, imm32","TESTQ imm32, r/m64","testq imm32, r/m64","REX.W F7 /1 id","N.S.","V","","","r,r","Y","64" +"TEST r/m64, r64","TESTQ r64, r/m64","testq r64, r/m64","REX.W 85 /r","N.S.","V","","","r,r","Y","64" +"TEST AX, imm16","TESTW imm16, AX","testw imm16, AX","A9 iw","V","V","","operand16","r,r","Y","16" +"TEST r/m16, imm16","TESTW imm16, r/m16","testw imm16, r/m16","F7 /0 iw","V","V","","operand16","r,r","Y","16" +"TEST r/m16, imm16","TESTW imm16, r/m16","testw imm16, r/m16","F7 /1 iw","V","V","","operand16","r,r","Y","16" +"TEST r/m16, r16","TESTW r16, r/m16","testw r16, r/m16","85 /r","V","V","","operand16","r,r","Y","16" +"TZCNT r32, r/m32","TZCNTL r/m32, r32","tzcntl r/m32, r32","F3 0F BC /r","V","V","BMI1","operand32","w,r","Y","32" +"TZCNT r64, r/m64","TZCNTQ r/m64, r64","tzcntq r/m64, r64","F3 REX.W 0F BC /r","N.S.","V","BMI1","","w,r","Y","64" +"TZCNT r16, r/m16","TZCNTW r/m16, r16","tzcntw r/m16, r16","F3 0F BC /r","V","V","BMI1","operand16","w,r","Y","16" +"TZMSK r32V, r/m32","TZMSKL r/m32, r32V","tzmskl r/m32, r32V","XOP.NDD.128.09.WIG 01 /4","V","V","TBM","amd,operand16,operand32","w,r","Y","32" +"TZMSK r64V, r/m64","TZMSKQ r/m64, r64V","tzmskq r/m64, r64V","XOP.NDD.128.09.WIG 01 /4","N.S.","V","TBM","amd,operand64","w,r","Y","64" +"UCOMISD xmm1, xmm2/m64","UCOMISD xmm2/m64, xmm1","ucomisd xmm2/m64, xmm1","66 0F 2E /r","V","V","SSE2","","r,r","","" +"UCOMISS xmm1, xmm2/m32","UCOMISS xmm2/m32, xmm1","ucomiss xmm2/m32, xmm1","0F 2E /r","V","V","SSE","","r,r","","" +"UD0 r32, r/m32","UD0 r/m32, r32","ud0 r/m32, r32","0F FF /r","V","V","PPRO","","r,r","","" +"UD1 r32, r/m32","UD1 r/m32, r32","ud1 r/m32, r32","0F B9 /r","V","V","PPRO","","r,r","","" +"UD2","UD2","ud2","0F 0B","V","V","PPRO","","","","" +"UNPCKHPD xmm1, xmm2/m128","UNPCKHPD xmm2/m128, xmm1","unpckhpd xmm2/m128, xmm1","66 0F 15 /r","V","V","SSE2","","rw,r","","" +"UNPCKHPS xmm1, xmm2/m128","UNPCKHPS xmm2/m128, xmm1","unpckhps xmm2/m128, xmm1","0F 15 /r","V","V","SSE","","rw,r","","" +"UNPCKLPD xmm1, xmm2/m128","UNPCKLPD xmm2/m128, xmm1","unpcklpd xmm2/m128, xmm1","66 0F 14 /r","V","V","SSE2","","rw,r","","" +"UNPCKLPS xmm1, xmm2/m128","UNPCKLPS xmm2/m128, xmm1","unpcklps xmm2/m128, xmm1","0F 14 /r","V","V","SSE","","rw,r","","" +"V4FMADDPS zmm1, {k}{z}, zmmV+3, m128","V4FMADDPS m128, zmmV+3, {k}{z}, zmm1","v4fmaddps m128, zmmV+3, {k}{z}, zmm1","EVEX.DDS.512.F2.0F38.W0 9A /r","V","V","AVX512_4FMAPS","modrm_memonly,scale16","rw,r,r,r","","" +"V4FMADDSS xmm1, {k}{z}, xmmV+3, m128","V4FMADDSS m128, xmmV+3, {k}{z}, xmm1","v4fmaddss m128, xmmV+3, {k}{z}, xmm1","EVEX.DDS.LIG.F2.0F38.W0 9B /r","V","V","AVX512_4FMAPS","modrm_memonly,scale16","rw,r,r,r","","" +"V4FNMADDPS zmm1, {k}{z}, zmmV+3, m128","V4FNMADDPS m128, zmmV+3, {k}{z}, zmm1","v4fnmaddps m128, zmmV+3, {k}{z}, zmm1","EVEX.DDS.512.F2.0F38.W0 AA /r","V","V","AVX512_4FMAPS","modrm_memonly,scale16","rw,r,r,r","","" +"V4FNMADDSS xmm1, {k}{z}, xmmV+3, m128","V4FNMADDSS m128, xmmV+3, {k}{z}, xmm1","v4fnmaddss m128, xmmV+3, {k}{z}, xmm1","EVEX.DDS.LIG.F2.0F38.W0 AB /r","V","V","AVX512_4FMAPS","modrm_memonly,scale16","rw,r,r,r","","" +"VADDPD xmm1, xmmV, xmm2/m128","VADDPD xmm2/m128, xmmV, xmm1","vaddpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 58 /r","V","V","AVX","","w,r,r","","" +"VADDPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VADDPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vaddpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 58 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VADDPD ymm1, ymmV, ymm2/m256","VADDPD ymm2/m256, ymmV, ymm1","vaddpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 58 /r","V","V","AVX","","w,r,r","","" +"VADDPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VADDPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vaddpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 58 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VADDPD zmm1{er}, {k}{z}, zmmV, zmm2","VADDPD zmm2, zmmV, {k}{z}, zmm1{er}","vaddpd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.66.0F.W1 58 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VADDPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VADDPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vaddpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 58 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VADDPS xmm1, xmmV, xmm2/m128","VADDPS xmm2/m128, xmmV, xmm1","vaddps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 58 /r","V","V","AVX","","w,r,r","","" +"VADDPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VADDPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vaddps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 58 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VADDPS ymm1, ymmV, ymm2/m256","VADDPS ymm2/m256, ymmV, ymm1","vaddps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 58 /r","V","V","AVX","","w,r,r","","" +"VADDPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VADDPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vaddps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 58 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VADDPS zmm1{er}, {k}{z}, zmmV, zmm2","VADDPS zmm2, zmmV, {k}{z}, zmm1{er}","vaddps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.0F.W0 58 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VADDPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VADDPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vaddps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 58 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VADDSD xmm1{er}, {k}{z}, xmmV, xmm2","VADDSD xmm2, xmmV, {k}{z}, xmm1{er}","vaddsd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F2.0F.W1 58 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VADDSD xmm1, xmmV, xmm2/m64","VADDSD xmm2/m64, xmmV, xmm1","vaddsd xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 58 /r","V","V","AVX","","w,r,r","","" +"VADDSD xmm1, {k}{z}, xmmV, xmm2/m64","VADDSD xmm2/m64, xmmV, {k}{z}, xmm1","vaddsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 58 /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VADDSS xmm1{er}, {k}{z}, xmmV, xmm2","VADDSS xmm2, xmmV, {k}{z}, xmm1{er}","vaddss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F3.0F.W0 58 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VADDSS xmm1, xmmV, xmm2/m32","VADDSS xmm2/m32, xmmV, xmm1","vaddss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 58 /r","V","V","AVX","","w,r,r","","" +"VADDSS xmm1, {k}{z}, xmmV, xmm2/m32","VADDSS xmm2/m32, xmmV, {k}{z}, xmm1","vaddss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 58 /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VADDSUBPD xmm1, xmmV, xmm2/m128","VADDSUBPD xmm2/m128, xmmV, xmm1","vaddsubpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG D0 /r","V","V","AVX","","w,r,r","","" +"VADDSUBPD ymm1, ymmV, ymm2/m256","VADDSUBPD ymm2/m256, ymmV, ymm1","vaddsubpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG D0 /r","V","V","AVX","","w,r,r","","" +"VADDSUBPS xmm1, xmmV, xmm2/m128","VADDSUBPS xmm2/m128, xmmV, xmm1","vaddsubps xmm2/m128, xmmV, xmm1","VEX.NDS.128.F2.0F.WIG D0 /r","V","V","AVX","","w,r,r","","" +"VADDSUBPS ymm1, ymmV, ymm2/m256","VADDSUBPS ymm2/m256, ymmV, ymm1","vaddsubps ymm2/m256, ymmV, ymm1","VEX.NDS.256.F2.0F.WIG D0 /r","V","V","AVX","","w,r,r","","" +"VAESDEC xmm1, xmmV, xmm2/m128","VAESDEC xmm2/m128, xmmV, xmm1","vaesdec xmm2/m128, xmmV, xmm1","EVEX.NDS.128.66.0F38.WIG DE /r","V","V","AES+AVX512VL","scale16","w,r,r","","" +"VAESDEC xmm1, xmmV, xmm2/m128","VAESDEC xmm2/m128, xmmV, xmm1","vaesdec xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG DE /r","V","V","AES+AVX","","w,r,r","","" +"VAESDEC ymm1, ymmV, ymm2/m256","VAESDEC ymm2/m256, ymmV, ymm1","vaesdec ymm2/m256, ymmV, ymm1","EVEX.NDS.256.66.0F38.WIG DE /r","V","V","AES+AVX512VL","scale32","w,r,r","","" +"VAESDEC ymm1, ymmV, ymm2/m256","VAESDEC ymm2/m256, ymmV, ymm1","vaesdec ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG DE /r","V","V","VAES+AVX","","w,r,r","","" +"VAESDEC zmm1, zmmV, zmm2/m512","VAESDEC zmm2/m512, zmmV, zmm1","vaesdec zmm2/m512, zmmV, zmm1","EVEX.NDS.512.66.0F38.WIG DE /r","V","V","AES+AVX512F","scale64","w,r,r","","" +"VAESDECLAST xmm1, xmmV, xmm2/m128","VAESDECLAST xmm2/m128, xmmV, xmm1","vaesdeclast xmm2/m128, xmmV, xmm1","EVEX.NDS.128.66.0F38.WIG DF /r","V","V","AES+AVX512VL","scale16","w,r,r","","" +"VAESDECLAST xmm1, xmmV, xmm2/m128","VAESDECLAST xmm2/m128, xmmV, xmm1","vaesdeclast xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG DF /r","V","V","AES+AVX","","w,r,r","","" +"VAESDECLAST ymm1, ymmV, ymm2/m256","VAESDECLAST ymm2/m256, ymmV, ymm1","vaesdeclast ymm2/m256, ymmV, ymm1","EVEX.NDS.256.66.0F38.WIG DF /r","V","V","AES+AVX512VL","scale32","w,r,r","","" +"VAESDECLAST ymm1, ymmV, ymm2/m256","VAESDECLAST ymm2/m256, ymmV, ymm1","vaesdeclast ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG DF /r","V","V","VAES+AVX","","w,r,r","","" +"VAESDECLAST zmm1, zmmV, zmm2/m512","VAESDECLAST zmm2/m512, zmmV, zmm1","vaesdeclast zmm2/m512, zmmV, zmm1","EVEX.NDS.512.66.0F38.WIG DF /r","V","V","AES+AVX512F","scale64","w,r,r","","" +"VAESENC xmm1, xmmV, xmm2/m128","VAESENC xmm2/m128, xmmV, xmm1","vaesenc xmm2/m128, xmmV, xmm1","EVEX.NDS.128.66.0F38.WIG DC /r","V","V","AES+AVX512VL","scale16","w,r,r","","" +"VAESENC xmm1, xmmV, xmm2/m128","VAESENC xmm2/m128, xmmV, xmm1","vaesenc xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG DC /r","V","V","AES+AVX","","w,r,r","","" +"VAESENC ymm1, ymmV, ymm2/m256","VAESENC ymm2/m256, ymmV, ymm1","vaesenc ymm2/m256, ymmV, ymm1","EVEX.NDS.256.66.0F38.WIG DC /r","V","V","AES+AVX512VL","scale32","w,r,r","","" +"VAESENC ymm1, ymmV, ymm2/m256","VAESENC ymm2/m256, ymmV, ymm1","vaesenc ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG DC /r","V","V","VAES+AVX","","w,r,r","","" +"VAESENC zmm1, zmmV, zmm2/m512","VAESENC zmm2/m512, zmmV, zmm1","vaesenc zmm2/m512, zmmV, zmm1","EVEX.NDS.512.66.0F38.WIG DC /r","V","V","AES+AVX512F","scale64","w,r,r","","" +"VAESENCLAST xmm1, xmmV, xmm2/m128","VAESENCLAST xmm2/m128, xmmV, xmm1","vaesenclast xmm2/m128, xmmV, xmm1","EVEX.NDS.128.66.0F38.WIG DD /r","V","V","AES+AVX512VL","scale16","w,r,r","","" +"VAESENCLAST xmm1, xmmV, xmm2/m128","VAESENCLAST xmm2/m128, xmmV, xmm1","vaesenclast xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG DD /r","V","V","AES+AVX","","w,r,r","","" +"VAESENCLAST ymm1, ymmV, ymm2/m256","VAESENCLAST ymm2/m256, ymmV, ymm1","vaesenclast ymm2/m256, ymmV, ymm1","EVEX.NDS.256.66.0F38.WIG DD /r","V","V","AES+AVX512VL","scale32","w,r,r","","" +"VAESENCLAST ymm1, ymmV, ymm2/m256","VAESENCLAST ymm2/m256, ymmV, ymm1","vaesenclast ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG DD /r","V","V","VAES+AVX","","w,r,r","","" +"VAESENCLAST zmm1, zmmV, zmm2/m512","VAESENCLAST zmm2/m512, zmmV, zmm1","vaesenclast zmm2/m512, zmmV, zmm1","EVEX.NDS.512.66.0F38.WIG DD /r","V","V","AES+AVX512F","scale64","w,r,r","","" +"VAESIMC xmm1, xmm2/m128","VAESIMC xmm2/m128, xmm1","vaesimc xmm2/m128, xmm1","VEX.128.66.0F38.WIG DB /r","V","V","AES+AVX","","w,r","","" +"VAESKEYGENASSIST xmm1, xmm2/m128, imm8u","VAESKEYGENASSIST imm8u, xmm2/m128, xmm1","vaeskeygenassist imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.WIG DF /r ib","V","V","AES+AVX","","w,r,r","","" +"VALIGND xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst, imm8u","VALIGND imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","valignd imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W0 03 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r,r","","" +"VALIGND ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u","VALIGND imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","valignd imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 03 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VALIGND zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u","VALIGND imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","valignd imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 03 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r,r","","" +"VALIGNQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u","VALIGNQ imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","valignq imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W1 03 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VALIGNQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VALIGNQ imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","valignq imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 03 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VALIGNQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VALIGNQ imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","valignq imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 03 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VANDNPD xmm1, xmmV, xmm2/m128","VANDNPD xmm2/m128, xmmV, xmm1","vandnpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 55 /r","V","V","AVX","","w,r,r","","" +"VANDNPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VANDNPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vandnpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 55 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VANDNPD ymm1, ymmV, ymm2/m256","VANDNPD ymm2/m256, ymmV, ymm1","vandnpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 55 /r","V","V","AVX","","w,r,r","","" +"VANDNPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VANDNPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vandnpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 55 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VANDNPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VANDNPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vandnpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 55 /r","V","V","AVX512DQ","bscale8,scale64","w,r,r,r","","" +"VANDNPS xmm1, xmmV, xmm2/m128","VANDNPS xmm2/m128, xmmV, xmm1","vandnps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 55 /r","V","V","AVX","","w,r,r","","" +"VANDNPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VANDNPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vandnps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 55 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VANDNPS ymm1, ymmV, ymm2/m256","VANDNPS ymm2/m256, ymmV, ymm1","vandnps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 55 /r","V","V","AVX","","w,r,r","","" +"VANDNPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VANDNPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vandnps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 55 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VANDNPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VANDNPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vandnps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 55 /r","V","V","AVX512DQ","bscale4,scale64","w,r,r,r","","" +"VANDPD xmm1, xmmV, xmm2/m128","VANDPD xmm2/m128, xmmV, xmm1","vandpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 54 /r","V","V","AVX","","w,r,r","","" +"VANDPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VANDPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vandpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 54 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VANDPD ymm1, ymmV, ymm2/m256","VANDPD ymm2/m256, ymmV, ymm1","vandpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 54 /r","V","V","AVX","","w,r,r","","" +"VANDPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VANDPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vandpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 54 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VANDPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VANDPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vandpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 54 /r","V","V","AVX512DQ","bscale8,scale64","w,r,r,r","","" +"VANDPS xmm1, xmmV, xmm2/m128","VANDPS xmm2/m128, xmmV, xmm1","vandps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 54 /r","V","V","AVX","","w,r,r","","" +"VANDPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VANDPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vandps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 54 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VANDPS ymm1, ymmV, ymm2/m256","VANDPS ymm2/m256, ymmV, ymm1","vandps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 54 /r","V","V","AVX","","w,r,r","","" +"VANDPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VANDPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vandps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 54 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VANDPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VANDPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vandps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 54 /r","V","V","AVX512DQ","bscale4,scale64","w,r,r,r","","" +"VBLENDMPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VBLENDMPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vblendmpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 65 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VBLENDMPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VBLENDMPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vblendmpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 65 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VBLENDMPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VBLENDMPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vblendmpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 65 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VBLENDMPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VBLENDMPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vblendmps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 65 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VBLENDMPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VBLENDMPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vblendmps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 65 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VBLENDMPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VBLENDMPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vblendmps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 65 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VBLENDPD xmm1, xmmV, xmm2/m128, imm8u","VBLENDPD imm8u, xmm2/m128, xmmV, xmm1","vblendpd imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 0D /r ib","V","V","AVX","","w,r,r,r","","" +"VBLENDPD ymm1, ymmV, ymm2/m256, imm8u","VBLENDPD imm8u, ymm2/m256, ymmV, ymm1","vblendpd imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.WIG 0D /r ib","V","V","AVX","","w,r,r,r","","" +"VBLENDPS xmm1, xmmV, xmm2/m128, imm8u","VBLENDPS imm8u, xmm2/m128, xmmV, xmm1","vblendps imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 0C /r ib","V","V","AVX","","w,r,r,r","","" +"VBLENDPS ymm1, ymmV, ymm2/m256, imm8u","VBLENDPS imm8u, ymm2/m256, ymmV, ymm1","vblendps imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.WIG 0C /r ib","V","V","AVX","","w,r,r,r","","" +"VBLENDVPD xmm1, xmmV, xmm2/m128, xmmIH","VBLENDVPD xmmIH, xmm2/m128, xmmV, xmm1","vblendvpd xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 4B /r /is4","V","V","AVX","","w,r,r,r","","" +"VBLENDVPD ymm1, ymmV, ymm2/m256, ymmIH","VBLENDVPD ymmIH, ymm2/m256, ymmV, ymm1","vblendvpd ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 4B /r /is4","V","V","AVX","","w,r,r,r","","" +"VBLENDVPS xmm1, xmmV, xmm2/m128, xmmIH","VBLENDVPS xmmIH, xmm2/m128, xmmV, xmm1","vblendvps xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 4A /r /is4","V","V","AVX","","w,r,r,r","","" +"VBLENDVPS ymm1, ymmV, ymm2/m256, ymmIH","VBLENDVPS ymmIH, ymm2/m256, ymmV, ymm1","vblendvps ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 4A /r /is4","V","V","AVX","","w,r,r,r","","" +"VBROADCASTF128 ymm1, m128","VBROADCASTF128 m128, ymm1","vbroadcastf128 m128, ymm1","VEX.256.66.0F38.W0 1A /r","V","V","AVX","modrm_memonly","w,r","","" +"VBROADCASTF32X2 ymm1, {k}{z}, xmm2/m64","VBROADCASTF32X2 xmm2/m64, {k}{z}, ymm1","vbroadcastf32x2 xmm2/m64, {k}{z}, ymm1","EVEX.256.66.0F38.W0 19 /r","V","V","AVX512DQ+AVX512VL","scale8","w,r,r","","" +"VBROADCASTF32X2 zmm1, {k}{z}, xmm2/m64","VBROADCASTF32X2 xmm2/m64, {k}{z}, zmm1","vbroadcastf32x2 xmm2/m64, {k}{z}, zmm1","EVEX.512.66.0F38.W0 19 /r","V","V","AVX512DQ","scale8","w,r,r","","" +"VBROADCASTF32X4 ymm1, {k}{z}, m128","VBROADCASTF32X4 m128, {k}{z}, ymm1","vbroadcastf32x4 m128, {k}{z}, ymm1","EVEX.256.66.0F38.W0 1A /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale16","w,r,r","","" +"VBROADCASTF32X4 zmm1, {k}{z}, m128","VBROADCASTF32X4 m128, {k}{z}, zmm1","vbroadcastf32x4 m128, {k}{z}, zmm1","EVEX.512.66.0F38.W0 1A /r","V","V","AVX512F","modrm_memonly,scale16","w,r,r","","" +"VBROADCASTF32X8 zmm1, {k}{z}, m256","VBROADCASTF32X8 m256, {k}{z}, zmm1","vbroadcastf32x8 m256, {k}{z}, zmm1","EVEX.512.66.0F38.W0 1B /r","V","V","AVX512DQ","modrm_memonly,scale32","w,r,r","","" +"VBROADCASTF64X2 ymm1, {k}{z}, m128","VBROADCASTF64X2 m128, {k}{z}, ymm1","vbroadcastf64x2 m128, {k}{z}, ymm1","EVEX.256.66.0F38.W1 1A /r","V","V","AVX512DQ+AVX512VL","modrm_memonly,scale16","w,r,r","","" +"VBROADCASTF64X2 zmm1, {k}{z}, m128","VBROADCASTF64X2 m128, {k}{z}, zmm1","vbroadcastf64x2 m128, {k}{z}, zmm1","EVEX.512.66.0F38.W1 1A /r","V","V","AVX512DQ","modrm_memonly,scale16","w,r,r","","" +"VBROADCASTF64X4 zmm1, {k}{z}, m256","VBROADCASTF64X4 m256, {k}{z}, zmm1","vbroadcastf64x4 m256, {k}{z}, zmm1","EVEX.512.66.0F38.W1 1B /r","V","V","AVX512F","modrm_memonly,scale32","w,r,r","","" +"VBROADCASTI128 ymm1, m128","VBROADCASTI128 m128, ymm1","vbroadcasti128 m128, ymm1","VEX.256.66.0F38.W0 5A /r","V","V","AVX2","modrm_memonly","w,r","","" +"VBROADCASTI32X2 xmm1, {k}{z}, xmm2/m64","VBROADCASTI32X2 xmm2/m64, {k}{z}, xmm1","vbroadcasti32x2 xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.W0 59 /r","V","V","AVX512DQ+AVX512VL","scale8","w,r,r","","" +"VBROADCASTI32X2 ymm1, {k}{z}, xmm2/m64","VBROADCASTI32X2 xmm2/m64, {k}{z}, ymm1","vbroadcasti32x2 xmm2/m64, {k}{z}, ymm1","EVEX.256.66.0F38.W0 59 /r","V","V","AVX512DQ+AVX512VL","scale8","w,r,r","","" +"VBROADCASTI32X2 zmm1, {k}{z}, xmm2/m64","VBROADCASTI32X2 xmm2/m64, {k}{z}, zmm1","vbroadcasti32x2 xmm2/m64, {k}{z}, zmm1","EVEX.512.66.0F38.W0 59 /r","V","V","AVX512DQ","scale8","w,r,r","","" +"VBROADCASTI32X4 ymm1, {k}{z}, m128","VBROADCASTI32X4 m128, {k}{z}, ymm1","vbroadcasti32x4 m128, {k}{z}, ymm1","EVEX.256.66.0F38.W0 5A /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale16","w,r,r","","" +"VBROADCASTI32X4 zmm1, {k}{z}, m128","VBROADCASTI32X4 m128, {k}{z}, zmm1","vbroadcasti32x4 m128, {k}{z}, zmm1","EVEX.512.66.0F38.W0 5A /r","V","V","AVX512F","modrm_memonly,scale16","w,r,r","","" +"VBROADCASTI32X8 zmm1, {k}{z}, m256","VBROADCASTI32X8 m256, {k}{z}, zmm1","vbroadcasti32x8 m256, {k}{z}, zmm1","EVEX.512.66.0F38.W0 5B /r","V","V","AVX512DQ","modrm_memonly,scale32","w,r,r","","" +"VBROADCASTI64X2 ymm1, {k}{z}, m128","VBROADCASTI64X2 m128, {k}{z}, ymm1","vbroadcasti64x2 m128, {k}{z}, ymm1","EVEX.256.66.0F38.W1 5A /r","V","V","AVX512DQ+AVX512VL","modrm_memonly,scale16","w,r,r","","" +"VBROADCASTI64X2 zmm1, {k}{z}, m128","VBROADCASTI64X2 m128, {k}{z}, zmm1","vbroadcasti64x2 m128, {k}{z}, zmm1","EVEX.512.66.0F38.W1 5A /r","V","V","AVX512DQ","modrm_memonly,scale16","w,r,r","","" +"VBROADCASTI64X4 zmm1, {k}{z}, m256","VBROADCASTI64X4 m256, {k}{z}, zmm1","vbroadcasti64x4 m256, {k}{z}, zmm1","EVEX.512.66.0F38.W1 5B /r","V","V","AVX512F","modrm_memonly,scale32","w,r,r","","" +"VBROADCASTSD ymm1, m64","VBROADCASTSD m64, ymm1","vbroadcastsd m64, ymm1","VEX.256.66.0F38.W0 19 /r","V","V","AVX","modrm_memonly","w,r","","" +"VBROADCASTSD ymm1, xmm2","VBROADCASTSD xmm2, ymm1","vbroadcastsd xmm2, ymm1","VEX.256.66.0F38.W0 19 /r","V","V","AVX2","modrm_regonly","w,r","","" +"VBROADCASTSD ymm1, {k}{z}, xmm2/m64","VBROADCASTSD xmm2/m64, {k}{z}, ymm1","vbroadcastsd xmm2/m64, {k}{z}, ymm1","EVEX.256.66.0F38.W1 19 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VBROADCASTSD zmm1, {k}{z}, xmm2/m64","VBROADCASTSD xmm2/m64, {k}{z}, zmm1","vbroadcastsd xmm2/m64, {k}{z}, zmm1","EVEX.512.66.0F38.W1 19 /r","V","V","AVX512F","scale8","w,r,r","","" +"VBROADCASTSS xmm1, m32","VBROADCASTSS m32, xmm1","vbroadcastss m32, xmm1","VEX.128.66.0F38.W0 18 /r","V","V","AVX","modrm_memonly","w,r","","" +"VBROADCASTSS ymm1, m32","VBROADCASTSS m32, ymm1","vbroadcastss m32, ymm1","VEX.256.66.0F38.W0 18 /r","V","V","AVX","modrm_memonly","w,r","","" +"VBROADCASTSS xmm1, xmm2","VBROADCASTSS xmm2, xmm1","vbroadcastss xmm2, xmm1","VEX.128.66.0F38.W0 18 /r","V","V","AVX2","modrm_regonly","w,r","","" +"VBROADCASTSS ymm1, xmm2","VBROADCASTSS xmm2, ymm1","vbroadcastss xmm2, ymm1","VEX.256.66.0F38.W0 18 /r","V","V","AVX2","modrm_regonly","w,r","","" +"VBROADCASTSS xmm1, {k}{z}, xmm2/m32","VBROADCASTSS xmm2/m32, {k}{z}, xmm1","vbroadcastss xmm2/m32, {k}{z}, xmm1","EVEX.128.66.0F38.W0 18 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VBROADCASTSS ymm1, {k}{z}, xmm2/m32","VBROADCASTSS xmm2/m32, {k}{z}, ymm1","vbroadcastss xmm2/m32, {k}{z}, ymm1","EVEX.256.66.0F38.W0 18 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VBROADCASTSS zmm1, {k}{z}, xmm2/m32","VBROADCASTSS xmm2/m32, {k}{z}, zmm1","vbroadcastss xmm2/m32, {k}{z}, zmm1","EVEX.512.66.0F38.W0 18 /r","V","V","AVX512F","scale4","w,r,r","","" +"VCMPPD xmm1, xmmV, xmm2/m128, imm8u","VCMPPD imm8u, xmm2/m128, xmmV, xmm1","vcmppd imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG C2 /r ib","V","V","AVX","","w,r,r,r","","" +"VCMPPD k1, {k}, xmmV, xmm2/m128/m64bcst, imm8u","VCMPPD imm8u, xmm2/m128/m64bcst, xmmV, {k}, k1","vcmppd imm8u, xmm2/m128/m64bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F.W1 C2 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VCMPPD ymm1, ymmV, ymm2/m256, imm8u","VCMPPD imm8u, ymm2/m256, ymmV, ymm1","vcmppd imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG C2 /r ib","V","V","AVX","","w,r,r,r","","" +"VCMPPD k1, {k}, ymmV, ymm2/m256/m64bcst, imm8u","VCMPPD imm8u, ymm2/m256/m64bcst, ymmV, {k}, k1","vcmppd imm8u, ymm2/m256/m64bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F.W1 C2 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VCMPPD k1{sae}, {k}, zmmV, zmm2, imm8u","VCMPPD imm8u, zmm2, zmmV, {k}, k1{sae}","vcmppd imm8u, zmm2, zmmV, {k}, k1{sae}","EVEX.NDS.512.66.0F.W1 C2 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r,r","","" +"VCMPPD k1, {k}, zmmV, zmm2/m512/m64bcst, imm8u","VCMPPD imm8u, zmm2/m512/m64bcst, zmmV, {k}, k1","vcmppd imm8u, zmm2/m512/m64bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F.W1 C2 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VCMPPS xmm1, xmmV, xmm2/m128, imm8u","VCMPPS imm8u, xmm2/m128, xmmV, xmm1","vcmpps imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG C2 /r ib","V","V","AVX","","w,r,r,r","","" +"VCMPPS k1, {k}, xmmV, xmm2/m128/m32bcst, imm8u","VCMPPS imm8u, xmm2/m128/m32bcst, xmmV, {k}, k1","vcmpps imm8u, xmm2/m128/m32bcst, xmmV, {k}, k1","EVEX.NDS.128.0F.W0 C2 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r,r","","" +"VCMPPS ymm1, ymmV, ymm2/m256, imm8u","VCMPPS imm8u, ymm2/m256, ymmV, ymm1","vcmpps imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG C2 /r ib","V","V","AVX","","w,r,r,r","","" +"VCMPPS k1, {k}, ymmV, ymm2/m256/m32bcst, imm8u","VCMPPS imm8u, ymm2/m256/m32bcst, ymmV, {k}, k1","vcmpps imm8u, ymm2/m256/m32bcst, ymmV, {k}, k1","EVEX.NDS.256.0F.W0 C2 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VCMPPS k1{sae}, {k}, zmmV, zmm2, imm8u","VCMPPS imm8u, zmm2, zmmV, {k}, k1{sae}","vcmpps imm8u, zmm2, zmmV, {k}, k1{sae}","EVEX.NDS.512.0F.W0 C2 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r,r","","" +"VCMPPS k1, {k}, zmmV, zmm2/m512/m32bcst, imm8u","VCMPPS imm8u, zmm2/m512/m32bcst, zmmV, {k}, k1","vcmpps imm8u, zmm2/m512/m32bcst, zmmV, {k}, k1","EVEX.NDS.512.0F.W0 C2 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r,r","","" +"VCMPSD k1{sae}, {k}, xmmV, xmm2, imm8u","VCMPSD imm8u, xmm2, xmmV, {k}, k1{sae}","vcmpsd imm8u, xmm2, xmmV, {k}, k1{sae}","EVEX.NDS.128.F2.0F.W1 C2 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r,r","","" +"VCMPSD xmm1, xmmV, xmm2/m64, imm8u","VCMPSD imm8u, xmm2/m64, xmmV, xmm1","vcmpsd imm8u, xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG C2 /r ib","V","V","AVX","","w,r,r,r","","" +"VCMPSD k1, {k}, xmmV, xmm2/m64, imm8u","VCMPSD imm8u, xmm2/m64, xmmV, {k}, k1","vcmpsd imm8u, xmm2/m64, xmmV, {k}, k1","EVEX.NDS.LIG.F2.0F.W1 C2 /r ib","V","V","AVX512F","scale8","w,r,r,r,r","","" +"VCMPSS k1{sae}, {k}, xmmV, xmm2, imm8u","VCMPSS imm8u, xmm2, xmmV, {k}, k1{sae}","vcmpss imm8u, xmm2, xmmV, {k}, k1{sae}","EVEX.NDS.128.F3.0F.W0 C2 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r,r","","" +"VCMPSS xmm1, xmmV, xmm2/m32, imm8u","VCMPSS imm8u, xmm2/m32, xmmV, xmm1","vcmpss imm8u, xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG C2 /r ib","V","V","AVX","","w,r,r,r","","" +"VCMPSS k1, {k}, xmmV, xmm2/m32, imm8u","VCMPSS imm8u, xmm2/m32, xmmV, {k}, k1","vcmpss imm8u, xmm2/m32, xmmV, {k}, k1","EVEX.NDS.LIG.F3.0F.W0 C2 /r ib","V","V","AVX512F","scale4","w,r,r,r,r","","" +"VCOMISD xmm1{sae}, xmm2","VCOMISD xmm2, xmm1{sae}","vcomisd xmm2, xmm1{sae}","EVEX.128.66.0F.W1 2F /r","V","V","AVX512F","modrm_regonly","r,r","","" +"VCOMISD xmm1, xmm2/m64","VCOMISD xmm2/m64, xmm1","vcomisd xmm2/m64, xmm1","EVEX.LIG.66.0F.W1 2F /r","V","V","AVX512F","scale8","r,r","","" +"VCOMISD xmm1, xmm2/m64","VCOMISD xmm2/m64, xmm1","vcomisd xmm2/m64, xmm1","VEX.LIG.66.0F.WIG 2F /r","V","V","AVX","","r,r","","" +"VCOMISS xmm1{sae}, xmm2","VCOMISS xmm2, xmm1{sae}","vcomiss xmm2, xmm1{sae}","EVEX.128.0F.W0 2F /r","V","V","AVX512F","modrm_regonly","r,r","","" +"VCOMISS xmm1, xmm2/m32","VCOMISS xmm2/m32, xmm1","vcomiss xmm2/m32, xmm1","EVEX.LIG.0F.W0 2F /r","V","V","AVX512F","scale4","r,r","","" +"VCOMISS xmm1, xmm2/m32","VCOMISS xmm2/m32, xmm1","vcomiss xmm2/m32, xmm1","VEX.LIG.0F.WIG 2F /r","V","V","AVX","","r,r","","" +"VCOMPRESSPD xmm2/m128, {k}{z}, xmm1","VCOMPRESSPD xmm1, {k}{z}, xmm2/m128","vcompresspd xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F38.W1 8A /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VCOMPRESSPD ymm2/m256, {k}{z}, ymm1","VCOMPRESSPD ymm1, {k}{z}, ymm2/m256","vcompresspd ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F38.W1 8A /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VCOMPRESSPD zmm2/m512, {k}{z}, zmm1","VCOMPRESSPD zmm1, {k}{z}, zmm2/m512","vcompresspd zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F38.W1 8A /r","V","V","AVX512F","scale8","w,r,r","","" +"VCOMPRESSPS xmm2/m128, {k}{z}, xmm1","VCOMPRESSPS xmm1, {k}{z}, xmm2/m128","vcompressps xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F38.W0 8A /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VCOMPRESSPS ymm2/m256, {k}{z}, ymm1","VCOMPRESSPS ymm1, {k}{z}, ymm2/m256","vcompressps ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F38.W0 8A /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VCOMPRESSPS zmm2/m512, {k}{z}, zmm1","VCOMPRESSPS zmm1, {k}{z}, zmm2/m512","vcompressps zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F38.W0 8A /r","V","V","AVX512F","scale4","w,r,r","","" +"VCVTDQ2PD ymm1, xmm2/m128","VCVTDQ2PD xmm2/m128, ymm1","vcvtdq2pd xmm2/m128, ymm1","VEX.256.F3.0F.WIG E6 /r","V","V","AVX","","w,r","","" +"VCVTDQ2PD xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTDQ2PD xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtdq2pd xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.F3.0F.W0 E6 /r","V","V","AVX512F+AVX512VL","bscale4,scale8","w,r,r","","" +"VCVTDQ2PD ymm1, {k}{z}, xmm2/m256/m32bcst","VCVTDQ2PD xmm2/m256/m32bcst, {k}{z}, ymm1","vcvtdq2pd xmm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.F3.0F.W0 E6 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTDQ2PD xmm1, xmm2/m64","VCVTDQ2PD xmm2/m64, xmm1","vcvtdq2pd xmm2/m64, xmm1","VEX.128.F3.0F.WIG E6 /r","V","V","AVX","","w,r","","" +"VCVTDQ2PD zmm1, {k}{z}, ymm2/m512/m32bcst","VCVTDQ2PD ymm2/m512/m32bcst, {k}{z}, zmm1","vcvtdq2pd ymm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.F3.0F.W0 E6 /r","V","V","AVX512F","bscale4,scale32","w,r,r","","" +"VCVTDQ2PS xmm1, xmm2/m128","VCVTDQ2PS xmm2/m128, xmm1","vcvtdq2ps xmm2/m128, xmm1","VEX.128.0F.WIG 5B /r","V","V","AVX","","w,r","","" +"VCVTDQ2PS xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTDQ2PS xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtdq2ps xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.0F.W0 5B /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTDQ2PS ymm1, ymm2/m256","VCVTDQ2PS ymm2/m256, ymm1","vcvtdq2ps ymm2/m256, ymm1","VEX.256.0F.WIG 5B /r","V","V","AVX","","w,r","","" +"VCVTDQ2PS ymm1, {k}{z}, ymm2/m256/m32bcst","VCVTDQ2PS ymm2/m256/m32bcst, {k}{z}, ymm1","vcvtdq2ps ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.0F.W0 5B /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VCVTDQ2PS zmm1{er}, {k}{z}, zmm2","VCVTDQ2PS zmm2, {k}{z}, zmm1{er}","vcvtdq2ps zmm2, {k}{z}, zmm1{er}","EVEX.512.0F.W0 5B /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VCVTDQ2PS zmm1, {k}{z}, zmm2/m512/m32bcst","VCVTDQ2PS zmm2/m512/m32bcst, {k}{z}, zmm1","vcvtdq2ps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.0F.W0 5B /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VCVTPD2DQ ymm1{er}, {k}{z}, zmm2","VCVTPD2DQ zmm2, {k}{z}, ymm1{er}","vcvtpd2dq zmm2, {k}{z}, ymm1{er}","EVEX.512.F2.0F.W1 E6 /r","V","V","AVX512F","modrm_regonly","w,r,r","Y","" +"VCVTPD2DQ ymm1, {k}{z}, zmm2/m512/m64bcst","VCVTPD2DQ zmm2/m512/m64bcst, {k}{z}, ymm1","vcvtpd2dq zmm2/m512/m64bcst, {k}{z}, ymm1","EVEX.512.F2.0F.W1 E6 /r","V","V","AVX512F","bscale8,scale64","w,r,r","Y","512" +"VCVTPD2DQ xmm1, xmm2/m128","VCVTPD2DQX xmm2/m128, xmm1","vcvtpd2dqx xmm2/m128, xmm1","VEX.128.F2.0F.WIG E6 /r","V","V","AVX","","w,r","Y","128" +"VCVTPD2DQ xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTPD2DQX xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtpd2dqx xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.F2.0F.W1 E6 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","Y","128" +"VCVTPD2DQ xmm1, ymm2/m256","VCVTPD2DQY ymm2/m256, xmm1","vcvtpd2dqy ymm2/m256, xmm1","VEX.256.F2.0F.WIG E6 /r","V","V","AVX","","w,r","Y","256" +"VCVTPD2DQ xmm1, {k}{z}, ymm2/m256/m64bcst","VCVTPD2DQY ymm2/m256/m64bcst, {k}{z}, xmm1","vcvtpd2dqy ymm2/m256/m64bcst, {k}{z}, xmm1","EVEX.256.F2.0F.W1 E6 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","Y","256" +"VCVTPD2PS ymm1{er}, {k}{z}, zmm2","VCVTPD2PS zmm2, {k}{z}, ymm1{er}","vcvtpd2ps zmm2, {k}{z}, ymm1{er}","EVEX.512.66.0F.W1 5A /r","V","V","AVX512F","modrm_regonly","w,r,r","Y","" +"VCVTPD2PS ymm1, {k}{z}, zmm2/m512/m64bcst","VCVTPD2PS zmm2/m512/m64bcst, {k}{z}, ymm1","vcvtpd2ps zmm2/m512/m64bcst, {k}{z}, ymm1","EVEX.512.66.0F.W1 5A /r","V","V","AVX512F","bscale8,scale64","w,r,r","Y","512" +"VCVTPD2PS xmm1, xmm2/m128","VCVTPD2PSX xmm2/m128, xmm1","vcvtpd2psx xmm2/m128, xmm1","VEX.128.66.0F.WIG 5A /r","V","V","AVX","","w,r","Y","128" +"VCVTPD2PS xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTPD2PSX xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtpd2psx xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F.W1 5A /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","Y","128" +"VCVTPD2PS xmm1, ymm2/m256","VCVTPD2PSY ymm2/m256, xmm1","vcvtpd2psy ymm2/m256, xmm1","VEX.256.66.0F.WIG 5A /r","V","V","AVX","","w,r","Y","256" +"VCVTPD2PS xmm1, {k}{z}, ymm2/m256/m64bcst","VCVTPD2PSY ymm2/m256/m64bcst, {k}{z}, xmm1","vcvtpd2psy ymm2/m256/m64bcst, {k}{z}, xmm1","EVEX.256.66.0F.W1 5A /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","Y","256" +"VCVTPD2QQ xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTPD2QQ xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtpd2qq xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F.W1 7B /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r","","" +"VCVTPD2QQ ymm1, {k}{z}, ymm2/m256/m64bcst","VCVTPD2QQ ymm2/m256/m64bcst, {k}{z}, ymm1","vcvtpd2qq ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F.W1 7B /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r","","" +"VCVTPD2QQ zmm1{er}, {k}{z}, zmm2","VCVTPD2QQ zmm2, {k}{z}, zmm1{er}","vcvtpd2qq zmm2, {k}{z}, zmm1{er}","EVEX.512.66.0F.W1 7B /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTPD2QQ zmm1, {k}{z}, zmm2/m512/m64bcst","VCVTPD2QQ zmm2/m512/m64bcst, {k}{z}, zmm1","vcvtpd2qq zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F.W1 7B /r","V","V","AVX512DQ","bscale8,scale64","w,r,r","","" +"VCVTPD2UDQ ymm1{er}, {k}{z}, zmm2","VCVTPD2UDQ zmm2, {k}{z}, ymm1{er}","vcvtpd2udq zmm2, {k}{z}, ymm1{er}","EVEX.512.0F.W1 79 /r","V","V","AVX512F","modrm_regonly","w,r,r","Y","" +"VCVTPD2UDQ ymm1, {k}{z}, zmm2/m512/m64bcst","VCVTPD2UDQ zmm2/m512/m64bcst, {k}{z}, ymm1","vcvtpd2udq zmm2/m512/m64bcst, {k}{z}, ymm1","EVEX.512.0F.W1 79 /r","V","V","AVX512F","bscale8,scale64","w,r,r","Y","512" +"VCVTPD2UDQ xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTPD2UDQX xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtpd2udqx xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.0F.W1 79 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","Y","128" +"VCVTPD2UDQ xmm1, {k}{z}, ymm2/m256/m64bcst","VCVTPD2UDQY ymm2/m256/m64bcst, {k}{z}, xmm1","vcvtpd2udqy ymm2/m256/m64bcst, {k}{z}, xmm1","EVEX.256.0F.W1 79 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","Y","256" +"VCVTPD2UQQ xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTPD2UQQ xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtpd2uqq xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F.W1 79 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r","","" +"VCVTPD2UQQ ymm1, {k}{z}, ymm2/m256/m64bcst","VCVTPD2UQQ ymm2/m256/m64bcst, {k}{z}, ymm1","vcvtpd2uqq ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F.W1 79 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r","","" +"VCVTPD2UQQ zmm1{er}, {k}{z}, zmm2","VCVTPD2UQQ zmm2, {k}{z}, zmm1{er}","vcvtpd2uqq zmm2, {k}{z}, zmm1{er}","EVEX.512.66.0F.W1 79 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTPD2UQQ zmm1, {k}{z}, zmm2/m512/m64bcst","VCVTPD2UQQ zmm2/m512/m64bcst, {k}{z}, zmm1","vcvtpd2uqq zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F.W1 79 /r","V","V","AVX512DQ","bscale8,scale64","w,r,r","","" +"VCVTPH2PS ymm1, xmm2/m128","VCVTPH2PS xmm2/m128, ymm1","vcvtph2ps xmm2/m128, ymm1","VEX.256.66.0F38.W0 13 /r","V","V","F16C","","w,r","","" +"VCVTPH2PS ymm1, {k}{z}, xmm2/m128","VCVTPH2PS xmm2/m128, {k}{z}, ymm1","vcvtph2ps xmm2/m128, {k}{z}, ymm1","EVEX.256.66.0F38.W0 13 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VCVTPH2PS xmm1, xmm2/m64","VCVTPH2PS xmm2/m64, xmm1","vcvtph2ps xmm2/m64, xmm1","VEX.128.66.0F38.W0 13 /r","V","V","F16C","","w,r","","" +"VCVTPH2PS xmm1, {k}{z}, xmm2/m64","VCVTPH2PS xmm2/m64, {k}{z}, xmm1","vcvtph2ps xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.W0 13 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VCVTPH2PS zmm1{sae}, {k}{z}, ymm2","VCVTPH2PS ymm2, {k}{z}, zmm1{sae}","vcvtph2ps ymm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W0 13 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VCVTPH2PS zmm1, {k}{z}, ymm2/m256","VCVTPH2PS ymm2/m256, {k}{z}, zmm1","vcvtph2ps ymm2/m256, {k}{z}, zmm1","EVEX.512.66.0F38.W0 13 /r","V","V","AVX512F","scale32","w,r,r","","" +"VCVTPS2DQ xmm1, xmm2/m128","VCVTPS2DQ xmm2/m128, xmm1","vcvtps2dq xmm2/m128, xmm1","VEX.128.66.0F.WIG 5B /r","V","V","AVX","","w,r","","" +"VCVTPS2DQ xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTPS2DQ xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtps2dq xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F.W0 5B /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTPS2DQ ymm1, ymm2/m256","VCVTPS2DQ ymm2/m256, ymm1","vcvtps2dq ymm2/m256, ymm1","VEX.256.66.0F.WIG 5B /r","V","V","AVX","","w,r","","" +"VCVTPS2DQ ymm1, {k}{z}, ymm2/m256/m32bcst","VCVTPS2DQ ymm2/m256/m32bcst, {k}{z}, ymm1","vcvtps2dq ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F.W0 5B /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VCVTPS2DQ zmm1{er}, {k}{z}, zmm2","VCVTPS2DQ zmm2, {k}{z}, zmm1{er}","vcvtps2dq zmm2, {k}{z}, zmm1{er}","EVEX.512.66.0F.W0 5B /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VCVTPS2DQ zmm1, {k}{z}, zmm2/m512/m32bcst","VCVTPS2DQ zmm2/m512/m32bcst, {k}{z}, zmm1","vcvtps2dq zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F.W0 5B /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VCVTPS2PD ymm1, xmm2/m128","VCVTPS2PD xmm2/m128, ymm1","vcvtps2pd xmm2/m128, ymm1","VEX.256.0F.WIG 5A /r","V","V","AVX","","w,r","","" +"VCVTPS2PD xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTPS2PD xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtps2pd xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.0F.W0 5A /r","V","V","AVX512F+AVX512VL","bscale4,scale8","w,r,r","","" +"VCVTPS2PD ymm1, {k}{z}, xmm2/m256/m32bcst","VCVTPS2PD xmm2/m256/m32bcst, {k}{z}, ymm1","vcvtps2pd xmm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.0F.W0 5A /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTPS2PD xmm1, xmm2/m64","VCVTPS2PD xmm2/m64, xmm1","vcvtps2pd xmm2/m64, xmm1","VEX.128.0F.WIG 5A /r","V","V","AVX","","w,r","","" +"VCVTPS2PD zmm1{sae}, {k}{z}, ymm2","VCVTPS2PD ymm2, {k}{z}, zmm1{sae}","vcvtps2pd ymm2, {k}{z}, zmm1{sae}","EVEX.512.0F.W0 5A /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VCVTPS2PD zmm1, {k}{z}, ymm2/m512/m32bcst","VCVTPS2PD ymm2/m512/m32bcst, {k}{z}, zmm1","vcvtps2pd ymm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.0F.W0 5A /r","V","V","AVX512F","bscale4,scale32","w,r,r","","" +"VCVTPS2PH xmm2/m64, xmm1, imm8u","VCVTPS2PH imm8u, xmm1, xmm2/m64","vcvtps2ph imm8u, xmm1, xmm2/m64","VEX.128.66.0F3A.W0 1D /r ib","V","V","F16C","","w,r,r","","" +"VCVTPS2PH xmm2/m64, {k}{z}, xmm1, imm8u","VCVTPS2PH imm8u, xmm1, {k}{z}, xmm2/m64","vcvtps2ph imm8u, xmm1, {k}{z}, xmm2/m64","EVEX.128.66.0F3A.W0 1D /r ib","V","V","AVX512F+AVX512VL","scale8","w,r,r,r","","" +"VCVTPS2PH xmm2/m128, ymm1, imm8u","VCVTPS2PH imm8u, ymm1, xmm2/m128","vcvtps2ph imm8u, ymm1, xmm2/m128","VEX.256.66.0F3A.W0 1D /r ib","V","V","F16C","","w,r,r","","" +"VCVTPS2PH xmm2/m128, {k}{z}, ymm1, imm8u","VCVTPS2PH imm8u, ymm1, {k}{z}, xmm2/m128","vcvtps2ph imm8u, ymm1, {k}{z}, xmm2/m128","EVEX.256.66.0F3A.W0 1D /r ib","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VCVTPS2PH ymm2/m256, {k}{z}, zmm1, imm8u","VCVTPS2PH imm8u, zmm1, {k}{z}, ymm2/m256","vcvtps2ph imm8u, zmm1, {k}{z}, ymm2/m256","EVEX.512.66.0F3A.W0 1D /r ib","V","V","AVX512F","scale32","w,r,r,r","","" +"VCVTPS2PH ymm2{sae}, {k}{z}, zmm1, imm8u","VCVTPS2PH imm8u, zmm1, {k}{z}, ymm2{sae}","vcvtps2ph imm8u, zmm1, {k}{z}, ymm2{sae}","EVEX.512.66.0F3A.W0 1D /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VCVTPS2QQ xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTPS2QQ xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtps2qq xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F.W0 7B /r","V","V","AVX512DQ+AVX512VL","bscale4,scale8","w,r,r","","" +"VCVTPS2QQ ymm1, {k}{z}, xmm2/m256/m32bcst","VCVTPS2QQ xmm2/m256/m32bcst, {k}{z}, ymm1","vcvtps2qq xmm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F.W0 7B /r","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTPS2QQ zmm1{er}, {k}{z}, ymm2","VCVTPS2QQ ymm2, {k}{z}, zmm1{er}","vcvtps2qq ymm2, {k}{z}, zmm1{er}","EVEX.512.66.0F.W0 7B /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTPS2QQ zmm1, {k}{z}, ymm2/m512/m32bcst","VCVTPS2QQ ymm2/m512/m32bcst, {k}{z}, zmm1","vcvtps2qq ymm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F.W0 7B /r","V","V","AVX512DQ","bscale4,scale32","w,r,r","","" +"VCVTPS2UDQ xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTPS2UDQ xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtps2udq xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.0F.W0 79 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTPS2UDQ ymm1, {k}{z}, ymm2/m256/m32bcst","VCVTPS2UDQ ymm2/m256/m32bcst, {k}{z}, ymm1","vcvtps2udq ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.0F.W0 79 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VCVTPS2UDQ zmm1{er}, {k}{z}, zmm2","VCVTPS2UDQ zmm2, {k}{z}, zmm1{er}","vcvtps2udq zmm2, {k}{z}, zmm1{er}","EVEX.512.0F.W0 79 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VCVTPS2UDQ zmm1, {k}{z}, zmm2/m512/m32bcst","VCVTPS2UDQ zmm2/m512/m32bcst, {k}{z}, zmm1","vcvtps2udq zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.0F.W0 79 /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VCVTPS2UQQ xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTPS2UQQ xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtps2uqq xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F.W0 79 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale8","w,r,r","","" +"VCVTPS2UQQ ymm1, {k}{z}, xmm2/m256/m32bcst","VCVTPS2UQQ xmm2/m256/m32bcst, {k}{z}, ymm1","vcvtps2uqq xmm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F.W0 79 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTPS2UQQ zmm1{er}, {k}{z}, ymm2","VCVTPS2UQQ ymm2, {k}{z}, zmm1{er}","vcvtps2uqq ymm2, {k}{z}, zmm1{er}","EVEX.512.66.0F.W0 79 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTPS2UQQ zmm1, {k}{z}, ymm2/m512/m32bcst","VCVTPS2UQQ ymm2/m512/m32bcst, {k}{z}, zmm1","vcvtps2uqq ymm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F.W0 79 /r","V","V","AVX512DQ","bscale4,scale32","w,r,r","","" +"VCVTQQ2PD xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTQQ2PD xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtqq2pd xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.F3.0F.W1 E6 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r","","" +"VCVTQQ2PD ymm1, {k}{z}, ymm2/m256/m64bcst","VCVTQQ2PD ymm2/m256/m64bcst, {k}{z}, ymm1","vcvtqq2pd ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.F3.0F.W1 E6 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r","","" +"VCVTQQ2PD zmm1{er}, {k}{z}, zmm2","VCVTQQ2PD zmm2, {k}{z}, zmm1{er}","vcvtqq2pd zmm2, {k}{z}, zmm1{er}","EVEX.512.F3.0F.W1 E6 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTQQ2PD zmm1, {k}{z}, zmm2/m512/m64bcst","VCVTQQ2PD zmm2/m512/m64bcst, {k}{z}, zmm1","vcvtqq2pd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.F3.0F.W1 E6 /r","V","V","AVX512DQ","bscale8,scale64","w,r,r","","" +"VCVTQQ2PS ymm1{er}, {k}{z}, zmm2","VCVTQQ2PS zmm2, {k}{z}, ymm1{er}","vcvtqq2ps zmm2, {k}{z}, ymm1{er}","EVEX.512.0F.W1 5B /r","V","V","AVX512DQ","modrm_regonly","w,r,r","Y","" +"VCVTQQ2PS ymm1, {k}{z}, zmm2/m512/m64bcst","VCVTQQ2PS zmm2/m512/m64bcst, {k}{z}, ymm1","vcvtqq2ps zmm2/m512/m64bcst, {k}{z}, ymm1","EVEX.512.0F.W1 5B /r","V","V","AVX512DQ","bscale8,scale64","w,r,r","Y","512" +"VCVTQQ2PS xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTQQ2PSX xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtqq2psx xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.0F.W1 5B /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r","Y","128" +"VCVTQQ2PS xmm1, {k}{z}, ymm2/m256/m64bcst","VCVTQQ2PSY ymm2/m256/m64bcst, {k}{z}, xmm1","vcvtqq2psy ymm2/m256/m64bcst, {k}{z}, xmm1","EVEX.256.0F.W1 5B /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r","Y","256" +"VCVTSD2SI r32{er}, xmm2","VCVTSD2SI xmm2, r32{er}","vcvtsd2si xmm2, r32{er}","EVEX.128.F2.0F.W0 2D /r","V","V","AVX512F","modrm_regonly","w,r","Y","32" +"VCVTSD2SI r32, xmm2/m64","VCVTSD2SI xmm2/m64, r32","vcvtsd2si xmm2/m64, r32","EVEX.LIG.F2.0F.W0 2D /r","V","V","AVX512F","scale8","w,r","Y","32" +"VCVTSD2SI r32, xmm2/m64","VCVTSD2SI xmm2/m64, r32","vcvtsd2si xmm2/m64, r32","VEX.LIG.F2.0F.W0 2D /r","V","V","AVX","","w,r","Y","32" +"VCVTSD2SI r64{er}, xmm2","VCVTSD2SIQ xmm2, r64{er}","vcvtsd2siq xmm2, r64{er}","EVEX.128.F2.0F.W1 2D /r","N.S.","V","AVX512F","modrm_regonly","w,r","Y","64" +"VCVTSD2SI r64, xmm2/m64","VCVTSD2SIQ xmm2/m64, r64","vcvtsd2siq xmm2/m64, r64","EVEX.LIG.F2.0F.W1 2D /r","N.S.","V","AVX512F","scale8","w,r","Y","64" +"VCVTSD2SI r64, xmm2/m64","VCVTSD2SIQ xmm2/m64, r64","vcvtsd2siq xmm2/m64, r64","VEX.LIG.F2.0F.W1 2D /r","N.S.","V","AVX","","w,r","Y","64" +"VCVTSD2SS xmm1{er}, {k}{z}, xmmV, xmm2","VCVTSD2SS xmm2, xmmV, {k}{z}, xmm1{er}","vcvtsd2ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F2.0F.W1 5A /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VCVTSD2SS xmm1, xmmV, xmm2/m64","VCVTSD2SS xmm2/m64, xmmV, xmm1","vcvtsd2ss xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 5A /r","V","V","AVX","","w,r,r","","" +"VCVTSD2SS xmm1, {k}{z}, xmmV, xmm2/m64","VCVTSD2SS xmm2/m64, xmmV, {k}{z}, xmm1","vcvtsd2ss xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 5A /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VCVTSD2USI r32{er}, xmm2","VCVTSD2USIL xmm2, r32{er}","vcvtsd2usi xmm2, r32{er}","EVEX.128.F2.0F.W0 79 /r","V","V","AVX512F","modrm_regonly","w,r","Y","32" +"VCVTSD2USI r32, xmm2/m64","VCVTSD2USIL xmm2/m64, r32","vcvtsd2usi xmm2/m64, r32","EVEX.LIG.F2.0F.W0 79 /r","V","V","AVX512F","scale8","w,r","Y","32" +"VCVTSD2USI r64{er}, xmm2","VCVTSD2USIQ xmm2, r64{er}","vcvtsd2usi xmm2, r64{er}","EVEX.128.F2.0F.W1 79 /r","N.S.","V","AVX512F","modrm_regonly","w,r","Y","64" +"VCVTSD2USI r64, xmm2/m64","VCVTSD2USIQ xmm2/m64, r64","vcvtsd2usi xmm2/m64, r64","EVEX.LIG.F2.0F.W1 79 /r","N.S.","V","AVX512F","scale8","w,r","Y","64" +"VCVTSI2SD xmm1, xmmV, r/m32","VCVTSI2SDL r/m32, xmmV, xmm1","vcvtsi2sdl r/m32, xmmV, xmm1","EVEX.NDS.LIG.F2.0F.W0 2A /r","V","V","AVX512F","scale4","w,r,r","Y","32" +"VCVTSI2SD xmm1, xmmV, r/m32","VCVTSI2SDL r/m32, xmmV, xmm1","vcvtsi2sdl r/m32, xmmV, xmm1","VEX.NDS.LIG.F2.0F.W0 2A /r","V","V","AVX","","w,r,r","Y","32" +"VCVTSI2SD xmm1, xmmV, r/m64","VCVTSI2SDQ r/m64, xmmV, xmm1","vcvtsi2sdq r/m64, xmmV, xmm1","EVEX.NDS.LIG.F2.0F.W1 2A /r","N.S.","V","AVX512F","scale8","w,r,r","Y","64" +"VCVTSI2SD xmm1, xmmV, r/m64","VCVTSI2SDQ r/m64, xmmV, xmm1","vcvtsi2sdq r/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.W1 2A /r","N.S.","V","AVX","","w,r,r","Y","64" +"VCVTSI2SD xmm1{er}, xmmV, rmr64","VCVTSI2SDQ rmr64, xmmV, xmm1{er}","vcvtsi2sdq rmr64, xmmV, xmm1{er}","EVEX.NDS.128.F2.0F.W1 2A /r","N.S.","V","AVX512F","modrm_regonly","w,r,r","Y","64" +"VCVTSI2SS xmm1, xmmV, r/m32","VCVTSI2SSL r/m32, xmmV, xmm1","vcvtsi2ssl r/m32, xmmV, xmm1","EVEX.NDS.LIG.F3.0F.W0 2A /r","V","V","AVX512F","scale4","w,r,r","Y","32" +"VCVTSI2SS xmm1, xmmV, r/m32","VCVTSI2SSL r/m32, xmmV, xmm1","vcvtsi2ssl r/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.W0 2A /r","V","V","AVX","","w,r,r","Y","32" +"VCVTSI2SS xmm1{er}, xmmV, rmr32","VCVTSI2SSL rmr32, xmmV, xmm1{er}","vcvtsi2ssl rmr32, xmmV, xmm1{er}","EVEX.NDS.128.F3.0F.W0 2A /r","V","V","AVX512F","modrm_regonly","w,r,r","Y","32" +"VCVTSI2SS xmm1, xmmV, r/m64","VCVTSI2SSQ r/m64, xmmV, xmm1","vcvtsi2ssq r/m64, xmmV, xmm1","EVEX.NDS.LIG.F3.0F.W1 2A /r","N.S.","V","AVX512F","scale8","w,r,r","Y","64" +"VCVTSI2SS xmm1, xmmV, r/m64","VCVTSI2SSQ r/m64, xmmV, xmm1","vcvtsi2ssq r/m64, xmmV, xmm1","VEX.NDS.LIG.F3.0F.W1 2A /r","N.S.","V","AVX","","w,r,r","Y","64" +"VCVTSI2SS xmm1{er}, xmmV, rmr64","VCVTSI2SSQ rmr64, xmmV, xmm1{er}","vcvtsi2ssq rmr64, xmmV, xmm1{er}","EVEX.NDS.128.F3.0F.W1 2A /r","N.S.","V","AVX512F","modrm_regonly","w,r,r","Y","64" +"VCVTSS2SD xmm1{sae}, {k}{z}, xmmV, xmm2","VCVTSS2SD xmm2, xmmV, {k}{z}, xmm1{sae}","vcvtss2sd xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.F3.0F.W0 5A /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VCVTSS2SD xmm1, xmmV, xmm2/m32","VCVTSS2SD xmm2/m32, xmmV, xmm1","vcvtss2sd xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 5A /r","V","V","AVX","","w,r,r","","" +"VCVTSS2SD xmm1, {k}{z}, xmmV, xmm2/m32","VCVTSS2SD xmm2/m32, xmmV, {k}{z}, xmm1","vcvtss2sd xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 5A /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VCVTSS2SI r32{er}, xmm2","VCVTSS2SI xmm2, r32{er}","vcvtss2si xmm2, r32{er}","EVEX.128.F3.0F.W0 2D /r","V","V","AVX512F","modrm_regonly","w,r","Y","32" +"VCVTSS2SI r32, xmm2/m32","VCVTSS2SI xmm2/m32, r32","vcvtss2si xmm2/m32, r32","EVEX.LIG.F3.0F.W0 2D /r","V","V","AVX512F","scale4","w,r","Y","32" +"VCVTSS2SI r32, xmm2/m32","VCVTSS2SI xmm2/m32, r32","vcvtss2si xmm2/m32, r32","VEX.LIG.F3.0F.W0 2D /r","V","V","AVX","","w,r","Y","32" +"VCVTSS2SI r64{er}, xmm2","VCVTSS2SIQ xmm2, r64{er}","vcvtss2siq xmm2, r64{er}","EVEX.128.F3.0F.W1 2D /r","N.S.","V","AVX512F","modrm_regonly","w,r","Y","64" +"VCVTSS2SI r64, xmm2/m32","VCVTSS2SIQ xmm2/m32, r64","vcvtss2siq xmm2/m32, r64","EVEX.LIG.F3.0F.W1 2D /r","N.S.","V","AVX512F","scale4","w,r","Y","64" +"VCVTSS2SI r64, xmm2/m32","VCVTSS2SIQ xmm2/m32, r64","vcvtss2siq xmm2/m32, r64","VEX.LIG.F3.0F.W1 2D /r","N.S.","V","AVX","","w,r","Y","64" +"VCVTSS2USI r32{er}, xmm2","VCVTSS2USIL xmm2, r32{er}","vcvtss2usil xmm2, r32{er}","EVEX.128.F3.0F.W0 79 /r","V","V","AVX512F","modrm_regonly","w,r","Y","32" +"VCVTSS2USI r32, xmm2/m32","VCVTSS2USIL xmm2/m32, r32","vcvtss2usil xmm2/m32, r32","EVEX.LIG.F3.0F.W0 79 /r","V","V","AVX512F","scale4","w,r","Y","32" +"VCVTSS2USI r64{er}, xmm2","VCVTSS2USIQ xmm2, r64{er}","vcvtss2usiq xmm2, r64{er}","EVEX.128.F3.0F.W1 79 /r","N.S.","V","AVX512F","modrm_regonly","w,r","Y","64" +"VCVTSS2USI r64, xmm2/m32","VCVTSS2USIQ xmm2/m32, r64","vcvtss2usiq xmm2/m32, r64","EVEX.LIG.F3.0F.W1 79 /r","N.S.","V","AVX512F","scale4","w,r","Y","64" +"VCVTTPD2DQ ymm1{sae}, {k}{z}, zmm2","VCVTTPD2DQ zmm2, {k}{z}, ymm1{sae}","vcvttpd2dq zmm2, {k}{z}, ymm1{sae}","EVEX.512.66.0F.W1 E6 /r","V","V","AVX512F","modrm_regonly","w,r,r","Y","" +"VCVTTPD2DQ ymm1, {k}{z}, zmm2/m512/m64bcst","VCVTTPD2DQ zmm2/m512/m64bcst, {k}{z}, ymm1","vcvttpd2dq zmm2/m512/m64bcst, {k}{z}, ymm1","EVEX.512.66.0F.W1 E6 /r","V","V","AVX512F","bscale8,scale64","w,r,r","Y","512" +"VCVTTPD2DQ xmm1, xmm2/m128","VCVTTPD2DQX xmm2/m128, xmm1","vcvttpd2dqx xmm2/m128, xmm1","VEX.128.66.0F.WIG E6 /r","V","V","AVX","","w,r","Y","128" +"VCVTTPD2DQ xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTTPD2DQX xmm2/m128/m64bcst, {k}{z}, xmm1","vcvttpd2dqx xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F.W1 E6 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","Y","128" +"VCVTTPD2DQ xmm1, ymm2/m256","VCVTTPD2DQY ymm2/m256, xmm1","vcvttpd2dqy ymm2/m256, xmm1","VEX.256.66.0F.WIG E6 /r","V","V","AVX","","w,r","Y","256" +"VCVTTPD2DQ xmm1, {k}{z}, ymm2/m256/m64bcst","VCVTTPD2DQY ymm2/m256/m64bcst, {k}{z}, xmm1","vcvttpd2dqy ymm2/m256/m64bcst, {k}{z}, xmm1","EVEX.256.66.0F.W1 E6 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","Y","256" +"VCVTTPD2QQ xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTTPD2QQ xmm2/m128/m64bcst, {k}{z}, xmm1","vcvttpd2qq xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F.W1 7A /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r","","" +"VCVTTPD2QQ ymm1, {k}{z}, ymm2/m256/m64bcst","VCVTTPD2QQ ymm2/m256/m64bcst, {k}{z}, ymm1","vcvttpd2qq ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F.W1 7A /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r","","" +"VCVTTPD2QQ zmm1{sae}, {k}{z}, zmm2","VCVTTPD2QQ zmm2, {k}{z}, zmm1{sae}","vcvttpd2qq zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F.W1 7A /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTTPD2QQ zmm1, {k}{z}, zmm2/m512/m64bcst","VCVTTPD2QQ zmm2/m512/m64bcst, {k}{z}, zmm1","vcvttpd2qq zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F.W1 7A /r","V","V","AVX512DQ","bscale8,scale64","w,r,r","","" +"VCVTTPD2UDQ ymm1{sae}, {k}{z}, zmm2","VCVTTPD2UDQ zmm2, {k}{z}, ymm1{sae}","vcvttpd2udq zmm2, {k}{z}, ymm1{sae}","EVEX.512.0F.W1 78 /r","V","V","AVX512F","modrm_regonly","w,r,r","Y","" +"VCVTTPD2UDQ ymm1, {k}{z}, zmm2/m512/m64bcst","VCVTTPD2UDQ zmm2/m512/m64bcst, {k}{z}, ymm1","vcvttpd2udq zmm2/m512/m64bcst, {k}{z}, ymm1","EVEX.512.0F.W1 78 /r","V","V","AVX512F","bscale8,scale64","w,r,r","Y","512" +"VCVTTPD2UDQ xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTTPD2UDQX xmm2/m128/m64bcst, {k}{z}, xmm1","vcvttpd2udqx xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.0F.W1 78 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","Y","128" +"VCVTTPD2UDQ xmm1, {k}{z}, ymm2/m256/m64bcst","VCVTTPD2UDQY ymm2/m256/m64bcst, {k}{z}, xmm1","vcvttpd2udqy ymm2/m256/m64bcst, {k}{z}, xmm1","EVEX.256.0F.W1 78 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","Y","256" +"VCVTTPD2UQQ xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTTPD2UQQ xmm2/m128/m64bcst, {k}{z}, xmm1","vcvttpd2uqq xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F.W1 78 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r","","" +"VCVTTPD2UQQ ymm1, {k}{z}, ymm2/m256/m64bcst","VCVTTPD2UQQ ymm2/m256/m64bcst, {k}{z}, ymm1","vcvttpd2uqq ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F.W1 78 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r","","" +"VCVTTPD2UQQ zmm1{sae}, {k}{z}, zmm2","VCVTTPD2UQQ zmm2, {k}{z}, zmm1{sae}","vcvttpd2uqq zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F.W1 78 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTTPD2UQQ zmm1, {k}{z}, zmm2/m512/m64bcst","VCVTTPD2UQQ zmm2/m512/m64bcst, {k}{z}, zmm1","vcvttpd2uqq zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F.W1 78 /r","V","V","AVX512DQ","bscale8,scale64","w,r,r","","" +"VCVTTPS2DQ xmm1, xmm2/m128","VCVTTPS2DQ xmm2/m128, xmm1","vcvttps2dq xmm2/m128, xmm1","VEX.128.F3.0F.WIG 5B /r","V","V","AVX","","w,r","","" +"VCVTTPS2DQ xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTTPS2DQ xmm2/m128/m32bcst, {k}{z}, xmm1","vcvttps2dq xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.F3.0F.W0 5B /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTTPS2DQ ymm1, ymm2/m256","VCVTTPS2DQ ymm2/m256, ymm1","vcvttps2dq ymm2/m256, ymm1","VEX.256.F3.0F.WIG 5B /r","V","V","AVX","","w,r","","" +"VCVTTPS2DQ ymm1, {k}{z}, ymm2/m256/m32bcst","VCVTTPS2DQ ymm2/m256/m32bcst, {k}{z}, ymm1","vcvttps2dq ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.F3.0F.W0 5B /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VCVTTPS2DQ zmm1{sae}, {k}{z}, zmm2","VCVTTPS2DQ zmm2, {k}{z}, zmm1{sae}","vcvttps2dq zmm2, {k}{z}, zmm1{sae}","EVEX.512.F3.0F.W0 5B /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VCVTTPS2DQ zmm1, {k}{z}, zmm2/m512/m32bcst","VCVTTPS2DQ zmm2/m512/m32bcst, {k}{z}, zmm1","vcvttps2dq zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.F3.0F.W0 5B /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VCVTTPS2QQ xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTTPS2QQ xmm2/m128/m32bcst, {k}{z}, xmm1","vcvttps2qq xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F.W0 7A /r","V","V","AVX512DQ+AVX512VL","bscale4,scale8","w,r,r","","" +"VCVTTPS2QQ ymm1, {k}{z}, xmm2/m256/m32bcst","VCVTTPS2QQ xmm2/m256/m32bcst, {k}{z}, ymm1","vcvttps2qq xmm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F.W0 7A /r","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTTPS2QQ zmm1{sae}, {k}{z}, ymm2","VCVTTPS2QQ ymm2, {k}{z}, zmm1{sae}","vcvttps2qq ymm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F.W0 7A /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTTPS2QQ zmm1, {k}{z}, ymm2/m512/m32bcst","VCVTTPS2QQ ymm2/m512/m32bcst, {k}{z}, zmm1","vcvttps2qq ymm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F.W0 7A /r","V","V","AVX512DQ","bscale4,scale32","w,r,r","","" +"VCVTTPS2UDQ xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTTPS2UDQ xmm2/m128/m32bcst, {k}{z}, xmm1","vcvttps2udq xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.0F.W0 78 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTTPS2UDQ ymm1, {k}{z}, ymm2/m256/m32bcst","VCVTTPS2UDQ ymm2/m256/m32bcst, {k}{z}, ymm1","vcvttps2udq ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.0F.W0 78 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VCVTTPS2UDQ zmm1{sae}, {k}{z}, zmm2","VCVTTPS2UDQ zmm2, {k}{z}, zmm1{sae}","vcvttps2udq zmm2, {k}{z}, zmm1{sae}","EVEX.512.0F.W0 78 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VCVTTPS2UDQ zmm1, {k}{z}, zmm2/m512/m32bcst","VCVTTPS2UDQ zmm2/m512/m32bcst, {k}{z}, zmm1","vcvttps2udq zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.0F.W0 78 /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VCVTTPS2UQQ xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTTPS2UQQ xmm2/m128/m32bcst, {k}{z}, xmm1","vcvttps2uqq xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F.W0 78 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale8","w,r,r","","" +"VCVTTPS2UQQ ymm1, {k}{z}, xmm2/m256/m32bcst","VCVTTPS2UQQ xmm2/m256/m32bcst, {k}{z}, ymm1","vcvttps2uqq xmm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F.W0 78 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTTPS2UQQ zmm1{sae}, {k}{z}, ymm2","VCVTTPS2UQQ ymm2, {k}{z}, zmm1{sae}","vcvttps2uqq ymm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F.W0 78 /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTTPS2UQQ zmm1, {k}{z}, ymm2/m512/m32bcst","VCVTTPS2UQQ ymm2/m512/m32bcst, {k}{z}, zmm1","vcvttps2uqq ymm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F.W0 78 /r","V","V","AVX512DQ","bscale4,scale32","w,r,r","","" +"VCVTTSD2SI r32{sae}, xmm2","VCVTTSD2SI xmm2, r32{sae}","vcvttsd2si xmm2, r32{sae}","EVEX.128.F2.0F.W0 2C /r","V","V","AVX512F","modrm_regonly","w,r","Y","32" +"VCVTTSD2SI r32, xmm2/m64","VCVTTSD2SI xmm2/m64, r32","vcvttsd2si xmm2/m64, r32","EVEX.LIG.F2.0F.W0 2C /r","V","V","AVX512F","scale8","w,r","Y","32" +"VCVTTSD2SI r32, xmm2/m64","VCVTTSD2SI xmm2/m64, r32","vcvttsd2si xmm2/m64, r32","VEX.LIG.F2.0F.W0 2C /r","V","V","AVX","","w,r","Y","32" +"VCVTTSD2SI r64{sae}, xmm2","VCVTTSD2SIQ xmm2, r64{sae}","vcvttsd2siq xmm2, r64{sae}","EVEX.128.F2.0F.W1 2C /r","N.S.","V","AVX512F","modrm_regonly","w,r","Y","64" +"VCVTTSD2SI r64, xmm2/m64","VCVTTSD2SIQ xmm2/m64, r64","vcvttsd2siq xmm2/m64, r64","EVEX.LIG.F2.0F.W1 2C /r","N.S.","V","AVX512F","scale8","w,r","Y","64" +"VCVTTSD2SI r64, xmm2/m64","VCVTTSD2SIQ xmm2/m64, r64","vcvttsd2siq xmm2/m64, r64","VEX.LIG.F2.0F.W1 2C /r","N.S.","V","AVX","","w,r","Y","64" +"VCVTTSD2USI r32{sae}, xmm2","VCVTTSD2USIL xmm2, r32{sae}","vcvttsd2usil xmm2, r32{sae}","EVEX.128.F2.0F.W0 78 /r","V","V","AVX512F","modrm_regonly","w,r","Y","32" +"VCVTTSD2USI r32, xmm2/m64","VCVTTSD2USIL xmm2/m64, r32","vcvttsd2usil xmm2/m64, r32","EVEX.LIG.F2.0F.W0 78 /r","V","V","AVX512F","scale8","w,r","Y","32" +"VCVTTSD2USI r64{sae}, xmm2","VCVTTSD2USIQ xmm2, r64{sae}","vcvttsd2usiq xmm2, r64{sae}","EVEX.128.F2.0F.W1 78 /r","N.S.","V","AVX512F","modrm_regonly","w,r","Y","64" +"VCVTTSD2USI r64, xmm2/m64","VCVTTSD2USIQ xmm2/m64, r64","vcvttsd2usiq xmm2/m64, r64","EVEX.LIG.F2.0F.W1 78 /r","N.S.","V","AVX512F","scale8","w,r","Y","64" +"VCVTTSS2SI r32{sae}, xmm2","VCVTTSS2SI xmm2, r32{sae}","vcvttss2si xmm2, r32{sae}","EVEX.128.F3.0F.W0 2C /r","V","V","AVX512F","modrm_regonly","w,r","Y","32" +"VCVTTSS2SI r32, xmm2/m32","VCVTTSS2SI xmm2/m32, r32","vcvttss2si xmm2/m32, r32","EVEX.LIG.F3.0F.W0 2C /r","V","V","AVX512F","scale4","w,r","Y","32" +"VCVTTSS2SI r32, xmm2/m32","VCVTTSS2SI xmm2/m32, r32","vcvttss2si xmm2/m32, r32","VEX.LIG.F3.0F.W0 2C /r","V","V","AVX","","w,r","Y","32" +"VCVTTSS2SI r64{sae}, xmm2","VCVTTSS2SIQ xmm2, r64{sae}","vcvttss2siq xmm2, r64{sae}","EVEX.128.F3.0F.W1 2C /r","N.S.","V","AVX512F","modrm_regonly","w,r","Y","64" +"VCVTTSS2SI r64, xmm2/m32","VCVTTSS2SIQ xmm2/m32, r64","vcvttss2siq xmm2/m32, r64","EVEX.LIG.F3.0F.W1 2C /r","N.S.","V","AVX512F","scale4","w,r","Y","64" +"VCVTTSS2SI r64, xmm2/m32","VCVTTSS2SIQ xmm2/m32, r64","vcvttss2siq xmm2/m32, r64","VEX.LIG.F3.0F.W1 2C /r","N.S.","V","AVX","","w,r","Y","64" +"VCVTTSS2USI r32{sae}, xmm2","VCVTTSS2USIL xmm2, r32{sae}","vcvttss2usil xmm2, r32{sae}","EVEX.128.F3.0F.W0 78 /r","V","V","AVX512F","modrm_regonly","w,r","Y","32" +"VCVTTSS2USI r32, xmm2/m32","VCVTTSS2USIL xmm2/m32, r32","vcvttss2usil xmm2/m32, r32","EVEX.LIG.F3.0F.W0 78 /r","V","V","AVX512F","scale4","w,r","Y","32" +"VCVTTSS2USI r64{sae}, xmm2","VCVTTSS2USIQ xmm2, r64{sae}","vcvttss2usiq xmm2, r64{sae}","EVEX.128.F3.0F.W1 78 /r","N.S.","V","AVX512F","modrm_regonly","w,r","Y","64" +"VCVTTSS2USI r64, xmm2/m32","VCVTTSS2USIQ xmm2/m32, r64","vcvttss2usiq xmm2/m32, r64","EVEX.LIG.F3.0F.W1 78 /r","N.S.","V","AVX512F","scale4","w,r","Y","64" +"VCVTUDQ2PD xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTUDQ2PD xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtudq2pd xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.F3.0F.W0 7A /r","V","V","AVX512F+AVX512VL","bscale4,scale8","w,r,r","","" +"VCVTUDQ2PD ymm1, {k}{z}, xmm2/m256/m32bcst","VCVTUDQ2PD xmm2/m256/m32bcst, {k}{z}, ymm1","vcvtudq2pd xmm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.F3.0F.W0 7A /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTUDQ2PD zmm1, {k}{z}, ymm2/m512/m32bcst","VCVTUDQ2PD ymm2/m512/m32bcst, {k}{z}, zmm1","vcvtudq2pd ymm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.F3.0F.W0 7A /r","V","V","AVX512F","bscale4,scale32","w,r,r","","" +"VCVTUDQ2PS xmm1, {k}{z}, xmm2/m128/m32bcst","VCVTUDQ2PS xmm2/m128/m32bcst, {k}{z}, xmm1","vcvtudq2ps xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.F2.0F.W0 7A /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VCVTUDQ2PS ymm1, {k}{z}, ymm2/m256/m32bcst","VCVTUDQ2PS ymm2/m256/m32bcst, {k}{z}, ymm1","vcvtudq2ps ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.F2.0F.W0 7A /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VCVTUDQ2PS zmm1{er}, {k}{z}, zmm2","VCVTUDQ2PS zmm2, {k}{z}, zmm1{er}","vcvtudq2ps zmm2, {k}{z}, zmm1{er}","EVEX.512.F2.0F.W0 7A /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VCVTUDQ2PS zmm1, {k}{z}, zmm2/m512/m32bcst","VCVTUDQ2PS zmm2/m512/m32bcst, {k}{z}, zmm1","vcvtudq2ps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.F2.0F.W0 7A /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VCVTUQQ2PD xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTUQQ2PD xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtuqq2pd xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.F3.0F.W1 7A /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r","","" +"VCVTUQQ2PD ymm1, {k}{z}, ymm2/m256/m64bcst","VCVTUQQ2PD ymm2/m256/m64bcst, {k}{z}, ymm1","vcvtuqq2pd ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.F3.0F.W1 7A /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r","","" +"VCVTUQQ2PD zmm1{er}, {k}{z}, zmm2","VCVTUQQ2PD zmm2, {k}{z}, zmm1{er}","vcvtuqq2pd zmm2, {k}{z}, zmm1{er}","EVEX.512.F3.0F.W1 7A /r","V","V","AVX512DQ","modrm_regonly","w,r,r","","" +"VCVTUQQ2PD zmm1, {k}{z}, zmm2/m512/m64bcst","VCVTUQQ2PD zmm2/m512/m64bcst, {k}{z}, zmm1","vcvtuqq2pd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.F3.0F.W1 7A /r","V","V","AVX512DQ","bscale8,scale64","w,r,r","","" +"VCVTUQQ2PS ymm1{er}, {k}{z}, zmm2","VCVTUQQ2PS zmm2, {k}{z}, ymm1{er}","vcvtuqq2ps zmm2, {k}{z}, ymm1{er}","EVEX.512.F2.0F.W1 7A /r","V","V","AVX512DQ","modrm_regonly","w,r,r","Y","" +"VCVTUQQ2PS ymm1, {k}{z}, zmm2/m512/m64bcst","VCVTUQQ2PS zmm2/m512/m64bcst, {k}{z}, ymm1","vcvtuqq2ps zmm2/m512/m64bcst, {k}{z}, ymm1","EVEX.512.F2.0F.W1 7A /r","V","V","AVX512DQ","bscale8,scale64","w,r,r","Y","512" +"VCVTUQQ2PS xmm1, {k}{z}, xmm2/m128/m64bcst","VCVTUQQ2PSX xmm2/m128/m64bcst, {k}{z}, xmm1","vcvtuqq2psx xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.F2.0F.W1 7A /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r","Y","128" +"VCVTUQQ2PS xmm1, {k}{z}, ymm2/m256/m64bcst","VCVTUQQ2PSY ymm2/m256/m64bcst, {k}{z}, xmm1","vcvtuqq2psy ymm2/m256/m64bcst, {k}{z}, xmm1","EVEX.256.F2.0F.W1 7A /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r","Y","256" +"VCVTUSI2SD xmm1, xmmV, r/m32","VCVTUSI2SDL r/m32, xmmV, xmm1","vcvtusi2sd r/m32, xmmV, xmm1","EVEX.NDS.LIG.F2.0F.W0 7B /r","V","V","AVX512F","scale4","w,r,r","Y","32" +"VCVTUSI2SD xmm1, xmmV, r/m64","VCVTUSI2SDQ r/m64, xmmV, xmm1","vcvtusi2sd r/m64, xmmV, xmm1","EVEX.NDS.LIG.F2.0F.W1 7B /r","N.S.","V","AVX512F","scale8","w,r,r","Y","64" +"VCVTUSI2SD xmm1{er}, xmmV, rmr64","VCVTUSI2SDQ rmr64, xmmV, xmm1{er}","vcvtusi2sd rmr64, xmmV, xmm1{er}","EVEX.NDS.128.F2.0F.W1 7B /r","N.S.","V","AVX512F","modrm_regonly","w,r,r","Y","64" +"VCVTUSI2SS xmm1, xmmV, r/m32","VCVTUSI2SSL r/m32, xmmV, xmm1","vcvtusi2ssl r/m32, xmmV, xmm1","EVEX.NDS.LIG.F3.0F.W0 7B /r","V","V","AVX512F","scale4","w,r,r","Y","32" +"VCVTUSI2SS xmm1{er}, xmmV, rmr32","VCVTUSI2SSL rmr32, xmmV, xmm1{er}","vcvtusi2ssl rmr32, xmmV, xmm1{er}","EVEX.NDS.128.F3.0F.W0 7B /r","V","V","AVX512F","modrm_regonly","w,r,r","Y","32" +"VCVTUSI2SS xmm1, xmmV, r/m64","VCVTUSI2SSQ r/m64, xmmV, xmm1","vcvtusi2ssq r/m64, xmmV, xmm1","EVEX.NDS.LIG.F3.0F.W1 7B /r","N.S.","V","AVX512F","scale8","w,r,r","Y","64" +"VCVTUSI2SS xmm1{er}, xmmV, rmr64","VCVTUSI2SSQ rmr64, xmmV, xmm1{er}","vcvtusi2ssq rmr64, xmmV, xmm1{er}","EVEX.NDS.128.F3.0F.W1 7B /r","N.S.","V","AVX512F","modrm_regonly","w,r,r","Y","64" +"VDBPSADBW xmm1, {k}{z}, xmmV, xmm2/m128, imm8u","VDBPSADBW imm8u, xmm2/m128, xmmV, {k}{z}, xmm1","vdbpsadbw imm8u, xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W0 42 /r ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r,r","","" +"VDBPSADBW ymm1, {k}{z}, ymmV, ymm2/m256, imm8u","VDBPSADBW imm8u, ymm2/m256, ymmV, {k}{z}, ymm1","vdbpsadbw imm8u, ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 42 /r ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r,r","","" +"VDBPSADBW zmm1, {k}{z}, zmmV, zmm2/m512, imm8u","VDBPSADBW imm8u, zmm2/m512, zmmV, {k}{z}, zmm1","vdbpsadbw imm8u, zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 42 /r ib","V","V","AVX512BW","scale64","w,r,r,r,r","","" +"VDIVPD xmm1, xmmV, xmm2/m128","VDIVPD xmm2/m128, xmmV, xmm1","vdivpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 5E /r","V","V","AVX","","w,r,r","","" +"VDIVPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VDIVPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vdivpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 5E /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VDIVPD ymm1, ymmV, ymm2/m256","VDIVPD ymm2/m256, ymmV, ymm1","vdivpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 5E /r","V","V","AVX","","w,r,r","","" +"VDIVPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VDIVPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vdivpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 5E /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VDIVPD zmm1{er}, {k}{z}, zmmV, zmm2","VDIVPD zmm2, zmmV, {k}{z}, zmm1{er}","vdivpd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.66.0F.W1 5E /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VDIVPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VDIVPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vdivpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 5E /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VDIVPS xmm1, xmmV, xmm2/m128","VDIVPS xmm2/m128, xmmV, xmm1","vdivps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 5E /r","V","V","AVX","","w,r,r","","" +"VDIVPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VDIVPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vdivps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 5E /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VDIVPS ymm1, ymmV, ymm2/m256","VDIVPS ymm2/m256, ymmV, ymm1","vdivps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 5E /r","V","V","AVX","","w,r,r","","" +"VDIVPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VDIVPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vdivps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 5E /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VDIVPS zmm1{er}, {k}{z}, zmmV, zmm2","VDIVPS zmm2, zmmV, {k}{z}, zmm1{er}","vdivps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.0F.W0 5E /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VDIVPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VDIVPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vdivps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 5E /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VDIVSD xmm1{er}, {k}{z}, xmmV, xmm2","VDIVSD xmm2, xmmV, {k}{z}, xmm1{er}","vdivsd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F2.0F.W1 5E /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VDIVSD xmm1, xmmV, xmm2/m64","VDIVSD xmm2/m64, xmmV, xmm1","vdivsd xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 5E /r","V","V","AVX","","w,r,r","","" +"VDIVSD xmm1, {k}{z}, xmmV, xmm2/m64","VDIVSD xmm2/m64, xmmV, {k}{z}, xmm1","vdivsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 5E /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VDIVSS xmm1{er}, {k}{z}, xmmV, xmm2","VDIVSS xmm2, xmmV, {k}{z}, xmm1{er}","vdivss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F3.0F.W0 5E /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VDIVSS xmm1, xmmV, xmm2/m32","VDIVSS xmm2/m32, xmmV, xmm1","vdivss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 5E /r","V","V","AVX","","w,r,r","","" +"VDIVSS xmm1, {k}{z}, xmmV, xmm2/m32","VDIVSS xmm2/m32, xmmV, {k}{z}, xmm1","vdivss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 5E /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VDPPD xmm1, xmmV, xmm2/m128, imm8u","VDPPD imm8u, xmm2/m128, xmmV, xmm1","vdppd imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 41 /r ib","V","V","AVX","","w,r,r,r","","" +"VDPPS xmm1, xmmV, xmm2/m128, imm8u","VDPPS imm8u, xmm2/m128, xmmV, xmm1","vdpps imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 40 /r ib","V","V","AVX","","w,r,r,r","","" +"VDPPS ymm1, ymmV, ymm2/m256, imm8u","VDPPS imm8u, ymm2/m256, ymmV, ymm1","vdpps imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.WIG 40 /r ib","V","V","AVX","","w,r,r,r","","" +"VERR r/m16","VERR r/m16","verr r/m16","0F 00 /4","V","V","","","r","","" +"VERW r/m16","VERW r/m16","verw r/m16","0F 00 /5","V","V","","","r","","" +"VEXP2PD zmm1{sae}, {k}{z}, zmm2","VEXP2PD zmm2, {k}{z}, zmm1{sae}","vexp2pd zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W1 C8 /r","V","V","AVX512ER","modrm_regonly","w,r,r","","" +"VEXP2PD zmm1, {k}{z}, zmm2/m512/m64bcst","VEXP2PD zmm2/m512/m64bcst, {k}{z}, zmm1","vexp2pd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 C8 /r","V","V","AVX512ER","bscale8,scale64","w,r,r","","" +"VEXP2PS zmm1{sae}, {k}{z}, zmm2","VEXP2PS zmm2, {k}{z}, zmm1{sae}","vexp2ps zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W0 C8 /r","V","V","AVX512ER","modrm_regonly","w,r,r","","" +"VEXP2PS zmm1, {k}{z}, zmm2/m512/m32bcst","VEXP2PS zmm2/m512/m32bcst, {k}{z}, zmm1","vexp2ps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 C8 /r","V","V","AVX512ER","bscale4,scale64","w,r,r","","" +"VEXPANDPD xmm1, {k}{z}, xmm2/m128","VEXPANDPD xmm2/m128, {k}{z}, xmm1","vexpandpd xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.W1 88 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VEXPANDPD ymm1, {k}{z}, ymm2/m256","VEXPANDPD ymm2/m256, {k}{z}, ymm1","vexpandpd ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.W1 88 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VEXPANDPD zmm1, {k}{z}, zmm2/m512","VEXPANDPD zmm2/m512, {k}{z}, zmm1","vexpandpd zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.W1 88 /r","V","V","AVX512F","scale8","w,r,r","","" +"VEXPANDPS xmm1, {k}{z}, xmm2/m128","VEXPANDPS xmm2/m128, {k}{z}, xmm1","vexpandps xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.W0 88 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VEXPANDPS ymm1, {k}{z}, ymm2/m256","VEXPANDPS ymm2/m256, {k}{z}, ymm1","vexpandps ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.W0 88 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VEXPANDPS zmm1, {k}{z}, zmm2/m512","VEXPANDPS zmm2/m512, {k}{z}, zmm1","vexpandps zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.W0 88 /r","V","V","AVX512F","scale4","w,r,r","","" +"VEXTRACTF128 xmm2/m128, ymm1, imm8u:1","VEXTRACTF128 imm8u:1, ymm1, xmm2/m128","vextractf128 imm8u:1, ymm1, xmm2/m128","VEX.256.66.0F3A.W0 19 /r ib","V","V","AVX","","w,r,r","","" +"VEXTRACTF32X4 xmm2/m128, {k}{z}, ymm1, imm8u:1","VEXTRACTF32X4 imm8u:1, ymm1, {k}{z}, xmm2/m128","vextractf32x4 imm8u:1, ymm1, {k}{z}, xmm2/m128","EVEX.256.66.0F3A.W0 19 /r ib","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VEXTRACTF32X4 xmm2/m128, {k}{z}, zmm1, imm8u:2","VEXTRACTF32X4 imm8u:2, zmm1, {k}{z}, xmm2/m128","vextractf32x4 imm8u:2, zmm1, {k}{z}, xmm2/m128","EVEX.512.66.0F3A.W0 19 /r ib","V","V","AVX512F","scale16","w,r,r,r","","" +"VEXTRACTF32X8 ymm2/m256, {k}{z}, zmm1, imm8u:1","VEXTRACTF32X8 imm8u:1, zmm1, {k}{z}, ymm2/m256","vextractf32x8 imm8u:1, zmm1, {k}{z}, ymm2/m256","EVEX.512.66.0F3A.W0 1B /r ib","V","V","AVX512DQ","scale32","w,r,r,r","","" +"VEXTRACTF64X2 xmm2/m128, {k}{z}, ymm1, imm8u:1","VEXTRACTF64X2 imm8u:1, ymm1, {k}{z}, xmm2/m128","vextractf64x2 imm8u:1, ymm1, {k}{z}, xmm2/m128","EVEX.256.66.0F3A.W1 19 /r ib","V","V","AVX512DQ+AVX512VL","scale16","w,r,r,r","","" +"VEXTRACTF64X2 xmm2/m128, {k}{z}, zmm1, imm8u:2","VEXTRACTF64X2 imm8u:2, zmm1, {k}{z}, xmm2/m128","vextractf64x2 imm8u:2, zmm1, {k}{z}, xmm2/m128","EVEX.512.66.0F3A.W1 19 /r ib","V","V","AVX512DQ","scale16","w,r,r,r","","" +"VEXTRACTF64X4 ymm2/m256, {k}{z}, zmm1, imm8u","VEXTRACTF64X4 imm8u, zmm1, {k}{z}, ymm2/m256","vextractf64x4 imm8u, zmm1, {k}{z}, ymm2/m256","EVEX.512.66.0F3A.W1 1B /r ib","V","V","AVX512F","scale32","w,r,r,r","","" +"VEXTRACTI128 xmm2/m128, ymm1, imm8u:1","VEXTRACTI128 imm8u:1, ymm1, xmm2/m128","vextracti128 imm8u:1, ymm1, xmm2/m128","VEX.256.66.0F3A.W0 39 /r ib","V","V","AVX2","","w,r,r","","" +"VEXTRACTI32X4 xmm2/m128, {k}{z}, ymm1, imm8u:1","VEXTRACTI32X4 imm8u:1, ymm1, {k}{z}, xmm2/m128","vextracti32x4 imm8u:1, ymm1, {k}{z}, xmm2/m128","EVEX.256.66.0F3A.W0 39 /r ib","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VEXTRACTI32X4 xmm2/m128, {k}{z}, zmm1, imm8u:2","VEXTRACTI32X4 imm8u:2, zmm1, {k}{z}, xmm2/m128","vextracti32x4 imm8u:2, zmm1, {k}{z}, xmm2/m128","EVEX.512.66.0F3A.W0 39 /r ib","V","V","AVX512F","scale16","w,r,r,r","","" +"VEXTRACTI32X8 ymm2/m256, {k}{z}, zmm1, imm8u:1","VEXTRACTI32X8 imm8u:1, zmm1, {k}{z}, ymm2/m256","vextracti32x8 imm8u:1, zmm1, {k}{z}, ymm2/m256","EVEX.512.66.0F3A.W0 3B /r ib","V","V","AVX512DQ","scale32","w,r,r,r","","" +"VEXTRACTI64X2 xmm2/m128, {k}{z}, ymm1, imm8u:1","VEXTRACTI64X2 imm8u:1, ymm1, {k}{z}, xmm2/m128","vextracti64x2 imm8u:1, ymm1, {k}{z}, xmm2/m128","EVEX.256.66.0F3A.W1 39 /r ib","V","V","AVX512DQ+AVX512VL","scale16","w,r,r,r","","" +"VEXTRACTI64X2 xmm2/m128, {k}{z}, zmm1, imm8u:2","VEXTRACTI64X2 imm8u:2, zmm1, {k}{z}, xmm2/m128","vextracti64x2 imm8u:2, zmm1, {k}{z}, xmm2/m128","EVEX.512.66.0F3A.W1 39 /r ib","V","V","AVX512DQ","scale16","w,r,r,r","","" +"VEXTRACTI64X4 ymm2/m256, {k}{z}, zmm1, imm8u:1","VEXTRACTI64X4 imm8u:1, zmm1, {k}{z}, ymm2/m256","vextracti64x4 imm8u:1, zmm1, {k}{z}, ymm2/m256","EVEX.512.66.0F3A.W1 3B /r ib","V","V","AVX512F","scale32","w,r,r,r","","" +"VEXTRACTPS r/m32, xmm1, imm8u:2","VEXTRACTPS imm8u:2, xmm1, r/m32","vextractps imm8u:2, xmm1, r/m32","EVEX.128.66.0F3A.WIG 17 /r ib","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VEXTRACTPS r/m32, xmm1, imm8u:2","VEXTRACTPS imm8u:2, xmm1, r/m32","vextractps imm8u:2, xmm1, r/m32","VEX.128.66.0F3A.WIG 17 /r ib","V","V","AVX","","w,r,r","","" +"VFIXUPIMMPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u","VFIXUPIMMPD imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfixupimmpd imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F3A.W1 54 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r,r","","" +"VFIXUPIMMPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VFIXUPIMMPD imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfixupimmpd imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F3A.W1 54 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r,r","","" +"VFIXUPIMMPD zmm1{sae}, {k}{z}, zmmV, zmm2, imm8u","VFIXUPIMMPD imm8u, zmm2, zmmV, {k}{z}, zmm1{sae}","vfixupimmpd imm8u, zmm2, zmmV, {k}{z}, zmm1{sae}","EVEX.DDS.512.66.0F3A.W1 54 /r ib","V","V","AVX512F","modrm_regonly","rw,r,r,r,r","","" +"VFIXUPIMMPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VFIXUPIMMPD imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfixupimmpd imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F3A.W1 54 /r ib","V","V","AVX512F","bscale8,scale64","rw,r,r,r,r","","" +"VFIXUPIMMPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst, imm8u","VFIXUPIMMPS imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfixupimmps imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F3A.W0 54 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r,r","","" +"VFIXUPIMMPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u","VFIXUPIMMPS imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfixupimmps imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F3A.W0 54 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r,r","","" +"VFIXUPIMMPS zmm1{sae}, {k}{z}, zmmV, zmm2, imm8u","VFIXUPIMMPS imm8u, zmm2, zmmV, {k}{z}, zmm1{sae}","vfixupimmps imm8u, zmm2, zmmV, {k}{z}, zmm1{sae}","EVEX.DDS.512.66.0F3A.W0 54 /r ib","V","V","AVX512F","modrm_regonly","rw,r,r,r,r","","" +"VFIXUPIMMPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u","VFIXUPIMMPS imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfixupimmps imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F3A.W0 54 /r ib","V","V","AVX512F","bscale4,scale64","rw,r,r,r,r","","" +"VFIXUPIMMSD xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u","VFIXUPIMMSD imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","vfixupimmsd imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.DDS.128.66.0F3A.W1 55 /r ib","V","V","AVX512F","modrm_regonly","rw,r,r,r,r","","" +"VFIXUPIMMSD xmm1, {k}{z}, xmmV, xmm2/m64, imm8u","VFIXUPIMMSD imm8u, xmm2/m64, xmmV, {k}{z}, xmm1","vfixupimmsd imm8u, xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F3A.W1 55 /r ib","V","V","AVX512F","scale8","rw,r,r,r,r","","" +"VFIXUPIMMSS xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u","VFIXUPIMMSS imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","vfixupimmss imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.DDS.128.66.0F3A.W0 55 /r ib","V","V","AVX512F","modrm_regonly","rw,r,r,r,r","","" +"VFIXUPIMMSS xmm1, {k}{z}, xmmV, xmm2/m32, imm8u","VFIXUPIMMSS imm8u, xmm2/m32, xmmV, {k}{z}, xmm1","vfixupimmss imm8u, xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F3A.W0 55 /r ib","V","V","AVX512F","scale4","rw,r,r,r,r","","" +"VFMADD132PD xmm1, xmmV, xmm2/m128","VFMADD132PD xmm2/m128, xmmV, xmm1","vfmadd132pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 98 /r","V","V","FMA","","rw,r,r","","" +"VFMADD132PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMADD132PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmadd132pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 98 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMADD132PD ymm1, ymmV, ymm2/m256","VFMADD132PD ymm2/m256, ymmV, ymm1","vfmadd132pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 98 /r","V","V","FMA","","rw,r,r","","" +"VFMADD132PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMADD132PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmadd132pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 98 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMADD132PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMADD132PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmadd132pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 98 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD132PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMADD132PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmadd132pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 98 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMADD132PS xmm1, xmmV, xmm2/m128","VFMADD132PS xmm2/m128, xmmV, xmm1","vfmadd132ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 98 /r","V","V","FMA","","rw,r,r","","" +"VFMADD132PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMADD132PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmadd132ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 98 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMADD132PS ymm1, ymmV, ymm2/m256","VFMADD132PS ymm2/m256, ymmV, ymm1","vfmadd132ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 98 /r","V","V","FMA","","rw,r,r","","" +"VFMADD132PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMADD132PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmadd132ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 98 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMADD132PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMADD132PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmadd132ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 98 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD132PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMADD132PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmadd132ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 98 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMADD132SD xmm1{er}, {k}{z}, xmmV, xmm2","VFMADD132SD xmm2, xmmV, {k}{z}, xmm1{er}","vfmadd132sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 99 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD132SD xmm1, xmmV, xmm2/m64","VFMADD132SD xmm2/m64, xmmV, xmm1","vfmadd132sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 99 /r","V","V","FMA","","rw,r,r","","" +"VFMADD132SD xmm1, {k}{z}, xmmV, xmm2/m64","VFMADD132SD xmm2/m64, xmmV, {k}{z}, xmm1","vfmadd132sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 99 /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFMADD132SS xmm1{er}, {k}{z}, xmmV, xmm2","VFMADD132SS xmm2, xmmV, {k}{z}, xmm1{er}","vfmadd132ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 99 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD132SS xmm1, xmmV, xmm2/m32","VFMADD132SS xmm2/m32, xmmV, xmm1","vfmadd132ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 99 /r","V","V","FMA","","rw,r,r","","" +"VFMADD132SS xmm1, {k}{z}, xmmV, xmm2/m32","VFMADD132SS xmm2/m32, xmmV, {k}{z}, xmm1","vfmadd132ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 99 /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFMADD213PD xmm1, xmmV, xmm2/m128","VFMADD213PD xmm2/m128, xmmV, xmm1","vfmadd213pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 A8 /r","V","V","FMA","","rw,r,r","","" +"VFMADD213PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMADD213PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmadd213pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 A8 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMADD213PD ymm1, ymmV, ymm2/m256","VFMADD213PD ymm2/m256, ymmV, ymm1","vfmadd213pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 A8 /r","V","V","FMA","","rw,r,r","","" +"VFMADD213PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMADD213PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmadd213pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 A8 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMADD213PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMADD213PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmadd213pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 A8 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD213PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMADD213PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmadd213pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 A8 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMADD213PS xmm1, xmmV, xmm2/m128","VFMADD213PS xmm2/m128, xmmV, xmm1","vfmadd213ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 A8 /r","V","V","FMA","","rw,r,r","","" +"VFMADD213PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMADD213PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmadd213ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 A8 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMADD213PS ymm1, ymmV, ymm2/m256","VFMADD213PS ymm2/m256, ymmV, ymm1","vfmadd213ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 A8 /r","V","V","FMA","","rw,r,r","","" +"VFMADD213PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMADD213PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmadd213ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 A8 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMADD213PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMADD213PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmadd213ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 A8 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD213PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMADD213PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmadd213ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 A8 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMADD213SD xmm1{er}, {k}{z}, xmmV, xmm2","VFMADD213SD xmm2, xmmV, {k}{z}, xmm1{er}","vfmadd213sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 A9 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD213SD xmm1, xmmV, xmm2/m64","VFMADD213SD xmm2/m64, xmmV, xmm1","vfmadd213sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 A9 /r","V","V","FMA","","rw,r,r","","" +"VFMADD213SD xmm1, {k}{z}, xmmV, xmm2/m64","VFMADD213SD xmm2/m64, xmmV, {k}{z}, xmm1","vfmadd213sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 A9 /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFMADD213SS xmm1{er}, {k}{z}, xmmV, xmm2","VFMADD213SS xmm2, xmmV, {k}{z}, xmm1{er}","vfmadd213ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 A9 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD213SS xmm1, xmmV, xmm2/m32","VFMADD213SS xmm2/m32, xmmV, xmm1","vfmadd213ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 A9 /r","V","V","FMA","","rw,r,r","","" +"VFMADD213SS xmm1, {k}{z}, xmmV, xmm2/m32","VFMADD213SS xmm2/m32, xmmV, {k}{z}, xmm1","vfmadd213ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 A9 /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFMADD231PD xmm1, xmmV, xmm2/m128","VFMADD231PD xmm2/m128, xmmV, xmm1","vfmadd231pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 B8 /r","V","V","FMA","","rw,r,r","","" +"VFMADD231PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMADD231PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmadd231pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 B8 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMADD231PD ymm1, ymmV, ymm2/m256","VFMADD231PD ymm2/m256, ymmV, ymm1","vfmadd231pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 B8 /r","V","V","FMA","","rw,r,r","","" +"VFMADD231PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMADD231PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmadd231pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 B8 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMADD231PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMADD231PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmadd231pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 B8 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD231PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMADD231PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmadd231pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 B8 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMADD231PS xmm1, xmmV, xmm2/m128","VFMADD231PS xmm2/m128, xmmV, xmm1","vfmadd231ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 B8 /r","V","V","FMA","","rw,r,r","","" +"VFMADD231PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMADD231PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmadd231ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 B8 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMADD231PS ymm1, ymmV, ymm2/m256","VFMADD231PS ymm2/m256, ymmV, ymm1","vfmadd231ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 B8 /r","V","V","FMA","","rw,r,r","","" +"VFMADD231PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMADD231PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmadd231ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 B8 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMADD231PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMADD231PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmadd231ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 B8 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD231PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMADD231PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmadd231ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 B8 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMADD231SD xmm1{er}, {k}{z}, xmmV, xmm2","VFMADD231SD xmm2, xmmV, {k}{z}, xmm1{er}","vfmadd231sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 B9 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD231SD xmm1, xmmV, xmm2/m64","VFMADD231SD xmm2/m64, xmmV, xmm1","vfmadd231sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 B9 /r","V","V","FMA","","rw,r,r","","" +"VFMADD231SD xmm1, {k}{z}, xmmV, xmm2/m64","VFMADD231SD xmm2/m64, xmmV, {k}{z}, xmm1","vfmadd231sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 B9 /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFMADD231SS xmm1{er}, {k}{z}, xmmV, xmm2","VFMADD231SS xmm2, xmmV, {k}{z}, xmm1{er}","vfmadd231ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 B9 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADD231SS xmm1, xmmV, xmm2/m32","VFMADD231SS xmm2/m32, xmmV, xmm1","vfmadd231ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 B9 /r","V","V","FMA","","rw,r,r","","" +"VFMADD231SS xmm1, {k}{z}, xmmV, xmm2/m32","VFMADD231SS xmm2/m32, xmmV, {k}{z}, xmm1","vfmadd231ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 B9 /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFMADDPD xmm1, xmmV, xmmIH, xmm2/m128","VFMADDPD xmm2/m128, xmmIH, xmmV, xmm1","vfmaddpd xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 69 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDPD xmm1, xmmV, xmm2/m128, xmmIH","VFMADDPD xmmIH, xmm2/m128, xmmV, xmm1","vfmaddpd xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 69 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDPD ymm1, ymmV, ymmIH, ymm2/m256","VFMADDPD ymm2/m256, ymmIH, ymmV, ymm1","vfmaddpd ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 69 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDPD ymm1, ymmV, ymm2/m256, ymmIH","VFMADDPD ymmIH, ymm2/m256, ymmV, ymm1","vfmaddpd ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 69 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDPS xmm1, xmmV, xmmIH, xmm2/m128","VFMADDPS xmm2/m128, xmmIH, xmmV, xmm1","vfmaddps xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 68 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDPS xmm1, xmmV, xmm2/m128, xmmIH","VFMADDPS xmmIH, xmm2/m128, xmmV, xmm1","vfmaddps xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 68 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDPS ymm1, ymmV, ymmIH, ymm2/m256","VFMADDPS ymm2/m256, ymmIH, ymmV, ymm1","vfmaddps ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 68 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDPS ymm1, ymmV, ymm2/m256, ymmIH","VFMADDPS ymmIH, ymm2/m256, ymmV, ymm1","vfmaddps ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 68 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSD xmm1, xmmV, xmmIH, xmm2/m64","VFMADDSD xmm2/m64, xmmIH, xmmV, xmm1","vfmaddsd xmm2/m64, xmmIH, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W1 6B /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSD xmm1, xmmV, xmm2/m64, xmmIH","VFMADDSD xmmIH, xmm2/m64, xmmV, xmm1","vfmaddsd xmmIH, xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W0 6B /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSS xmm1, xmmV, xmmIH, xmm2/m32","VFMADDSS xmm2/m32, xmmIH, xmmV, xmm1","vfmaddss xmm2/m32, xmmIH, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W1 6A /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSS xmm1, xmmV, xmm2/m32, xmmIH","VFMADDSS xmmIH, xmm2/m32, xmmV, xmm1","vfmaddss xmmIH, xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W0 6A /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSUB132PD xmm1, xmmV, xmm2/m128","VFMADDSUB132PD xmm2/m128, xmmV, xmm1","vfmaddsub132pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 96 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB132PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMADDSUB132PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmaddsub132pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 96 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMADDSUB132PD ymm1, ymmV, ymm2/m256","VFMADDSUB132PD ymm2/m256, ymmV, ymm1","vfmaddsub132pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 96 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB132PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMADDSUB132PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmaddsub132pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 96 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMADDSUB132PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMADDSUB132PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmaddsub132pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 96 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADDSUB132PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMADDSUB132PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmaddsub132pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 96 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMADDSUB132PS xmm1, xmmV, xmm2/m128","VFMADDSUB132PS xmm2/m128, xmmV, xmm1","vfmaddsub132ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 96 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB132PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMADDSUB132PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmaddsub132ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 96 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMADDSUB132PS ymm1, ymmV, ymm2/m256","VFMADDSUB132PS ymm2/m256, ymmV, ymm1","vfmaddsub132ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 96 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB132PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMADDSUB132PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmaddsub132ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 96 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMADDSUB132PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMADDSUB132PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmaddsub132ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 96 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADDSUB132PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMADDSUB132PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmaddsub132ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 96 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMADDSUB213PD xmm1, xmmV, xmm2/m128","VFMADDSUB213PD xmm2/m128, xmmV, xmm1","vfmaddsub213pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 A6 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB213PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMADDSUB213PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmaddsub213pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 A6 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMADDSUB213PD ymm1, ymmV, ymm2/m256","VFMADDSUB213PD ymm2/m256, ymmV, ymm1","vfmaddsub213pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 A6 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB213PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMADDSUB213PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmaddsub213pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 A6 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMADDSUB213PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMADDSUB213PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmaddsub213pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 A6 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADDSUB213PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMADDSUB213PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmaddsub213pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 A6 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMADDSUB213PS xmm1, xmmV, xmm2/m128","VFMADDSUB213PS xmm2/m128, xmmV, xmm1","vfmaddsub213ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 A6 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB213PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMADDSUB213PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmaddsub213ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 A6 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMADDSUB213PS ymm1, ymmV, ymm2/m256","VFMADDSUB213PS ymm2/m256, ymmV, ymm1","vfmaddsub213ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 A6 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB213PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMADDSUB213PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmaddsub213ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 A6 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMADDSUB213PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMADDSUB213PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmaddsub213ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 A6 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADDSUB213PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMADDSUB213PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmaddsub213ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 A6 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMADDSUB231PD xmm1, xmmV, xmm2/m128","VFMADDSUB231PD xmm2/m128, xmmV, xmm1","vfmaddsub231pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 B6 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB231PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMADDSUB231PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmaddsub231pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 B6 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMADDSUB231PD ymm1, ymmV, ymm2/m256","VFMADDSUB231PD ymm2/m256, ymmV, ymm1","vfmaddsub231pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 B6 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB231PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMADDSUB231PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmaddsub231pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 B6 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMADDSUB231PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMADDSUB231PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmaddsub231pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 B6 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADDSUB231PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMADDSUB231PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmaddsub231pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 B6 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMADDSUB231PS xmm1, xmmV, xmm2/m128","VFMADDSUB231PS xmm2/m128, xmmV, xmm1","vfmaddsub231ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 B6 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB231PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMADDSUB231PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmaddsub231ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 B6 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMADDSUB231PS ymm1, ymmV, ymm2/m256","VFMADDSUB231PS ymm2/m256, ymmV, ymm1","vfmaddsub231ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 B6 /r","V","V","FMA","","rw,r,r","","" +"VFMADDSUB231PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMADDSUB231PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmaddsub231ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 B6 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMADDSUB231PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMADDSUB231PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmaddsub231ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 B6 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMADDSUB231PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMADDSUB231PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmaddsub231ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 B6 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMADDSUBPD xmm1, xmmV, xmmIH, xmm2/m128","VFMADDSUBPD xmm2/m128, xmmIH, xmmV, xmm1","vfmaddsubpd xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 5D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSUBPD xmm1, xmmV, xmm2/m128, xmmIH","VFMADDSUBPD xmmIH, xmm2/m128, xmmV, xmm1","vfmaddsubpd xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 5D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSUBPD ymm1, ymmV, ymmIH, ymm2/m256","VFMADDSUBPD ymm2/m256, ymmIH, ymmV, ymm1","vfmaddsubpd ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 5D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSUBPD ymm1, ymmV, ymm2/m256, ymmIH","VFMADDSUBPD ymmIH, ymm2/m256, ymmV, ymm1","vfmaddsubpd ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 5D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSUBPS xmm1, xmmV, xmmIH, xmm2/m128","VFMADDSUBPS xmm2/m128, xmmIH, xmmV, xmm1","vfmaddsubps xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 5C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSUBPS xmm1, xmmV, xmm2/m128, xmmIH","VFMADDSUBPS xmmIH, xmm2/m128, xmmV, xmm1","vfmaddsubps xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 5C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSUBPS ymm1, ymmV, ymmIH, ymm2/m256","VFMADDSUBPS ymm2/m256, ymmIH, ymmV, ymm1","vfmaddsubps ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 5C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMADDSUBPS ymm1, ymmV, ymm2/m256, ymmIH","VFMADDSUBPS ymmIH, ymm2/m256, ymmV, ymm1","vfmaddsubps ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 5C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUB132PD xmm1, xmmV, xmm2/m128","VFMSUB132PD xmm2/m128, xmmV, xmm1","vfmsub132pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 9A /r","V","V","FMA","","rw,r,r","","" +"VFMSUB132PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMSUB132PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmsub132pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 9A /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMSUB132PD ymm1, ymmV, ymm2/m256","VFMSUB132PD ymm2/m256, ymmV, ymm1","vfmsub132pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 9A /r","V","V","FMA","","rw,r,r","","" +"VFMSUB132PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMSUB132PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmsub132pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 9A /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMSUB132PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUB132PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmsub132pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 9A /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB132PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMSUB132PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmsub132pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 9A /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMSUB132PS xmm1, xmmV, xmm2/m128","VFMSUB132PS xmm2/m128, xmmV, xmm1","vfmsub132ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 9A /r","V","V","FMA","","rw,r,r","","" +"VFMSUB132PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMSUB132PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmsub132ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 9A /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMSUB132PS ymm1, ymmV, ymm2/m256","VFMSUB132PS ymm2/m256, ymmV, ymm1","vfmsub132ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 9A /r","V","V","FMA","","rw,r,r","","" +"VFMSUB132PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMSUB132PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmsub132ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 9A /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMSUB132PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUB132PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmsub132ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 9A /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB132PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMSUB132PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmsub132ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 9A /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMSUB132SD xmm1{er}, {k}{z}, xmmV, xmm2","VFMSUB132SD xmm2, xmmV, {k}{z}, xmm1{er}","vfmsub132sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 9B /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB132SD xmm1, xmmV, xmm2/m64","VFMSUB132SD xmm2/m64, xmmV, xmm1","vfmsub132sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 9B /r","V","V","FMA","","rw,r,r","","" +"VFMSUB132SD xmm1, {k}{z}, xmmV, xmm2/m64","VFMSUB132SD xmm2/m64, xmmV, {k}{z}, xmm1","vfmsub132sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 9B /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFMSUB132SS xmm1{er}, {k}{z}, xmmV, xmm2","VFMSUB132SS xmm2, xmmV, {k}{z}, xmm1{er}","vfmsub132ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 9B /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB132SS xmm1, xmmV, xmm2/m32","VFMSUB132SS xmm2/m32, xmmV, xmm1","vfmsub132ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 9B /r","V","V","FMA","","rw,r,r","","" +"VFMSUB132SS xmm1, {k}{z}, xmmV, xmm2/m32","VFMSUB132SS xmm2/m32, xmmV, {k}{z}, xmm1","vfmsub132ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 9B /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFMSUB213PD xmm1, xmmV, xmm2/m128","VFMSUB213PD xmm2/m128, xmmV, xmm1","vfmsub213pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 AA /r","V","V","FMA","","rw,r,r","","" +"VFMSUB213PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMSUB213PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmsub213pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 AA /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMSUB213PD ymm1, ymmV, ymm2/m256","VFMSUB213PD ymm2/m256, ymmV, ymm1","vfmsub213pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 AA /r","V","V","FMA","","rw,r,r","","" +"VFMSUB213PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMSUB213PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmsub213pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 AA /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMSUB213PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUB213PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmsub213pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 AA /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB213PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMSUB213PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmsub213pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 AA /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMSUB213PS xmm1, xmmV, xmm2/m128","VFMSUB213PS xmm2/m128, xmmV, xmm1","vfmsub213ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 AA /r","V","V","FMA","","rw,r,r","","" +"VFMSUB213PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMSUB213PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmsub213ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 AA /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMSUB213PS ymm1, ymmV, ymm2/m256","VFMSUB213PS ymm2/m256, ymmV, ymm1","vfmsub213ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 AA /r","V","V","FMA","","rw,r,r","","" +"VFMSUB213PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMSUB213PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmsub213ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 AA /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMSUB213PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUB213PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmsub213ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 AA /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB213PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMSUB213PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmsub213ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 AA /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMSUB213SD xmm1{er}, {k}{z}, xmmV, xmm2","VFMSUB213SD xmm2, xmmV, {k}{z}, xmm1{er}","vfmsub213sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 AB /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB213SD xmm1, xmmV, xmm2/m64","VFMSUB213SD xmm2/m64, xmmV, xmm1","vfmsub213sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 AB /r","V","V","FMA","","rw,r,r","","" +"VFMSUB213SD xmm1, {k}{z}, xmmV, xmm2/m64","VFMSUB213SD xmm2/m64, xmmV, {k}{z}, xmm1","vfmsub213sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 AB /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFMSUB213SS xmm1{er}, {k}{z}, xmmV, xmm2","VFMSUB213SS xmm2, xmmV, {k}{z}, xmm1{er}","vfmsub213ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 AB /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB213SS xmm1, xmmV, xmm2/m32","VFMSUB213SS xmm2/m32, xmmV, xmm1","vfmsub213ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 AB /r","V","V","FMA","","rw,r,r","","" +"VFMSUB213SS xmm1, {k}{z}, xmmV, xmm2/m32","VFMSUB213SS xmm2/m32, xmmV, {k}{z}, xmm1","vfmsub213ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 AB /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFMSUB231PD xmm1, xmmV, xmm2/m128","VFMSUB231PD xmm2/m128, xmmV, xmm1","vfmsub231pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 BA /r","V","V","FMA","","rw,r,r","","" +"VFMSUB231PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMSUB231PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmsub231pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 BA /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMSUB231PD ymm1, ymmV, ymm2/m256","VFMSUB231PD ymm2/m256, ymmV, ymm1","vfmsub231pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 BA /r","V","V","FMA","","rw,r,r","","" +"VFMSUB231PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMSUB231PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmsub231pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 BA /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMSUB231PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUB231PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmsub231pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 BA /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB231PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMSUB231PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmsub231pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 BA /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMSUB231PS xmm1, xmmV, xmm2/m128","VFMSUB231PS xmm2/m128, xmmV, xmm1","vfmsub231ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 BA /r","V","V","FMA","","rw,r,r","","" +"VFMSUB231PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMSUB231PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmsub231ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 BA /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMSUB231PS ymm1, ymmV, ymm2/m256","VFMSUB231PS ymm2/m256, ymmV, ymm1","vfmsub231ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 BA /r","V","V","FMA","","rw,r,r","","" +"VFMSUB231PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMSUB231PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmsub231ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 BA /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMSUB231PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUB231PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmsub231ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 BA /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB231PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMSUB231PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmsub231ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 BA /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMSUB231SD xmm1{er}, {k}{z}, xmmV, xmm2","VFMSUB231SD xmm2, xmmV, {k}{z}, xmm1{er}","vfmsub231sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 BB /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB231SD xmm1, xmmV, xmm2/m64","VFMSUB231SD xmm2/m64, xmmV, xmm1","vfmsub231sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 BB /r","V","V","FMA","","rw,r,r","","" +"VFMSUB231SD xmm1, {k}{z}, xmmV, xmm2/m64","VFMSUB231SD xmm2/m64, xmmV, {k}{z}, xmm1","vfmsub231sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 BB /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFMSUB231SS xmm1{er}, {k}{z}, xmmV, xmm2","VFMSUB231SS xmm2, xmmV, {k}{z}, xmm1{er}","vfmsub231ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 BB /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUB231SS xmm1, xmmV, xmm2/m32","VFMSUB231SS xmm2/m32, xmmV, xmm1","vfmsub231ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 BB /r","V","V","FMA","","rw,r,r","","" +"VFMSUB231SS xmm1, {k}{z}, xmmV, xmm2/m32","VFMSUB231SS xmm2/m32, xmmV, {k}{z}, xmm1","vfmsub231ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 BB /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFMSUBADD132PD xmm1, xmmV, xmm2/m128","VFMSUBADD132PD xmm2/m128, xmmV, xmm1","vfmsubadd132pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 97 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD132PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMSUBADD132PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmsubadd132pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 97 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMSUBADD132PD ymm1, ymmV, ymm2/m256","VFMSUBADD132PD ymm2/m256, ymmV, ymm1","vfmsubadd132pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 97 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD132PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMSUBADD132PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmsubadd132pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 97 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMSUBADD132PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUBADD132PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmsubadd132pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 97 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUBADD132PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMSUBADD132PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmsubadd132pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 97 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMSUBADD132PS xmm1, xmmV, xmm2/m128","VFMSUBADD132PS xmm2/m128, xmmV, xmm1","vfmsubadd132ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 97 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD132PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMSUBADD132PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmsubadd132ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 97 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMSUBADD132PS ymm1, ymmV, ymm2/m256","VFMSUBADD132PS ymm2/m256, ymmV, ymm1","vfmsubadd132ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 97 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD132PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMSUBADD132PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmsubadd132ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 97 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMSUBADD132PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUBADD132PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmsubadd132ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 97 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUBADD132PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMSUBADD132PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmsubadd132ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 97 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMSUBADD213PD xmm1, xmmV, xmm2/m128","VFMSUBADD213PD xmm2/m128, xmmV, xmm1","vfmsubadd213pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 A7 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD213PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMSUBADD213PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmsubadd213pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 A7 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMSUBADD213PD ymm1, ymmV, ymm2/m256","VFMSUBADD213PD ymm2/m256, ymmV, ymm1","vfmsubadd213pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 A7 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD213PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMSUBADD213PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmsubadd213pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 A7 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMSUBADD213PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUBADD213PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmsubadd213pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 A7 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUBADD213PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMSUBADD213PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmsubadd213pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 A7 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMSUBADD213PS xmm1, xmmV, xmm2/m128","VFMSUBADD213PS xmm2/m128, xmmV, xmm1","vfmsubadd213ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 A7 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD213PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMSUBADD213PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmsubadd213ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 A7 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMSUBADD213PS ymm1, ymmV, ymm2/m256","VFMSUBADD213PS ymm2/m256, ymmV, ymm1","vfmsubadd213ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 A7 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD213PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMSUBADD213PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmsubadd213ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 A7 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMSUBADD213PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUBADD213PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmsubadd213ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 A7 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUBADD213PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMSUBADD213PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmsubadd213ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 A7 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMSUBADD231PD xmm1, xmmV, xmm2/m128","VFMSUBADD231PD xmm2/m128, xmmV, xmm1","vfmsubadd231pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 B7 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD231PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFMSUBADD231PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfmsubadd231pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 B7 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFMSUBADD231PD ymm1, ymmV, ymm2/m256","VFMSUBADD231PD ymm2/m256, ymmV, ymm1","vfmsubadd231pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 B7 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD231PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFMSUBADD231PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfmsubadd231pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 B7 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFMSUBADD231PD zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUBADD231PD zmm2, zmmV, {k}{z}, zmm1{er}","vfmsubadd231pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 B7 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUBADD231PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFMSUBADD231PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfmsubadd231pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 B7 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFMSUBADD231PS xmm1, xmmV, xmm2/m128","VFMSUBADD231PS xmm2/m128, xmmV, xmm1","vfmsubadd231ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 B7 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD231PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFMSUBADD231PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfmsubadd231ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 B7 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFMSUBADD231PS ymm1, ymmV, ymm2/m256","VFMSUBADD231PS ymm2/m256, ymmV, ymm1","vfmsubadd231ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 B7 /r","V","V","FMA","","rw,r,r","","" +"VFMSUBADD231PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFMSUBADD231PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfmsubadd231ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 B7 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFMSUBADD231PS zmm1{er}, {k}{z}, zmmV, zmm2","VFMSUBADD231PS zmm2, zmmV, {k}{z}, zmm1{er}","vfmsubadd231ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 B7 /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFMSUBADD231PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFMSUBADD231PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfmsubadd231ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 B7 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFMSUBADDPD xmm1, xmmV, xmmIH, xmm2/m128","VFMSUBADDPD xmm2/m128, xmmIH, xmmV, xmm1","vfmsubaddpd xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 5F /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBADDPD xmm1, xmmV, xmm2/m128, xmmIH","VFMSUBADDPD xmmIH, xmm2/m128, xmmV, xmm1","vfmsubaddpd xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 5F /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBADDPD ymm1, ymmV, ymmIH, ymm2/m256","VFMSUBADDPD ymm2/m256, ymmIH, ymmV, ymm1","vfmsubaddpd ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 5F /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBADDPD ymm1, ymmV, ymm2/m256, ymmIH","VFMSUBADDPD ymmIH, ymm2/m256, ymmV, ymm1","vfmsubaddpd ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 5F /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBADDPS xmm1, xmmV, xmmIH, xmm2/m128","VFMSUBADDPS xmm2/m128, xmmIH, xmmV, xmm1","vfmsubaddps xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 5E /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBADDPS xmm1, xmmV, xmm2/m128, xmmIH","VFMSUBADDPS xmmIH, xmm2/m128, xmmV, xmm1","vfmsubaddps xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 5E /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBADDPS ymm1, ymmV, ymmIH, ymm2/m256","VFMSUBADDPS ymm2/m256, ymmIH, ymmV, ymm1","vfmsubaddps ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 5E /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBADDPS ymm1, ymmV, ymm2/m256, ymmIH","VFMSUBADDPS ymmIH, ymm2/m256, ymmV, ymm1","vfmsubaddps ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 5E /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBPD xmm1, xmmV, xmmIH, xmm2/m128","VFMSUBPD xmm2/m128, xmmIH, xmmV, xmm1","vfmsubpd xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 6D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBPD xmm1, xmmV, xmm2/m128, xmmIH","VFMSUBPD xmmIH, xmm2/m128, xmmV, xmm1","vfmsubpd xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 6D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBPD ymm1, ymmV, ymmIH, ymm2/m256","VFMSUBPD ymm2/m256, ymmIH, ymmV, ymm1","vfmsubpd ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 6D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBPD ymm1, ymmV, ymm2/m256, ymmIH","VFMSUBPD ymmIH, ymm2/m256, ymmV, ymm1","vfmsubpd ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 6D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBPS xmm1, xmmV, xmmIH, xmm2/m128","VFMSUBPS xmm2/m128, xmmIH, xmmV, xmm1","vfmsubps xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 6C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBPS xmm1, xmmV, xmm2/m128, xmmIH","VFMSUBPS xmmIH, xmm2/m128, xmmV, xmm1","vfmsubps xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 6C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBPS ymm1, ymmV, ymmIH, ymm2/m256","VFMSUBPS ymm2/m256, ymmIH, ymmV, ymm1","vfmsubps ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 6C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBPS ymm1, ymmV, ymm2/m256, ymmIH","VFMSUBPS ymmIH, ymm2/m256, ymmV, ymm1","vfmsubps ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 6C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBSD xmm1, xmmV, xmmIH, xmm2/m64","VFMSUBSD xmm2/m64, xmmIH, xmmV, xmm1","vfmsubsd xmm2/m64, xmmIH, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W1 6F /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBSD xmm1, xmmV, xmm2/m64, xmmIH","VFMSUBSD xmmIH, xmm2/m64, xmmV, xmm1","vfmsubsd xmmIH, xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W0 6F /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBSS xmm1, xmmV, xmmIH, xmm2/m32","VFMSUBSS xmm2/m32, xmmIH, xmmV, xmm1","vfmsubss xmm2/m32, xmmIH, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W1 6E /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFMSUBSS xmm1, xmmV, xmm2/m32, xmmIH","VFMSUBSS xmmIH, xmm2/m32, xmmV, xmm1","vfmsubss xmmIH, xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W0 6E /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADD132PD xmm1, xmmV, xmm2/m128","VFNMADD132PD xmm2/m128, xmmV, xmm1","vfnmadd132pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 9C /r","V","V","FMA","","rw,r,r","","" +"VFNMADD132PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFNMADD132PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfnmadd132pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 9C /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFNMADD132PD ymm1, ymmV, ymm2/m256","VFNMADD132PD ymm2/m256, ymmV, ymm1","vfnmadd132pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 9C /r","V","V","FMA","","rw,r,r","","" +"VFNMADD132PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFNMADD132PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfnmadd132pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 9C /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFNMADD132PD zmm1{er}, {k}{z}, zmmV, zmm2","VFNMADD132PD zmm2, zmmV, {k}{z}, zmm1{er}","vfnmadd132pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 9C /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD132PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFNMADD132PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfnmadd132pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 9C /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFNMADD132PS xmm1, xmmV, xmm2/m128","VFNMADD132PS xmm2/m128, xmmV, xmm1","vfnmadd132ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 9C /r","V","V","FMA","","rw,r,r","","" +"VFNMADD132PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFNMADD132PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfnmadd132ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 9C /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFNMADD132PS ymm1, ymmV, ymm2/m256","VFNMADD132PS ymm2/m256, ymmV, ymm1","vfnmadd132ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 9C /r","V","V","FMA","","rw,r,r","","" +"VFNMADD132PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFNMADD132PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfnmadd132ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 9C /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFNMADD132PS zmm1{er}, {k}{z}, zmmV, zmm2","VFNMADD132PS zmm2, zmmV, {k}{z}, zmm1{er}","vfnmadd132ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 9C /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD132PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFNMADD132PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfnmadd132ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 9C /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFNMADD132SD xmm1{er}, {k}{z}, xmmV, xmm2","VFNMADD132SD xmm2, xmmV, {k}{z}, xmm1{er}","vfnmadd132sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 9D /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD132SD xmm1, xmmV, xmm2/m64","VFNMADD132SD xmm2/m64, xmmV, xmm1","vfnmadd132sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 9D /r","V","V","FMA","","rw,r,r","","" +"VFNMADD132SD xmm1, {k}{z}, xmmV, xmm2/m64","VFNMADD132SD xmm2/m64, xmmV, {k}{z}, xmm1","vfnmadd132sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 9D /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFNMADD132SS xmm1{er}, {k}{z}, xmmV, xmm2","VFNMADD132SS xmm2, xmmV, {k}{z}, xmm1{er}","vfnmadd132ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 9D /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD132SS xmm1, xmmV, xmm2/m32","VFNMADD132SS xmm2/m32, xmmV, xmm1","vfnmadd132ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 9D /r","V","V","FMA","","rw,r,r","","" +"VFNMADD132SS xmm1, {k}{z}, xmmV, xmm2/m32","VFNMADD132SS xmm2/m32, xmmV, {k}{z}, xmm1","vfnmadd132ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 9D /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFNMADD213PD xmm1, xmmV, xmm2/m128","VFNMADD213PD xmm2/m128, xmmV, xmm1","vfnmadd213pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 AC /r","V","V","FMA","","rw,r,r","","" +"VFNMADD213PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFNMADD213PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfnmadd213pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 AC /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFNMADD213PD ymm1, ymmV, ymm2/m256","VFNMADD213PD ymm2/m256, ymmV, ymm1","vfnmadd213pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 AC /r","V","V","FMA","","rw,r,r","","" +"VFNMADD213PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFNMADD213PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfnmadd213pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 AC /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFNMADD213PD zmm1{er}, {k}{z}, zmmV, zmm2","VFNMADD213PD zmm2, zmmV, {k}{z}, zmm1{er}","vfnmadd213pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 AC /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD213PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFNMADD213PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfnmadd213pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 AC /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFNMADD213PS xmm1, xmmV, xmm2/m128","VFNMADD213PS xmm2/m128, xmmV, xmm1","vfnmadd213ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 AC /r","V","V","FMA","","rw,r,r","","" +"VFNMADD213PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFNMADD213PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfnmadd213ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 AC /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFNMADD213PS ymm1, ymmV, ymm2/m256","VFNMADD213PS ymm2/m256, ymmV, ymm1","vfnmadd213ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 AC /r","V","V","FMA","","rw,r,r","","" +"VFNMADD213PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFNMADD213PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfnmadd213ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 AC /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFNMADD213PS zmm1{er}, {k}{z}, zmmV, zmm2","VFNMADD213PS zmm2, zmmV, {k}{z}, zmm1{er}","vfnmadd213ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 AC /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD213PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFNMADD213PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfnmadd213ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 AC /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFNMADD213SD xmm1{er}, {k}{z}, xmmV, xmm2","VFNMADD213SD xmm2, xmmV, {k}{z}, xmm1{er}","vfnmadd213sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 AD /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD213SD xmm1, xmmV, xmm2/m64","VFNMADD213SD xmm2/m64, xmmV, xmm1","vfnmadd213sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 AD /r","V","V","FMA","","rw,r,r","","" +"VFNMADD213SD xmm1, {k}{z}, xmmV, xmm2/m64","VFNMADD213SD xmm2/m64, xmmV, {k}{z}, xmm1","vfnmadd213sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 AD /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFNMADD213SS xmm1{er}, {k}{z}, xmmV, xmm2","VFNMADD213SS xmm2, xmmV, {k}{z}, xmm1{er}","vfnmadd213ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 AD /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD213SS xmm1, xmmV, xmm2/m32","VFNMADD213SS xmm2/m32, xmmV, xmm1","vfnmadd213ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 AD /r","V","V","FMA","","rw,r,r","","" +"VFNMADD213SS xmm1, {k}{z}, xmmV, xmm2/m32","VFNMADD213SS xmm2/m32, xmmV, {k}{z}, xmm1","vfnmadd213ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 AD /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFNMADD231PD xmm1, xmmV, xmm2/m128","VFNMADD231PD xmm2/m128, xmmV, xmm1","vfnmadd231pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 BC /r","V","V","FMA","","rw,r,r","","" +"VFNMADD231PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFNMADD231PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfnmadd231pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 BC /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFNMADD231PD ymm1, ymmV, ymm2/m256","VFNMADD231PD ymm2/m256, ymmV, ymm1","vfnmadd231pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 BC /r","V","V","FMA","","rw,r,r","","" +"VFNMADD231PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFNMADD231PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfnmadd231pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 BC /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFNMADD231PD zmm1{er}, {k}{z}, zmmV, zmm2","VFNMADD231PD zmm2, zmmV, {k}{z}, zmm1{er}","vfnmadd231pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 BC /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD231PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFNMADD231PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfnmadd231pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 BC /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFNMADD231PS xmm1, xmmV, xmm2/m128","VFNMADD231PS xmm2/m128, xmmV, xmm1","vfnmadd231ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 BC /r","V","V","FMA","","rw,r,r","","" +"VFNMADD231PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFNMADD231PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfnmadd231ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 BC /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFNMADD231PS ymm1, ymmV, ymm2/m256","VFNMADD231PS ymm2/m256, ymmV, ymm1","vfnmadd231ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 BC /r","V","V","FMA","","rw,r,r","","" +"VFNMADD231PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFNMADD231PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfnmadd231ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 BC /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFNMADD231PS zmm1{er}, {k}{z}, zmmV, zmm2","VFNMADD231PS zmm2, zmmV, {k}{z}, zmm1{er}","vfnmadd231ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 BC /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD231PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFNMADD231PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfnmadd231ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 BC /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFNMADD231SD xmm1{er}, {k}{z}, xmmV, xmm2","VFNMADD231SD xmm2, xmmV, {k}{z}, xmm1{er}","vfnmadd231sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 BD /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD231SD xmm1, xmmV, xmm2/m64","VFNMADD231SD xmm2/m64, xmmV, xmm1","vfnmadd231sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 BD /r","V","V","FMA","","rw,r,r","","" +"VFNMADD231SD xmm1, {k}{z}, xmmV, xmm2/m64","VFNMADD231SD xmm2/m64, xmmV, {k}{z}, xmm1","vfnmadd231sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 BD /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFNMADD231SS xmm1{er}, {k}{z}, xmmV, xmm2","VFNMADD231SS xmm2, xmmV, {k}{z}, xmm1{er}","vfnmadd231ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 BD /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMADD231SS xmm1, xmmV, xmm2/m32","VFNMADD231SS xmm2/m32, xmmV, xmm1","vfnmadd231ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 BD /r","V","V","FMA","","rw,r,r","","" +"VFNMADD231SS xmm1, {k}{z}, xmmV, xmm2/m32","VFNMADD231SS xmm2/m32, xmmV, {k}{z}, xmm1","vfnmadd231ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 BD /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFNMADDPD xmm1, xmmV, xmmIH, xmm2/m128","VFNMADDPD xmm2/m128, xmmIH, xmmV, xmm1","vfnmaddpd xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 79 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDPD xmm1, xmmV, xmm2/m128, xmmIH","VFNMADDPD xmmIH, xmm2/m128, xmmV, xmm1","vfnmaddpd xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 79 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDPD ymm1, ymmV, ymmIH, ymm2/m256","VFNMADDPD ymm2/m256, ymmIH, ymmV, ymm1","vfnmaddpd ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 79 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDPD ymm1, ymmV, ymm2/m256, ymmIH","VFNMADDPD ymmIH, ymm2/m256, ymmV, ymm1","vfnmaddpd ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 79 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDPS xmm1, xmmV, xmmIH, xmm2/m128","VFNMADDPS xmm2/m128, xmmIH, xmmV, xmm1","vfnmaddps xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 78 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDPS xmm1, xmmV, xmm2/m128, xmmIH","VFNMADDPS xmmIH, xmm2/m128, xmmV, xmm1","vfnmaddps xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 78 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDPS ymm1, ymmV, ymmIH, ymm2/m256","VFNMADDPS ymm2/m256, ymmIH, ymmV, ymm1","vfnmaddps ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 78 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDPS ymm1, ymmV, ymm2/m256, ymmIH","VFNMADDPS ymmIH, ymm2/m256, ymmV, ymm1","vfnmaddps ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 78 /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDSD xmm1, xmmV, xmmIH, xmm2/m64","VFNMADDSD xmm2/m64, xmmIH, xmmV, xmm1","vfnmaddsd xmm2/m64, xmmIH, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W1 7B /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDSD xmm1, xmmV, xmm2/m64, xmmIH","VFNMADDSD xmmIH, xmm2/m64, xmmV, xmm1","vfnmaddsd xmmIH, xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W0 7B /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDSS xmm1, xmmV, xmmIH, xmm2/m32","VFNMADDSS xmm2/m32, xmmIH, xmmV, xmm1","vfnmaddss xmm2/m32, xmmIH, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W1 7A /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMADDSS xmm1, xmmV, xmm2/m32, xmmIH","VFNMADDSS xmmIH, xmm2/m32, xmmV, xmm1","vfnmaddss xmmIH, xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W0 7A /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUB132PD xmm1, xmmV, xmm2/m128","VFNMSUB132PD xmm2/m128, xmmV, xmm1","vfnmsub132pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 9E /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB132PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFNMSUB132PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfnmsub132pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 9E /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFNMSUB132PD ymm1, ymmV, ymm2/m256","VFNMSUB132PD ymm2/m256, ymmV, ymm1","vfnmsub132pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 9E /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB132PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFNMSUB132PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfnmsub132pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 9E /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFNMSUB132PD zmm1{er}, {k}{z}, zmmV, zmm2","VFNMSUB132PD zmm2, zmmV, {k}{z}, zmm1{er}","vfnmsub132pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 9E /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB132PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFNMSUB132PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfnmsub132pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 9E /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFNMSUB132PS xmm1, xmmV, xmm2/m128","VFNMSUB132PS xmm2/m128, xmmV, xmm1","vfnmsub132ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 9E /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB132PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFNMSUB132PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfnmsub132ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 9E /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFNMSUB132PS ymm1, ymmV, ymm2/m256","VFNMSUB132PS ymm2/m256, ymmV, ymm1","vfnmsub132ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 9E /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB132PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFNMSUB132PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfnmsub132ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 9E /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFNMSUB132PS zmm1{er}, {k}{z}, zmmV, zmm2","VFNMSUB132PS zmm2, zmmV, {k}{z}, zmm1{er}","vfnmsub132ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 9E /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB132PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFNMSUB132PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfnmsub132ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 9E /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFNMSUB132SD xmm1{er}, {k}{z}, xmmV, xmm2","VFNMSUB132SD xmm2, xmmV, {k}{z}, xmm1{er}","vfnmsub132sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 9F /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB132SD xmm1, xmmV, xmm2/m64","VFNMSUB132SD xmm2/m64, xmmV, xmm1","vfnmsub132sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 9F /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB132SD xmm1, {k}{z}, xmmV, xmm2/m64","VFNMSUB132SD xmm2/m64, xmmV, {k}{z}, xmm1","vfnmsub132sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 9F /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFNMSUB132SS xmm1{er}, {k}{z}, xmmV, xmm2","VFNMSUB132SS xmm2, xmmV, {k}{z}, xmm1{er}","vfnmsub132ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 9F /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB132SS xmm1, xmmV, xmm2/m32","VFNMSUB132SS xmm2/m32, xmmV, xmm1","vfnmsub132ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 9F /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB132SS xmm1, {k}{z}, xmmV, xmm2/m32","VFNMSUB132SS xmm2/m32, xmmV, {k}{z}, xmm1","vfnmsub132ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 9F /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFNMSUB213PD xmm1, xmmV, xmm2/m128","VFNMSUB213PD xmm2/m128, xmmV, xmm1","vfnmsub213pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 AE /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB213PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFNMSUB213PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfnmsub213pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 AE /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFNMSUB213PD ymm1, ymmV, ymm2/m256","VFNMSUB213PD ymm2/m256, ymmV, ymm1","vfnmsub213pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 AE /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB213PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFNMSUB213PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfnmsub213pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 AE /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFNMSUB213PD zmm1{er}, {k}{z}, zmmV, zmm2","VFNMSUB213PD zmm2, zmmV, {k}{z}, zmm1{er}","vfnmsub213pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 AE /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB213PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFNMSUB213PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfnmsub213pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 AE /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFNMSUB213PS xmm1, xmmV, xmm2/m128","VFNMSUB213PS xmm2/m128, xmmV, xmm1","vfnmsub213ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 AE /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB213PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFNMSUB213PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfnmsub213ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 AE /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFNMSUB213PS ymm1, ymmV, ymm2/m256","VFNMSUB213PS ymm2/m256, ymmV, ymm1","vfnmsub213ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 AE /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB213PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFNMSUB213PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfnmsub213ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 AE /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFNMSUB213PS zmm1{er}, {k}{z}, zmmV, zmm2","VFNMSUB213PS zmm2, zmmV, {k}{z}, zmm1{er}","vfnmsub213ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 AE /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB213PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFNMSUB213PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfnmsub213ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 AE /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFNMSUB213SD xmm1{er}, {k}{z}, xmmV, xmm2","VFNMSUB213SD xmm2, xmmV, {k}{z}, xmm1{er}","vfnmsub213sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 AF /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB213SD xmm1, xmmV, xmm2/m64","VFNMSUB213SD xmm2/m64, xmmV, xmm1","vfnmsub213sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 AF /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB213SD xmm1, {k}{z}, xmmV, xmm2/m64","VFNMSUB213SD xmm2/m64, xmmV, {k}{z}, xmm1","vfnmsub213sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 AF /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFNMSUB213SS xmm1{er}, {k}{z}, xmmV, xmm2","VFNMSUB213SS xmm2, xmmV, {k}{z}, xmm1{er}","vfnmsub213ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 AF /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB213SS xmm1, xmmV, xmm2/m32","VFNMSUB213SS xmm2/m32, xmmV, xmm1","vfnmsub213ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 AF /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB213SS xmm1, {k}{z}, xmmV, xmm2/m32","VFNMSUB213SS xmm2/m32, xmmV, {k}{z}, xmm1","vfnmsub213ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 AF /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFNMSUB231PD xmm1, xmmV, xmm2/m128","VFNMSUB231PD xmm2/m128, xmmV, xmm1","vfnmsub231pd xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W1 BE /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB231PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VFNMSUB231PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vfnmsub231pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 BE /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VFNMSUB231PD ymm1, ymmV, ymm2/m256","VFNMSUB231PD ymm2/m256, ymmV, ymm1","vfnmsub231pd ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W1 BE /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB231PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VFNMSUB231PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vfnmsub231pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 BE /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VFNMSUB231PD zmm1{er}, {k}{z}, zmmV, zmm2","VFNMSUB231PD zmm2, zmmV, {k}{z}, zmm1{er}","vfnmsub231pd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W1 BE /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB231PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VFNMSUB231PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vfnmsub231pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 BE /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VFNMSUB231PS xmm1, xmmV, xmm2/m128","VFNMSUB231PS xmm2/m128, xmmV, xmm1","vfnmsub231ps xmm2/m128, xmmV, xmm1","VEX.DDS.128.66.0F38.W0 BE /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB231PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VFNMSUB231PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vfnmsub231ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 BE /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VFNMSUB231PS ymm1, ymmV, ymm2/m256","VFNMSUB231PS ymm2/m256, ymmV, ymm1","vfnmsub231ps ymm2/m256, ymmV, ymm1","VEX.DDS.256.66.0F38.W0 BE /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB231PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VFNMSUB231PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vfnmsub231ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 BE /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VFNMSUB231PS zmm1{er}, {k}{z}, zmmV, zmm2","VFNMSUB231PS zmm2, zmmV, {k}{z}, zmm1{er}","vfnmsub231ps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.DDS.512.66.0F38.W0 BE /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB231PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VFNMSUB231PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vfnmsub231ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 BE /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VFNMSUB231SD xmm1{er}, {k}{z}, xmmV, xmm2","VFNMSUB231SD xmm2, xmmV, {k}{z}, xmm1{er}","vfnmsub231sd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W1 BF /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB231SD xmm1, xmmV, xmm2/m64","VFNMSUB231SD xmm2/m64, xmmV, xmm1","vfnmsub231sd xmm2/m64, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W1 BF /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB231SD xmm1, {k}{z}, xmmV, xmm2/m64","VFNMSUB231SD xmm2/m64, xmmV, {k}{z}, xmm1","vfnmsub231sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W1 BF /r","V","V","AVX512F","scale8","rw,r,r,r","","" +"VFNMSUB231SS xmm1{er}, {k}{z}, xmmV, xmm2","VFNMSUB231SS xmm2, xmmV, {k}{z}, xmm1{er}","vfnmsub231ss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.DDS.128.66.0F38.W0 BF /r","V","V","AVX512F","modrm_regonly","rw,r,r,r","","" +"VFNMSUB231SS xmm1, xmmV, xmm2/m32","VFNMSUB231SS xmm2/m32, xmmV, xmm1","vfnmsub231ss xmm2/m32, xmmV, xmm1","VEX.DDS.LIG.66.0F38.W0 BF /r","V","V","FMA","","rw,r,r","","" +"VFNMSUB231SS xmm1, {k}{z}, xmmV, xmm2/m32","VFNMSUB231SS xmm2/m32, xmmV, {k}{z}, xmm1","vfnmsub231ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.DDS.LIG.66.0F38.W0 BF /r","V","V","AVX512F","scale4","rw,r,r,r","","" +"VFNMSUBPD xmm1, xmmV, xmmIH, xmm2/m128","VFNMSUBPD xmm2/m128, xmmIH, xmmV, xmm1","vfnmsubpd xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 7D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBPD xmm1, xmmV, xmm2/m128, xmmIH","VFNMSUBPD xmmIH, xmm2/m128, xmmV, xmm1","vfnmsubpd xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 7D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBPD ymm1, ymmV, ymmIH, ymm2/m256","VFNMSUBPD ymm2/m256, ymmIH, ymmV, ymm1","vfnmsubpd ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 7D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBPD ymm1, ymmV, ymm2/m256, ymmIH","VFNMSUBPD ymmIH, ymm2/m256, ymmV, ymm1","vfnmsubpd ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 7D /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBPS xmm1, xmmV, xmmIH, xmm2/m128","VFNMSUBPS xmm2/m128, xmmIH, xmmV, xmm1","vfnmsubps xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 7C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBPS xmm1, xmmV, xmm2/m128, xmmIH","VFNMSUBPS xmmIH, xmm2/m128, xmmV, xmm1","vfnmsubps xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 7C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBPS ymm1, ymmV, ymmIH, ymm2/m256","VFNMSUBPS ymm2/m256, ymmIH, ymmV, ymm1","vfnmsubps ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 7C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBPS ymm1, ymmV, ymm2/m256, ymmIH","VFNMSUBPS ymmIH, ymm2/m256, ymmV, ymm1","vfnmsubps ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 7C /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBSD xmm1, xmmV, xmmIH, xmm2/m64","VFNMSUBSD xmm2/m64, xmmIH, xmmV, xmm1","vfnmsubsd xmm2/m64, xmmIH, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W1 7F /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBSD xmm1, xmmV, xmm2/m64, xmmIH","VFNMSUBSD xmmIH, xmm2/m64, xmmV, xmm1","vfnmsubsd xmmIH, xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W0 7F /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBSS xmm1, xmmV, xmmIH, xmm2/m32","VFNMSUBSS xmm2/m32, xmmIH, xmmV, xmm1","vfnmsubss xmm2/m32, xmmIH, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W1 7E /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFNMSUBSS xmm1, xmmV, xmm2/m32, xmmIH","VFNMSUBSS xmmIH, xmm2/m32, xmmV, xmm1","vfnmsubss xmmIH, xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.W0 7E /r /is4","V","V","FMA4","amd","w,r,r,r","","" +"VFPCLASSPD k1, {k}, xmm2/m128/m64bcst, imm8u","VFPCLASSPDX imm8u, xmm2/m128/m64bcst, {k}, k1","vfpclasspdx imm8u, xmm2/m128/m64bcst, {k}, k1","EVEX.128.66.0F3A.W1 66 /r ib","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r,r","Y","128" +"VFPCLASSPD k1, {k}, ymm2/m256/m64bcst, imm8u","VFPCLASSPDY imm8u, ymm2/m256/m64bcst, {k}, k1","vfpclasspdy imm8u, ymm2/m256/m64bcst, {k}, k1","EVEX.256.66.0F3A.W1 66 /r ib","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r,r","Y","256" +"VFPCLASSPD k1, {k}, zmm2/m512/m64bcst, imm8u","VFPCLASSPDZ imm8u, zmm2/m512/m64bcst, {k}, k1","vfpclasspdz imm8u, zmm2/m512/m64bcst, {k}, k1","EVEX.512.66.0F3A.W1 66 /r ib","V","V","AVX512DQ","bscale8,scale64","w,r,r,r","Y","512" +"VFPCLASSPS k1, {k}, xmm2/m128/m32bcst, imm8u","VFPCLASSPSX imm8u, xmm2/m128/m32bcst, {k}, k1","vfpclasspsx imm8u, xmm2/m128/m32bcst, {k}, k1","EVEX.128.66.0F3A.W0 66 /r ib","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r,r","Y","128" +"VFPCLASSPS k1, {k}, ymm2/m256/m32bcst, imm8u","VFPCLASSPSY imm8u, ymm2/m256/m32bcst, {k}, k1","vfpclasspsy imm8u, ymm2/m256/m32bcst, {k}, k1","EVEX.256.66.0F3A.W0 66 /r ib","V","V","AVX512DQ+AVX512VL","bscale4,scale32","w,r,r,r","Y","256" +"VFPCLASSPS k1, {k}, zmm2/m512/m32bcst, imm8u","VFPCLASSPSZ imm8u, zmm2/m512/m32bcst, {k}, k1","vfpclasspsz imm8u, zmm2/m512/m32bcst, {k}, k1","EVEX.512.66.0F3A.W0 66 /r ib","V","V","AVX512DQ","bscale4,scale64","w,r,r,r","Y","512" +"VFPCLASSSD k1, {k}, xmm2/m64, imm8u","VFPCLASSSD imm8u, xmm2/m64, {k}, k1","vfpclasssd imm8u, xmm2/m64, {k}, k1","EVEX.LIG.66.0F3A.W1 67 /r ib","V","V","AVX512DQ","scale8","w,r,r,r","","" +"VFPCLASSSS k1, {k}, xmm2/m32, imm8u","VFPCLASSSS imm8u, xmm2/m32, {k}, k1","vfpclassss imm8u, xmm2/m32, {k}, k1","EVEX.LIG.66.0F3A.W0 67 /r ib","V","V","AVX512DQ","scale4","w,r,r,r","","" +"VFRCZPD xmm1, xmm2/m128","VFRCZPD xmm2/m128, xmm1","vfrczpd xmm2/m128, xmm1","XOP.128.09.W0 81 /r","V","V","XOP","amd","w,r","","" +"VFRCZPD ymm1, ymm2/m256","VFRCZPD ymm2/m256, ymm1","vfrczpd ymm2/m256, ymm1","XOP.256.09.W0 81 /r","V","V","XOP","amd","w,r","","" +"VFRCZPS xmm1, xmm2/m128","VFRCZPS xmm2/m128, xmm1","vfrczps xmm2/m128, xmm1","XOP.128.09.W0 80 /r","V","V","XOP","amd","w,r","","" +"VFRCZPS ymm1, ymm2/m256","VFRCZPS ymm2/m256, ymm1","vfrczps ymm2/m256, ymm1","XOP.256.09.W0 80 /r","V","V","XOP","amd","w,r","","" +"VFRCZSD xmm1, xmm2/m64","VFRCZSD xmm2/m64, xmm1","vfrczsd xmm2/m64, xmm1","XOP.128.09.W0 83 /r","V","V","XOP","amd","w,r","","" +"VFRCZSS xmm1, xmm2/m32","VFRCZSS xmm2/m32, xmm1","vfrczss xmm2/m32, xmm1","XOP.128.09.W0 82 /r","V","V","XOP","amd","w,r","","" +"VGATHERDPD xmm1, {k1-k7}, vm32x","VGATHERDPD vm32x, {k1-k7}, xmm1","vgatherdpd vm32x, {k1-k7}, xmm1","EVEX.128.66.0F38.W1 92 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VGATHERDPD ymm1, {k1-k7}, vm32x","VGATHERDPD vm32x, {k1-k7}, ymm1","vgatherdpd vm32x, {k1-k7}, ymm1","EVEX.256.66.0F38.W1 92 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VGATHERDPD zmm1, {k1-k7}, vm32y","VGATHERDPD vm32y, {k1-k7}, zmm1","vgatherdpd vm32y, {k1-k7}, zmm1","EVEX.512.66.0F38.W1 92 /vsib","V","V","AVX512F","modrm_memonly,scale8","w,rw,r","","" +"VGATHERDPD xmm1, vm32x, xmmV","VGATHERDPD xmmV, vm32x, xmm1","vgatherdpd xmmV, vm32x, xmm1","VEX.DDS.128.66.0F38.W1 92 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VGATHERDPD ymm1, vm32x, ymmV","VGATHERDPD ymmV, vm32x, ymm1","vgatherdpd ymmV, vm32x, ymm1","VEX.DDS.256.66.0F38.W1 92 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VGATHERDPS xmm1, {k1-k7}, vm32x","VGATHERDPS vm32x, {k1-k7}, xmm1","vgatherdps vm32x, {k1-k7}, xmm1","EVEX.128.66.0F38.W0 92 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VGATHERDPS ymm1, {k1-k7}, vm32y","VGATHERDPS vm32y, {k1-k7}, ymm1","vgatherdps vm32y, {k1-k7}, ymm1","EVEX.256.66.0F38.W0 92 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VGATHERDPS zmm1, {k1-k7}, vm32z","VGATHERDPS vm32z, {k1-k7}, zmm1","vgatherdps vm32z, {k1-k7}, zmm1","EVEX.512.66.0F38.W0 92 /vsib","V","V","AVX512F","modrm_memonly,scale4","w,rw,r","","" +"VGATHERDPS xmm1, vm32x, xmmV","VGATHERDPS xmmV, vm32x, xmm1","vgatherdps xmmV, vm32x, xmm1","VEX.DDS.128.66.0F38.W0 92 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VGATHERDPS ymm1, vm32y, ymmV","VGATHERDPS ymmV, vm32y, ymm1","vgatherdps ymmV, vm32y, ymm1","VEX.DDS.256.66.0F38.W0 92 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VGATHERPF0DPD vm32y, {k1-k7}","VGATHERPF0DPD {k1-k7}, vm32y","vgatherpf0dpd {k1-k7}, vm32y","EVEX.512.66.0F38.W1 C6 /1","V","V","AVX512PF","modrm_memonly,scale8","r,rw","","" +"VGATHERPF0DPS vm32z, {k1-k7}","VGATHERPF0DPS {k1-k7}, vm32z","vgatherpf0dps {k1-k7}, vm32z","EVEX.512.66.0F38.W0 C6 /1","V","V","AVX512PF","modrm_memonly,scale4","r,rw","","" +"VGATHERPF0QPD vm64z, {k1-k7}","VGATHERPF0QPD {k1-k7}, vm64z","vgatherpf0qpd {k1-k7}, vm64z","EVEX.512.66.0F38.W1 C7 /1","V","V","AVX512PF","modrm_memonly,scale8","r,rw","","" +"VGATHERPF0QPS vm64z, {k1-k7}","VGATHERPF0QPS {k1-k7}, vm64z","vgatherpf0qps {k1-k7}, vm64z","EVEX.512.66.0F38.W0 C7 /1","V","V","AVX512PF","modrm_memonly,scale4","r,rw","","" +"VGATHERPF1DPD vm32y, {k1-k7}","VGATHERPF1DPD {k1-k7}, vm32y","vgatherpf1dpd {k1-k7}, vm32y","EVEX.512.66.0F38.W1 C6 /2","V","V","AVX512PF","modrm_memonly,scale8","r,rw","","" +"VGATHERPF1DPS vm32z, {k1-k7}","VGATHERPF1DPS {k1-k7}, vm32z","vgatherpf1dps {k1-k7}, vm32z","EVEX.512.66.0F38.W0 C6 /2","V","V","AVX512PF","modrm_memonly,scale4","r,rw","","" +"VGATHERPF1QPD vm64z, {k1-k7}","VGATHERPF1QPD {k1-k7}, vm64z","vgatherpf1qpd {k1-k7}, vm64z","EVEX.512.66.0F38.W1 C7 /2","V","V","AVX512PF","modrm_memonly,scale8","r,rw","","" +"VGATHERPF1QPS vm64z, {k1-k7}","VGATHERPF1QPS {k1-k7}, vm64z","vgatherpf1qps {k1-k7}, vm64z","EVEX.512.66.0F38.W0 C7 /2","V","V","AVX512PF","modrm_memonly,scale4","r,rw","","" +"VGATHERQPD xmm1, {k1-k7}, vm64x","VGATHERQPD vm64x, {k1-k7}, xmm1","vgatherqpd vm64x, {k1-k7}, xmm1","EVEX.128.66.0F38.W1 93 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VGATHERQPD ymm1, {k1-k7}, vm64y","VGATHERQPD vm64y, {k1-k7}, ymm1","vgatherqpd vm64y, {k1-k7}, ymm1","EVEX.256.66.0F38.W1 93 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VGATHERQPD zmm1, {k1-k7}, vm64z","VGATHERQPD vm64z, {k1-k7}, zmm1","vgatherqpd vm64z, {k1-k7}, zmm1","EVEX.512.66.0F38.W1 93 /vsib","V","V","AVX512F","modrm_memonly,scale8","w,rw,r","","" +"VGATHERQPD xmm1, vm64x, xmmV","VGATHERQPD xmmV, vm64x, xmm1","vgatherqpd xmmV, vm64x, xmm1","VEX.DDS.128.66.0F38.W1 93 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VGATHERQPD ymm1, vm64y, ymmV","VGATHERQPD ymmV, vm64y, ymm1","vgatherqpd ymmV, vm64y, ymm1","VEX.DDS.256.66.0F38.W1 93 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VGATHERQPS xmm1, {k1-k7}, vm64x","VGATHERQPS vm64x, {k1-k7}, xmm1","vgatherqps vm64x, {k1-k7}, xmm1","EVEX.128.66.0F38.W0 93 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VGATHERQPS xmm1, {k1-k7}, vm64y","VGATHERQPS vm64y, {k1-k7}, xmm1","vgatherqps vm64y, {k1-k7}, xmm1","EVEX.256.66.0F38.W0 93 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VGATHERQPS ymm1, {k1-k7}, vm64z","VGATHERQPS vm64z, {k1-k7}, ymm1","vgatherqps vm64z, {k1-k7}, ymm1","EVEX.512.66.0F38.W0 93 /vsib","V","V","AVX512F","modrm_memonly,scale4","w,rw,r","","" +"VGATHERQPS xmm1, vm64x, xmmV","VGATHERQPS xmmV, vm64x, xmm1","vgatherqps xmmV, vm64x, xmm1","VEX.DDS.128.66.0F38.W0 93 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VGATHERQPS xmm1, vm64y, xmmV","VGATHERQPS xmmV, vm64y, xmm1","vgatherqps xmmV, vm64y, xmm1","VEX.DDS.256.66.0F38.W0 93 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VGETEXPPD xmm1, {k}{z}, xmm2/m128/m64bcst","VGETEXPPD xmm2/m128/m64bcst, {k}{z}, xmm1","vgetexppd xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W1 42 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","","" +"VGETEXPPD ymm1, {k}{z}, ymm2/m256/m64bcst","VGETEXPPD ymm2/m256/m64bcst, {k}{z}, ymm1","vgetexppd ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W1 42 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","","" +"VGETEXPPD zmm1{sae}, {k}{z}, zmm2","VGETEXPPD zmm2, {k}{z}, zmm1{sae}","vgetexppd zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W1 42 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VGETEXPPD zmm1, {k}{z}, zmm2/m512/m64bcst","VGETEXPPD zmm2/m512/m64bcst, {k}{z}, zmm1","vgetexppd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 42 /r","V","V","AVX512F","bscale8,scale64","w,r,r","","" +"VGETEXPPS xmm1, {k}{z}, xmm2/m128/m32bcst","VGETEXPPS xmm2/m128/m32bcst, {k}{z}, xmm1","vgetexpps xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W0 42 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VGETEXPPS ymm1, {k}{z}, ymm2/m256/m32bcst","VGETEXPPS ymm2/m256/m32bcst, {k}{z}, ymm1","vgetexpps ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W0 42 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VGETEXPPS zmm1{sae}, {k}{z}, zmm2","VGETEXPPS zmm2, {k}{z}, zmm1{sae}","vgetexpps zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W0 42 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VGETEXPPS zmm1, {k}{z}, zmm2/m512/m32bcst","VGETEXPPS zmm2/m512/m32bcst, {k}{z}, zmm1","vgetexpps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 42 /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VGETEXPSD xmm1{sae}, {k}{z}, xmmV, xmm2","VGETEXPSD xmm2, xmmV, {k}{z}, xmm1{sae}","vgetexpsd xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F38.W1 43 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VGETEXPSD xmm1, {k}{z}, xmmV, xmm2/m64","VGETEXPSD xmm2/m64, xmmV, {k}{z}, xmm1","vgetexpsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W1 43 /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VGETEXPSS xmm1{sae}, {k}{z}, xmmV, xmm2","VGETEXPSS xmm2, xmmV, {k}{z}, xmm1{sae}","vgetexpss xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F38.W0 43 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VGETEXPSS xmm1, {k}{z}, xmmV, xmm2/m32","VGETEXPSS xmm2/m32, xmmV, {k}{z}, xmm1","vgetexpss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W0 43 /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VGETMANTPD xmm1, {k}{z}, xmm2/m128/m64bcst, imm8u:4","VGETMANTPD imm8u:4, xmm2/m128/m64bcst, {k}{z}, xmm1","vgetmantpd imm8u:4, xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F3A.W1 26 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VGETMANTPD ymm1, {k}{z}, ymm2/m256/m64bcst, imm8u:4","VGETMANTPD imm8u:4, ymm2/m256/m64bcst, {k}{z}, ymm1","vgetmantpd imm8u:4, ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W1 26 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VGETMANTPD zmm1{sae}, {k}{z}, zmm2, imm8u:4","VGETMANTPD imm8u:4, zmm2, {k}{z}, zmm1{sae}","vgetmantpd imm8u:4, zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F3A.W1 26 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VGETMANTPD zmm1, {k}{z}, zmm2/m512/m64bcst, imm8u:4","VGETMANTPD imm8u:4, zmm2/m512/m64bcst, {k}{z}, zmm1","vgetmantpd imm8u:4, zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W1 26 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VGETMANTPS xmm1, {k}{z}, xmm2/m128/m32bcst, imm8u:4","VGETMANTPS imm8u:4, xmm2/m128/m32bcst, {k}{z}, xmm1","vgetmantps imm8u:4, xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F3A.W0 26 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VGETMANTPS ymm1, {k}{z}, ymm2/m256/m32bcst, imm8u:4","VGETMANTPS imm8u:4, ymm2/m256/m32bcst, {k}{z}, ymm1","vgetmantps imm8u:4, ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W0 26 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VGETMANTPS zmm1{sae}, {k}{z}, zmm2, imm8u:4","VGETMANTPS imm8u:4, zmm2, {k}{z}, zmm1{sae}","vgetmantps imm8u:4, zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F3A.W0 26 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VGETMANTPS zmm1, {k}{z}, zmm2/m512/m32bcst, imm8u:4","VGETMANTPS imm8u:4, zmm2/m512/m32bcst, {k}{z}, zmm1","vgetmantps imm8u:4, zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W0 26 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VGETMANTSD xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u:4","VGETMANTSD imm8u:4, xmm2, xmmV, {k}{z}, xmm1{sae}","vgetmantsd imm8u:4, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F3A.W1 27 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r,r","","" +"VGETMANTSD xmm1, {k}{z}, xmmV, xmm2/m64, imm8u:4","VGETMANTSD imm8u:4, xmm2/m64, xmmV, {k}{z}, xmm1","vgetmantsd imm8u:4, xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F3A.W1 27 /r ib","V","V","AVX512F","scale8","w,r,r,r,r","","" +"VGETMANTSS xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u:4","VGETMANTSS imm8u:4, xmm2, xmmV, {k}{z}, xmm1{sae}","vgetmantss imm8u:4, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F3A.W0 27 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r,r","","" +"VGETMANTSS xmm1, {k}{z}, xmmV, xmm2/m32, imm8u:4","VGETMANTSS imm8u:4, xmm2/m32, xmmV, {k}{z}, xmm1","vgetmantss imm8u:4, xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F3A.W0 27 /r ib","V","V","AVX512F","scale4","w,r,r,r,r","","" +"VGF2P8AFFINEINVQB xmm1, xmmV, xmm2/m128, imm8u","VGF2P8AFFINEINVQB imm8u, xmm2/m128, xmmV, xmm1","vgf2p8affineinvqb imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 CF /r ib","V","V","GFNI+AVX","","w,r,r,r","","" +"VGF2P8AFFINEINVQB xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u","VGF2P8AFFINEINVQB imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vgf2p8affineinvqb imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W1 CF /r ib","V","V","GFNI+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VGF2P8AFFINEINVQB ymm1, ymmV, ymm2/m256, imm8u","VGF2P8AFFINEINVQB imm8u, ymm2/m256, ymmV, ymm1","vgf2p8affineinvqb imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 CF /r ib","V","V","GFNI+AVX","","w,r,r,r","","" +"VGF2P8AFFINEINVQB ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VGF2P8AFFINEINVQB imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vgf2p8affineinvqb imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 CF /r ib","V","V","GFNI+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VGF2P8AFFINEINVQB zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VGF2P8AFFINEINVQB imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vgf2p8affineinvqb imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 CF /r ib","V","V","GFNI+AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VGF2P8AFFINEQB xmm1, xmmV, xmm2/m128, imm8u","VGF2P8AFFINEQB imm8u, xmm2/m128, xmmV, xmm1","vgf2p8affineqb imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 CE /r ib","V","V","GFNI+AVX","","w,r,r,r","","" +"VGF2P8AFFINEQB xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u","VGF2P8AFFINEQB imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vgf2p8affineqb imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W1 CE /r ib","V","V","GFNI+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VGF2P8AFFINEQB ymm1, ymmV, ymm2/m256, imm8u","VGF2P8AFFINEQB imm8u, ymm2/m256, ymmV, ymm1","vgf2p8affineqb imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 CE /r ib","V","V","GFNI+AVX","","w,r,r,r","","" +"VGF2P8AFFINEQB ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VGF2P8AFFINEQB imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vgf2p8affineqb imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 CE /r ib","V","V","GFNI+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VGF2P8AFFINEQB zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VGF2P8AFFINEQB imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vgf2p8affineqb imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 CE /r ib","V","V","GFNI+AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VGF2P8MULB xmm1, xmmV, xmm2/m128","VGF2P8MULB xmm2/m128, xmmV, xmm1","vgf2p8mulb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 CF /r","V","V","GFNI+AVX","","w,r,r","","" +"VGF2P8MULB xmm1, {k}{z}, xmmV, xmm2/m128","VGF2P8MULB xmm2/m128, xmmV, {k}{z}, xmm1","vgf2p8mulb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 CF /r","V","V","GFNI+AVX512VL","scale16","w,r,r,r","","" +"VGF2P8MULB ymm1, ymmV, ymm2/m256","VGF2P8MULB ymm2/m256, ymmV, ymm1","vgf2p8mulb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 CF /r","V","V","GFNI+AVX","","w,r,r","","" +"VGF2P8MULB ymm1, {k}{z}, ymmV, ymm2/m256","VGF2P8MULB ymm2/m256, ymmV, {k}{z}, ymm1","vgf2p8mulb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 CF /r","V","V","GFNI+AVX512VL","scale32","w,r,r,r","","" +"VGF2P8MULB zmm1, {k}{z}, zmmV, zmm2/m512","VGF2P8MULB zmm2/m512, zmmV, {k}{z}, zmm1","vgf2p8mulb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 CF /r","V","V","GFNI+AVX512F","scale64","w,r,r,r","","" +"VHADDPD xmm1, xmmV, xmm2/m128","VHADDPD xmm2/m128, xmmV, xmm1","vhaddpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 7C /r","V","V","AVX","","w,r,r","","" +"VHADDPD ymm1, ymmV, ymm2/m256","VHADDPD ymm2/m256, ymmV, ymm1","vhaddpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 7C /r","V","V","AVX","","w,r,r","","" +"VHADDPS xmm1, xmmV, xmm2/m128","VHADDPS xmm2/m128, xmmV, xmm1","vhaddps xmm2/m128, xmmV, xmm1","VEX.NDS.128.F2.0F.WIG 7C /r","V","V","AVX","","w,r,r","","" +"VHADDPS ymm1, ymmV, ymm2/m256","VHADDPS ymm2/m256, ymmV, ymm1","vhaddps ymm2/m256, ymmV, ymm1","VEX.NDS.256.F2.0F.WIG 7C /r","V","V","AVX","","w,r,r","","" +"VHSUBPD xmm1, xmmV, xmm2/m128","VHSUBPD xmm2/m128, xmmV, xmm1","vhsubpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 7D /r","V","V","AVX","","w,r,r","","" +"VHSUBPD ymm1, ymmV, ymm2/m256","VHSUBPD ymm2/m256, ymmV, ymm1","vhsubpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 7D /r","V","V","AVX","","w,r,r","","" +"VHSUBPS xmm1, xmmV, xmm2/m128","VHSUBPS xmm2/m128, xmmV, xmm1","vhsubps xmm2/m128, xmmV, xmm1","VEX.NDS.128.F2.0F.WIG 7D /r","V","V","AVX","","w,r,r","","" +"VHSUBPS ymm1, ymmV, ymm2/m256","VHSUBPS ymm2/m256, ymmV, ymm1","vhsubps ymm2/m256, ymmV, ymm1","VEX.NDS.256.F2.0F.WIG 7D /r","V","V","AVX","","w,r,r","","" +"VINSERTF128 ymm1, ymmV, xmm2/m128, imm8u:1","VINSERTF128 imm8u:1, xmm2/m128, ymmV, ymm1","vinsertf128 imm8u:1, xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 18 /r ib","V","V","AVX","","w,r,r,r","","" +"VINSERTF32X4 ymm1, {k}{z}, ymmV, xmm2/m128, imm8u:1","VINSERTF32X4 imm8u:1, xmm2/m128, ymmV, {k}{z}, ymm1","vinsertf32x4 imm8u:1, xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 18 /r ib","V","V","AVX512F+AVX512VL","scale16","w,r,r,r,r","","" +"VINSERTF32X4 zmm1, {k}{z}, zmmV, xmm2/m128, imm8u:2","VINSERTF32X4 imm8u:2, xmm2/m128, zmmV, {k}{z}, zmm1","vinsertf32x4 imm8u:2, xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 18 /r ib","V","V","AVX512F","scale16","w,r,r,r,r","","" +"VINSERTF32X8 zmm1, {k}{z}, zmmV, ymm2/m256, imm8u:1","VINSERTF32X8 imm8u:1, ymm2/m256, zmmV, {k}{z}, zmm1","vinsertf32x8 imm8u:1, ymm2/m256, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 1A /r ib","V","V","AVX512DQ","scale32","w,r,r,r,r","","" +"VINSERTF64X2 ymm1, {k}{z}, ymmV, xmm2/m128, imm8u:1","VINSERTF64X2 imm8u:1, xmm2/m128, ymmV, {k}{z}, ymm1","vinsertf64x2 imm8u:1, xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 18 /r ib","V","V","AVX512DQ+AVX512VL","scale16","w,r,r,r,r","","" +"VINSERTF64X2 zmm1, {k}{z}, zmmV, xmm2/m128, imm8u:2","VINSERTF64X2 imm8u:2, xmm2/m128, zmmV, {k}{z}, zmm1","vinsertf64x2 imm8u:2, xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 18 /r ib","V","V","AVX512DQ","scale16","w,r,r,r,r","","" +"VINSERTF64X4 zmm1, {k}{z}, zmmV, ymm2/m256, imm8u:1","VINSERTF64X4 imm8u:1, ymm2/m256, zmmV, {k}{z}, zmm1","vinsertf64x4 imm8u:1, ymm2/m256, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 1A /r ib","V","V","AVX512F","scale32","w,r,r,r,r","","" +"VINSERTI128 ymm1, ymmV, xmm2/m128, imm8u:1","VINSERTI128 imm8u:1, xmm2/m128, ymmV, ymm1","vinserti128 imm8u:1, xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 38 /r ib","V","V","AVX2","","w,r,r,r","","" +"VINSERTI32X4 ymm1, {k}{z}, ymmV, xmm2/m128, imm8u:1","VINSERTI32X4 imm8u:1, xmm2/m128, ymmV, {k}{z}, ymm1","vinserti32x4 imm8u:1, xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 38 /r ib","V","V","AVX512F+AVX512VL","scale16","w,r,r,r,r","","" +"VINSERTI32X4 zmm1, {k}{z}, zmmV, xmm2/m128, imm8u:2","VINSERTI32X4 imm8u:2, xmm2/m128, zmmV, {k}{z}, zmm1","vinserti32x4 imm8u:2, xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 38 /r ib","V","V","AVX512F","scale16","w,r,r,r,r","","" +"VINSERTI32X8 zmm1, {k}{z}, zmmV, ymm2/m256, imm8u:1","VINSERTI32X8 imm8u:1, ymm2/m256, zmmV, {k}{z}, zmm1","vinserti32x8 imm8u:1, ymm2/m256, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 3A /r ib","V","V","AVX512DQ","scale32","w,r,r,r,r","","" +"VINSERTI64X2 ymm1, {k}{z}, ymmV, xmm2/m128, imm8u:1","VINSERTI64X2 imm8u:1, xmm2/m128, ymmV, {k}{z}, ymm1","vinserti64x2 imm8u:1, xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 38 /r ib","V","V","AVX512DQ+AVX512VL","scale16","w,r,r,r,r","","" +"VINSERTI64X2 zmm1, {k}{z}, zmmV, xmm2/m128, imm8u:2","VINSERTI64X2 imm8u:2, xmm2/m128, zmmV, {k}{z}, zmm1","vinserti64x2 imm8u:2, xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 38 /r ib","V","V","AVX512DQ","scale16","w,r,r,r,r","","" +"VINSERTI64X4 zmm1, {k}{z}, zmmV, ymm2/m256, imm8u:1","VINSERTI64X4 imm8u:1, ymm2/m256, zmmV, {k}{z}, zmm1","vinserti64x4 imm8u:1, ymm2/m256, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 3A /r ib","V","V","AVX512F","scale32","w,r,r,r,r","","" +"VINSERTPS xmm1, xmmV, xmm2/m32, imm8u","VINSERTPS imm8u, xmm2/m32, xmmV, xmm1","vinsertps imm8u, xmm2/m32, xmmV, xmm1","EVEX.NDS.128.66.0F3A.W0 21 /r ib","V","V","AVX512F+AVX512VL","scale4","w,r,r,r","","" +"VINSERTPS xmm1, xmmV, xmm2/m32, imm8u","VINSERTPS imm8u, xmm2/m32, xmmV, xmm1","vinsertps imm8u, xmm2/m32, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 21 /r ib","V","V","AVX","","w,r,r,r","","" +"VLDDQU xmm1, m128","VLDDQU m128, xmm1","vlddqu m128, xmm1","VEX.128.F2.0F.WIG F0 /r","V","V","AVX","modrm_memonly","w,r","","" +"VLDDQU ymm1, m256","VLDDQU m256, ymm1","vlddqu m256, ymm1","VEX.256.F2.0F.WIG F0 /r","V","V","AVX","modrm_memonly","w,r","","" +"VLDMXCSR m32","VLDMXCSR m32","vldmxcsr m32","VEX.128.0F.WIG AE /2","V","V","AVX","modrm_memonly","r","","" +"VMASKMOVDQU xmm1, xmm2","VMASKMOVDQU xmm2, xmm1","vmaskmovdqu xmm2, xmm1","VEX.128.66.0F.WIG F7 /r","V","V","AVX","modrm_regonly","r,r","","" +"VMASKMOVPD xmm1, xmmV, m128","VMASKMOVPD m128, xmmV, xmm1","vmaskmovpd m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 2D /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMASKMOVPD ymm1, ymmV, m256","VMASKMOVPD m256, ymmV, ymm1","vmaskmovpd m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 2D /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMASKMOVPD m128, xmmV, xmm1","VMASKMOVPD xmm1, xmmV, m128","vmaskmovpd xmm1, xmmV, m128","VEX.NDS.128.66.0F38.W0 2F /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMASKMOVPD m256, ymmV, ymm1","VMASKMOVPD ymm1, ymmV, m256","vmaskmovpd ymm1, ymmV, m256","VEX.NDS.256.66.0F38.W0 2F /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMASKMOVPS xmm1, xmmV, m128","VMASKMOVPS m128, xmmV, xmm1","vmaskmovps m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 2C /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMASKMOVPS ymm1, ymmV, m256","VMASKMOVPS m256, ymmV, ymm1","vmaskmovps m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 2C /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMASKMOVPS m128, xmmV, xmm1","VMASKMOVPS xmm1, xmmV, m128","vmaskmovps xmm1, xmmV, m128","VEX.NDS.128.66.0F38.W0 2E /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMASKMOVPS m256, ymmV, ymm1","VMASKMOVPS ymm1, ymmV, m256","vmaskmovps ymm1, ymmV, m256","VEX.NDS.256.66.0F38.W0 2E /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMAXPD xmm1, xmmV, xmm2/m128","VMAXPD xmm2/m128, xmmV, xmm1","vmaxpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 5F /r","V","V","AVX","","w,r,r","","" +"VMAXPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VMAXPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vmaxpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 5F /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VMAXPD ymm1, ymmV, ymm2/m256","VMAXPD ymm2/m256, ymmV, ymm1","vmaxpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 5F /r","V","V","AVX","","w,r,r","","" +"VMAXPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VMAXPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vmaxpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 5F /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VMAXPD zmm1{sae}, {k}{z}, zmmV, zmm2","VMAXPD zmm2, zmmV, {k}{z}, zmm1{sae}","vmaxpd zmm2, zmmV, {k}{z}, zmm1{sae}","EVEX.NDS.512.66.0F.W1 5F /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMAXPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VMAXPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vmaxpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 5F /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VMAXPS xmm1, xmmV, xmm2/m128","VMAXPS xmm2/m128, xmmV, xmm1","vmaxps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 5F /r","V","V","AVX","","w,r,r","","" +"VMAXPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VMAXPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vmaxps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 5F /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VMAXPS ymm1, ymmV, ymm2/m256","VMAXPS ymm2/m256, ymmV, ymm1","vmaxps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 5F /r","V","V","AVX","","w,r,r","","" +"VMAXPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VMAXPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vmaxps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 5F /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VMAXPS zmm1{sae}, {k}{z}, zmmV, zmm2","VMAXPS zmm2, zmmV, {k}{z}, zmm1{sae}","vmaxps zmm2, zmmV, {k}{z}, zmm1{sae}","EVEX.NDS.512.0F.W0 5F /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMAXPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VMAXPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vmaxps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 5F /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VMAXSD xmm1{sae}, {k}{z}, xmmV, xmm2","VMAXSD xmm2, xmmV, {k}{z}, xmm1{sae}","vmaxsd xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.F2.0F.W1 5F /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMAXSD xmm1, xmmV, xmm2/m64","VMAXSD xmm2/m64, xmmV, xmm1","vmaxsd xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 5F /r","V","V","AVX","","w,r,r","","" +"VMAXSD xmm1, {k}{z}, xmmV, xmm2/m64","VMAXSD xmm2/m64, xmmV, {k}{z}, xmm1","vmaxsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 5F /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VMAXSS xmm1{sae}, {k}{z}, xmmV, xmm2","VMAXSS xmm2, xmmV, {k}{z}, xmm1{sae}","vmaxss xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.F3.0F.W0 5F /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMAXSS xmm1, xmmV, xmm2/m32","VMAXSS xmm2/m32, xmmV, xmm1","vmaxss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 5F /r","V","V","AVX","","w,r,r","","" +"VMAXSS xmm1, {k}{z}, xmmV, xmm2/m32","VMAXSS xmm2/m32, xmmV, {k}{z}, xmm1","vmaxss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 5F /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VMCALL","VMCALL","vmcall","0F 01 C1","V","V","VTX","","","","" +"VMCLEAR m64","VMCLEAR m64","vmclear m64","66 0F C7 /6","V","V","VTX","modrm_memonly","r","","" +"VMFUNC","VMFUNC","vmfunc","0F 01 D4","V","V","","","","","" +"VMINPD xmm1, xmmV, xmm2/m128","VMINPD xmm2/m128, xmmV, xmm1","vminpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 5D /r","V","V","AVX","","w,r,r","","" +"VMINPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VMINPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vminpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 5D /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VMINPD ymm1, ymmV, ymm2/m256","VMINPD ymm2/m256, ymmV, ymm1","vminpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 5D /r","V","V","AVX","","w,r,r","","" +"VMINPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VMINPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vminpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 5D /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VMINPD zmm1{sae}, {k}{z}, zmmV, zmm2","VMINPD zmm2, zmmV, {k}{z}, zmm1{sae}","vminpd zmm2, zmmV, {k}{z}, zmm1{sae}","EVEX.NDS.512.66.0F.W1 5D /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMINPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VMINPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vminpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 5D /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VMINPS xmm1, xmmV, xmm2/m128","VMINPS xmm2/m128, xmmV, xmm1","vminps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 5D /r","V","V","AVX","","w,r,r","","" +"VMINPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VMINPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vminps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 5D /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VMINPS ymm1, ymmV, ymm2/m256","VMINPS ymm2/m256, ymmV, ymm1","vminps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 5D /r","V","V","AVX","","w,r,r","","" +"VMINPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VMINPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vminps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 5D /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VMINPS zmm1{sae}, {k}{z}, zmmV, zmm2","VMINPS zmm2, zmmV, {k}{z}, zmm1{sae}","vminps zmm2, zmmV, {k}{z}, zmm1{sae}","EVEX.NDS.512.0F.W0 5D /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMINPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VMINPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vminps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 5D /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VMINSD xmm1{sae}, {k}{z}, xmmV, xmm2","VMINSD xmm2, xmmV, {k}{z}, xmm1{sae}","vminsd xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.F2.0F.W1 5D /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMINSD xmm1, xmmV, xmm2/m64","VMINSD xmm2/m64, xmmV, xmm1","vminsd xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 5D /r","V","V","AVX","","w,r,r","","" +"VMINSD xmm1, {k}{z}, xmmV, xmm2/m64","VMINSD xmm2/m64, xmmV, {k}{z}, xmm1","vminsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 5D /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VMINSS xmm1{sae}, {k}{z}, xmmV, xmm2","VMINSS xmm2, xmmV, {k}{z}, xmm1{sae}","vminss xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.F3.0F.W0 5D /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMINSS xmm1, xmmV, xmm2/m32","VMINSS xmm2/m32, xmmV, xmm1","vminss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 5D /r","V","V","AVX","","w,r,r","","" +"VMINSS xmm1, {k}{z}, xmmV, xmm2/m32","VMINSS xmm2/m32, xmmV, {k}{z}, xmm1","vminss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 5D /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VMLAUNCH","VMLAUNCH","vmlaunch","0F 01 C2","V","V","VTX","","","","" +"VMLOAD EAX","VMLOADL EAX","vmloadl EAX","0F 01 DA","V","V","SVM","amd,modrm_regonly,operand32","r","Y","32" +"VMLOAD RAX","VMLOADQ RAX","vmloadq RAX","REX.W 0F 01 DA","N.S.","V","SVM","amd,modrm_regonly","r","Y","64" +"VMLOAD AX","VMLOADW AX","vmloadw AX","0F 01 DA","V","V","SVM","amd,modrm_regonly,operand16","r","Y","16" +"VMMCALL","VMMCALL","vmmcall","0F 01 D9","V","V","SVM","amd","","","" +"VMOVAPD xmm2/m128, xmm1","VMOVAPD xmm1, xmm2/m128","vmovapd xmm1, xmm2/m128","VEX.128.66.0F.WIG 29 /r","V","V","AVX","","w,r","","" +"VMOVAPD xmm2/m128, {k}{z}, xmm1","VMOVAPD xmm1, {k}{z}, xmm2/m128","vmovapd xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F.W1 29 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVAPD xmm1, xmm2/m128","VMOVAPD xmm2/m128, xmm1","vmovapd xmm2/m128, xmm1","VEX.128.66.0F.WIG 28 /r","V","V","AVX","","w,r","","" +"VMOVAPD xmm1, {k}{z}, xmm2/m128","VMOVAPD xmm2/m128, {k}{z}, xmm1","vmovapd xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F.W1 28 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVAPD ymm2/m256, ymm1","VMOVAPD ymm1, ymm2/m256","vmovapd ymm1, ymm2/m256","VEX.256.66.0F.WIG 29 /r","V","V","AVX","","w,r","","" +"VMOVAPD ymm2/m256, {k}{z}, ymm1","VMOVAPD ymm1, {k}{z}, ymm2/m256","vmovapd ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F.W1 29 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVAPD ymm1, ymm2/m256","VMOVAPD ymm2/m256, ymm1","vmovapd ymm2/m256, ymm1","VEX.256.66.0F.WIG 28 /r","V","V","AVX","","w,r","","" +"VMOVAPD ymm1, {k}{z}, ymm2/m256","VMOVAPD ymm2/m256, {k}{z}, ymm1","vmovapd ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F.W1 28 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVAPD zmm2/m512, {k}{z}, zmm1","VMOVAPD zmm1, {k}{z}, zmm2/m512","vmovapd zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F.W1 29 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVAPD zmm1, {k}{z}, zmm2/m512","VMOVAPD zmm2/m512, {k}{z}, zmm1","vmovapd zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F.W1 28 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVAPS xmm2/m128, xmm1","VMOVAPS xmm1, xmm2/m128","vmovaps xmm1, xmm2/m128","VEX.128.0F.WIG 29 /r","V","V","AVX","","w,r","","" +"VMOVAPS xmm2/m128, {k}{z}, xmm1","VMOVAPS xmm1, {k}{z}, xmm2/m128","vmovaps xmm1, {k}{z}, xmm2/m128","EVEX.128.0F.W0 29 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVAPS xmm1, xmm2/m128","VMOVAPS xmm2/m128, xmm1","vmovaps xmm2/m128, xmm1","VEX.128.0F.WIG 28 /r","V","V","AVX","","w,r","","" +"VMOVAPS xmm1, {k}{z}, xmm2/m128","VMOVAPS xmm2/m128, {k}{z}, xmm1","vmovaps xmm2/m128, {k}{z}, xmm1","EVEX.128.0F.W0 28 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVAPS ymm2/m256, ymm1","VMOVAPS ymm1, ymm2/m256","vmovaps ymm1, ymm2/m256","VEX.256.0F.WIG 29 /r","V","V","AVX","","w,r","","" +"VMOVAPS ymm2/m256, {k}{z}, ymm1","VMOVAPS ymm1, {k}{z}, ymm2/m256","vmovaps ymm1, {k}{z}, ymm2/m256","EVEX.256.0F.W0 29 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVAPS ymm1, ymm2/m256","VMOVAPS ymm2/m256, ymm1","vmovaps ymm2/m256, ymm1","VEX.256.0F.WIG 28 /r","V","V","AVX","","w,r","","" +"VMOVAPS ymm1, {k}{z}, ymm2/m256","VMOVAPS ymm2/m256, {k}{z}, ymm1","vmovaps ymm2/m256, {k}{z}, ymm1","EVEX.256.0F.W0 28 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVAPS zmm2/m512, {k}{z}, zmm1","VMOVAPS zmm1, {k}{z}, zmm2/m512","vmovaps zmm1, {k}{z}, zmm2/m512","EVEX.512.0F.W0 29 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVAPS zmm1, {k}{z}, zmm2/m512","VMOVAPS zmm2/m512, {k}{z}, zmm1","vmovaps zmm2/m512, {k}{z}, zmm1","EVEX.512.0F.W0 28 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVD xmm1, r/m32","VMOVD r/m32, xmm1","vmovd r/m32, xmm1","EVEX.128.66.0F.W0 6E /r","V","V","AVX512F+AVX512VL","scale4","w,r","","" +"VMOVD xmm1, r/m32","VMOVD r/m32, xmm1","vmovd r/m32, xmm1","VEX.128.66.0F.W0 6E /r","V","V","AVX","","w,r","","" +"VMOVD r/m32, xmm1","VMOVD xmm1, r/m32","vmovd xmm1, r/m32","EVEX.128.66.0F.W0 7E /r","V","V","AVX512F+AVX512VL","scale4","w,r","","" +"VMOVD r/m32, xmm1","VMOVD xmm1, r/m32","vmovd xmm1, r/m32","VEX.128.66.0F.W0 7E /r","V","V","AVX","","w,r","","" +"VMOVDDUP xmm1, xmm2/m64","VMOVDDUP xmm2/m64, xmm1","vmovddup xmm2/m64, xmm1","VEX.128.F2.0F.WIG 12 /r","V","V","AVX","","w,r","","" +"VMOVDDUP xmm1, {k}{z}, xmm2/m64","VMOVDDUP xmm2/m64, {k}{z}, xmm1","vmovddup xmm2/m64, {k}{z}, xmm1","EVEX.128.F2.0F.W1 12 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VMOVDDUP ymm1, ymm2/m256","VMOVDDUP ymm2/m256, ymm1","vmovddup ymm2/m256, ymm1","VEX.256.F2.0F.WIG 12 /r","V","V","AVX","","w,r","","" +"VMOVDDUP ymm1, {k}{z}, ymm2/m256","VMOVDDUP ymm2/m256, {k}{z}, ymm1","vmovddup ymm2/m256, {k}{z}, ymm1","EVEX.256.F2.0F.W1 12 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVDDUP zmm1, {k}{z}, zmm2/m512","VMOVDDUP zmm2/m512, {k}{z}, zmm1","vmovddup zmm2/m512, {k}{z}, zmm1","EVEX.512.F2.0F.W1 12 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVDQA xmm2/m128, xmm1","VMOVDQA xmm1, xmm2/m128","vmovdqa xmm1, xmm2/m128","VEX.128.66.0F.WIG 7F /r","V","V","AVX","","w,r","","" +"VMOVDQA xmm1, xmm2/m128","VMOVDQA xmm2/m128, xmm1","vmovdqa xmm2/m128, xmm1","VEX.128.66.0F.WIG 6F /r","V","V","AVX","","w,r","","" +"VMOVDQA ymm2/m256, ymm1","VMOVDQA ymm1, ymm2/m256","vmovdqa ymm1, ymm2/m256","VEX.256.66.0F.WIG 7F /r","V","V","AVX","","w,r","","" +"VMOVDQA ymm1, ymm2/m256","VMOVDQA ymm2/m256, ymm1","vmovdqa ymm2/m256, ymm1","VEX.256.66.0F.WIG 6F /r","V","V","AVX","","w,r","","" +"VMOVDQA32 xmm2/m128, {k}{z}, xmm1","VMOVDQA32 xmm1, {k}{z}, xmm2/m128","vmovdqa32 xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F.W0 7F /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVDQA32 xmm1, {k}{z}, xmm2/m128","VMOVDQA32 xmm2/m128, {k}{z}, xmm1","vmovdqa32 xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F.W0 6F /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVDQA32 ymm2/m256, {k}{z}, ymm1","VMOVDQA32 ymm1, {k}{z}, ymm2/m256","vmovdqa32 ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F.W0 7F /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVDQA32 ymm1, {k}{z}, ymm2/m256","VMOVDQA32 ymm2/m256, {k}{z}, ymm1","vmovdqa32 ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F.W0 6F /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVDQA32 zmm2/m512, {k}{z}, zmm1","VMOVDQA32 zmm1, {k}{z}, zmm2/m512","vmovdqa32 zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F.W0 7F /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVDQA32 zmm1, {k}{z}, zmm2/m512","VMOVDQA32 zmm2/m512, {k}{z}, zmm1","vmovdqa32 zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F.W0 6F /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVDQA64 xmm2/m128, {k}{z}, xmm1","VMOVDQA64 xmm1, {k}{z}, xmm2/m128","vmovdqa64 xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F.W1 7F /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","Y","128" +"VMOVDQA64 xmm1, {k}{z}, xmm2/m128","VMOVDQA64 xmm2/m128, {k}{z}, xmm1","vmovdqa64 xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F.W1 6F /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","Y","128" +"VMOVDQA64 ymm2/m256, {k}{z}, ymm1","VMOVDQA64 ymm1, {k}{z}, ymm2/m256","vmovdqa64 ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F.W1 7F /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","Y","256" +"VMOVDQA64 ymm1, {k}{z}, ymm2/m256","VMOVDQA64 ymm2/m256, {k}{z}, ymm1","vmovdqa64 ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F.W1 6F /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","Y","256" +"VMOVDQA64 zmm2/m512, {k}{z}, zmm1","VMOVDQA64 zmm1, {k}{z}, zmm2/m512","vmovdqa64 zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F.W1 7F /r","V","V","AVX512F","scale64","w,r,r","Y","512" +"VMOVDQA64 zmm1, {k}{z}, zmm2/m512","VMOVDQA64 zmm2/m512, {k}{z}, zmm1","vmovdqa64 zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F.W1 6F /r","V","V","AVX512F","scale64","w,r,r","Y","512" +"VMOVDQU xmm2/m128, xmm1","VMOVDQU xmm1, xmm2/m128","vmovdqu xmm1, xmm2/m128","VEX.128.F3.0F.WIG 7F /r","V","V","AVX","","w,r","","" +"VMOVDQU xmm1, xmm2/m128","VMOVDQU xmm2/m128, xmm1","vmovdqu xmm2/m128, xmm1","VEX.128.F3.0F.WIG 6F /r","V","V","AVX","","w,r","","" +"VMOVDQU ymm2/m256, ymm1","VMOVDQU ymm1, ymm2/m256","vmovdqu ymm1, ymm2/m256","VEX.256.F3.0F.WIG 7F /r","V","V","AVX","","w,r","","" +"VMOVDQU ymm1, ymm2/m256","VMOVDQU ymm2/m256, ymm1","vmovdqu ymm2/m256, ymm1","VEX.256.F3.0F.WIG 6F /r","V","V","AVX","","w,r","","" +"VMOVDQU16 xmm2/m128, {k}{z}, xmm1","VMOVDQU16 xmm1, {k}{z}, xmm2/m128","vmovdqu16 xmm1, {k}{z}, xmm2/m128","EVEX.128.F2.0F.W1 7F /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VMOVDQU16 xmm1, {k}{z}, xmm2/m128","VMOVDQU16 xmm2/m128, {k}{z}, xmm1","vmovdqu16 xmm2/m128, {k}{z}, xmm1","EVEX.128.F2.0F.W1 6F /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VMOVDQU16 ymm2/m256, {k}{z}, ymm1","VMOVDQU16 ymm1, {k}{z}, ymm2/m256","vmovdqu16 ymm1, {k}{z}, ymm2/m256","EVEX.256.F2.0F.W1 7F /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r","","" +"VMOVDQU16 ymm1, {k}{z}, ymm2/m256","VMOVDQU16 ymm2/m256, {k}{z}, ymm1","vmovdqu16 ymm2/m256, {k}{z}, ymm1","EVEX.256.F2.0F.W1 6F /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r","","" +"VMOVDQU16 zmm2/m512, {k}{z}, zmm1","VMOVDQU16 zmm1, {k}{z}, zmm2/m512","vmovdqu16 zmm1, {k}{z}, zmm2/m512","EVEX.512.F2.0F.W1 7F /r","V","V","AVX512BW","scale64","w,r,r","","" +"VMOVDQU16 zmm1, {k}{z}, zmm2/m512","VMOVDQU16 zmm2/m512, {k}{z}, zmm1","vmovdqu16 zmm2/m512, {k}{z}, zmm1","EVEX.512.F2.0F.W1 6F /r","V","V","AVX512BW","scale64","w,r,r","","" +"VMOVDQU32 xmm2/m128, {k}{z}, xmm1","VMOVDQU32 xmm1, {k}{z}, xmm2/m128","vmovdqu32 xmm1, {k}{z}, xmm2/m128","EVEX.128.F3.0F.W0 7F /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","Y","128" +"VMOVDQU32 xmm1, {k}{z}, xmm2/m128","VMOVDQU32 xmm2/m128, {k}{z}, xmm1","vmovdqu32 xmm2/m128, {k}{z}, xmm1","EVEX.128.F3.0F.W0 6F /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","Y","128" +"VMOVDQU32 ymm2/m256, {k}{z}, ymm1","VMOVDQU32 ymm1, {k}{z}, ymm2/m256","vmovdqu32 ymm1, {k}{z}, ymm2/m256","EVEX.256.F3.0F.W0 7F /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","Y","256" +"VMOVDQU32 ymm1, {k}{z}, ymm2/m256","VMOVDQU32 ymm2/m256, {k}{z}, ymm1","vmovdqu32 ymm2/m256, {k}{z}, ymm1","EVEX.256.F3.0F.W0 6F /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","Y","256" +"VMOVDQU32 zmm2/m512, {k}{z}, zmm1","VMOVDQU32 zmm1, {k}{z}, zmm2/m512","vmovdqu32 zmm1, {k}{z}, zmm2/m512","EVEX.512.F3.0F.W0 7F /r","V","V","AVX512F","scale64","w,r,r","Y","512" +"VMOVDQU32 zmm1, {k}{z}, zmm2/m512","VMOVDQU32 zmm2/m512, {k}{z}, zmm1","vmovdqu32 zmm2/m512, {k}{z}, zmm1","EVEX.512.F3.0F.W0 6F /r","V","V","AVX512F","scale64","w,r,r","Y","512" +"VMOVDQU64 xmm2/m128, {k}{z}, xmm1","VMOVDQU64 xmm1, {k}{z}, xmm2/m128","vmovdqu64 xmm1, {k}{z}, xmm2/m128","EVEX.128.F3.0F.W1 7F /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","Y","128" +"VMOVDQU64 xmm1, {k}{z}, xmm2/m128","VMOVDQU64 xmm2/m128, {k}{z}, xmm1","vmovdqu64 xmm2/m128, {k}{z}, xmm1","EVEX.128.F3.0F.W1 6F /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","Y","128" +"VMOVDQU64 ymm2/m256, {k}{z}, ymm1","VMOVDQU64 ymm1, {k}{z}, ymm2/m256","vmovdqu64 ymm1, {k}{z}, ymm2/m256","EVEX.256.F3.0F.W1 7F /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","Y","256" +"VMOVDQU64 ymm1, {k}{z}, ymm2/m256","VMOVDQU64 ymm2/m256, {k}{z}, ymm1","vmovdqu64 ymm2/m256, {k}{z}, ymm1","EVEX.256.F3.0F.W1 6F /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","Y","256" +"VMOVDQU64 zmm2/m512, {k}{z}, zmm1","VMOVDQU64 zmm1, {k}{z}, zmm2/m512","vmovdqu64 zmm1, {k}{z}, zmm2/m512","EVEX.512.F3.0F.W1 7F /r","V","V","AVX512F","scale64","w,r,r","Y","512" +"VMOVDQU64 zmm1, {k}{z}, zmm2/m512","VMOVDQU64 zmm2/m512, {k}{z}, zmm1","vmovdqu64 zmm2/m512, {k}{z}, zmm1","EVEX.512.F3.0F.W1 6F /r","V","V","AVX512F","scale64","w,r,r","Y","512" +"VMOVDQU8 xmm2/m128, {k}{z}, xmm1","VMOVDQU8 xmm1, {k}{z}, xmm2/m128","vmovdqu8 xmm1, {k}{z}, xmm2/m128","EVEX.128.F2.0F.W0 7F /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","Y","128" +"VMOVDQU8 xmm1, {k}{z}, xmm2/m128","VMOVDQU8 xmm2/m128, {k}{z}, xmm1","vmovdqu8 xmm2/m128, {k}{z}, xmm1","EVEX.128.F2.0F.W0 6F /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","Y","128" +"VMOVDQU8 ymm2/m256, {k}{z}, ymm1","VMOVDQU8 ymm1, {k}{z}, ymm2/m256","vmovdqu8 ymm1, {k}{z}, ymm2/m256","EVEX.256.F2.0F.W0 7F /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r","Y","256" +"VMOVDQU8 ymm1, {k}{z}, ymm2/m256","VMOVDQU8 ymm2/m256, {k}{z}, ymm1","vmovdqu8 ymm2/m256, {k}{z}, ymm1","EVEX.256.F2.0F.W0 6F /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r","Y","256" +"VMOVDQU8 zmm2/m512, {k}{z}, zmm1","VMOVDQU8 zmm1, {k}{z}, zmm2/m512","vmovdqu8 zmm1, {k}{z}, zmm2/m512","EVEX.512.F2.0F.W0 7F /r","V","V","AVX512BW","scale64","w,r,r","Y","512" +"VMOVDQU8 zmm1, {k}{z}, zmm2/m512","VMOVDQU8 zmm2/m512, {k}{z}, zmm1","vmovdqu8 zmm2/m512, {k}{z}, zmm1","EVEX.512.F2.0F.W0 6F /r","V","V","AVX512BW","scale64","w,r,r","Y","512" +"VMOVHLPS xmm1, xmmV, xmm2","VMOVHLPS xmm2, xmmV, xmm1","vmovhlps xmm2, xmmV, xmm1","EVEX.NDS.128.0F.W0 12 /r","V","V","AVX512F+AVX512VL","modrm_regonly","w,r,r","","" +"VMOVHLPS xmm1, xmmV, xmm2","VMOVHLPS xmm2, xmmV, xmm1","vmovhlps xmm2, xmmV, xmm1","VEX.NDS.128.0F.WIG 12 /r","V","V","AVX","modrm_regonly","w,r,r","","" +"VMOVHPD xmm1, xmmV, m64","VMOVHPD m64, xmmV, xmm1","vmovhpd m64, xmmV, xmm1","EVEX.NDS.LIG.66.0F.W1 16 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,r,r","","" +"VMOVHPD xmm1, xmmV, m64","VMOVHPD m64, xmmV, xmm1","vmovhpd m64, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 16 /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMOVHPD m64, xmm1","VMOVHPD xmm1, m64","vmovhpd xmm1, m64","EVEX.LIG.66.0F.W1 17 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,r","","" +"VMOVHPD m64, xmm1","VMOVHPD xmm1, m64","vmovhpd xmm1, m64","VEX.128.66.0F.WIG 17 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVHPS xmm1, xmmV, m64","VMOVHPS m64, xmmV, xmm1","vmovhps m64, xmmV, xmm1","EVEX.NDS.128.0F.W0 16 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,r,r","","" +"VMOVHPS xmm1, xmmV, m64","VMOVHPS m64, xmmV, xmm1","vmovhps m64, xmmV, xmm1","VEX.NDS.128.0F.WIG 16 /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMOVHPS m64, xmm1","VMOVHPS xmm1, m64","vmovhps xmm1, m64","EVEX.128.0F.W0 17 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,r","","" +"VMOVHPS m64, xmm1","VMOVHPS xmm1, m64","vmovhps xmm1, m64","VEX.128.0F.WIG 17 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVLHPS xmm1, xmmV, xmm2","VMOVLHPS xmm2, xmmV, xmm1","vmovlhps xmm2, xmmV, xmm1","EVEX.NDS.128.0F.W0 16 /r","V","V","AVX512F+AVX512VL","modrm_regonly","w,r,r","","" +"VMOVLHPS xmm1, xmmV, xmm2","VMOVLHPS xmm2, xmmV, xmm1","vmovlhps xmm2, xmmV, xmm1","VEX.NDS.128.0F.WIG 16 /r","V","V","AVX","modrm_regonly","w,r,r","","" +"VMOVLPD xmm1, xmmV, m64","VMOVLPD m64, xmmV, xmm1","vmovlpd m64, xmmV, xmm1","EVEX.NDS.LIG.66.0F.W1 12 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,r,r","","" +"VMOVLPD xmm1, xmmV, m64","VMOVLPD m64, xmmV, xmm1","vmovlpd m64, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 12 /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMOVLPD m64, xmm1","VMOVLPD xmm1, m64","vmovlpd xmm1, m64","EVEX.LIG.66.0F.W1 13 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,r","","" +"VMOVLPD m64, xmm1","VMOVLPD xmm1, m64","vmovlpd xmm1, m64","VEX.128.66.0F.WIG 13 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVLPS xmm1, xmmV, m64","VMOVLPS m64, xmmV, xmm1","vmovlps m64, xmmV, xmm1","EVEX.NDS.128.0F.W0 12 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,r,r","","" +"VMOVLPS xmm1, xmmV, m64","VMOVLPS m64, xmmV, xmm1","vmovlps m64, xmmV, xmm1","VEX.NDS.128.0F.WIG 12 /r","V","V","AVX","modrm_memonly","w,r,r","","" +"VMOVLPS m64, xmm1","VMOVLPS xmm1, m64","vmovlps xmm1, m64","EVEX.128.0F.W0 13 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,r","","" +"VMOVLPS m64, xmm1","VMOVLPS xmm1, m64","vmovlps xmm1, m64","VEX.128.0F.WIG 13 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVMSKPD r32, xmm2","VMOVMSKPD xmm2, r32","vmovmskpd xmm2, r32","VEX.128.66.0F.WIG 50 /r","V","V","AVX","modrm_regonly","w,r","","" +"VMOVMSKPD r32, ymm2","VMOVMSKPD ymm2, r32","vmovmskpd ymm2, r32","VEX.256.66.0F.WIG 50 /r","V","V","AVX","modrm_regonly","w,r","","" +"VMOVMSKPS r32, xmm2","VMOVMSKPS xmm2, r32","vmovmskps xmm2, r32","VEX.128.0F.WIG 50 /r","V","V","AVX","modrm_regonly","w,r","","" +"VMOVMSKPS r32, ymm2","VMOVMSKPS ymm2, r32","vmovmskps ymm2, r32","VEX.256.0F.WIG 50 /r","V","V","AVX","modrm_regonly","w,r","","" +"VMOVNTDQ m128, xmm1","VMOVNTDQ xmm1, m128","vmovntdq xmm1, m128","EVEX.128.66.0F.W0 E7 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale16","w,r","","" +"VMOVNTDQ m128, xmm1","VMOVNTDQ xmm1, m128","vmovntdq xmm1, m128","VEX.128.66.0F.WIG E7 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVNTDQ m256, ymm1","VMOVNTDQ ymm1, m256","vmovntdq ymm1, m256","EVEX.256.66.0F.W0 E7 /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale32","w,r","","" +"VMOVNTDQ m256, ymm1","VMOVNTDQ ymm1, m256","vmovntdq ymm1, m256","VEX.256.66.0F.WIG E7 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVNTDQ m512, zmm1","VMOVNTDQ zmm1, m512","vmovntdq zmm1, m512","EVEX.512.66.0F.W0 E7 /r","V","V","AVX512F","modrm_memonly,scale64","w,r","","" +"VMOVNTDQA xmm1, m128","VMOVNTDQA m128, xmm1","vmovntdqa m128, xmm1","EVEX.128.66.0F38.W0 2A /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale16","w,r","","" +"VMOVNTDQA xmm1, m128","VMOVNTDQA m128, xmm1","vmovntdqa m128, xmm1","VEX.128.66.0F38.WIG 2A /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVNTDQA ymm1, m256","VMOVNTDQA m256, ymm1","vmovntdqa m256, ymm1","EVEX.256.66.0F38.W0 2A /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale32","w,r","","" +"VMOVNTDQA ymm1, m256","VMOVNTDQA m256, ymm1","vmovntdqa m256, ymm1","VEX.256.66.0F38.WIG 2A /r","V","V","AVX2","modrm_memonly","w,r","","" +"VMOVNTDQA zmm1, m512","VMOVNTDQA m512, zmm1","vmovntdqa m512, zmm1","EVEX.512.66.0F38.W0 2A /r","V","V","AVX512F","modrm_memonly,scale64","w,r","","" +"VMOVNTPD m128, xmm1","VMOVNTPD xmm1, m128","vmovntpd xmm1, m128","EVEX.128.66.0F.W1 2B /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale16","w,r","","" +"VMOVNTPD m128, xmm1","VMOVNTPD xmm1, m128","vmovntpd xmm1, m128","VEX.128.66.0F.WIG 2B /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVNTPD m256, ymm1","VMOVNTPD ymm1, m256","vmovntpd ymm1, m256","EVEX.256.66.0F.W1 2B /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale32","w,r","","" +"VMOVNTPD m256, ymm1","VMOVNTPD ymm1, m256","vmovntpd ymm1, m256","VEX.256.66.0F.WIG 2B /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVNTPD m512, zmm1","VMOVNTPD zmm1, m512","vmovntpd zmm1, m512","EVEX.512.66.0F.W1 2B /r","V","V","AVX512F","modrm_memonly,scale64","w,r","","" +"VMOVNTPS m128, xmm1","VMOVNTPS xmm1, m128","vmovntps xmm1, m128","EVEX.128.0F.W0 2B /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale16","w,r","","" +"VMOVNTPS m128, xmm1","VMOVNTPS xmm1, m128","vmovntps xmm1, m128","VEX.128.0F.WIG 2B /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVNTPS m256, ymm1","VMOVNTPS ymm1, m256","vmovntps ymm1, m256","EVEX.256.0F.W0 2B /r","V","V","AVX512F+AVX512VL","modrm_memonly,scale32","w,r","","" +"VMOVNTPS m256, ymm1","VMOVNTPS ymm1, m256","vmovntps ymm1, m256","VEX.256.0F.WIG 2B /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVNTPS m512, zmm1","VMOVNTPS zmm1, m512","vmovntps zmm1, m512","EVEX.512.0F.W0 2B /r","V","V","AVX512F","modrm_memonly,scale64","w,r","","" +"VMOVQ xmm1, r/m64","VMOVQ r/m64, xmm1","vmovq r/m64, xmm1","EVEX.128.66.0F.W1 6E /r","N.S.","V","AVX512F+AVX512VL","scale8","w,r","","" +"VMOVQ xmm1, r/m64","VMOVQ r/m64, xmm1","vmovq r/m64, xmm1","VEX.128.66.0F.W1 6E /r","N.S.","V","AVX","","w,r","","" +"VMOVQ r/m64, xmm1","VMOVQ xmm1, r/m64","vmovq xmm1, r/m64","EVEX.128.66.0F.W1 7E /r","N.S.","V","AVX512F+AVX512VL","scale8","w,r","","" +"VMOVQ r/m64, xmm1","VMOVQ xmm1, r/m64","vmovq xmm1, r/m64","VEX.128.66.0F.W1 7E /r","N.S.","V","AVX","","w,r","","" +"VMOVQ xmm2/m64, xmm1","VMOVQ xmm1, xmm2/m64","vmovq xmm1, xmm2/m64","EVEX.LIG.66.0F.W1 D6 /r","V","V","AVX512F+AVX512VL","scale8","w,r","","" +"VMOVQ xmm2/m64, xmm1","VMOVQ xmm1, xmm2/m64","vmovq xmm1, xmm2/m64","VEX.128.66.0F.WIG D6 /r","V","V","AVX","","w,r","","" +"VMOVQ xmm1, xmm2/m64","VMOVQ xmm2/m64, xmm1","vmovq xmm2/m64, xmm1","EVEX.LIG.F3.0F.W1 7E /r","V","V","AVX512F+AVX512VL","scale8","w,r","","" +"VMOVQ xmm1, xmm2/m64","VMOVQ xmm2/m64, xmm1","vmovq xmm2/m64, xmm1","VEX.128.F3.0F.WIG 7E /r","V","V","AVX","","w,r","","" +"VMOVSD xmm1, m64","VMOVSD m64, xmm1","vmovsd m64, xmm1","VEX.LIG.F2.0F.WIG 10 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVSD xmm1, {k}{z}, m64","VMOVSD m64, {k}{z}, xmm1","vmovsd m64, {k}{z}, xmm1","EVEX.LIG.F2.0F.W1 10 /r","V","V","AVX512F","modrm_memonly,scale8","w,r,r","","" +"VMOVSD m64, xmm1","VMOVSD xmm1, m64","vmovsd xmm1, m64","VEX.LIG.F2.0F.WIG 11 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVSD xmm2, xmmV, xmm1","VMOVSD xmm1, xmmV, xmm2","vmovsd xmm1, xmmV, xmm2","VEX.NDS.LIG.F2.0F.WIG 11 /r","V","V","AVX","modrm_regonly","w,r,r","","" +"VMOVSD xmm2, {k}{z}, xmmV, xmm1","VMOVSD xmm1, xmmV, {k}{z}, xmm2","vmovsd xmm1, xmmV, {k}{z}, xmm2","EVEX.NDS.LIG.F2.0F.W1 11 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMOVSD m64, {k}, xmm1","VMOVSD xmm1, {k}, m64","vmovsd xmm1, {k}, m64","EVEX.LIG.F2.0F.W1 11 /r","V","V","AVX512F","modrm_memonly,scale8","w,r,r","","" +"VMOVSD xmm1, xmmV, xmm2","VMOVSD xmm2, xmmV, xmm1","vmovsd xmm2, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 10 /r","V","V","AVX","modrm_regonly","w,r,r","","" +"VMOVSD xmm1, {k}{z}, xmmV, xmm2","VMOVSD xmm2, xmmV, {k}{z}, xmm1","vmovsd xmm2, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 10 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMOVSHDUP xmm1, xmm2/m128","VMOVSHDUP xmm2/m128, xmm1","vmovshdup xmm2/m128, xmm1","VEX.128.F3.0F.WIG 16 /r","V","V","AVX","","w,r","","" +"VMOVSHDUP xmm1, {k}{z}, xmm2/m128","VMOVSHDUP xmm2/m128, {k}{z}, xmm1","vmovshdup xmm2/m128, {k}{z}, xmm1","EVEX.128.F3.0F.W0 16 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVSHDUP ymm1, ymm2/m256","VMOVSHDUP ymm2/m256, ymm1","vmovshdup ymm2/m256, ymm1","VEX.256.F3.0F.WIG 16 /r","V","V","AVX","","w,r","","" +"VMOVSHDUP ymm1, {k}{z}, ymm2/m256","VMOVSHDUP ymm2/m256, {k}{z}, ymm1","vmovshdup ymm2/m256, {k}{z}, ymm1","EVEX.256.F3.0F.W0 16 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVSHDUP zmm1, {k}{z}, zmm2/m512","VMOVSHDUP zmm2/m512, {k}{z}, zmm1","vmovshdup zmm2/m512, {k}{z}, zmm1","EVEX.512.F3.0F.W0 16 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVSLDUP xmm1, xmm2/m128","VMOVSLDUP xmm2/m128, xmm1","vmovsldup xmm2/m128, xmm1","VEX.128.F3.0F.WIG 12 /r","V","V","AVX","","w,r","","" +"VMOVSLDUP xmm1, {k}{z}, xmm2/m128","VMOVSLDUP xmm2/m128, {k}{z}, xmm1","vmovsldup xmm2/m128, {k}{z}, xmm1","EVEX.128.F3.0F.W0 12 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVSLDUP ymm1, ymm2/m256","VMOVSLDUP ymm2/m256, ymm1","vmovsldup ymm2/m256, ymm1","VEX.256.F3.0F.WIG 12 /r","V","V","AVX","","w,r","","" +"VMOVSLDUP ymm1, {k}{z}, ymm2/m256","VMOVSLDUP ymm2/m256, {k}{z}, ymm1","vmovsldup ymm2/m256, {k}{z}, ymm1","EVEX.256.F3.0F.W0 12 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVSLDUP zmm1, {k}{z}, zmm2/m512","VMOVSLDUP zmm2/m512, {k}{z}, zmm1","vmovsldup zmm2/m512, {k}{z}, zmm1","EVEX.512.F3.0F.W0 12 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVSS xmm1, m32","VMOVSS m32, xmm1","vmovss m32, xmm1","VEX.LIG.F3.0F.WIG 10 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVSS xmm1, {k}{z}, m32","VMOVSS m32, {k}{z}, xmm1","vmovss m32, {k}{z}, xmm1","EVEX.LIG.F3.0F.W0 10 /r","V","V","AVX512F","modrm_memonly,scale4","w,r,r","","" +"VMOVSS m32, xmm1","VMOVSS xmm1, m32","vmovss xmm1, m32","VEX.LIG.F3.0F.WIG 11 /r","V","V","AVX","modrm_memonly","w,r","","" +"VMOVSS xmm2, xmmV, xmm1","VMOVSS xmm1, xmmV, xmm2","vmovss xmm1, xmmV, xmm2","VEX.NDS.LIG.F3.0F.WIG 11 /r","V","V","AVX","modrm_regonly","w,r,r","","" +"VMOVSS xmm2, {k}{z}, xmmV, xmm1","VMOVSS xmm1, xmmV, {k}{z}, xmm2","vmovss xmm1, xmmV, {k}{z}, xmm2","EVEX.NDS.LIG.F3.0F.W0 11 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMOVSS m32, {k}, xmm1","VMOVSS xmm1, {k}, m32","vmovss xmm1, {k}, m32","EVEX.LIG.F3.0F.W0 11 /r","V","V","AVX512F","modrm_memonly,scale4","w,r,r","","" +"VMOVSS xmm1, xmmV, xmm2","VMOVSS xmm2, xmmV, xmm1","vmovss xmm2, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 10 /r","V","V","AVX","modrm_regonly","w,r,r","","" +"VMOVSS xmm1, {k}{z}, xmmV, xmm2","VMOVSS xmm2, xmmV, {k}{z}, xmm1","vmovss xmm2, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 10 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMOVUPD xmm2/m128, xmm1","VMOVUPD xmm1, xmm2/m128","vmovupd xmm1, xmm2/m128","VEX.128.66.0F.WIG 11 /r","V","V","AVX","","w,r","","" +"VMOVUPD xmm2/m128, {k}{z}, xmm1","VMOVUPD xmm1, {k}{z}, xmm2/m128","vmovupd xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F.W1 11 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVUPD xmm1, xmm2/m128","VMOVUPD xmm2/m128, xmm1","vmovupd xmm2/m128, xmm1","VEX.128.66.0F.WIG 10 /r","V","V","AVX","","w,r","","" +"VMOVUPD xmm1, {k}{z}, xmm2/m128","VMOVUPD xmm2/m128, {k}{z}, xmm1","vmovupd xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F.W1 10 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVUPD ymm2/m256, ymm1","VMOVUPD ymm1, ymm2/m256","vmovupd ymm1, ymm2/m256","VEX.256.66.0F.WIG 11 /r","V","V","AVX","","w,r","","" +"VMOVUPD ymm2/m256, {k}{z}, ymm1","VMOVUPD ymm1, {k}{z}, ymm2/m256","vmovupd ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F.W1 11 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVUPD ymm1, ymm2/m256","VMOVUPD ymm2/m256, ymm1","vmovupd ymm2/m256, ymm1","VEX.256.66.0F.WIG 10 /r","V","V","AVX","","w,r","","" +"VMOVUPD ymm1, {k}{z}, ymm2/m256","VMOVUPD ymm2/m256, {k}{z}, ymm1","vmovupd ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F.W1 10 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVUPD zmm2/m512, {k}{z}, zmm1","VMOVUPD zmm1, {k}{z}, zmm2/m512","vmovupd zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F.W1 11 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVUPD zmm1, {k}{z}, zmm2/m512","VMOVUPD zmm2/m512, {k}{z}, zmm1","vmovupd zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F.W1 10 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVUPS xmm2/m128, xmm1","VMOVUPS xmm1, xmm2/m128","vmovups xmm1, xmm2/m128","VEX.128.0F.WIG 11 /r","V","V","AVX","","w,r","","" +"VMOVUPS xmm2/m128, {k}{z}, xmm1","VMOVUPS xmm1, {k}{z}, xmm2/m128","vmovups xmm1, {k}{z}, xmm2/m128","EVEX.128.0F.W0 11 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVUPS xmm1, xmm2/m128","VMOVUPS xmm2/m128, xmm1","vmovups xmm2/m128, xmm1","VEX.128.0F.WIG 10 /r","V","V","AVX","","w,r","","" +"VMOVUPS xmm1, {k}{z}, xmm2/m128","VMOVUPS xmm2/m128, {k}{z}, xmm1","vmovups xmm2/m128, {k}{z}, xmm1","EVEX.128.0F.W0 10 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VMOVUPS ymm2/m256, ymm1","VMOVUPS ymm1, ymm2/m256","vmovups ymm1, ymm2/m256","VEX.256.0F.WIG 11 /r","V","V","AVX","","w,r","","" +"VMOVUPS ymm2/m256, {k}{z}, ymm1","VMOVUPS ymm1, {k}{z}, ymm2/m256","vmovups ymm1, {k}{z}, ymm2/m256","EVEX.256.0F.W0 11 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVUPS ymm1, ymm2/m256","VMOVUPS ymm2/m256, ymm1","vmovups ymm2/m256, ymm1","VEX.256.0F.WIG 10 /r","V","V","AVX","","w,r","","" +"VMOVUPS ymm1, {k}{z}, ymm2/m256","VMOVUPS ymm2/m256, {k}{z}, ymm1","vmovups ymm2/m256, {k}{z}, ymm1","EVEX.256.0F.W0 10 /r","V","V","AVX512F+AVX512VL","scale32","w,r,r","","" +"VMOVUPS zmm2/m512, {k}{z}, zmm1","VMOVUPS zmm1, {k}{z}, zmm2/m512","vmovups zmm1, {k}{z}, zmm2/m512","EVEX.512.0F.W0 11 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMOVUPS zmm1, {k}{z}, zmm2/m512","VMOVUPS zmm2/m512, {k}{z}, zmm1","vmovups zmm2/m512, {k}{z}, zmm1","EVEX.512.0F.W0 10 /r","V","V","AVX512F","scale64","w,r,r","","" +"VMPSADBW xmm1, xmmV, xmm2/m128, imm8u","VMPSADBW imm8u, xmm2/m128, xmmV, xmm1","vmpsadbw imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 42 /r ib","V","V","AVX","","w,r,r,r","","" +"VMPSADBW ymm1, ymmV, ymm2/m256, imm8u","VMPSADBW imm8u, ymm2/m256, ymmV, ymm1","vmpsadbw imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.WIG 42 /r ib","V","V","AVX2","","w,r,r,r","","" +"VMPTRLD m64","VMPTRLD m64","vmptrld m64","0F C7 /6","V","V","VTX","modrm_memonly","r","","" +"VMPTRST m64","VMPTRST m64","vmptrst m64","0F C7 /7","V","V","VTX","modrm_memonly","w","","" +"VMREAD r/m32, r32","VMREAD r32, r/m32","vmread r32, r/m32","0F 78 /r","V","N.S.","VTX","","rw,r","","" +"VMREAD r/m64, r64","VMREAD r64, r/m64","vmread r64, r/m64","0F 78 /r","N.S.","V","VTX","default64","rw,r","","" +"VMRESUME","VMRESUME","vmresume","0F 01 C3","V","V","VTX","","","","" +"VMRUN EAX","VMRUNL EAX","vmrunl EAX","0F 01 D8","V","V","SVM","amd,modrm_regonly,operand32","r","Y","32" +"VMRUN RAX","VMRUNQ RAX","vmrunq RAX","REX.W 0F 01 D8","N.S.","V","SVM","amd,modrm_regonly","r","Y","64" +"VMRUN AX","VMRUNW AX","vmrunw AX","0F 01 D8","V","V","SVM","amd,modrm_regonly,operand16","r","Y","16" +"VMSAVE","VMSAVE","vmsave","0F 01 DB","V","V","SVM","amd","","","" +"VMULPD xmm1, xmmV, xmm2/m128","VMULPD xmm2/m128, xmmV, xmm1","vmulpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 59 /r","V","V","AVX","","w,r,r","","" +"VMULPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VMULPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vmulpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 59 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VMULPD ymm1, ymmV, ymm2/m256","VMULPD ymm2/m256, ymmV, ymm1","vmulpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 59 /r","V","V","AVX","","w,r,r","","" +"VMULPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VMULPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vmulpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 59 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VMULPD zmm1{er}, {k}{z}, zmmV, zmm2","VMULPD zmm2, zmmV, {k}{z}, zmm1{er}","vmulpd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.66.0F.W1 59 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMULPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VMULPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vmulpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 59 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VMULPS xmm1, xmmV, xmm2/m128","VMULPS xmm2/m128, xmmV, xmm1","vmulps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 59 /r","V","V","AVX","","w,r,r","","" +"VMULPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VMULPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vmulps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 59 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VMULPS ymm1, ymmV, ymm2/m256","VMULPS ymm2/m256, ymmV, ymm1","vmulps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 59 /r","V","V","AVX","","w,r,r","","" +"VMULPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VMULPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vmulps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 59 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VMULPS zmm1{er}, {k}{z}, zmmV, zmm2","VMULPS zmm2, zmmV, {k}{z}, zmm1{er}","vmulps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.0F.W0 59 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMULPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VMULPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vmulps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 59 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VMULSD xmm1{er}, {k}{z}, xmmV, xmm2","VMULSD xmm2, xmmV, {k}{z}, xmm1{er}","vmulsd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F2.0F.W1 59 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMULSD xmm1, xmmV, xmm2/m64","VMULSD xmm2/m64, xmmV, xmm1","vmulsd xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 59 /r","V","V","AVX","","w,r,r","","" +"VMULSD xmm1, {k}{z}, xmmV, xmm2/m64","VMULSD xmm2/m64, xmmV, {k}{z}, xmm1","vmulsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 59 /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VMULSS xmm1{er}, {k}{z}, xmmV, xmm2","VMULSS xmm2, xmmV, {k}{z}, xmm1{er}","vmulss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F3.0F.W0 59 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VMULSS xmm1, xmmV, xmm2/m32","VMULSS xmm2/m32, xmmV, xmm1","vmulss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 59 /r","V","V","AVX","","w,r,r","","" +"VMULSS xmm1, {k}{z}, xmmV, xmm2/m32","VMULSS xmm2/m32, xmmV, {k}{z}, xmm1","vmulss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 59 /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VMWRITE r32, r/m32","VMWRITE r/m32, r32","vmwrite r/m32, r32","0F 79 /r","V","N.S.","VTX","","r,r","","" +"VMWRITE r64, r/m64","VMWRITE r/m64, r64","vmwrite r/m64, r64","0F 79 /r","N.S.","V","VTX","default64","r,r","","" +"VMXOFF","VMXOFF","vmxoff","0F 01 C4","V","V","VTX","","","","" +"VMXON m64","VMXON m64","vmxon m64","F3 0F C7 /6","V","V","VTX","modrm_memonly","r","","" +"VORPD xmm1, xmmV, xmm2/m128","VORPD xmm2/m128, xmmV, xmm1","vorpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 56 /r","V","V","AVX","","w,r,r","","" +"VORPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VORPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vorpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 56 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VORPD ymm1, ymmV, ymm2/m256","VORPD ymm2/m256, ymmV, ymm1","vorpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 56 /r","V","V","AVX","","w,r,r","","" +"VORPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VORPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vorpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 56 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VORPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VORPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vorpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 56 /r","V","V","AVX512DQ","bscale8,scale64","w,r,r,r","","" +"VORPS xmm1, xmmV, xmm2/m128","VORPS xmm2/m128, xmmV, xmm1","vorps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 56 /r","V","V","AVX","","w,r,r","","" +"VORPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VORPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vorps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 56 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VORPS ymm1, ymmV, ymm2/m256","VORPS ymm2/m256, ymmV, ymm1","vorps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 56 /r","V","V","AVX","","w,r,r","","" +"VORPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VORPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vorps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 56 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VORPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VORPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vorps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 56 /r","V","V","AVX512DQ","bscale4,scale64","w,r,r,r","","" +"VP4DPWSSD zmm1, {k}{z}, zmmV+3, m128","VP4DPWSSD m128, zmmV+3, {k}{z}, zmm1","vp4dpwssd m128, zmmV+3, {k}{z}, zmm1","EVEX.DDS.512.F2.0F38.W0 52 /r","V","V","AVX512_4VNNIW","modrm_memonly,scale16","rw,r,r,r","","" +"VP4DPWSSDS zmm1, {k}{z}, zmmV+3, m128","VP4DPWSSDS m128, zmmV+3, {k}{z}, zmm1","vp4dpwssds m128, zmmV+3, {k}{z}, zmm1","EVEX.DDS.512.F2.0F38.W0 53 /r","V","V","AVX512_4VNNIW","modrm_memonly,scale16","rw,r,r,r","","" +"VPABSB xmm1, xmm2/m128","VPABSB xmm2/m128, xmm1","vpabsb xmm2/m128, xmm1","VEX.128.66.0F38.WIG 1C /r","V","V","AVX","","w,r","","" +"VPABSB xmm1, {k}{z}, xmm2/m128","VPABSB xmm2/m128, {k}{z}, xmm1","vpabsb xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 1C /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPABSB ymm1, ymm2/m256","VPABSB ymm2/m256, ymm1","vpabsb ymm2/m256, ymm1","VEX.256.66.0F38.WIG 1C /r","V","V","AVX2","","w,r","","" +"VPABSB ymm1, {k}{z}, ymm2/m256","VPABSB ymm2/m256, {k}{z}, ymm1","vpabsb ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 1C /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r","","" +"VPABSB zmm1, {k}{z}, zmm2/m512","VPABSB zmm2/m512, {k}{z}, zmm1","vpabsb zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 1C /r","V","V","AVX512BW","scale64","w,r,r","","" +"VPABSD xmm1, xmm2/m128","VPABSD xmm2/m128, xmm1","vpabsd xmm2/m128, xmm1","VEX.128.66.0F38.WIG 1E /r","V","V","AVX","","w,r","","" +"VPABSD xmm1, {k}{z}, xmm2/m128/m32bcst","VPABSD xmm2/m128/m32bcst, {k}{z}, xmm1","vpabsd xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W0 1E /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VPABSD ymm1, ymm2/m256","VPABSD ymm2/m256, ymm1","vpabsd ymm2/m256, ymm1","VEX.256.66.0F38.WIG 1E /r","V","V","AVX2","","w,r","","" +"VPABSD ymm1, {k}{z}, ymm2/m256/m32bcst","VPABSD ymm2/m256/m32bcst, {k}{z}, ymm1","vpabsd ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W0 1E /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VPABSD zmm1, {k}{z}, zmm2/m512/m32bcst","VPABSD zmm2/m512/m32bcst, {k}{z}, zmm1","vpabsd zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 1E /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VPABSQ xmm1, {k}{z}, xmm2/m128/m64bcst","VPABSQ xmm2/m128/m64bcst, {k}{z}, xmm1","vpabsq xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W1 1F /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","","" +"VPABSQ ymm1, {k}{z}, ymm2/m256/m64bcst","VPABSQ ymm2/m256/m64bcst, {k}{z}, ymm1","vpabsq ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W1 1F /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","","" +"VPABSQ zmm1, {k}{z}, zmm2/m512/m64bcst","VPABSQ zmm2/m512/m64bcst, {k}{z}, zmm1","vpabsq zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 1F /r","V","V","AVX512F","bscale8,scale64","w,r,r","","" +"VPABSW xmm1, xmm2/m128","VPABSW xmm2/m128, xmm1","vpabsw xmm2/m128, xmm1","VEX.128.66.0F38.WIG 1D /r","V","V","AVX","","w,r","","" +"VPABSW xmm1, {k}{z}, xmm2/m128","VPABSW xmm2/m128, {k}{z}, xmm1","vpabsw xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 1D /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPABSW ymm1, ymm2/m256","VPABSW ymm2/m256, ymm1","vpabsw ymm2/m256, ymm1","VEX.256.66.0F38.WIG 1D /r","V","V","AVX2","","w,r","","" +"VPABSW ymm1, {k}{z}, ymm2/m256","VPABSW ymm2/m256, {k}{z}, ymm1","vpabsw ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 1D /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r","","" +"VPABSW zmm1, {k}{z}, zmm2/m512","VPABSW zmm2/m512, {k}{z}, zmm1","vpabsw zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 1D /r","V","V","AVX512BW","scale64","w,r,r","","" +"VPACKSSDW xmm1, xmmV, xmm2/m128","VPACKSSDW xmm2/m128, xmmV, xmm1","vpackssdw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 6B /r","V","V","AVX","","w,r,r","","" +"VPACKSSDW xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPACKSSDW xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpackssdw xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 6B /r","V","V","AVX512BW+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPACKSSDW ymm1, ymmV, ymm2/m256","VPACKSSDW ymm2/m256, ymmV, ymm1","vpackssdw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 6B /r","V","V","AVX2","","w,r,r","","" +"VPACKSSDW ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPACKSSDW ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpackssdw ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 6B /r","V","V","AVX512BW+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPACKSSDW zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPACKSSDW zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpackssdw zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 6B /r","V","V","AVX512BW","bscale4,scale64","w,r,r,r","","" +"VPACKSSWB xmm1, xmmV, xmm2/m128","VPACKSSWB xmm2/m128, xmmV, xmm1","vpacksswb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 63 /r","V","V","AVX","","w,r,r","","" +"VPACKSSWB xmm1, {k}{z}, xmmV, xmm2/m128","VPACKSSWB xmm2/m128, xmmV, {k}{z}, xmm1","vpacksswb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG 63 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPACKSSWB ymm1, ymmV, ymm2/m256","VPACKSSWB ymm2/m256, ymmV, ymm1","vpacksswb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 63 /r","V","V","AVX2","","w,r,r","","" +"VPACKSSWB ymm1, {k}{z}, ymmV, ymm2/m256","VPACKSSWB ymm2/m256, ymmV, {k}{z}, ymm1","vpacksswb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG 63 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPACKSSWB zmm1, {k}{z}, zmmV, zmm2/m512","VPACKSSWB zmm2/m512, zmmV, {k}{z}, zmm1","vpacksswb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG 63 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPACKUSDW xmm1, xmmV, xmm2/m128","VPACKUSDW xmm2/m128, xmmV, xmm1","vpackusdw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 2B /r","V","V","AVX","","w,r,r","","" +"VPACKUSDW xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPACKUSDW xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpackusdw xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 2B /r","V","V","AVX512BW+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPACKUSDW ymm1, ymmV, ymm2/m256","VPACKUSDW ymm2/m256, ymmV, ymm1","vpackusdw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 2B /r","V","V","AVX2","","w,r,r","","" +"VPACKUSDW ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPACKUSDW ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpackusdw ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 2B /r","V","V","AVX512BW+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPACKUSDW zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPACKUSDW zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpackusdw zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 2B /r","V","V","AVX512BW","bscale4,scale64","w,r,r,r","","" +"VPACKUSWB xmm1, xmmV, xmm2/m128","VPACKUSWB xmm2/m128, xmmV, xmm1","vpackuswb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 67 /r","V","V","AVX","","w,r,r","","" +"VPACKUSWB xmm1, {k}{z}, xmmV, xmm2/m128","VPACKUSWB xmm2/m128, xmmV, {k}{z}, xmm1","vpackuswb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG 67 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPACKUSWB ymm1, ymmV, ymm2/m256","VPACKUSWB ymm2/m256, ymmV, ymm1","vpackuswb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 67 /r","V","V","AVX2","","w,r,r","","" +"VPACKUSWB ymm1, {k}{z}, ymmV, ymm2/m256","VPACKUSWB ymm2/m256, ymmV, {k}{z}, ymm1","vpackuswb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG 67 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPACKUSWB zmm1, {k}{z}, zmmV, zmm2/m512","VPACKUSWB zmm2/m512, zmmV, {k}{z}, zmm1","vpackuswb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG 67 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPADDB xmm1, xmmV, xmm2/m128","VPADDB xmm2/m128, xmmV, xmm1","vpaddb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG FC /r","V","V","AVX","","w,r,r","","" +"VPADDB xmm1, {k}{z}, xmmV, xmm2/m128","VPADDB xmm2/m128, xmmV, {k}{z}, xmm1","vpaddb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG FC /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPADDB ymm1, ymmV, ymm2/m256","VPADDB ymm2/m256, ymmV, ymm1","vpaddb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG FC /r","V","V","AVX2","","w,r,r","","" +"VPADDB ymm1, {k}{z}, ymmV, ymm2/m256","VPADDB ymm2/m256, ymmV, {k}{z}, ymm1","vpaddb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG FC /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPADDB zmm1, {k}{z}, zmmV, zmm2/m512","VPADDB zmm2/m512, zmmV, {k}{z}, zmm1","vpaddb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG FC /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPADDD xmm1, xmmV, xmm2/m128","VPADDD xmm2/m128, xmmV, xmm1","vpaddd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG FE /r","V","V","AVX","","w,r,r","","" +"VPADDD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPADDD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpaddd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 FE /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPADDD ymm1, ymmV, ymm2/m256","VPADDD ymm2/m256, ymmV, ymm1","vpaddd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG FE /r","V","V","AVX2","","w,r,r","","" +"VPADDD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPADDD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpaddd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 FE /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPADDD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPADDD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpaddd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 FE /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPADDQ xmm1, xmmV, xmm2/m128","VPADDQ xmm2/m128, xmmV, xmm1","vpaddq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG D4 /r","V","V","AVX","","w,r,r","","" +"VPADDQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPADDQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpaddq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 D4 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPADDQ ymm1, ymmV, ymm2/m256","VPADDQ ymm2/m256, ymmV, ymm1","vpaddq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG D4 /r","V","V","AVX2","","w,r,r","","" +"VPADDQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPADDQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpaddq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 D4 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPADDQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPADDQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpaddq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 D4 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPADDSB xmm1, xmmV, xmm2/m128","VPADDSB xmm2/m128, xmmV, xmm1","vpaddsb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG EC /r","V","V","AVX","","w,r,r","","" +"VPADDSB xmm1, {k}{z}, xmmV, xmm2/m128","VPADDSB xmm2/m128, xmmV, {k}{z}, xmm1","vpaddsb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG EC /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPADDSB ymm1, ymmV, ymm2/m256","VPADDSB ymm2/m256, ymmV, ymm1","vpaddsb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG EC /r","V","V","AVX2","","w,r,r","","" +"VPADDSB ymm1, {k}{z}, ymmV, ymm2/m256","VPADDSB ymm2/m256, ymmV, {k}{z}, ymm1","vpaddsb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG EC /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPADDSB zmm1, {k}{z}, zmmV, zmm2/m512","VPADDSB zmm2/m512, zmmV, {k}{z}, zmm1","vpaddsb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG EC /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPADDSW xmm1, xmmV, xmm2/m128","VPADDSW xmm2/m128, xmmV, xmm1","vpaddsw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG ED /r","V","V","AVX","","w,r,r","","" +"VPADDSW xmm1, {k}{z}, xmmV, xmm2/m128","VPADDSW xmm2/m128, xmmV, {k}{z}, xmm1","vpaddsw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG ED /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPADDSW ymm1, ymmV, ymm2/m256","VPADDSW ymm2/m256, ymmV, ymm1","vpaddsw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG ED /r","V","V","AVX2","","w,r,r","","" +"VPADDSW ymm1, {k}{z}, ymmV, ymm2/m256","VPADDSW ymm2/m256, ymmV, {k}{z}, ymm1","vpaddsw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG ED /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPADDSW zmm1, {k}{z}, zmmV, zmm2/m512","VPADDSW zmm2/m512, zmmV, {k}{z}, zmm1","vpaddsw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG ED /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPADDUSB xmm1, xmmV, xmm2/m128","VPADDUSB xmm2/m128, xmmV, xmm1","vpaddusb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG DC /r","V","V","AVX","","w,r,r","","" +"VPADDUSB xmm1, {k}{z}, xmmV, xmm2/m128","VPADDUSB xmm2/m128, xmmV, {k}{z}, xmm1","vpaddusb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG DC /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPADDUSB ymm1, ymmV, ymm2/m256","VPADDUSB ymm2/m256, ymmV, ymm1","vpaddusb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG DC /r","V","V","AVX2","","w,r,r","","" +"VPADDUSB ymm1, {k}{z}, ymmV, ymm2/m256","VPADDUSB ymm2/m256, ymmV, {k}{z}, ymm1","vpaddusb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG DC /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPADDUSB zmm1, {k}{z}, zmmV, zmm2/m512","VPADDUSB zmm2/m512, zmmV, {k}{z}, zmm1","vpaddusb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG DC /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPADDUSW xmm1, xmmV, xmm2/m128","VPADDUSW xmm2/m128, xmmV, xmm1","vpaddusw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG DD /r","V","V","AVX","","w,r,r","","" +"VPADDUSW xmm1, {k}{z}, xmmV, xmm2/m128","VPADDUSW xmm2/m128, xmmV, {k}{z}, xmm1","vpaddusw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG DD /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPADDUSW ymm1, ymmV, ymm2/m256","VPADDUSW ymm2/m256, ymmV, ymm1","vpaddusw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG DD /r","V","V","AVX2","","w,r,r","","" +"VPADDUSW ymm1, {k}{z}, ymmV, ymm2/m256","VPADDUSW ymm2/m256, ymmV, {k}{z}, ymm1","vpaddusw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG DD /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPADDUSW zmm1, {k}{z}, zmmV, zmm2/m512","VPADDUSW zmm2/m512, zmmV, {k}{z}, zmm1","vpaddusw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG DD /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPADDW xmm1, xmmV, xmm2/m128","VPADDW xmm2/m128, xmmV, xmm1","vpaddw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG FD /r","V","V","AVX","","w,r,r","","" +"VPADDW xmm1, {k}{z}, xmmV, xmm2/m128","VPADDW xmm2/m128, xmmV, {k}{z}, xmm1","vpaddw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG FD /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPADDW ymm1, ymmV, ymm2/m256","VPADDW ymm2/m256, ymmV, ymm1","vpaddw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG FD /r","V","V","AVX2","","w,r,r","","" +"VPADDW ymm1, {k}{z}, ymmV, ymm2/m256","VPADDW ymm2/m256, ymmV, {k}{z}, ymm1","vpaddw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG FD /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPADDW zmm1, {k}{z}, zmmV, zmm2/m512","VPADDW zmm2/m512, zmmV, {k}{z}, zmm1","vpaddw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG FD /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPALIGNR xmm1, xmmV, xmm2/m128, imm8u","VPALIGNR imm8u, xmm2/m128, xmmV, xmm1","vpalignr imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 0F /r ib","V","V","AVX","","w,r,r,r","","" +"VPALIGNR xmm1, {k}{z}, xmmV, xmm2/m128, imm8u","VPALIGNR imm8u, xmm2/m128, xmmV, {k}{z}, xmm1","vpalignr imm8u, xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.WIG 0F /r ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r,r","","" +"VPALIGNR ymm1, ymmV, ymm2/m256, imm8u","VPALIGNR imm8u, ymm2/m256, ymmV, ymm1","vpalignr imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.WIG 0F /r ib","V","V","AVX2","","w,r,r,r","","" +"VPALIGNR ymm1, {k}{z}, ymmV, ymm2/m256, imm8u","VPALIGNR imm8u, ymm2/m256, ymmV, {k}{z}, ymm1","vpalignr imm8u, ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.WIG 0F /r ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r,r","","" +"VPALIGNR zmm1, {k}{z}, zmmV, zmm2/m512, imm8u","VPALIGNR imm8u, zmm2/m512, zmmV, {k}{z}, zmm1","vpalignr imm8u, zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.WIG 0F /r ib","V","V","AVX512BW","scale64","w,r,r,r,r","","" +"VPAND xmm1, xmmV, xmm2/m128","VPAND xmm2/m128, xmmV, xmm1","vpand xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG DB /r","V","V","AVX","","w,r,r","","" +"VPAND ymm1, ymmV, ymm2/m256","VPAND ymm2/m256, ymmV, ymm1","vpand ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG DB /r","V","V","AVX2","","w,r,r","","" +"VPANDD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPANDD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpandd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 DB /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPANDD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPANDD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpandd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 DB /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPANDD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPANDD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpandd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 DB /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPANDN xmm1, xmmV, xmm2/m128","VPANDN xmm2/m128, xmmV, xmm1","vpandn xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG DF /r","V","V","AVX","","w,r,r","","" +"VPANDN ymm1, ymmV, ymm2/m256","VPANDN ymm2/m256, ymmV, ymm1","vpandn ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG DF /r","V","V","AVX2","","w,r,r","","" +"VPANDND xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPANDND xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpandnd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 DF /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPANDND ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPANDND ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpandnd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 DF /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPANDND zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPANDND zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpandnd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 DF /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPANDNQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPANDNQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpandnq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 DF /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPANDNQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPANDNQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpandnq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 DF /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPANDNQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPANDNQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpandnq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 DF /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPANDQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPANDQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpandq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 DB /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPANDQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPANDQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpandq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 DB /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPANDQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPANDQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpandq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 DB /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPAVGB xmm1, xmmV, xmm2/m128","VPAVGB xmm2/m128, xmmV, xmm1","vpavgb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG E0 /r","V","V","AVX","","w,r,r","","" +"VPAVGB xmm1, {k}{z}, xmmV, xmm2/m128","VPAVGB xmm2/m128, xmmV, {k}{z}, xmm1","vpavgb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG E0 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPAVGB ymm1, ymmV, ymm2/m256","VPAVGB ymm2/m256, ymmV, ymm1","vpavgb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG E0 /r","V","V","AVX2","","w,r,r","","" +"VPAVGB ymm1, {k}{z}, ymmV, ymm2/m256","VPAVGB ymm2/m256, ymmV, {k}{z}, ymm1","vpavgb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG E0 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPAVGB zmm1, {k}{z}, zmmV, zmm2/m512","VPAVGB zmm2/m512, zmmV, {k}{z}, zmm1","vpavgb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG E0 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPAVGW xmm1, xmmV, xmm2/m128","VPAVGW xmm2/m128, xmmV, xmm1","vpavgw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG E3 /r","V","V","AVX","","w,r,r","","" +"VPAVGW xmm1, {k}{z}, xmmV, xmm2/m128","VPAVGW xmm2/m128, xmmV, {k}{z}, xmm1","vpavgw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG E3 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPAVGW ymm1, ymmV, ymm2/m256","VPAVGW ymm2/m256, ymmV, ymm1","vpavgw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG E3 /r","V","V","AVX2","","w,r,r","","" +"VPAVGW ymm1, {k}{z}, ymmV, ymm2/m256","VPAVGW ymm2/m256, ymmV, {k}{z}, ymm1","vpavgw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG E3 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPAVGW zmm1, {k}{z}, zmmV, zmm2/m512","VPAVGW zmm2/m512, zmmV, {k}{z}, zmm1","vpavgw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG E3 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPBLENDD xmm1, xmmV, xmm2/m128, imm8u","VPBLENDD imm8u, xmm2/m128, xmmV, xmm1","vpblendd imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 02 /r ib","V","V","AVX2","","w,r,r,r","","" +"VPBLENDD ymm1, ymmV, ymm2/m256, imm8u","VPBLENDD imm8u, ymm2/m256, ymmV, ymm1","vpblendd imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 02 /r ib","V","V","AVX2","","w,r,r,r","","" +"VPBLENDMB xmm1, {k}{z}, xmmV, xmm2/m128","VPBLENDMB xmm2/m128, xmmV, {k}{z}, xmm1","vpblendmb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 66 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPBLENDMB ymm1, {k}{z}, ymmV, ymm2/m256","VPBLENDMB ymm2/m256, ymmV, {k}{z}, ymm1","vpblendmb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 66 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPBLENDMB zmm1, {k}{z}, zmmV, zmm2/m512","VPBLENDMB zmm2/m512, zmmV, {k}{z}, zmm1","vpblendmb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 66 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPBLENDMD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPBLENDMD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpblendmd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 64 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPBLENDMD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPBLENDMD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpblendmd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 64 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPBLENDMD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPBLENDMD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpblendmd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 64 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPBLENDMQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPBLENDMQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpblendmq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 64 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPBLENDMQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPBLENDMQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpblendmq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 64 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPBLENDMQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPBLENDMQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpblendmq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 64 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPBLENDMW xmm1, {k}{z}, xmmV, xmm2/m128","VPBLENDMW xmm2/m128, xmmV, {k}{z}, xmm1","vpblendmw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 66 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPBLENDMW ymm1, {k}{z}, ymmV, ymm2/m256","VPBLENDMW ymm2/m256, ymmV, {k}{z}, ymm1","vpblendmw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 66 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPBLENDMW zmm1, {k}{z}, zmmV, zmm2/m512","VPBLENDMW zmm2/m512, zmmV, {k}{z}, zmm1","vpblendmw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 66 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPBLENDVB xmm1, xmmV, xmm2/m128, xmmIH","VPBLENDVB xmmIH, xmm2/m128, xmmV, xmm1","vpblendvb xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 4C /r /is4","V","V","AVX","","w,r,r,r","","" +"VPBLENDVB ymm1, ymmV, ymm2/m256, ymmIH","VPBLENDVB ymmIH, ymm2/m256, ymmV, ymm1","vpblendvb ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 4C /r /is4","V","V","AVX2","","w,r,r,r","","" +"VPBLENDW xmm1, xmmV, xmm2/m128, imm8u","VPBLENDW imm8u, xmm2/m128, xmmV, xmm1","vpblendw imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 0E /r ib","V","V","AVX","","w,r,r,r","","" +"VPBLENDW ymm1, ymmV, ymm2/m256, imm8u","VPBLENDW imm8u, ymm2/m256, ymmV, ymm1","vpblendw imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.WIG 0E /r ib","V","V","AVX2","","w,r,r,r","","" +"VPBROADCASTB xmm1, {k}{z}, rmr32","VPBROADCASTB rmr32, {k}{z}, xmm1","vpbroadcastb rmr32, {k}{z}, xmm1","EVEX.128.66.0F38.W0 7A /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r,r","","" +"VPBROADCASTB ymm1, {k}{z}, rmr32","VPBROADCASTB rmr32, {k}{z}, ymm1","vpbroadcastb rmr32, {k}{z}, ymm1","EVEX.256.66.0F38.W0 7A /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r,r","","" +"VPBROADCASTB zmm1, {k}{z}, rmr32","VPBROADCASTB rmr32, {k}{z}, zmm1","vpbroadcastb rmr32, {k}{z}, zmm1","EVEX.512.66.0F38.W0 7A /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"VPBROADCASTB xmm1, xmm2/m8","VPBROADCASTB xmm2/m8, xmm1","vpbroadcastb xmm2/m8, xmm1","VEX.128.66.0F38.W0 78 /r","V","V","AVX2","","w,r","","" +"VPBROADCASTB ymm1, xmm2/m8","VPBROADCASTB xmm2/m8, ymm1","vpbroadcastb xmm2/m8, ymm1","VEX.256.66.0F38.W0 78 /r","V","V","AVX2","","w,r","","" +"VPBROADCASTB xmm1, {k}{z}, xmm2/m8","VPBROADCASTB xmm2/m8, {k}{z}, xmm1","vpbroadcastb xmm2/m8, {k}{z}, xmm1","EVEX.128.66.0F38.W0 78 /r","V","V","AVX512BW+AVX512VL","scale1","w,r,r","","" +"VPBROADCASTB ymm1, {k}{z}, xmm2/m8","VPBROADCASTB xmm2/m8, {k}{z}, ymm1","vpbroadcastb xmm2/m8, {k}{z}, ymm1","EVEX.256.66.0F38.W0 78 /r","V","V","AVX512BW+AVX512VL","scale1","w,r,r","","" +"VPBROADCASTB zmm1, {k}{z}, xmm2/m8","VPBROADCASTB xmm2/m8, {k}{z}, zmm1","vpbroadcastb xmm2/m8, {k}{z}, zmm1","EVEX.512.66.0F38.W0 78 /r","V","V","AVX512BW","scale1","w,r,r","","" +"VPBROADCASTD xmm1, {k}{z}, rmr32","VPBROADCASTD rmr32, {k}{z}, xmm1","vpbroadcastd rmr32, {k}{z}, xmm1","EVEX.128.66.0F38.W0 7C /r","V","V","AVX512F+AVX512VL","modrm_regonly","w,r,r","","" +"VPBROADCASTD ymm1, {k}{z}, rmr32","VPBROADCASTD rmr32, {k}{z}, ymm1","vpbroadcastd rmr32, {k}{z}, ymm1","EVEX.256.66.0F38.W0 7C /r","V","V","AVX512F+AVX512VL","modrm_regonly","w,r,r","","" +"VPBROADCASTD zmm1, {k}{z}, rmr32","VPBROADCASTD rmr32, {k}{z}, zmm1","vpbroadcastd rmr32, {k}{z}, zmm1","EVEX.512.66.0F38.W0 7C /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VPBROADCASTD xmm1, xmm2/m32","VPBROADCASTD xmm2/m32, xmm1","vpbroadcastd xmm2/m32, xmm1","VEX.128.66.0F38.W0 58 /r","V","V","AVX2","","w,r","","" +"VPBROADCASTD ymm1, xmm2/m32","VPBROADCASTD xmm2/m32, ymm1","vpbroadcastd xmm2/m32, ymm1","VEX.256.66.0F38.W0 58 /r","V","V","AVX2","","w,r","","" +"VPBROADCASTD xmm1, {k}{z}, xmm2/m32","VPBROADCASTD xmm2/m32, {k}{z}, xmm1","vpbroadcastd xmm2/m32, {k}{z}, xmm1","EVEX.128.66.0F38.W0 58 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPBROADCASTD ymm1, {k}{z}, xmm2/m32","VPBROADCASTD xmm2/m32, {k}{z}, ymm1","vpbroadcastd xmm2/m32, {k}{z}, ymm1","EVEX.256.66.0F38.W0 58 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPBROADCASTD zmm1, {k}{z}, xmm2/m32","VPBROADCASTD xmm2/m32, {k}{z}, zmm1","vpbroadcastd xmm2/m32, {k}{z}, zmm1","EVEX.512.66.0F38.W0 58 /r","V","V","AVX512F","scale4","w,r,r","","" +"VPBROADCASTMB2Q xmm1, k2","VPBROADCASTMB2Q k2, xmm1","vpbroadcastmb2q k2, xmm1","EVEX.128.F3.0F38.W1 2A /r","V","V","AVX512CD+AVX512VL","modrm_regonly","w,r","","" +"VPBROADCASTMB2Q ymm1, k2","VPBROADCASTMB2Q k2, ymm1","vpbroadcastmb2q k2, ymm1","EVEX.256.F3.0F38.W1 2A /r","V","V","AVX512CD+AVX512VL","modrm_regonly","w,r","","" +"VPBROADCASTMB2Q zmm1, k2","VPBROADCASTMB2Q k2, zmm1","vpbroadcastmb2q k2, zmm1","EVEX.512.F3.0F38.W1 2A /r","V","V","AVX512CD","modrm_regonly","w,r","","" +"VPBROADCASTMW2D xmm1, k2","VPBROADCASTMW2D k2, xmm1","vpbroadcastmw2d k2, xmm1","EVEX.128.F3.0F38.W0 3A /r","V","V","AVX512CD+AVX512VL","modrm_regonly","w,r","","" +"VPBROADCASTMW2D ymm1, k2","VPBROADCASTMW2D k2, ymm1","vpbroadcastmw2d k2, ymm1","EVEX.256.F3.0F38.W0 3A /r","V","V","AVX512CD+AVX512VL","modrm_regonly","w,r","","" +"VPBROADCASTMW2D zmm1, k2","VPBROADCASTMW2D k2, zmm1","vpbroadcastmw2d k2, zmm1","EVEX.512.F3.0F38.W0 3A /r","V","V","AVX512CD","modrm_regonly","w,r","","" +"VPBROADCASTQ xmm1, {k}{z}, rmr64","VPBROADCASTQ rmr64, {k}{z}, xmm1","vpbroadcastq rmr64, {k}{z}, xmm1","EVEX.128.66.0F38.W1 7C /r","N.S.","V","AVX512F+AVX512VL","modrm_regonly","w,r,r","","" +"VPBROADCASTQ ymm1, {k}{z}, rmr64","VPBROADCASTQ rmr64, {k}{z}, ymm1","vpbroadcastq rmr64, {k}{z}, ymm1","EVEX.256.66.0F38.W1 7C /r","N.S.","V","AVX512F+AVX512VL","modrm_regonly","w,r,r","","" +"VPBROADCASTQ zmm1, {k}{z}, rmr64","VPBROADCASTQ rmr64, {k}{z}, zmm1","vpbroadcastq rmr64, {k}{z}, zmm1","EVEX.512.66.0F38.W1 7C /r","N.S.","V","AVX512F","modrm_regonly","w,r,r","","" +"VPBROADCASTQ xmm1, xmm2/m64","VPBROADCASTQ xmm2/m64, xmm1","vpbroadcastq xmm2/m64, xmm1","VEX.128.66.0F38.W0 59 /r","V","V","AVX2","","w,r","","" +"VPBROADCASTQ ymm1, xmm2/m64","VPBROADCASTQ xmm2/m64, ymm1","vpbroadcastq xmm2/m64, ymm1","VEX.256.66.0F38.W0 59 /r","V","V","AVX2","","w,r","","" +"VPBROADCASTQ xmm1, {k}{z}, xmm2/m64","VPBROADCASTQ xmm2/m64, {k}{z}, xmm1","vpbroadcastq xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.W1 59 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPBROADCASTQ ymm1, {k}{z}, xmm2/m64","VPBROADCASTQ xmm2/m64, {k}{z}, ymm1","vpbroadcastq xmm2/m64, {k}{z}, ymm1","EVEX.256.66.0F38.W1 59 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPBROADCASTQ zmm1, {k}{z}, xmm2/m64","VPBROADCASTQ xmm2/m64, {k}{z}, zmm1","vpbroadcastq xmm2/m64, {k}{z}, zmm1","EVEX.512.66.0F38.W1 59 /r","V","V","AVX512F","scale8","w,r,r","","" +"VPBROADCASTW xmm1, {k}{z}, rmr32","VPBROADCASTW rmr32, {k}{z}, xmm1","vpbroadcastw rmr32, {k}{z}, xmm1","EVEX.128.66.0F38.W0 7B /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r,r","","" +"VPBROADCASTW ymm1, {k}{z}, rmr32","VPBROADCASTW rmr32, {k}{z}, ymm1","vpbroadcastw rmr32, {k}{z}, ymm1","EVEX.256.66.0F38.W0 7B /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r,r","","" +"VPBROADCASTW zmm1, {k}{z}, rmr32","VPBROADCASTW rmr32, {k}{z}, zmm1","vpbroadcastw rmr32, {k}{z}, zmm1","EVEX.512.66.0F38.W0 7B /r","V","V","AVX512BW","modrm_regonly","w,r,r","","" +"VPBROADCASTW xmm1, xmm2/m16","VPBROADCASTW xmm2/m16, xmm1","vpbroadcastw xmm2/m16, xmm1","VEX.128.66.0F38.W0 79 /r","V","V","AVX2","","w,r","","" +"VPBROADCASTW ymm1, xmm2/m16","VPBROADCASTW xmm2/m16, ymm1","vpbroadcastw xmm2/m16, ymm1","VEX.256.66.0F38.W0 79 /r","V","V","AVX2","","w,r","","" +"VPBROADCASTW xmm1, {k}{z}, xmm2/m16","VPBROADCASTW xmm2/m16, {k}{z}, xmm1","vpbroadcastw xmm2/m16, {k}{z}, xmm1","EVEX.128.66.0F38.W0 79 /r","V","V","AVX512BW+AVX512VL","scale2","w,r,r","","" +"VPBROADCASTW ymm1, {k}{z}, xmm2/m16","VPBROADCASTW xmm2/m16, {k}{z}, ymm1","vpbroadcastw xmm2/m16, {k}{z}, ymm1","EVEX.256.66.0F38.W0 79 /r","V","V","AVX512BW+AVX512VL","scale2","w,r,r","","" +"VPBROADCASTW zmm1, {k}{z}, xmm2/m16","VPBROADCASTW xmm2/m16, {k}{z}, zmm1","vpbroadcastw xmm2/m16, {k}{z}, zmm1","EVEX.512.66.0F38.W0 79 /r","V","V","AVX512BW","scale2","w,r,r","","" +"VPCLMULQDQ xmm1, xmmV, xmm2/m128, imm8u","VPCLMULQDQ imm8u, xmm2/m128, xmmV, xmm1","vpclmulqdq imm8u, xmm2/m128, xmmV, xmm1","EVEX.NDS.128.66.0F3A.WIG 44 /r ib","V","V","VPCLMULQDQ+AVX512VL","scale16","w,r,r,r","","" +"VPCLMULQDQ xmm1, xmmV, xmm2/m128, imm8u","VPCLMULQDQ imm8u, xmm2/m128, xmmV, xmm1","vpclmulqdq imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 44 /r ib","V","V","PCLMULQDQ+AVX","","w,r,r,r","","" +"VPCLMULQDQ ymm1, ymmV, ymm2/m256, imm8u","VPCLMULQDQ imm8u, ymm2/m256, ymmV, ymm1","vpclmulqdq imm8u, ymm2/m256, ymmV, ymm1","EVEX.NDS.256.66.0F3A.WIG 44 /r ib","V","V","VPCLMULQDQ+AVX512VL","scale32","w,r,r,r","","" +"VPCLMULQDQ ymm1, ymmV, ymm2/m256, imm8u","VPCLMULQDQ imm8u, ymm2/m256, ymmV, ymm1","vpclmulqdq imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.WIG 44 /r ib","V","V","VPCLMULQDQ","","w,r,r,r","","" +"VPCLMULQDQ zmm1, zmmV, zmm2/m512, imm8u","VPCLMULQDQ imm8u, zmm2/m512, zmmV, zmm1","vpclmulqdq imm8u, zmm2/m512, zmmV, zmm1","EVEX.NDS.512.66.0F3A.WIG 44 /r ib","V","V","VPCLMULQDQ+AVX512F","scale64","w,r,r,r","","" +"VPCMOV xmm1, xmmV, xmmIH, xmm2/m128","VPCMOV xmm2/m128, xmmIH, xmmV, xmm1","vpcmov xmm2/m128, xmmIH, xmmV, xmm1","XOP.NDS.128.08.W1 A2 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPCMOV xmm1, xmmV, xmm2/m128, xmmIH","VPCMOV xmmIH, xmm2/m128, xmmV, xmm1","vpcmov xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 A2 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPCMOV ymm1, ymmV, ymmIH, ymm2/m256","VPCMOV ymm2/m256, ymmIH, ymmV, ymm1","vpcmov ymm2/m256, ymmIH, ymmV, ymm1","XOP.NDS.256.08.W1 A2 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPCMOV ymm1, ymmV, ymm2/m256, ymmIH","VPCMOV ymmIH, ymm2/m256, ymmV, ymm1","vpcmov ymmIH, ymm2/m256, ymmV, ymm1","XOP.NDS.256.08.W0 A2 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPCMPB k1, {k}, xmmV, xmm2/m128, imm8u","VPCMPB imm8u, xmm2/m128, xmmV, {k}, k1","vpcmpb imm8u, xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F3A.W0 3F /r ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r,r","","" +"VPCMPB k1, {k}, ymmV, ymm2/m256, imm8u","VPCMPB imm8u, ymm2/m256, ymmV, {k}, k1","vpcmpb imm8u, ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F3A.W0 3F /r ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r,r","","" +"VPCMPB k1, {k}, zmmV, zmm2/m512, imm8u","VPCMPB imm8u, zmm2/m512, zmmV, {k}, k1","vpcmpb imm8u, zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F3A.W0 3F /r ib","V","V","AVX512BW","scale64","w,r,r,r,r","","" +"VPCMPD k1, {k}, xmmV, xmm2/m128/m32bcst, imm8u","VPCMPD imm8u, xmm2/m128/m32bcst, xmmV, {k}, k1","vpcmpd imm8u, xmm2/m128/m32bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F3A.W0 1F /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r,r","","" +"VPCMPD k1, {k}, ymmV, ymm2/m256/m32bcst, imm8u","VPCMPD imm8u, ymm2/m256/m32bcst, ymmV, {k}, k1","vpcmpd imm8u, ymm2/m256/m32bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F3A.W0 1F /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VPCMPD k1, {k}, zmmV, zmm2/m512/m32bcst, imm8u","VPCMPD imm8u, zmm2/m512/m32bcst, zmmV, {k}, k1","vpcmpd imm8u, zmm2/m512/m32bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F3A.W0 1F /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r,r","","" +"VPCMPEQB xmm1, xmmV, xmm2/m128","VPCMPEQB xmm2/m128, xmmV, xmm1","vpcmpeqb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 74 /r","V","V","AVX","","w,r,r","","" +"VPCMPEQB k1, {k}, xmmV, xmm2/m128","VPCMPEQB xmm2/m128, xmmV, {k}, k1","vpcmpeqb xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F.WIG 74 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPCMPEQB ymm1, ymmV, ymm2/m256","VPCMPEQB ymm2/m256, ymmV, ymm1","vpcmpeqb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 74 /r","V","V","AVX2","","w,r,r","","" +"VPCMPEQB k1, {k}, ymmV, ymm2/m256","VPCMPEQB ymm2/m256, ymmV, {k}, k1","vpcmpeqb ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F.WIG 74 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPCMPEQB k1, {k}, zmmV, zmm2/m512","VPCMPEQB zmm2/m512, zmmV, {k}, k1","vpcmpeqb zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F.WIG 74 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPCMPEQD xmm1, xmmV, xmm2/m128","VPCMPEQD xmm2/m128, xmmV, xmm1","vpcmpeqd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 76 /r","V","V","AVX","","w,r,r","","" +"VPCMPEQD k1, {k}, xmmV, xmm2/m128/m32bcst","VPCMPEQD xmm2/m128/m32bcst, xmmV, {k}, k1","vpcmpeqd xmm2/m128/m32bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F.W0 76 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPCMPEQD ymm1, ymmV, ymm2/m256","VPCMPEQD ymm2/m256, ymmV, ymm1","vpcmpeqd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 76 /r","V","V","AVX2","","w,r,r","","" +"VPCMPEQD k1, {k}, ymmV, ymm2/m256/m32bcst","VPCMPEQD ymm2/m256/m32bcst, ymmV, {k}, k1","vpcmpeqd ymm2/m256/m32bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F.W0 76 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPCMPEQD k1, {k}, zmmV, zmm2/m512/m32bcst","VPCMPEQD zmm2/m512/m32bcst, zmmV, {k}, k1","vpcmpeqd zmm2/m512/m32bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F.W0 76 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPCMPEQQ xmm1, xmmV, xmm2/m128","VPCMPEQQ xmm2/m128, xmmV, xmm1","vpcmpeqq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 29 /r","V","V","AVX","","w,r,r","","" +"VPCMPEQQ k1, {k}, xmmV, xmm2/m128/m64bcst","VPCMPEQQ xmm2/m128/m64bcst, xmmV, {k}, k1","vpcmpeqq xmm2/m128/m64bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F38.W1 29 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPCMPEQQ ymm1, ymmV, ymm2/m256","VPCMPEQQ ymm2/m256, ymmV, ymm1","vpcmpeqq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 29 /r","V","V","AVX2","","w,r,r","","" +"VPCMPEQQ k1, {k}, ymmV, ymm2/m256/m64bcst","VPCMPEQQ ymm2/m256/m64bcst, ymmV, {k}, k1","vpcmpeqq ymm2/m256/m64bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F38.W1 29 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPCMPEQQ k1, {k}, zmmV, zmm2/m512/m64bcst","VPCMPEQQ zmm2/m512/m64bcst, zmmV, {k}, k1","vpcmpeqq zmm2/m512/m64bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F38.W1 29 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPCMPEQW xmm1, xmmV, xmm2/m128","VPCMPEQW xmm2/m128, xmmV, xmm1","vpcmpeqw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 75 /r","V","V","AVX","","w,r,r","","" +"VPCMPEQW k1, {k}, xmmV, xmm2/m128","VPCMPEQW xmm2/m128, xmmV, {k}, k1","vpcmpeqw xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F.WIG 75 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPCMPEQW ymm1, ymmV, ymm2/m256","VPCMPEQW ymm2/m256, ymmV, ymm1","vpcmpeqw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 75 /r","V","V","AVX2","","w,r,r","","" +"VPCMPEQW k1, {k}, ymmV, ymm2/m256","VPCMPEQW ymm2/m256, ymmV, {k}, k1","vpcmpeqw ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F.WIG 75 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPCMPEQW k1, {k}, zmmV, zmm2/m512","VPCMPEQW zmm2/m512, zmmV, {k}, k1","vpcmpeqw zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F.WIG 75 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPCMPESTRI xmm1, xmm2/m128, imm8u","VPCMPESTRI imm8u, xmm2/m128, xmm1","vpcmpestri imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.WIG 61 /r ib","V","V","AVX","","r,r,r","","" +"VPCMPESTRM xmm1, xmm2/m128, imm8u","VPCMPESTRM imm8u, xmm2/m128, xmm1","vpcmpestrm imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.WIG 60 /r ib","V","V","AVX","","r,r,r","","" +"VPCMPGTB xmm1, xmmV, xmm2/m128","VPCMPGTB xmm2/m128, xmmV, xmm1","vpcmpgtb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 64 /r","V","V","AVX","","w,r,r","","" +"VPCMPGTB k1, {k}, xmmV, xmm2/m128","VPCMPGTB xmm2/m128, xmmV, {k}, k1","vpcmpgtb xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F.WIG 64 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPCMPGTB ymm1, ymmV, ymm2/m256","VPCMPGTB ymm2/m256, ymmV, ymm1","vpcmpgtb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 64 /r","V","V","AVX2","","w,r,r","","" +"VPCMPGTB k1, {k}, ymmV, ymm2/m256","VPCMPGTB ymm2/m256, ymmV, {k}, k1","vpcmpgtb ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F.WIG 64 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPCMPGTB k1, {k}, zmmV, zmm2/m512","VPCMPGTB zmm2/m512, zmmV, {k}, k1","vpcmpgtb zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F.WIG 64 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPCMPGTD xmm1, xmmV, xmm2/m128","VPCMPGTD xmm2/m128, xmmV, xmm1","vpcmpgtd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 66 /r","V","V","AVX","","w,r,r","","" +"VPCMPGTD k1, {k}, xmmV, xmm2/m128/m32bcst","VPCMPGTD xmm2/m128/m32bcst, xmmV, {k}, k1","vpcmpgtd xmm2/m128/m32bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F.W0 66 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPCMPGTD ymm1, ymmV, ymm2/m256","VPCMPGTD ymm2/m256, ymmV, ymm1","vpcmpgtd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 66 /r","V","V","AVX2","","w,r,r","","" +"VPCMPGTD k1, {k}, ymmV, ymm2/m256/m32bcst","VPCMPGTD ymm2/m256/m32bcst, ymmV, {k}, k1","vpcmpgtd ymm2/m256/m32bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F.W0 66 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPCMPGTD k1, {k}, zmmV, zmm2/m512/m32bcst","VPCMPGTD zmm2/m512/m32bcst, zmmV, {k}, k1","vpcmpgtd zmm2/m512/m32bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F.W0 66 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPCMPGTQ xmm1, xmmV, xmm2/m128","VPCMPGTQ xmm2/m128, xmmV, xmm1","vpcmpgtq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 37 /r","V","V","AVX","","w,r,r","","" +"VPCMPGTQ k1, {k}, xmmV, xmm2/m128/m64bcst","VPCMPGTQ xmm2/m128/m64bcst, xmmV, {k}, k1","vpcmpgtq xmm2/m128/m64bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F38.W1 37 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPCMPGTQ ymm1, ymmV, ymm2/m256","VPCMPGTQ ymm2/m256, ymmV, ymm1","vpcmpgtq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 37 /r","V","V","AVX2","","w,r,r","","" +"VPCMPGTQ k1, {k}, ymmV, ymm2/m256/m64bcst","VPCMPGTQ ymm2/m256/m64bcst, ymmV, {k}, k1","vpcmpgtq ymm2/m256/m64bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F38.W1 37 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPCMPGTQ k1, {k}, zmmV, zmm2/m512/m64bcst","VPCMPGTQ zmm2/m512/m64bcst, zmmV, {k}, k1","vpcmpgtq zmm2/m512/m64bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F38.W1 37 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPCMPGTW xmm1, xmmV, xmm2/m128","VPCMPGTW xmm2/m128, xmmV, xmm1","vpcmpgtw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 65 /r","V","V","AVX","","w,r,r","","" +"VPCMPGTW k1, {k}, xmmV, xmm2/m128","VPCMPGTW xmm2/m128, xmmV, {k}, k1","vpcmpgtw xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F.WIG 65 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPCMPGTW ymm1, ymmV, ymm2/m256","VPCMPGTW ymm2/m256, ymmV, ymm1","vpcmpgtw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 65 /r","V","V","AVX2","","w,r,r","","" +"VPCMPGTW k1, {k}, ymmV, ymm2/m256","VPCMPGTW ymm2/m256, ymmV, {k}, k1","vpcmpgtw ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F.WIG 65 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPCMPGTW k1, {k}, zmmV, zmm2/m512","VPCMPGTW zmm2/m512, zmmV, {k}, k1","vpcmpgtw zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F.WIG 65 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPCMPISTRI xmm1, xmm2/m128, imm8u","VPCMPISTRI imm8u, xmm2/m128, xmm1","vpcmpistri imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.WIG 63 /r ib","V","V","AVX","","r,r,r","","" +"VPCMPISTRM xmm1, xmm2/m128, imm8u","VPCMPISTRM imm8u, xmm2/m128, xmm1","vpcmpistrm imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.WIG 62 /r ib","V","V","AVX","","r,r,r","","" +"VPCMPQ k1, {k}, xmmV, xmm2/m128/m64bcst, imm8u","VPCMPQ imm8u, xmm2/m128/m64bcst, xmmV, {k}, k1","vpcmpq imm8u, xmm2/m128/m64bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F3A.W1 1F /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VPCMPQ k1, {k}, ymmV, ymm2/m256/m64bcst, imm8u","VPCMPQ imm8u, ymm2/m256/m64bcst, ymmV, {k}, k1","vpcmpq imm8u, ymm2/m256/m64bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F3A.W1 1F /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VPCMPQ k1, {k}, zmmV, zmm2/m512/m64bcst, imm8u","VPCMPQ imm8u, zmm2/m512/m64bcst, zmmV, {k}, k1","vpcmpq imm8u, zmm2/m512/m64bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F3A.W1 1F /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VPCMPUB k1, {k}, xmmV, xmm2/m128, imm8u","VPCMPUB imm8u, xmm2/m128, xmmV, {k}, k1","vpcmpub imm8u, xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F3A.W0 3E /r ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r,r","","" +"VPCMPUB k1, {k}, ymmV, ymm2/m256, imm8u","VPCMPUB imm8u, ymm2/m256, ymmV, {k}, k1","vpcmpub imm8u, ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F3A.W0 3E /r ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r,r","","" +"VPCMPUB k1, {k}, zmmV, zmm2/m512, imm8u","VPCMPUB imm8u, zmm2/m512, zmmV, {k}, k1","vpcmpub imm8u, zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F3A.W0 3E /r ib","V","V","AVX512BW","scale64","w,r,r,r,r","","" +"VPCMPUD k1, {k}, xmmV, xmm2/m128/m32bcst, imm8u","VPCMPUD imm8u, xmm2/m128/m32bcst, xmmV, {k}, k1","vpcmpud imm8u, xmm2/m128/m32bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F3A.W0 1E /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r,r","","" +"VPCMPUD k1, {k}, ymmV, ymm2/m256/m32bcst, imm8u","VPCMPUD imm8u, ymm2/m256/m32bcst, ymmV, {k}, k1","vpcmpud imm8u, ymm2/m256/m32bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F3A.W0 1E /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VPCMPUD k1, {k}, zmmV, zmm2/m512/m32bcst, imm8u","VPCMPUD imm8u, zmm2/m512/m32bcst, zmmV, {k}, k1","vpcmpud imm8u, zmm2/m512/m32bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F3A.W0 1E /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r,r","","" +"VPCMPUQ k1, {k}, xmmV, xmm2/m128/m64bcst, imm8u","VPCMPUQ imm8u, xmm2/m128/m64bcst, xmmV, {k}, k1","vpcmpuq imm8u, xmm2/m128/m64bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F3A.W1 1E /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VPCMPUQ k1, {k}, ymmV, ymm2/m256/m64bcst, imm8u","VPCMPUQ imm8u, ymm2/m256/m64bcst, ymmV, {k}, k1","vpcmpuq imm8u, ymm2/m256/m64bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F3A.W1 1E /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VPCMPUQ k1, {k}, zmmV, zmm2/m512/m64bcst, imm8u","VPCMPUQ imm8u, zmm2/m512/m64bcst, zmmV, {k}, k1","vpcmpuq imm8u, zmm2/m512/m64bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F3A.W1 1E /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VPCMPUW k1, {k}, xmmV, xmm2/m128, imm8u","VPCMPUW imm8u, xmm2/m128, xmmV, {k}, k1","vpcmpuw imm8u, xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F3A.W1 3E /r ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r,r","","" +"VPCMPUW k1, {k}, ymmV, ymm2/m256, imm8u","VPCMPUW imm8u, ymm2/m256, ymmV, {k}, k1","vpcmpuw imm8u, ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F3A.W1 3E /r ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r,r","","" +"VPCMPUW k1, {k}, zmmV, zmm2/m512, imm8u","VPCMPUW imm8u, zmm2/m512, zmmV, {k}, k1","vpcmpuw imm8u, zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F3A.W1 3E /r ib","V","V","AVX512BW","scale64","w,r,r,r,r","","" +"VPCMPW k1, {k}, xmmV, xmm2/m128, imm8u","VPCMPW imm8u, xmm2/m128, xmmV, {k}, k1","vpcmpw imm8u, xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F3A.W1 3F /r ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r,r","","" +"VPCMPW k1, {k}, ymmV, ymm2/m256, imm8u","VPCMPW imm8u, ymm2/m256, ymmV, {k}, k1","vpcmpw imm8u, ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F3A.W1 3F /r ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r,r","","" +"VPCMPW k1, {k}, zmmV, zmm2/m512, imm8u","VPCMPW imm8u, zmm2/m512, zmmV, {k}, k1","vpcmpw imm8u, zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F3A.W1 3F /r ib","V","V","AVX512BW","scale64","w,r,r,r,r","","" +"VPCOMB xmm1, xmmV, xmm2/m128, imm8u","VPCOMB imm8u, xmm2/m128, xmmV, xmm1","vpcomb imm8u, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 CC /r ib","V","V","XOP","amd","w,r,r,r","","" +"VPCOMD xmm1, xmmV, xmm2/m128, imm8u","VPCOMD imm8u, xmm2/m128, xmmV, xmm1","vpcomd imm8u, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 CE /r ib","V","V","XOP","amd","w,r,r,r","","" +"VPCOMPRESSB xmm2/m128, {k}{z}, xmm1","VPCOMPRESSB xmm1, {k}{z}, xmm2/m128","vpcompressb xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F38.W0 63 /r","V","V","AVX512_VBMI2+AVX512VL","scale1","w,r,r","","" +"VPCOMPRESSB ymm2/m256, {k}{z}, ymm1","VPCOMPRESSB ymm1, {k}{z}, ymm2/m256","vpcompressb ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F38.W0 63 /r","V","V","AVX512_VBMI2+AVX512VL","scale1","w,r,r","","" +"VPCOMPRESSB zmm2/m512, {k}{z}, zmm1","VPCOMPRESSB zmm1, {k}{z}, zmm2/m512","vpcompressb zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F38.W0 63 /r","V","V","AVX512_VBMI2","scale1","w,r,r","","" +"VPCOMPRESSD xmm2/m128, {k}{z}, xmm1","VPCOMPRESSD xmm1, {k}{z}, xmm2/m128","vpcompressd xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F38.W0 8B /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPCOMPRESSD ymm2/m256, {k}{z}, ymm1","VPCOMPRESSD ymm1, {k}{z}, ymm2/m256","vpcompressd ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F38.W0 8B /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPCOMPRESSD zmm2/m512, {k}{z}, zmm1","VPCOMPRESSD zmm1, {k}{z}, zmm2/m512","vpcompressd zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F38.W0 8B /r","V","V","AVX512F","scale4","w,r,r","","" +"VPCOMPRESSQ xmm2/m128, {k}{z}, xmm1","VPCOMPRESSQ xmm1, {k}{z}, xmm2/m128","vpcompressq xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F38.W1 8B /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPCOMPRESSQ ymm2/m256, {k}{z}, ymm1","VPCOMPRESSQ ymm1, {k}{z}, ymm2/m256","vpcompressq ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F38.W1 8B /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPCOMPRESSQ zmm2/m512, {k}{z}, zmm1","VPCOMPRESSQ zmm1, {k}{z}, zmm2/m512","vpcompressq zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F38.W1 8B /r","V","V","AVX512F","scale8","w,r,r","","" +"VPCOMPRESSW xmm2/m128, {k}{z}, xmm1","VPCOMPRESSW xmm1, {k}{z}, xmm2/m128","vpcompressw xmm1, {k}{z}, xmm2/m128","EVEX.128.66.0F38.W1 63 /r","V","V","AVX512_VBMI2+AVX512VL","scale2","w,r,r","","" +"VPCOMPRESSW ymm2/m256, {k}{z}, ymm1","VPCOMPRESSW ymm1, {k}{z}, ymm2/m256","vpcompressw ymm1, {k}{z}, ymm2/m256","EVEX.256.66.0F38.W1 63 /r","V","V","AVX512_VBMI2+AVX512VL","scale2","w,r,r","","" +"VPCOMPRESSW zmm2/m512, {k}{z}, zmm1","VPCOMPRESSW zmm1, {k}{z}, zmm2/m512","vpcompressw zmm1, {k}{z}, zmm2/m512","EVEX.512.66.0F38.W1 63 /r","V","V","AVX512_VBMI2","scale2","w,r,r","","" +"VPCOMQ xmm1, xmmV, xmm2/m128, imm8u","VPCOMQ imm8u, xmm2/m128, xmmV, xmm1","vpcomq imm8u, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 CF /r ib","V","V","XOP","amd","w,r,r,r","","" +"VPCOMUB xmm1, xmmV, xmm2/m128, imm8u","VPCOMUB imm8u, xmm2/m128, xmmV, xmm1","vpcomub imm8u, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 EC /r ib","V","V","XOP","amd","w,r,r,r","","" +"VPCOMUD xmm1, xmmV, xmm2/m128, imm8u","VPCOMUD imm8u, xmm2/m128, xmmV, xmm1","vpcomud imm8u, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 EE /r ib","V","V","XOP","amd","w,r,r,r","","" +"VPCOMUQ xmm1, xmmV, xmm2/m128, imm8u","VPCOMUQ imm8u, xmm2/m128, xmmV, xmm1","vpcomuq imm8u, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 EF /r ib","V","V","XOP","amd","w,r,r,r","","" +"VPCOMUW xmm1, xmmV, xmm2/m128, imm8u","VPCOMUW imm8u, xmm2/m128, xmmV, xmm1","vpcomuw imm8u, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 ED /r ib","V","V","XOP","amd","w,r,r,r","","" +"VPCOMW xmm1, xmmV, xmm2/m128, imm8u","VPCOMW imm8u, xmm2/m128, xmmV, xmm1","vpcomw imm8u, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 CD /r ib","V","V","XOP","amd","w,r,r,r","","" +"VPCONFLICTD xmm1, {k}{z}, xmm2/m128/m32bcst","VPCONFLICTD xmm2/m128/m32bcst, {k}{z}, xmm1","vpconflictd xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W0 C4 /r","V","V","AVX512CD+AVX512VL","bscale4,scale16","w,r,r","","" +"VPCONFLICTD ymm1, {k}{z}, ymm2/m256/m32bcst","VPCONFLICTD ymm2/m256/m32bcst, {k}{z}, ymm1","vpconflictd ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W0 C4 /r","V","V","AVX512CD+AVX512VL","bscale4,scale32","w,r,r","","" +"VPCONFLICTD zmm1, {k}{z}, zmm2/m512/m32bcst","VPCONFLICTD zmm2/m512/m32bcst, {k}{z}, zmm1","vpconflictd zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 C4 /r","V","V","AVX512CD","bscale4,scale64","w,r,r","","" +"VPCONFLICTQ xmm1, {k}{z}, xmm2/m128/m64bcst","VPCONFLICTQ xmm2/m128/m64bcst, {k}{z}, xmm1","vpconflictq xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W1 C4 /r","V","V","AVX512CD+AVX512VL","bscale8,scale16","w,r,r","","" +"VPCONFLICTQ ymm1, {k}{z}, ymm2/m256/m64bcst","VPCONFLICTQ ymm2/m256/m64bcst, {k}{z}, ymm1","vpconflictq ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W1 C4 /r","V","V","AVX512CD+AVX512VL","bscale8,scale32","w,r,r","","" +"VPCONFLICTQ zmm1, {k}{z}, zmm2/m512/m64bcst","VPCONFLICTQ zmm2/m512/m64bcst, {k}{z}, zmm1","vpconflictq zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 C4 /r","V","V","AVX512CD","bscale8,scale64","w,r,r","","" +"VPDPBUSD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPDPBUSD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpdpbusd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 50 /r","V","V","AVX512_VNNI+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPDPBUSD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPDPBUSD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpdpbusd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 50 /r","V","V","AVX512_VNNI+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPDPBUSD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPDPBUSD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpdpbusd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 50 /r","V","V","AVX512_VNNI","bscale4,scale64","rw,r,r,r","","" +"VPDPBUSDS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPDPBUSDS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpdpbusds xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 51 /r","V","V","AVX512_VNNI+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPDPBUSDS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPDPBUSDS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpdpbusds ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 51 /r","V","V","AVX512_VNNI+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPDPBUSDS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPDPBUSDS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpdpbusds zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 51 /r","V","V","AVX512_VNNI","bscale4,scale64","rw,r,r,r","","" +"VPDPWSSD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPDPWSSD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpdpwssd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 52 /r","V","V","AVX512_VNNI+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPDPWSSD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPDPWSSD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpdpwssd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 52 /r","V","V","AVX512_VNNI+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPDPWSSD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPDPWSSD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpdpwssd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 52 /r","V","V","AVX512_VNNI","bscale4,scale64","rw,r,r,r","","" +"VPDPWSSDS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPDPWSSDS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpdpwssds xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 53 /r","V","V","AVX512_VNNI+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPDPWSSDS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPDPWSSDS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpdpwssds ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 53 /r","V","V","AVX512_VNNI+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPDPWSSDS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPDPWSSDS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpdpwssds zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 53 /r","V","V","AVX512_VNNI","bscale4,scale64","rw,r,r,r","","" +"VPERM2F128 ymm1, ymmV, ymm2/m256, imm8u","VPERM2F128 imm8u, ymm2/m256, ymmV, ymm1","vperm2f128 imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 06 /r ib","V","V","AVX","","w,r,r,r","","" +"VPERM2I128 ymm1, ymmV, ymm2/m256, imm8u","VPERM2I128 imm8u, ymm2/m256, ymmV, ymm1","vperm2i128 imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 46 /r ib","V","V","AVX2","","w,r,r,r","","" +"VPERMB xmm1, {k}{z}, xmmV, xmm2/m128","VPERMB xmm2/m128, xmmV, {k}{z}, xmm1","vpermb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 8D /r","V","V","AVX512_VBMI+AVX512VL","scale16","w,r,r,r","","" +"VPERMB ymm1, {k}{z}, ymmV, ymm2/m256","VPERMB ymm2/m256, ymmV, {k}{z}, ymm1","vpermb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 8D /r","V","V","AVX512_VBMI+AVX512VL","scale32","w,r,r,r","","" +"VPERMB zmm1, {k}{z}, zmmV, zmm2/m512","VPERMB zmm2/m512, zmmV, {k}{z}, zmm1","vpermb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 8D /r","V","V","AVX512_VBMI","scale64","w,r,r,r","","" +"VPERMD ymm1, ymmV, ymm2/m256","VPERMD ymm2/m256, ymmV, ymm1","vpermd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 36 /r","V","V","AVX2","","w,r,r","","" +"VPERMD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPERMD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpermd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 36 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPERMD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPERMD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpermd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 36 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPERMI2B xmm1, {k}{z}, xmmV, xmm2/m128","VPERMI2B xmm2/m128, xmmV, {k}{z}, xmm1","vpermi2b xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 75 /r","V","V","AVX512_VBMI+AVX512VL","scale16","rw,r,r,r","","" +"VPERMI2B ymm1, {k}{z}, ymmV, ymm2/m256","VPERMI2B ymm2/m256, ymmV, {k}{z}, ymm1","vpermi2b ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 75 /r","V","V","AVX512_VBMI+AVX512VL","scale32","rw,r,r,r","","" +"VPERMI2B zmm1, {k}{z}, zmmV, zmm2/m512","VPERMI2B zmm2/m512, zmmV, {k}{z}, zmm1","vpermi2b zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 75 /r","V","V","AVX512_VBMI","scale64","rw,r,r,r","","" +"VPERMI2D xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPERMI2D xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpermi2d xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 76 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPERMI2D ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPERMI2D ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpermi2d ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 76 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPERMI2D zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPERMI2D zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpermi2d zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 76 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VPERMI2PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPERMI2PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpermi2pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 77 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VPERMI2PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPERMI2PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpermi2pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 77 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VPERMI2PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPERMI2PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpermi2pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 77 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VPERMI2PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPERMI2PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpermi2ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 77 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPERMI2PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPERMI2PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpermi2ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 77 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPERMI2PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPERMI2PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpermi2ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 77 /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VPERMI2Q xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPERMI2Q xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpermi2q xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 76 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VPERMI2Q ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPERMI2Q ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpermi2q ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 76 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VPERMI2Q zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPERMI2Q zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpermi2q zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 76 /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VPERMI2W xmm1, {k}{z}, xmmV, xmm2/m128","VPERMI2W xmm2/m128, xmmV, {k}{z}, xmm1","vpermi2w xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 75 /r","V","V","AVX512BW+AVX512VL","scale16","rw,r,r,r","","" +"VPERMI2W ymm1, {k}{z}, ymmV, ymm2/m256","VPERMI2W ymm2/m256, ymmV, {k}{z}, ymm1","vpermi2w ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 75 /r","V","V","AVX512BW+AVX512VL","scale32","rw,r,r,r","","" +"VPERMI2W zmm1, {k}{z}, zmmV, zmm2/m512","VPERMI2W zmm2/m512, zmmV, {k}{z}, zmm1","vpermi2w zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 75 /r","V","V","AVX512BW","scale64","rw,r,r,r","","" +"VPERMIL2PD xmm1, xmmV, xmmIH, xmm2/m128, imm8u","VPERMIL2PD imm8u, xmm2/m128, xmmIH, xmmV, xmm1","vpermil2pd imm8u, xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 49 /r /is4","V","V","XOP","amd","w,r,r,r,r","","" +"VPERMIL2PD xmm1, xmmV, xmm2/m128, xmmIH, imm8u","VPERMIL2PD imm8u, xmmIH, xmm2/m128, xmmV, xmm1","vpermil2pd imm8u, xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 49 /r /is4","V","V","XOP","amd","w,r,r,r,r","","" +"VPERMIL2PD ymm1, ymmV, ymmIH, ymm2/m256, imm8u","VPERMIL2PD imm8u, ymm2/m256, ymmIH, ymmV, ymm1","vpermil2pd imm8u, ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 49 /r /is4","V","V","XOP","amd","w,r,r,r,r","","" +"VPERMIL2PD ymm1, ymmV, ymm2/m256, ymmIH, imm8u","VPERMIL2PD imm8u, ymmIH, ymm2/m256, ymmV, ymm1","vpermil2pd imm8u, ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 49 /r /is4","V","V","XOP","amd","w,r,r,r,r","","" +"VPERMIL2PS xmm1, xmmV, xmmIH, xmm2/m128, imm8u","VPERMIL2PS imm8u, xmm2/m128, xmmIH, xmmV, xmm1","vpermil2ps imm8u, xmm2/m128, xmmIH, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 48 /r /is4","V","V","XOP","amd","w,r,r,r,r","","" +"VPERMIL2PS xmm1, xmmV, xmm2/m128, xmmIH, imm8u","VPERMIL2PS imm8u, xmmIH, xmm2/m128, xmmV, xmm1","vpermil2ps imm8u, xmmIH, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 48 /r /is4","V","V","XOP","amd","w,r,r,r,r","","" +"VPERMIL2PS ymm1, ymmV, ymmIH, ymm2/m256, imm8u","VPERMIL2PS imm8u, ymm2/m256, ymmIH, ymmV, ymm1","vpermil2ps imm8u, ymm2/m256, ymmIH, ymmV, ymm1","VEX.NDS.256.66.0F3A.W1 48 /r /is4","V","V","XOP","amd","w,r,r,r,r","","" +"VPERMIL2PS ymm1, ymmV, ymm2/m256, ymmIH, imm8u","VPERMIL2PS imm8u, ymmIH, ymm2/m256, ymmV, ymm1","vpermil2ps imm8u, ymmIH, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F3A.W0 48 /r /is4","V","V","XOP","amd","w,r,r,r,r","","" +"VPERMILPD xmm1, xmm2/m128, imm8u","VPERMILPD imm8u, xmm2/m128, xmm1","vpermilpd imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.W0 05 /r ib","V","V","AVX","","w,r,r","","" +"VPERMILPD xmm1, {k}{z}, xmm2/m128/m64bcst, imm8u","VPERMILPD imm8u, xmm2/m128/m64bcst, {k}{z}, xmm1","vpermilpd imm8u, xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F3A.W1 05 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPERMILPD ymm1, ymm2/m256, imm8u","VPERMILPD imm8u, ymm2/m256, ymm1","vpermilpd imm8u, ymm2/m256, ymm1","VEX.256.66.0F3A.W0 05 /r ib","V","V","AVX","","w,r,r","","" +"VPERMILPD ymm1, {k}{z}, ymm2/m256/m64bcst, imm8u","VPERMILPD imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","vpermilpd imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W1 05 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPERMILPD zmm1, {k}{z}, zmm2/m512/m64bcst, imm8u","VPERMILPD imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","vpermilpd imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W1 05 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPERMILPD xmm1, xmmV, xmm2/m128","VPERMILPD xmm2/m128, xmmV, xmm1","vpermilpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 0D /r","V","V","AVX","","w,r,r","","" +"VPERMILPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPERMILPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpermilpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 0D /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPERMILPD ymm1, ymmV, ymm2/m256","VPERMILPD ymm2/m256, ymmV, ymm1","vpermilpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 0D /r","V","V","AVX","","w,r,r","","" +"VPERMILPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPERMILPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpermilpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 0D /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPERMILPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPERMILPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpermilpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 0D /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPERMILPS xmm1, xmm2/m128, imm8u","VPERMILPS imm8u, xmm2/m128, xmm1","vpermilps imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.W0 04 /r ib","V","V","AVX","","w,r,r","","" +"VPERMILPS xmm1, {k}{z}, xmm2/m128/m32bcst, imm8u","VPERMILPS imm8u, xmm2/m128/m32bcst, {k}{z}, xmm1","vpermilps imm8u, xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F3A.W0 04 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPERMILPS ymm1, ymm2/m256, imm8u","VPERMILPS imm8u, ymm2/m256, ymm1","vpermilps imm8u, ymm2/m256, ymm1","VEX.256.66.0F3A.W0 04 /r ib","V","V","AVX","","w,r,r","","" +"VPERMILPS ymm1, {k}{z}, ymm2/m256/m32bcst, imm8u","VPERMILPS imm8u, ymm2/m256/m32bcst, {k}{z}, ymm1","vpermilps imm8u, ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W0 04 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPERMILPS zmm1, {k}{z}, zmm2/m512/m32bcst, imm8u","VPERMILPS imm8u, zmm2/m512/m32bcst, {k}{z}, zmm1","vpermilps imm8u, zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W0 04 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPERMILPS xmm1, xmmV, xmm2/m128","VPERMILPS xmm2/m128, xmmV, xmm1","vpermilps xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 0C /r","V","V","AVX","","w,r,r","","" +"VPERMILPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPERMILPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpermilps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 0C /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPERMILPS ymm1, ymmV, ymm2/m256","VPERMILPS ymm2/m256, ymmV, ymm1","vpermilps ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 0C /r","V","V","AVX","","w,r,r","","" +"VPERMILPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPERMILPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpermilps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 0C /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPERMILPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPERMILPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpermilps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 0C /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPERMPD ymm1, ymm2/m256, imm8u","VPERMPD imm8u, ymm2/m256, ymm1","vpermpd imm8u, ymm2/m256, ymm1","VEX.256.66.0F3A.W1 01 /r ib","V","V","AVX2","","w,r,r","","" +"VPERMPD ymm1, {k}{z}, ymm2/m256/m64bcst, imm8u","VPERMPD imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","vpermpd imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W1 01 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPERMPD zmm1, {k}{z}, zmm2/m512/m64bcst, imm8u","VPERMPD imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","vpermpd imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W1 01 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPERMPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPERMPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpermpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 16 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPERMPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPERMPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpermpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 16 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPERMPS ymm1, ymmV, ymm2/m256","VPERMPS ymm2/m256, ymmV, ymm1","vpermps ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 16 /r","V","V","AVX2","","w,r,r","","" +"VPERMPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPERMPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpermps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 16 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPERMPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPERMPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpermps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 16 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPERMQ ymm1, ymm2/m256, imm8u","VPERMQ imm8u, ymm2/m256, ymm1","vpermq imm8u, ymm2/m256, ymm1","VEX.256.66.0F3A.W1 00 /r ib","V","V","AVX2","","w,r,r","","" +"VPERMQ ymm1, {k}{z}, ymm2/m256/m64bcst, imm8u","VPERMQ imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","vpermq imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W1 00 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPERMQ zmm1, {k}{z}, zmm2/m512/m64bcst, imm8u","VPERMQ imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","vpermq imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W1 00 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPERMQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPERMQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpermq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 36 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPERMQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPERMQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpermq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 36 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPERMT2B xmm1, {k}{z}, xmmV, xmm2/m128","VPERMT2B xmm2/m128, xmmV, {k}{z}, xmm1","vpermt2b xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 7D /r","V","V","AVX512_VBMI+AVX512VL","scale16","rw,r,r,r","","" +"VPERMT2B ymm1, {k}{z}, ymmV, ymm2/m256","VPERMT2B ymm2/m256, ymmV, {k}{z}, ymm1","vpermt2b ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 7D /r","V","V","AVX512_VBMI+AVX512VL","scale32","rw,r,r,r","","" +"VPERMT2B zmm1, {k}{z}, zmmV, zmm2/m512","VPERMT2B zmm2/m512, zmmV, {k}{z}, zmm1","vpermt2b zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 7D /r","V","V","AVX512_VBMI","scale64","rw,r,r,r","","" +"VPERMT2D xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPERMT2D xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpermt2d xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 7E /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPERMT2D ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPERMT2D ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpermt2d ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 7E /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPERMT2D zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPERMT2D zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpermt2d zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 7E /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VPERMT2PD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPERMT2PD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpermt2pd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 7F /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VPERMT2PD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPERMT2PD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpermt2pd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 7F /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VPERMT2PD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPERMT2PD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpermt2pd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 7F /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VPERMT2PS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPERMT2PS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpermt2ps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 7F /r","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPERMT2PS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPERMT2PS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpermt2ps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 7F /r","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPERMT2PS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPERMT2PS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpermt2ps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 7F /r","V","V","AVX512F","bscale4,scale64","rw,r,r,r","","" +"VPERMT2Q xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPERMT2Q xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpermt2q xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 7E /r","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VPERMT2Q ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPERMT2Q ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpermt2q ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 7E /r","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VPERMT2Q zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPERMT2Q zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpermt2q zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 7E /r","V","V","AVX512F","bscale8,scale64","rw,r,r,r","","" +"VPERMT2W xmm1, {k}{z}, xmmV, xmm2/m128","VPERMT2W xmm2/m128, xmmV, {k}{z}, xmm1","vpermt2w xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 7D /r","V","V","AVX512BW+AVX512VL","scale16","rw,r,r,r","","" +"VPERMT2W ymm1, {k}{z}, ymmV, ymm2/m256","VPERMT2W ymm2/m256, ymmV, {k}{z}, ymm1","vpermt2w ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 7D /r","V","V","AVX512BW+AVX512VL","scale32","rw,r,r,r","","" +"VPERMT2W zmm1, {k}{z}, zmmV, zmm2/m512","VPERMT2W zmm2/m512, zmmV, {k}{z}, zmm1","vpermt2w zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 7D /r","V","V","AVX512BW","scale64","rw,r,r,r","","" +"VPERMW xmm1, {k}{z}, xmmV, xmm2/m128","VPERMW xmm2/m128, xmmV, {k}{z}, xmm1","vpermw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 8D /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPERMW ymm1, {k}{z}, ymmV, ymm2/m256","VPERMW ymm2/m256, ymmV, {k}{z}, ymm1","vpermw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 8D /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPERMW zmm1, {k}{z}, zmmV, zmm2/m512","VPERMW zmm2/m512, zmmV, {k}{z}, zmm1","vpermw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 8D /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPEXPANDB xmm1, {k}{z}, xmm2/m128","VPEXPANDB xmm2/m128, {k}{z}, xmm1","vpexpandb xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.W0 62 /r","V","V","AVX512_VBMI2+AVX512VL","scale1","w,r,r","","" +"VPEXPANDB ymm1, {k}{z}, ymm2/m256","VPEXPANDB ymm2/m256, {k}{z}, ymm1","vpexpandb ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.W0 62 /r","V","V","AVX512_VBMI2+AVX512VL","scale1","w,r,r","","" +"VPEXPANDB zmm1, {k}{z}, zmm2/m512","VPEXPANDB zmm2/m512, {k}{z}, zmm1","vpexpandb zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.W0 62 /r","V","V","AVX512_VBMI2","scale1","w,r,r","","" +"VPEXPANDD xmm1, {k}{z}, xmm2/m128","VPEXPANDD xmm2/m128, {k}{z}, xmm1","vpexpandd xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.W0 89 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPEXPANDD ymm1, {k}{z}, ymm2/m256","VPEXPANDD ymm2/m256, {k}{z}, ymm1","vpexpandd ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.W0 89 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPEXPANDD zmm1, {k}{z}, zmm2/m512","VPEXPANDD zmm2/m512, {k}{z}, zmm1","vpexpandd zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.W0 89 /r","V","V","AVX512F","scale4","w,r,r","","" +"VPEXPANDQ xmm1, {k}{z}, xmm2/m128","VPEXPANDQ xmm2/m128, {k}{z}, xmm1","vpexpandq xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.W1 89 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPEXPANDQ ymm1, {k}{z}, ymm2/m256","VPEXPANDQ ymm2/m256, {k}{z}, ymm1","vpexpandq ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.W1 89 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPEXPANDQ zmm1, {k}{z}, zmm2/m512","VPEXPANDQ zmm2/m512, {k}{z}, zmm1","vpexpandq zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.W1 89 /r","V","V","AVX512F","scale8","w,r,r","","" +"VPEXPANDW xmm1, {k}{z}, xmm2/m128","VPEXPANDW xmm2/m128, {k}{z}, xmm1","vpexpandw xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.W1 62 /r","V","V","AVX512_VBMI2+AVX512VL","scale2","w,r,r","","" +"VPEXPANDW ymm1, {k}{z}, ymm2/m256","VPEXPANDW ymm2/m256, {k}{z}, ymm1","vpexpandw ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.W1 62 /r","V","V","AVX512_VBMI2+AVX512VL","scale2","w,r,r","","" +"VPEXPANDW zmm1, {k}{z}, zmm2/m512","VPEXPANDW zmm2/m512, {k}{z}, zmm1","vpexpandw zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.W1 62 /r","V","V","AVX512_VBMI2","scale2","w,r,r","","" +"VPEXTRB r32/m8, xmm1, imm8u","VPEXTRB imm8u, xmm1, r32/m8","vpextrb imm8u, xmm1, r32/m8","EVEX.128.66.0F3A.WIG 14 /r ib","V","V","AVX512BW+AVX512VL","scale1","w,r,r","","" +"VPEXTRB r32/m8, xmm1, imm8u","VPEXTRB imm8u, xmm1, r32/m8","vpextrb imm8u, xmm1, r32/m8","VEX.128.66.0F3A.WIG 14 /r ib","V","V","AVX","","w,r,r","","" +"VPEXTRD r/m32, xmm1, imm8u","VPEXTRD imm8u, xmm1, r/m32","vpextrd imm8u, xmm1, r/m32","EVEX.128.66.0F3A.W0 16 /r ib","V","V","AVX512DQ+AVX512VL","scale4","w,r,r","","" +"VPEXTRD r/m32, xmm1, imm8u","VPEXTRD imm8u, xmm1, r/m32","vpextrd imm8u, xmm1, r/m32","VEX.128.66.0F3A.W0 16 /r ib","V","V","AVX","","w,r,r","","" +"VPEXTRQ r/m64, xmm1, imm8u","VPEXTRQ imm8u, xmm1, r/m64","vpextrq imm8u, xmm1, r/m64","EVEX.128.66.0F3A.W1 16 /r ib","N.S.","V","AVX512DQ+AVX512VL","scale8","w,r,r","","" +"VPEXTRQ r/m64, xmm1, imm8u","VPEXTRQ imm8u, xmm1, r/m64","vpextrq imm8u, xmm1, r/m64","VEX.128.66.0F3A.W1 16 /r ib","N.S.","V","AVX","","w,r,r","","" +"VPEXTRW r32/m16, xmm1, imm8u","VPEXTRW imm8u, xmm1, r32/m16","vpextrw imm8u, xmm1, r32/m16","EVEX.128.66.0F3A.WIG 15 /r ib","V","V","AVX512BW+AVX512VL","scale2","w,r,r","","" +"VPEXTRW r32/m16, xmm1, imm8u","VPEXTRW imm8u, xmm1, r32/m16","vpextrw imm8u, xmm1, r32/m16","VEX.128.66.0F3A.WIG 15 /r ib","V","V","AVX","","w,r,r","","" +"VPEXTRW r32, xmm2, imm8u","VPEXTRW imm8u, xmm2, r32","vpextrw imm8u, xmm2, r32","EVEX.128.66.0F.WIG C5 /r ib","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r,r","","" +"VPEXTRW r32, xmm2, imm8u","VPEXTRW imm8u, xmm2, r32","vpextrw imm8u, xmm2, r32","VEX.128.66.0F.WIG C5 /r ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPGATHERDD xmm1, {k1-k7}, vm32x","VPGATHERDD vm32x, {k1-k7}, xmm1","vpgatherdd vm32x, {k1-k7}, xmm1","EVEX.128.66.0F38.W0 90 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VPGATHERDD ymm1, {k1-k7}, vm32y","VPGATHERDD vm32y, {k1-k7}, ymm1","vpgatherdd vm32y, {k1-k7}, ymm1","EVEX.256.66.0F38.W0 90 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VPGATHERDD zmm1, {k1-k7}, vm32z","VPGATHERDD vm32z, {k1-k7}, zmm1","vpgatherdd vm32z, {k1-k7}, zmm1","EVEX.512.66.0F38.W0 90 /vsib","V","V","AVX512F","modrm_memonly,scale4","w,rw,r","","" +"VPGATHERDD xmm1, vm32x, xmmV","VPGATHERDD xmmV, vm32x, xmm1","vpgatherdd xmmV, vm32x, xmm1","VEX.DDS.128.66.0F38.W0 90 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VPGATHERDD ymm1, vm32y, ymmV","VPGATHERDD ymmV, vm32y, ymm1","vpgatherdd ymmV, vm32y, ymm1","VEX.DDS.256.66.0F38.W0 90 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VPGATHERDQ xmm1, {k1-k7}, vm32x","VPGATHERDQ vm32x, {k1-k7}, xmm1","vpgatherdq vm32x, {k1-k7}, xmm1","EVEX.128.66.0F38.W1 90 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VPGATHERDQ ymm1, {k1-k7}, vm32x","VPGATHERDQ vm32x, {k1-k7}, ymm1","vpgatherdq vm32x, {k1-k7}, ymm1","EVEX.256.66.0F38.W1 90 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VPGATHERDQ zmm1, {k1-k7}, vm32y","VPGATHERDQ vm32y, {k1-k7}, zmm1","vpgatherdq vm32y, {k1-k7}, zmm1","EVEX.512.66.0F38.W1 90 /vsib","V","V","AVX512F","modrm_memonly,scale8","w,rw,r","","" +"VPGATHERDQ xmm1, vm32x, xmmV","VPGATHERDQ xmmV, vm32x, xmm1","vpgatherdq xmmV, vm32x, xmm1","VEX.DDS.128.66.0F38.W1 90 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VPGATHERDQ ymm1, vm32x, ymmV","VPGATHERDQ ymmV, vm32x, ymm1","vpgatherdq ymmV, vm32x, ymm1","VEX.DDS.256.66.0F38.W1 90 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VPGATHERQD xmm1, {k1-k7}, vm64x","VPGATHERQD vm64x, {k1-k7}, xmm1","vpgatherqd vm64x, {k1-k7}, xmm1","EVEX.128.66.0F38.W0 91 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VPGATHERQD xmm1, {k1-k7}, vm64y","VPGATHERQD vm64y, {k1-k7}, xmm1","vpgatherqd vm64y, {k1-k7}, xmm1","EVEX.256.66.0F38.W0 91 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VPGATHERQD ymm1, {k1-k7}, vm64z","VPGATHERQD vm64z, {k1-k7}, ymm1","vpgatherqd vm64z, {k1-k7}, ymm1","EVEX.512.66.0F38.W0 91 /vsib","V","V","AVX512F","modrm_memonly,scale4","w,rw,r","","" +"VPGATHERQD xmm1, vm64x, xmmV","VPGATHERQD xmmV, vm64x, xmm1","vpgatherqd xmmV, vm64x, xmm1","VEX.DDS.128.66.0F38.W0 91 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VPGATHERQD xmm1, vm64y, xmmV","VPGATHERQD xmmV, vm64y, xmm1","vpgatherqd xmmV, vm64y, xmm1","VEX.DDS.256.66.0F38.W0 91 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VPGATHERQQ xmm1, {k1-k7}, vm64x","VPGATHERQQ vm64x, {k1-k7}, xmm1","vpgatherqq vm64x, {k1-k7}, xmm1","EVEX.128.66.0F38.W1 91 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VPGATHERQQ ymm1, {k1-k7}, vm64y","VPGATHERQQ vm64y, {k1-k7}, ymm1","vpgatherqq vm64y, {k1-k7}, ymm1","EVEX.256.66.0F38.W1 91 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VPGATHERQQ zmm1, {k1-k7}, vm64z","VPGATHERQQ vm64z, {k1-k7}, zmm1","vpgatherqq vm64z, {k1-k7}, zmm1","EVEX.512.66.0F38.W1 91 /vsib","V","V","AVX512F","modrm_memonly,scale8","w,rw,r","","" +"VPGATHERQQ xmm1, vm64x, xmmV","VPGATHERQQ xmmV, vm64x, xmm1","vpgatherqq xmmV, vm64x, xmm1","VEX.DDS.128.66.0F38.W1 91 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VPGATHERQQ ymm1, vm64y, ymmV","VPGATHERQQ ymmV, vm64y, ymm1","vpgatherqq ymmV, vm64y, ymm1","VEX.DDS.256.66.0F38.W1 91 /r","V","V","AVX2","modrm_memonly","rw,r,rw","","" +"VPHADDBD xmm1, xmm2/m128","VPHADDBD xmm2/m128, xmm1","vphaddbd xmm2/m128, xmm1","XOP.128.09.W0 C2 /r","V","V","XOP","amd","w,r","","" +"VPHADDBQ xmm1, xmm2/m128","VPHADDBQ xmm2/m128, xmm1","vphaddbq xmm2/m128, xmm1","XOP.128.09.W0 C3 /r","V","V","XOP","amd","w,r","","" +"VPHADDBW xmm1, xmm2/m128","VPHADDBW xmm2/m128, xmm1","vphaddbw xmm2/m128, xmm1","XOP.128.09.W0 C1 /r","V","V","XOP","amd","w,r","","" +"VPHADDD xmm1, xmmV, xmm2/m128","VPHADDD xmm2/m128, xmmV, xmm1","vphaddd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 02 /r","V","V","AVX","","w,r,r","","" +"VPHADDD ymm1, ymmV, ymm2/m256","VPHADDD ymm2/m256, ymmV, ymm1","vphaddd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 02 /r","V","V","AVX2","","w,r,r","","" +"VPHADDDQ xmm1, xmm2/m128","VPHADDDQ xmm2/m128, xmm1","vphadddq xmm2/m128, xmm1","XOP.128.09.W0 CB /r","V","V","XOP","amd","w,r","","" +"VPHADDSW xmm1, xmmV, xmm2/m128","VPHADDSW xmm2/m128, xmmV, xmm1","vphaddsw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 03 /r","V","V","AVX","","w,r,r","","" +"VPHADDSW ymm1, ymmV, ymm2/m256","VPHADDSW ymm2/m256, ymmV, ymm1","vphaddsw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 03 /r","V","V","AVX2","","w,r,r","","" +"VPHADDUBD xmm1, xmm2/m128","VPHADDUBD xmm2/m128, xmm1","vphaddubd xmm2/m128, xmm1","XOP.128.09.W0 D2 /r","V","V","XOP","amd","w,r","","" +"VPHADDUBQ xmm1, xmm2/m128","VPHADDUBQ xmm2/m128, xmm1","vphaddubq xmm2/m128, xmm1","XOP.128.09.W0 D3 /r","V","V","XOP","amd","w,r","","" +"VPHADDUBW xmm1, xmm2/m128","VPHADDUBW xmm2/m128, xmm1","vphaddubw xmm2/m128, xmm1","XOP.128.09.W0 D1 /r","V","V","XOP","amd","w,r","","" +"VPHADDUDQ xmm1, xmm2/m128","VPHADDUDQ xmm2/m128, xmm1","vphaddudq xmm2/m128, xmm1","XOP.128.09.W0 DB /r","V","V","XOP","amd","w,r","","" +"VPHADDUWD xmm1, xmm2/m128","VPHADDUWD xmm2/m128, xmm1","vphadduwd xmm2/m128, xmm1","XOP.128.09.W0 D6 /r","V","V","XOP","amd","w,r","","" +"VPHADDUWQ xmm1, xmm2/m128","VPHADDUWQ xmm2/m128, xmm1","vphadduwq xmm2/m128, xmm1","XOP.128.09.W0 D7 /r","V","V","XOP","amd","w,r","","" +"VPHADDW xmm1, xmmV, xmm2/m128","VPHADDW xmm2/m128, xmmV, xmm1","vphaddw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 01 /r","V","V","AVX","","w,r,r","","" +"VPHADDW ymm1, ymmV, ymm2/m256","VPHADDW ymm2/m256, ymmV, ymm1","vphaddw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 01 /r","V","V","AVX2","","w,r,r","","" +"VPHADDWD xmm1, xmm2/m128","VPHADDWD xmm2/m128, xmm1","vphaddwd xmm2/m128, xmm1","XOP.128.09.W0 C6 /r","V","V","XOP","amd","w,r","","" +"VPHADDWQ xmm1, xmm2/m128","VPHADDWQ xmm2/m128, xmm1","vphaddwq xmm2/m128, xmm1","XOP.128.09.W0 C7 /r","V","V","XOP","amd","w,r","","" +"VPHMINPOSUW xmm1, xmm2/m128","VPHMINPOSUW xmm2/m128, xmm1","vphminposuw xmm2/m128, xmm1","VEX.128.66.0F38.WIG 41 /r","V","V","AVX","","w,r","","" +"VPHSUBBW xmm1, xmm2/m128","VPHSUBBW xmm2/m128, xmm1","vphsubbw xmm2/m128, xmm1","XOP.128.09.W0 E1 /r","V","V","XOP","amd","w,r","","" +"VPHSUBD xmm1, xmmV, xmm2/m128","VPHSUBD xmm2/m128, xmmV, xmm1","vphsubd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 06 /r","V","V","AVX","","w,r,r","","" +"VPHSUBD ymm1, ymmV, ymm2/m256","VPHSUBD ymm2/m256, ymmV, ymm1","vphsubd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 06 /r","V","V","AVX2","","w,r,r","","" +"VPHSUBDQ xmm1, xmm2/m128","VPHSUBDQ xmm2/m128, xmm1","vphsubdq xmm2/m128, xmm1","XOP.128.09.W0 E3 /r","V","V","XOP","amd","w,r","","" +"VPHSUBSW xmm1, xmmV, xmm2/m128","VPHSUBSW xmm2/m128, xmmV, xmm1","vphsubsw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 07 /r","V","V","AVX","","w,r,r","","" +"VPHSUBSW ymm1, ymmV, ymm2/m256","VPHSUBSW ymm2/m256, ymmV, ymm1","vphsubsw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 07 /r","V","V","AVX2","","w,r,r","","" +"VPHSUBW xmm1, xmmV, xmm2/m128","VPHSUBW xmm2/m128, xmmV, xmm1","vphsubw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 05 /r","V","V","AVX","","w,r,r","","" +"VPHSUBW ymm1, ymmV, ymm2/m256","VPHSUBW ymm2/m256, ymmV, ymm1","vphsubw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 05 /r","V","V","AVX2","","w,r,r","","" +"VPHSUBWD xmm1, xmm2/m128","VPHSUBWD xmm2/m128, xmm1","vphsubwd xmm2/m128, xmm1","XOP.128.09.W0 E2 /r","V","V","XOP","amd","w,r","","" +"VPINSRB xmm1, xmmV, r32/m8, imm8u","VPINSRB imm8u, r32/m8, xmmV, xmm1","vpinsrb imm8u, r32/m8, xmmV, xmm1","EVEX.NDS.128.66.0F3A.WIG 20 /r ib","V","V","AVX512BW+AVX512VL","scale1","w,r,r,r","","" +"VPINSRB xmm1, xmmV, r32/m8, imm8u","VPINSRB imm8u, r32/m8, xmmV, xmm1","vpinsrb imm8u, r32/m8, xmmV, xmm1","VEX.NDS.128.66.0F3A.WIG 20 /r ib","V","V","AVX","","w,r,r,r","","" +"VPINSRD xmm1, xmmV, r/m32, imm8u","VPINSRD imm8u, r/m32, xmmV, xmm1","vpinsrd imm8u, r/m32, xmmV, xmm1","EVEX.NDS.128.66.0F3A.W0 22 /r ib","V","V","AVX512DQ+AVX512VL","scale4","w,r,r,r","","" +"VPINSRD xmm1, xmmV, r/m32, imm8u","VPINSRD imm8u, r/m32, xmmV, xmm1","vpinsrd imm8u, r/m32, xmmV, xmm1","VEX.NDS.128.66.0F3A.W0 22 /r ib","V","V","AVX","","w,r,r,r","","" +"VPINSRQ xmm1, xmmV, r/m64, imm8u","VPINSRQ imm8u, r/m64, xmmV, xmm1","vpinsrq imm8u, r/m64, xmmV, xmm1","EVEX.NDS.128.66.0F3A.W1 22 /r ib","N.S.","V","AVX512DQ+AVX512VL","scale8","w,r,r,r","","" +"VPINSRQ xmm1, xmmV, r/m64, imm8u","VPINSRQ imm8u, r/m64, xmmV, xmm1","vpinsrq imm8u, r/m64, xmmV, xmm1","VEX.NDS.128.66.0F3A.W1 22 /r ib","N.S.","V","AVX","","w,r,r,r","","" +"VPINSRW xmm1, xmmV, r32/m16, imm8u","VPINSRW imm8u, r32/m16, xmmV, xmm1","vpinsrw imm8u, r32/m16, xmmV, xmm1","EVEX.NDS.128.66.0F.WIG C4 /r ib","V","V","AVX512BW+AVX512VL","scale2","w,r,r,r","","" +"VPINSRW xmm1, xmmV, r32/m16, imm8u","VPINSRW imm8u, r32/m16, xmmV, xmm1","vpinsrw imm8u, r32/m16, xmmV, xmm1","VEX.NDS.128.66.0F.WIG C4 /r ib","V","V","AVX","","w,r,r,r","","" +"VPLZCNTD xmm1, {k}{z}, xmm2/m128/m32bcst","VPLZCNTD xmm2/m128/m32bcst, {k}{z}, xmm1","vplzcntd xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W0 44 /r","V","V","AVX512CD+AVX512VL","bscale4,scale16","w,r,r","","" +"VPLZCNTD ymm1, {k}{z}, ymm2/m256/m32bcst","VPLZCNTD ymm2/m256/m32bcst, {k}{z}, ymm1","vplzcntd ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W0 44 /r","V","V","AVX512CD+AVX512VL","bscale4,scale32","w,r,r","","" +"VPLZCNTD zmm1, {k}{z}, zmm2/m512/m32bcst","VPLZCNTD zmm2/m512/m32bcst, {k}{z}, zmm1","vplzcntd zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 44 /r","V","V","AVX512CD","bscale4,scale64","w,r,r","","" +"VPLZCNTQ xmm1, {k}{z}, xmm2/m128/m64bcst","VPLZCNTQ xmm2/m128/m64bcst, {k}{z}, xmm1","vplzcntq xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W1 44 /r","V","V","AVX512CD+AVX512VL","bscale8,scale16","w,r,r","","" +"VPLZCNTQ ymm1, {k}{z}, ymm2/m256/m64bcst","VPLZCNTQ ymm2/m256/m64bcst, {k}{z}, ymm1","vplzcntq ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W1 44 /r","V","V","AVX512CD+AVX512VL","bscale8,scale32","w,r,r","","" +"VPLZCNTQ zmm1, {k}{z}, zmm2/m512/m64bcst","VPLZCNTQ zmm2/m512/m64bcst, {k}{z}, zmm1","vplzcntq zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 44 /r","V","V","AVX512CD","bscale8,scale64","w,r,r","","" +"VPMACSDD xmm1, xmmV, xmm2/m128, xmmIH","VPMACSDD xmmIH, xmm2/m128, xmmV, xmm1","vpmacsdd xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 9E /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSDQH xmm1, xmmV, xmm2/m128, xmmIH","VPMACSDQH xmmIH, xmm2/m128, xmmV, xmm1","vpmacsdqh xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 9F /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSDQL xmm1, xmmV, xmm2/m128, xmmIH","VPMACSDQL xmmIH, xmm2/m128, xmmV, xmm1","vpmacsdql xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 97 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSSDD xmm1, xmmV, xmm2/m128, xmmIH","VPMACSSDD xmmIH, xmm2/m128, xmmV, xmm1","vpmacssdd xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 8E /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSSDQH xmm1, xmmV, xmm2/m128, xmmIH","VPMACSSDQH xmmIH, xmm2/m128, xmmV, xmm1","vpmacssdqh xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 8F /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSSDQL xmm1, xmmV, xmm2/m128, xmmIH","VPMACSSDQL xmmIH, xmm2/m128, xmmV, xmm1","vpmacssdql xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 87 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSSWD xmm1, xmmV, xmm2/m128, xmmIH","VPMACSSWD xmmIH, xmm2/m128, xmmV, xmm1","vpmacsswd xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 86 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSSWW xmm1, xmmV, xmm2/m128, xmmIH","VPMACSSWW xmmIH, xmm2/m128, xmmV, xmm1","vpmacssww xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 85 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSWD xmm1, xmmV, xmm2/m128, xmmIH","VPMACSWD xmmIH, xmm2/m128, xmmV, xmm1","vpmacswd xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 96 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMACSWW xmm1, xmmV, xmm2/m128, xmmIH","VPMACSWW xmmIH, xmm2/m128, xmmV, xmm1","vpmacsww xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 95 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMADCSSWD xmm1, xmmV, xmm2/m128, xmmIH","VPMADCSSWD xmmIH, xmm2/m128, xmmV, xmm1","vpmadcsswd xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 A6 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMADCSWD xmm1, xmmV, xmm2/m128, xmmIH","VPMADCSWD xmmIH, xmm2/m128, xmmV, xmm1","vpmadcswd xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 B6 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPMADD52HUQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMADD52HUQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpmadd52huq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 B5 /r","V","V","AVX512_IFMA+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VPMADD52HUQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMADD52HUQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpmadd52huq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 B5 /r","V","V","AVX512_IFMA+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VPMADD52HUQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMADD52HUQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpmadd52huq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 B5 /r","V","V","AVX512_IFMA","bscale8,scale64","rw,r,r,r","","" +"VPMADD52LUQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMADD52LUQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpmadd52luq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 B4 /r","V","V","AVX512_IFMA+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VPMADD52LUQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMADD52LUQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpmadd52luq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 B4 /r","V","V","AVX512_IFMA+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VPMADD52LUQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMADD52LUQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpmadd52luq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 B4 /r","V","V","AVX512_IFMA","bscale8,scale64","rw,r,r,r","","" +"VPMADDUBSW xmm1, xmmV, xmm2/m128","VPMADDUBSW xmm2/m128, xmmV, xmm1","vpmaddubsw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 04 /r","V","V","AVX","","w,r,r","","" +"VPMADDUBSW xmm1, {k}{z}, xmmV, xmm2/m128","VPMADDUBSW xmm2/m128, xmmV, {k}{z}, xmm1","vpmaddubsw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.WIG 04 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMADDUBSW ymm1, ymmV, ymm2/m256","VPMADDUBSW ymm2/m256, ymmV, ymm1","vpmaddubsw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 04 /r","V","V","AVX2","","w,r,r","","" +"VPMADDUBSW ymm1, {k}{z}, ymmV, ymm2/m256","VPMADDUBSW ymm2/m256, ymmV, {k}{z}, ymm1","vpmaddubsw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.WIG 04 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMADDUBSW zmm1, {k}{z}, zmmV, zmm2/m512","VPMADDUBSW zmm2/m512, zmmV, {k}{z}, zmm1","vpmaddubsw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.WIG 04 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMADDWD xmm1, xmmV, xmm2/m128","VPMADDWD xmm2/m128, xmmV, xmm1","vpmaddwd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG F5 /r","V","V","AVX","","w,r,r","","" +"VPMADDWD xmm1, {k}{z}, xmmV, xmm2/m128","VPMADDWD xmm2/m128, xmmV, {k}{z}, xmm1","vpmaddwd xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG F5 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMADDWD ymm1, ymmV, ymm2/m256","VPMADDWD ymm2/m256, ymmV, ymm1","vpmaddwd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG F5 /r","V","V","AVX2","","w,r,r","","" +"VPMADDWD ymm1, {k}{z}, ymmV, ymm2/m256","VPMADDWD ymm2/m256, ymmV, {k}{z}, ymm1","vpmaddwd ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG F5 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMADDWD zmm1, {k}{z}, zmmV, zmm2/m512","VPMADDWD zmm2/m512, zmmV, {k}{z}, zmm1","vpmaddwd zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG F5 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMASKMOVD xmm1, xmmV, m128","VPMASKMOVD m128, xmmV, xmm1","vpmaskmovd m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 8C /r","V","V","AVX2","modrm_memonly","w,r,r","","" +"VPMASKMOVD ymm1, ymmV, m256","VPMASKMOVD m256, ymmV, ymm1","vpmaskmovd m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 8C /r","V","V","AVX2","modrm_memonly","w,r,r","","" +"VPMASKMOVD m128, xmmV, xmm1","VPMASKMOVD xmm1, xmmV, m128","vpmaskmovd xmm1, xmmV, m128","VEX.NDS.128.66.0F38.W0 8E /r","V","V","AVX2","modrm_memonly","w,r,r","","" +"VPMASKMOVD m256, ymmV, ymm1","VPMASKMOVD ymm1, ymmV, m256","vpmaskmovd ymm1, ymmV, m256","VEX.NDS.256.66.0F38.W0 8E /r","V","V","AVX2","modrm_memonly","w,r,r","","" +"VPMASKMOVQ xmm1, xmmV, m128","VPMASKMOVQ m128, xmmV, xmm1","vpmaskmovq m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W1 8C /r","V","V","AVX2","modrm_memonly","w,r,r","","" +"VPMASKMOVQ ymm1, ymmV, m256","VPMASKMOVQ m256, ymmV, ymm1","vpmaskmovq m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W1 8C /r","V","V","AVX2","modrm_memonly","w,r,r","","" +"VPMASKMOVQ m128, xmmV, xmm1","VPMASKMOVQ xmm1, xmmV, m128","vpmaskmovq xmm1, xmmV, m128","VEX.NDS.128.66.0F38.W1 8E /r","V","V","AVX2","modrm_memonly","w,r,r","","" +"VPMASKMOVQ m256, ymmV, ymm1","VPMASKMOVQ ymm1, ymmV, m256","vpmaskmovq ymm1, ymmV, m256","VEX.NDS.256.66.0F38.W1 8E /r","V","V","AVX2","modrm_memonly","w,r,r","","" +"VPMAXSB xmm1, xmmV, xmm2/m128","VPMAXSB xmm2/m128, xmmV, xmm1","vpmaxsb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 3C /r","V","V","AVX","","w,r,r","","" +"VPMAXSB xmm1, {k}{z}, xmmV, xmm2/m128","VPMAXSB xmm2/m128, xmmV, {k}{z}, xmm1","vpmaxsb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.WIG 3C /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMAXSB ymm1, ymmV, ymm2/m256","VPMAXSB ymm2/m256, ymmV, ymm1","vpmaxsb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 3C /r","V","V","AVX2","","w,r,r","","" +"VPMAXSB ymm1, {k}{z}, ymmV, ymm2/m256","VPMAXSB ymm2/m256, ymmV, {k}{z}, ymm1","vpmaxsb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.WIG 3C /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMAXSB zmm1, {k}{z}, zmmV, zmm2/m512","VPMAXSB zmm2/m512, zmmV, {k}{z}, zmm1","vpmaxsb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.WIG 3C /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMAXSD xmm1, xmmV, xmm2/m128","VPMAXSD xmm2/m128, xmmV, xmm1","vpmaxsd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 3D /r","V","V","AVX","","w,r,r","","" +"VPMAXSD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPMAXSD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpmaxsd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 3D /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPMAXSD ymm1, ymmV, ymm2/m256","VPMAXSD ymm2/m256, ymmV, ymm1","vpmaxsd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 3D /r","V","V","AVX2","","w,r,r","","" +"VPMAXSD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPMAXSD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpmaxsd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 3D /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPMAXSD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPMAXSD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpmaxsd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 3D /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPMAXSQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMAXSQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpmaxsq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 3D /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPMAXSQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMAXSQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpmaxsq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 3D /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPMAXSQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMAXSQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpmaxsq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 3D /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPMAXSW xmm1, xmmV, xmm2/m128","VPMAXSW xmm2/m128, xmmV, xmm1","vpmaxsw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG EE /r","V","V","AVX","","w,r,r","","" +"VPMAXSW xmm1, {k}{z}, xmmV, xmm2/m128","VPMAXSW xmm2/m128, xmmV, {k}{z}, xmm1","vpmaxsw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG EE /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMAXSW ymm1, ymmV, ymm2/m256","VPMAXSW ymm2/m256, ymmV, ymm1","vpmaxsw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG EE /r","V","V","AVX2","","w,r,r","","" +"VPMAXSW ymm1, {k}{z}, ymmV, ymm2/m256","VPMAXSW ymm2/m256, ymmV, {k}{z}, ymm1","vpmaxsw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG EE /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMAXSW zmm1, {k}{z}, zmmV, zmm2/m512","VPMAXSW zmm2/m512, zmmV, {k}{z}, zmm1","vpmaxsw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG EE /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMAXUB xmm1, xmmV, xmm2/m128","VPMAXUB xmm2/m128, xmmV, xmm1","vpmaxub xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG DE /r","V","V","AVX","","w,r,r","","" +"VPMAXUB xmm1, {k}{z}, xmmV, xmm2/m128","VPMAXUB xmm2/m128, xmmV, {k}{z}, xmm1","vpmaxub xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG DE /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMAXUB ymm1, ymmV, ymm2/m256","VPMAXUB ymm2/m256, ymmV, ymm1","vpmaxub ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG DE /r","V","V","AVX2","","w,r,r","","" +"VPMAXUB ymm1, {k}{z}, ymmV, ymm2/m256","VPMAXUB ymm2/m256, ymmV, {k}{z}, ymm1","vpmaxub ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG DE /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMAXUB zmm1, {k}{z}, zmmV, zmm2/m512","VPMAXUB zmm2/m512, zmmV, {k}{z}, zmm1","vpmaxub zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG DE /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMAXUD xmm1, xmmV, xmm2/m128","VPMAXUD xmm2/m128, xmmV, xmm1","vpmaxud xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 3F /r","V","V","AVX","","w,r,r","","" +"VPMAXUD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPMAXUD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpmaxud xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 3F /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPMAXUD ymm1, ymmV, ymm2/m256","VPMAXUD ymm2/m256, ymmV, ymm1","vpmaxud ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 3F /r","V","V","AVX2","","w,r,r","","" +"VPMAXUD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPMAXUD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpmaxud ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 3F /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPMAXUD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPMAXUD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpmaxud zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 3F /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPMAXUQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMAXUQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpmaxuq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 3F /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPMAXUQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMAXUQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpmaxuq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 3F /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPMAXUQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMAXUQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpmaxuq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 3F /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPMAXUW xmm1, xmmV, xmm2/m128","VPMAXUW xmm2/m128, xmmV, xmm1","vpmaxuw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 3E /r","V","V","AVX","","w,r,r","","" +"VPMAXUW xmm1, {k}{z}, xmmV, xmm2/m128","VPMAXUW xmm2/m128, xmmV, {k}{z}, xmm1","vpmaxuw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.WIG 3E /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMAXUW ymm1, ymmV, ymm2/m256","VPMAXUW ymm2/m256, ymmV, ymm1","vpmaxuw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 3E /r","V","V","AVX2","","w,r,r","","" +"VPMAXUW ymm1, {k}{z}, ymmV, ymm2/m256","VPMAXUW ymm2/m256, ymmV, {k}{z}, ymm1","vpmaxuw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.WIG 3E /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMAXUW zmm1, {k}{z}, zmmV, zmm2/m512","VPMAXUW zmm2/m512, zmmV, {k}{z}, zmm1","vpmaxuw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.WIG 3E /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMINSB xmm1, xmmV, xmm2/m128","VPMINSB xmm2/m128, xmmV, xmm1","vpminsb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 38 /r","V","V","AVX","","w,r,r","","" +"VPMINSB xmm1, {k}{z}, xmmV, xmm2/m128","VPMINSB xmm2/m128, xmmV, {k}{z}, xmm1","vpminsb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.WIG 38 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMINSB ymm1, ymmV, ymm2/m256","VPMINSB ymm2/m256, ymmV, ymm1","vpminsb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 38 /r","V","V","AVX2","","w,r,r","","" +"VPMINSB ymm1, {k}{z}, ymmV, ymm2/m256","VPMINSB ymm2/m256, ymmV, {k}{z}, ymm1","vpminsb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.WIG 38 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMINSB zmm1, {k}{z}, zmmV, zmm2/m512","VPMINSB zmm2/m512, zmmV, {k}{z}, zmm1","vpminsb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.WIG 38 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMINSD xmm1, xmmV, xmm2/m128","VPMINSD xmm2/m128, xmmV, xmm1","vpminsd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 39 /r","V","V","AVX","","w,r,r","","" +"VPMINSD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPMINSD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpminsd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 39 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPMINSD ymm1, ymmV, ymm2/m256","VPMINSD ymm2/m256, ymmV, ymm1","vpminsd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 39 /r","V","V","AVX2","","w,r,r","","" +"VPMINSD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPMINSD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpminsd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 39 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPMINSD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPMINSD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpminsd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 39 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPMINSQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMINSQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpminsq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 39 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPMINSQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMINSQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpminsq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 39 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPMINSQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMINSQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpminsq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 39 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPMINSW xmm1, xmmV, xmm2/m128","VPMINSW xmm2/m128, xmmV, xmm1","vpminsw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG EA /r","V","V","AVX","","w,r,r","","" +"VPMINSW xmm1, {k}{z}, xmmV, xmm2/m128","VPMINSW xmm2/m128, xmmV, {k}{z}, xmm1","vpminsw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG EA /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMINSW ymm1, ymmV, ymm2/m256","VPMINSW ymm2/m256, ymmV, ymm1","vpminsw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG EA /r","V","V","AVX2","","w,r,r","","" +"VPMINSW ymm1, {k}{z}, ymmV, ymm2/m256","VPMINSW ymm2/m256, ymmV, {k}{z}, ymm1","vpminsw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG EA /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMINSW zmm1, {k}{z}, zmmV, zmm2/m512","VPMINSW zmm2/m512, zmmV, {k}{z}, zmm1","vpminsw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG EA /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMINUB xmm1, xmmV, xmm2/m128","VPMINUB xmm2/m128, xmmV, xmm1","vpminub xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG DA /r","V","V","AVX","","w,r,r","","" +"VPMINUB xmm1, {k}{z}, xmmV, xmm2/m128","VPMINUB xmm2/m128, xmmV, {k}{z}, xmm1","vpminub xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG DA /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMINUB ymm1, ymmV, ymm2/m256","VPMINUB ymm2/m256, ymmV, ymm1","vpminub ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG DA /r","V","V","AVX2","","w,r,r","","" +"VPMINUB ymm1, {k}{z}, ymmV, ymm2/m256","VPMINUB ymm2/m256, ymmV, {k}{z}, ymm1","vpminub ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG DA /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMINUB zmm1, {k}{z}, zmmV, zmm2/m512","VPMINUB zmm2/m512, zmmV, {k}{z}, zmm1","vpminub zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG DA /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMINUD xmm1, xmmV, xmm2/m128","VPMINUD xmm2/m128, xmmV, xmm1","vpminud xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 3B /r","V","V","AVX","","w,r,r","","" +"VPMINUD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPMINUD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpminud xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 3B /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPMINUD ymm1, ymmV, ymm2/m256","VPMINUD ymm2/m256, ymmV, ymm1","vpminud ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 3B /r","V","V","AVX2","","w,r,r","","" +"VPMINUD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPMINUD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpminud ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 3B /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPMINUD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPMINUD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpminud zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 3B /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPMINUQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMINUQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpminuq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 3B /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPMINUQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMINUQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpminuq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 3B /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPMINUQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMINUQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpminuq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 3B /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPMINUW xmm1, xmmV, xmm2/m128","VPMINUW xmm2/m128, xmmV, xmm1","vpminuw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 3A /r","V","V","AVX","","w,r,r","","" +"VPMINUW xmm1, {k}{z}, xmmV, xmm2/m128","VPMINUW xmm2/m128, xmmV, {k}{z}, xmm1","vpminuw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.WIG 3A /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMINUW ymm1, ymmV, ymm2/m256","VPMINUW ymm2/m256, ymmV, ymm1","vpminuw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 3A /r","V","V","AVX2","","w,r,r","","" +"VPMINUW ymm1, {k}{z}, ymmV, ymm2/m256","VPMINUW ymm2/m256, ymmV, {k}{z}, ymm1","vpminuw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.WIG 3A /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMINUW zmm1, {k}{z}, zmmV, zmm2/m512","VPMINUW zmm2/m512, zmmV, {k}{z}, zmm1","vpminuw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.WIG 3A /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMOVB2M k1, xmm2","VPMOVB2M xmm2, k1","vpmovb2m xmm2, k1","EVEX.128.F3.0F38.W0 29 /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r","","" +"VPMOVB2M k1, ymm2","VPMOVB2M ymm2, k1","vpmovb2m ymm2, k1","EVEX.256.F3.0F38.W0 29 /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r","","" +"VPMOVB2M k1, zmm2","VPMOVB2M zmm2, k1","vpmovb2m zmm2, k1","EVEX.512.F3.0F38.W0 29 /r","V","V","AVX512BW","modrm_regonly","w,r","","" +"VPMOVD2M k1, xmm2","VPMOVD2M xmm2, k1","vpmovd2m xmm2, k1","EVEX.128.F3.0F38.W0 39 /r","V","V","AVX512DQ+AVX512VL","modrm_regonly","w,r","","" +"VPMOVD2M k1, ymm2","VPMOVD2M ymm2, k1","vpmovd2m ymm2, k1","EVEX.256.F3.0F38.W0 39 /r","V","V","AVX512DQ+AVX512VL","modrm_regonly","w,r","","" +"VPMOVD2M k1, zmm2","VPMOVD2M zmm2, k1","vpmovd2m zmm2, k1","EVEX.512.F3.0F38.W0 39 /r","V","V","AVX512DQ","modrm_regonly","w,r","","" +"VPMOVDB xmm2/m32, {k}{z}, xmm1","VPMOVDB xmm1, {k}{z}, xmm2/m32","vpmovdb xmm1, {k}{z}, xmm2/m32","EVEX.128.F3.0F38.W0 31 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVDB xmm2/m64, {k}{z}, ymm1","VPMOVDB ymm1, {k}{z}, xmm2/m64","vpmovdb ymm1, {k}{z}, xmm2/m64","EVEX.256.F3.0F38.W0 31 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVDB xmm2/m128, {k}{z}, zmm1","VPMOVDB zmm1, {k}{z}, xmm2/m128","vpmovdb zmm1, {k}{z}, xmm2/m128","EVEX.512.F3.0F38.W0 31 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVDW xmm2/m64, {k}{z}, xmm1","VPMOVDW xmm1, {k}{z}, xmm2/m64","vpmovdw xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 33 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVDW xmm2/m128, {k}{z}, ymm1","VPMOVDW ymm1, {k}{z}, xmm2/m128","vpmovdw ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 33 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVDW ymm2/m256, {k}{z}, zmm1","VPMOVDW zmm1, {k}{z}, ymm2/m256","vpmovdw zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 33 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVM2B xmm1, k2","VPMOVM2B k2, xmm1","vpmovm2b k2, xmm1","EVEX.128.F3.0F38.W0 28 /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r","","" +"VPMOVM2B ymm1, k2","VPMOVM2B k2, ymm1","vpmovm2b k2, ymm1","EVEX.256.F3.0F38.W0 28 /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r","","" +"VPMOVM2B zmm1, k2","VPMOVM2B k2, zmm1","vpmovm2b k2, zmm1","EVEX.512.F3.0F38.W0 28 /r","V","V","AVX512BW","modrm_regonly","w,r","","" +"VPMOVM2D xmm1, k2","VPMOVM2D k2, xmm1","vpmovm2d k2, xmm1","EVEX.128.F3.0F38.W0 38 /r","V","V","AVX512DQ+AVX512VL","modrm_regonly","w,r","","" +"VPMOVM2D ymm1, k2","VPMOVM2D k2, ymm1","vpmovm2d k2, ymm1","EVEX.256.F3.0F38.W0 38 /r","V","V","AVX512DQ+AVX512VL","modrm_regonly","w,r","","" +"VPMOVM2D zmm1, k2","VPMOVM2D k2, zmm1","vpmovm2d k2, zmm1","EVEX.512.F3.0F38.W0 38 /r","V","V","AVX512DQ","modrm_regonly","w,r","","" +"VPMOVM2Q xmm1, k2","VPMOVM2Q k2, xmm1","vpmovm2q k2, xmm1","EVEX.128.F3.0F38.W1 38 /r","V","V","AVX512DQ+AVX512VL","modrm_regonly","w,r","","" +"VPMOVM2Q ymm1, k2","VPMOVM2Q k2, ymm1","vpmovm2q k2, ymm1","EVEX.256.F3.0F38.W1 38 /r","V","V","AVX512DQ+AVX512VL","modrm_regonly","w,r","","" +"VPMOVM2Q zmm1, k2","VPMOVM2Q k2, zmm1","vpmovm2q k2, zmm1","EVEX.512.F3.0F38.W1 38 /r","V","V","AVX512DQ","modrm_regonly","w,r","","" +"VPMOVM2W xmm1, k2","VPMOVM2W k2, xmm1","vpmovm2w k2, xmm1","EVEX.128.F3.0F38.W1 28 /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r","","" +"VPMOVM2W ymm1, k2","VPMOVM2W k2, ymm1","vpmovm2w k2, ymm1","EVEX.256.F3.0F38.W1 28 /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r","","" +"VPMOVM2W zmm1, k2","VPMOVM2W k2, zmm1","vpmovm2w k2, zmm1","EVEX.512.F3.0F38.W1 28 /r","V","V","AVX512BW","modrm_regonly","w,r","","" +"VPMOVMSKB r32, xmm2","VPMOVMSKB xmm2, r32","vpmovmskb xmm2, r32","VEX.128.66.0F.WIG D7 /r","V","V","AVX","modrm_regonly","w,r","","" +"VPMOVMSKB r32, ymm2","VPMOVMSKB ymm2, r32","vpmovmskb ymm2, r32","VEX.256.66.0F.WIG D7 /r","V","V","AVX2","modrm_regonly","w,r","","" +"VPMOVQ2M k1, xmm2","VPMOVQ2M xmm2, k1","vpmovq2m xmm2, k1","EVEX.128.F3.0F38.W1 39 /r","V","V","AVX512DQ+AVX512VL","modrm_regonly","w,r","","" +"VPMOVQ2M k1, ymm2","VPMOVQ2M ymm2, k1","vpmovq2m ymm2, k1","EVEX.256.F3.0F38.W1 39 /r","V","V","AVX512DQ+AVX512VL","modrm_regonly","w,r","","" +"VPMOVQ2M k1, zmm2","VPMOVQ2M zmm2, k1","vpmovq2m zmm2, k1","EVEX.512.F3.0F38.W1 39 /r","V","V","AVX512DQ","modrm_regonly","w,r","","" +"VPMOVQB xmm2/m16, {k}{z}, xmm1","VPMOVQB xmm1, {k}{z}, xmm2/m16","vpmovqb xmm1, {k}{z}, xmm2/m16","EVEX.128.F3.0F38.W0 32 /r","V","V","AVX512F+AVX512VL","scale2","w,r,r","","" +"VPMOVQB xmm2/m32, {k}{z}, ymm1","VPMOVQB ymm1, {k}{z}, xmm2/m32","vpmovqb ymm1, {k}{z}, xmm2/m32","EVEX.256.F3.0F38.W0 32 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVQB xmm2/m64, {k}{z}, zmm1","VPMOVQB zmm1, {k}{z}, xmm2/m64","vpmovqb zmm1, {k}{z}, xmm2/m64","EVEX.512.F3.0F38.W0 32 /r","V","V","AVX512F","scale8","w,r,r","","" +"VPMOVQD xmm2/m64, {k}{z}, xmm1","VPMOVQD xmm1, {k}{z}, xmm2/m64","vpmovqd xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 35 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVQD xmm2/m128, {k}{z}, ymm1","VPMOVQD ymm1, {k}{z}, xmm2/m128","vpmovqd ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 35 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVQD ymm2/m256, {k}{z}, zmm1","VPMOVQD zmm1, {k}{z}, ymm2/m256","vpmovqd zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 35 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVQW xmm2/m32, {k}{z}, xmm1","VPMOVQW xmm1, {k}{z}, xmm2/m32","vpmovqw xmm1, {k}{z}, xmm2/m32","EVEX.128.F3.0F38.W0 34 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVQW xmm2/m64, {k}{z}, ymm1","VPMOVQW ymm1, {k}{z}, xmm2/m64","vpmovqw ymm1, {k}{z}, xmm2/m64","EVEX.256.F3.0F38.W0 34 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVQW xmm2/m128, {k}{z}, zmm1","VPMOVQW zmm1, {k}{z}, xmm2/m128","vpmovqw zmm1, {k}{z}, xmm2/m128","EVEX.512.F3.0F38.W0 34 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVSDB xmm2/m32, {k}{z}, xmm1","VPMOVSDB xmm1, {k}{z}, xmm2/m32","vpmovsdb xmm1, {k}{z}, xmm2/m32","EVEX.128.F3.0F38.W0 21 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVSDB xmm2/m64, {k}{z}, ymm1","VPMOVSDB ymm1, {k}{z}, xmm2/m64","vpmovsdb ymm1, {k}{z}, xmm2/m64","EVEX.256.F3.0F38.W0 21 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVSDB xmm2/m128, {k}{z}, zmm1","VPMOVSDB zmm1, {k}{z}, xmm2/m128","vpmovsdb zmm1, {k}{z}, xmm2/m128","EVEX.512.F3.0F38.W0 21 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVSDW xmm2/m64, {k}{z}, xmm1","VPMOVSDW xmm1, {k}{z}, xmm2/m64","vpmovsdw xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 23 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVSDW xmm2/m128, {k}{z}, ymm1","VPMOVSDW ymm1, {k}{z}, xmm2/m128","vpmovsdw ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 23 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVSDW ymm2/m256, {k}{z}, zmm1","VPMOVSDW zmm1, {k}{z}, ymm2/m256","vpmovsdw zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 23 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVSQB xmm2/m16, {k}{z}, xmm1","VPMOVSQB xmm1, {k}{z}, xmm2/m16","vpmovsqb xmm1, {k}{z}, xmm2/m16","EVEX.128.F3.0F38.W0 22 /r","V","V","AVX512F+AVX512VL","scale2","w,r,r","","" +"VPMOVSQB xmm2/m32, {k}{z}, ymm1","VPMOVSQB ymm1, {k}{z}, xmm2/m32","vpmovsqb ymm1, {k}{z}, xmm2/m32","EVEX.256.F3.0F38.W0 22 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVSQB xmm2/m64, {k}{z}, zmm1","VPMOVSQB zmm1, {k}{z}, xmm2/m64","vpmovsqb zmm1, {k}{z}, xmm2/m64","EVEX.512.F3.0F38.W0 22 /r","V","V","AVX512F","scale8","w,r,r","","" +"VPMOVSQD xmm2/m64, {k}{z}, xmm1","VPMOVSQD xmm1, {k}{z}, xmm2/m64","vpmovsqd xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 25 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVSQD xmm2/m128, {k}{z}, ymm1","VPMOVSQD ymm1, {k}{z}, xmm2/m128","vpmovsqd ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 25 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVSQD ymm2/m256, {k}{z}, zmm1","VPMOVSQD zmm1, {k}{z}, ymm2/m256","vpmovsqd zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 25 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVSQW xmm2/m32, {k}{z}, xmm1","VPMOVSQW xmm1, {k}{z}, xmm2/m32","vpmovsqw xmm1, {k}{z}, xmm2/m32","EVEX.128.F3.0F38.W0 24 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVSQW xmm2/m64, {k}{z}, ymm1","VPMOVSQW ymm1, {k}{z}, xmm2/m64","vpmovsqw ymm1, {k}{z}, xmm2/m64","EVEX.256.F3.0F38.W0 24 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVSQW xmm2/m128, {k}{z}, zmm1","VPMOVSQW zmm1, {k}{z}, xmm2/m128","vpmovsqw zmm1, {k}{z}, xmm2/m128","EVEX.512.F3.0F38.W0 24 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVSWB xmm2/m64, {k}{z}, xmm1","VPMOVSWB xmm1, {k}{z}, xmm2/m64","vpmovswb xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 20 /r","V","V","AVX512BW+AVX512VL","scale8","w,r,r","","" +"VPMOVSWB xmm2/m128, {k}{z}, ymm1","VPMOVSWB ymm1, {k}{z}, xmm2/m128","vpmovswb ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 20 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPMOVSWB ymm2/m256, {k}{z}, zmm1","VPMOVSWB zmm1, {k}{z}, ymm2/m256","vpmovswb zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 20 /r","V","V","AVX512BW","scale32","w,r,r","","" +"VPMOVSXBD zmm1, {k}{z}, xmm2/m128","VPMOVSXBD xmm2/m128, {k}{z}, zmm1","vpmovsxbd xmm2/m128, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 21 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVSXBD xmm1, xmm2/m32","VPMOVSXBD xmm2/m32, xmm1","vpmovsxbd xmm2/m32, xmm1","VEX.128.66.0F38.WIG 21 /r","V","V","AVX","","w,r","","" +"VPMOVSXBD xmm1, {k}{z}, xmm2/m32","VPMOVSXBD xmm2/m32, {k}{z}, xmm1","vpmovsxbd xmm2/m32, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 21 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVSXBD ymm1, xmm2/m64","VPMOVSXBD xmm2/m64, ymm1","vpmovsxbd xmm2/m64, ymm1","VEX.256.66.0F38.WIG 21 /r","V","V","AVX2","","w,r","","" +"VPMOVSXBD ymm1, {k}{z}, xmm2/m64","VPMOVSXBD xmm2/m64, {k}{z}, ymm1","vpmovsxbd xmm2/m64, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 21 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVSXBQ xmm1, xmm2/m16","VPMOVSXBQ xmm2/m16, xmm1","vpmovsxbq xmm2/m16, xmm1","VEX.128.66.0F38.WIG 22 /r","V","V","AVX","","w,r","","" +"VPMOVSXBQ xmm1, {k}{z}, xmm2/m16","VPMOVSXBQ xmm2/m16, {k}{z}, xmm1","vpmovsxbq xmm2/m16, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 22 /r","V","V","AVX512F+AVX512VL","scale2","w,r,r","","" +"VPMOVSXBQ ymm1, xmm2/m32","VPMOVSXBQ xmm2/m32, ymm1","vpmovsxbq xmm2/m32, ymm1","VEX.256.66.0F38.WIG 22 /r","V","V","AVX2","","w,r","","" +"VPMOVSXBQ ymm1, {k}{z}, xmm2/m32","VPMOVSXBQ xmm2/m32, {k}{z}, ymm1","vpmovsxbq xmm2/m32, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 22 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVSXBQ zmm1, {k}{z}, xmm2/m64","VPMOVSXBQ xmm2/m64, {k}{z}, zmm1","vpmovsxbq xmm2/m64, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 22 /r","V","V","AVX512F","scale8","w,r,r","","" +"VPMOVSXBW ymm1, xmm2/m128","VPMOVSXBW xmm2/m128, ymm1","vpmovsxbw xmm2/m128, ymm1","VEX.256.66.0F38.WIG 20 /r","V","V","AVX2","","w,r","","" +"VPMOVSXBW ymm1, {k}{z}, xmm2/m128","VPMOVSXBW xmm2/m128, {k}{z}, ymm1","vpmovsxbw xmm2/m128, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 20 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPMOVSXBW xmm1, xmm2/m64","VPMOVSXBW xmm2/m64, xmm1","vpmovsxbw xmm2/m64, xmm1","VEX.128.66.0F38.WIG 20 /r","V","V","AVX","","w,r","","" +"VPMOVSXBW xmm1, {k}{z}, xmm2/m64","VPMOVSXBW xmm2/m64, {k}{z}, xmm1","vpmovsxbw xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 20 /r","V","V","AVX512BW+AVX512VL","scale8","w,r,r","","" +"VPMOVSXBW zmm1, {k}{z}, ymm2/m256","VPMOVSXBW ymm2/m256, {k}{z}, zmm1","vpmovsxbw ymm2/m256, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 20 /r","V","V","AVX512BW","scale32","w,r,r","","" +"VPMOVSXDQ ymm1, xmm2/m128","VPMOVSXDQ xmm2/m128, ymm1","vpmovsxdq xmm2/m128, ymm1","VEX.256.66.0F38.WIG 25 /r","V","V","AVX2","","w,r","","" +"VPMOVSXDQ ymm1, {k}{z}, xmm2/m128","VPMOVSXDQ xmm2/m128, {k}{z}, ymm1","vpmovsxdq xmm2/m128, {k}{z}, ymm1","EVEX.256.66.0F38.W0 25 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVSXDQ xmm1, xmm2/m64","VPMOVSXDQ xmm2/m64, xmm1","vpmovsxdq xmm2/m64, xmm1","VEX.128.66.0F38.WIG 25 /r","V","V","AVX","","w,r","","" +"VPMOVSXDQ xmm1, {k}{z}, xmm2/m64","VPMOVSXDQ xmm2/m64, {k}{z}, xmm1","vpmovsxdq xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.W0 25 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVSXDQ zmm1, {k}{z}, ymm2/m256","VPMOVSXDQ ymm2/m256, {k}{z}, zmm1","vpmovsxdq ymm2/m256, {k}{z}, zmm1","EVEX.512.66.0F38.W0 25 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVSXWD ymm1, xmm2/m128","VPMOVSXWD xmm2/m128, ymm1","vpmovsxwd xmm2/m128, ymm1","VEX.256.66.0F38.WIG 23 /r","V","V","AVX2","","w,r","","" +"VPMOVSXWD ymm1, {k}{z}, xmm2/m128","VPMOVSXWD xmm2/m128, {k}{z}, ymm1","vpmovsxwd xmm2/m128, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 23 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVSXWD xmm1, xmm2/m64","VPMOVSXWD xmm2/m64, xmm1","vpmovsxwd xmm2/m64, xmm1","VEX.128.66.0F38.WIG 23 /r","V","V","AVX","","w,r","","" +"VPMOVSXWD xmm1, {k}{z}, xmm2/m64","VPMOVSXWD xmm2/m64, {k}{z}, xmm1","vpmovsxwd xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 23 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVSXWD zmm1, {k}{z}, ymm2/m256","VPMOVSXWD ymm2/m256, {k}{z}, zmm1","vpmovsxwd ymm2/m256, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 23 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVSXWQ zmm1, {k}{z}, xmm2/m128","VPMOVSXWQ xmm2/m128, {k}{z}, zmm1","vpmovsxwq xmm2/m128, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 24 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVSXWQ xmm1, xmm2/m32","VPMOVSXWQ xmm2/m32, xmm1","vpmovsxwq xmm2/m32, xmm1","VEX.128.66.0F38.WIG 24 /r","V","V","AVX","","w,r","","" +"VPMOVSXWQ xmm1, {k}{z}, xmm2/m32","VPMOVSXWQ xmm2/m32, {k}{z}, xmm1","vpmovsxwq xmm2/m32, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 24 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVSXWQ ymm1, xmm2/m64","VPMOVSXWQ xmm2/m64, ymm1","vpmovsxwq xmm2/m64, ymm1","VEX.256.66.0F38.WIG 24 /r","V","V","AVX2","","w,r","","" +"VPMOVSXWQ ymm1, {k}{z}, xmm2/m64","VPMOVSXWQ xmm2/m64, {k}{z}, ymm1","vpmovsxwq xmm2/m64, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 24 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVUSDB xmm2/m32, {k}{z}, xmm1","VPMOVUSDB xmm1, {k}{z}, xmm2/m32","vpmovusdb xmm1, {k}{z}, xmm2/m32","EVEX.128.F3.0F38.W0 11 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVUSDB xmm2/m64, {k}{z}, ymm1","VPMOVUSDB ymm1, {k}{z}, xmm2/m64","vpmovusdb ymm1, {k}{z}, xmm2/m64","EVEX.256.F3.0F38.W0 11 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVUSDB xmm2/m128, {k}{z}, zmm1","VPMOVUSDB zmm1, {k}{z}, xmm2/m128","vpmovusdb zmm1, {k}{z}, xmm2/m128","EVEX.512.F3.0F38.W0 11 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVUSDW xmm2/m64, {k}{z}, xmm1","VPMOVUSDW xmm1, {k}{z}, xmm2/m64","vpmovusdw xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 13 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVUSDW xmm2/m128, {k}{z}, ymm1","VPMOVUSDW ymm1, {k}{z}, xmm2/m128","vpmovusdw ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 13 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVUSDW ymm2/m256, {k}{z}, zmm1","VPMOVUSDW zmm1, {k}{z}, ymm2/m256","vpmovusdw zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 13 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVUSQB xmm2/m16, {k}{z}, xmm1","VPMOVUSQB xmm1, {k}{z}, xmm2/m16","vpmovusqb xmm1, {k}{z}, xmm2/m16","EVEX.128.F3.0F38.W0 12 /r","V","V","AVX512F+AVX512VL","scale2","w,r,r","","" +"VPMOVUSQB xmm2/m32, {k}{z}, ymm1","VPMOVUSQB ymm1, {k}{z}, xmm2/m32","vpmovusqb ymm1, {k}{z}, xmm2/m32","EVEX.256.F3.0F38.W0 12 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVUSQB xmm2/m64, {k}{z}, zmm1","VPMOVUSQB zmm1, {k}{z}, xmm2/m64","vpmovusqb zmm1, {k}{z}, xmm2/m64","EVEX.512.F3.0F38.W0 12 /r","V","V","AVX512F","scale8","w,r,r","","" +"VPMOVUSQD xmm2/m64, {k}{z}, xmm1","VPMOVUSQD xmm1, {k}{z}, xmm2/m64","vpmovusqd xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 15 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVUSQD xmm2/m128, {k}{z}, ymm1","VPMOVUSQD ymm1, {k}{z}, xmm2/m128","vpmovusqd ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 15 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVUSQD ymm2/m256, {k}{z}, zmm1","VPMOVUSQD zmm1, {k}{z}, ymm2/m256","vpmovusqd zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 15 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVUSQW xmm2/m32, {k}{z}, xmm1","VPMOVUSQW xmm1, {k}{z}, xmm2/m32","vpmovusqw xmm1, {k}{z}, xmm2/m32","EVEX.128.F3.0F38.W0 14 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVUSQW xmm2/m64, {k}{z}, ymm1","VPMOVUSQW ymm1, {k}{z}, xmm2/m64","vpmovusqw ymm1, {k}{z}, xmm2/m64","EVEX.256.F3.0F38.W0 14 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVUSQW xmm2/m128, {k}{z}, zmm1","VPMOVUSQW zmm1, {k}{z}, xmm2/m128","vpmovusqw zmm1, {k}{z}, xmm2/m128","EVEX.512.F3.0F38.W0 14 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVUSWB xmm2/m64, {k}{z}, xmm1","VPMOVUSWB xmm1, {k}{z}, xmm2/m64","vpmovuswb xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 10 /r","V","V","AVX512BW+AVX512VL","scale8","w,r,r","","" +"VPMOVUSWB xmm2/m128, {k}{z}, ymm1","VPMOVUSWB ymm1, {k}{z}, xmm2/m128","vpmovuswb ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 10 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPMOVUSWB ymm2/m256, {k}{z}, zmm1","VPMOVUSWB zmm1, {k}{z}, ymm2/m256","vpmovuswb zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 10 /r","V","V","AVX512BW","scale32","w,r,r","","" +"VPMOVW2M k1, xmm2","VPMOVW2M xmm2, k1","vpmovw2m xmm2, k1","EVEX.128.F3.0F38.W1 29 /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r","","" +"VPMOVW2M k1, ymm2","VPMOVW2M ymm2, k1","vpmovw2m ymm2, k1","EVEX.256.F3.0F38.W1 29 /r","V","V","AVX512BW+AVX512VL","modrm_regonly","w,r","","" +"VPMOVW2M k1, zmm2","VPMOVW2M zmm2, k1","vpmovw2m zmm2, k1","EVEX.512.F3.0F38.W1 29 /r","V","V","AVX512BW","modrm_regonly","w,r","","" +"VPMOVWB xmm2/m64, {k}{z}, xmm1","VPMOVWB xmm1, {k}{z}, xmm2/m64","vpmovwb xmm1, {k}{z}, xmm2/m64","EVEX.128.F3.0F38.W0 30 /r","V","V","AVX512BW+AVX512VL","scale8","w,r,r","","" +"VPMOVWB xmm2/m128, {k}{z}, ymm1","VPMOVWB ymm1, {k}{z}, xmm2/m128","vpmovwb ymm1, {k}{z}, xmm2/m128","EVEX.256.F3.0F38.W0 30 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPMOVWB ymm2/m256, {k}{z}, zmm1","VPMOVWB zmm1, {k}{z}, ymm2/m256","vpmovwb zmm1, {k}{z}, ymm2/m256","EVEX.512.F3.0F38.W0 30 /r","V","V","AVX512BW","scale32","w,r,r","","" +"VPMOVZXBD zmm1, {k}{z}, xmm2/m128","VPMOVZXBD xmm2/m128, {k}{z}, zmm1","vpmovzxbd xmm2/m128, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 31 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVZXBD xmm1, xmm2/m32","VPMOVZXBD xmm2/m32, xmm1","vpmovzxbd xmm2/m32, xmm1","VEX.128.66.0F38.WIG 31 /r","V","V","AVX","","w,r","","" +"VPMOVZXBD xmm1, {k}{z}, xmm2/m32","VPMOVZXBD xmm2/m32, {k}{z}, xmm1","vpmovzxbd xmm2/m32, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 31 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVZXBD ymm1, xmm2/m64","VPMOVZXBD xmm2/m64, ymm1","vpmovzxbd xmm2/m64, ymm1","VEX.256.66.0F38.WIG 31 /r","V","V","AVX2","","w,r","","" +"VPMOVZXBD ymm1, {k}{z}, xmm2/m64","VPMOVZXBD xmm2/m64, {k}{z}, ymm1","vpmovzxbd xmm2/m64, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 31 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVZXBQ xmm1, xmm2/m16","VPMOVZXBQ xmm2/m16, xmm1","vpmovzxbq xmm2/m16, xmm1","VEX.128.66.0F38.WIG 32 /r","V","V","AVX","","w,r","","" +"VPMOVZXBQ xmm1, {k}{z}, xmm2/m16","VPMOVZXBQ xmm2/m16, {k}{z}, xmm1","vpmovzxbq xmm2/m16, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 32 /r","V","V","AVX512F+AVX512VL","scale2","w,r,r","","" +"VPMOVZXBQ ymm1, xmm2/m32","VPMOVZXBQ xmm2/m32, ymm1","vpmovzxbq xmm2/m32, ymm1","VEX.256.66.0F38.WIG 32 /r","V","V","AVX2","","w,r","","" +"VPMOVZXBQ ymm1, {k}{z}, xmm2/m32","VPMOVZXBQ xmm2/m32, {k}{z}, ymm1","vpmovzxbq xmm2/m32, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 32 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVZXBQ zmm1, {k}{z}, xmm2/m64","VPMOVZXBQ xmm2/m64, {k}{z}, zmm1","vpmovzxbq xmm2/m64, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 32 /r","V","V","AVX512F","scale8","w,r,r","","" +"VPMOVZXBW ymm1, xmm2/m128","VPMOVZXBW xmm2/m128, ymm1","vpmovzxbw xmm2/m128, ymm1","VEX.256.66.0F38.WIG 30 /r","V","V","AVX2","","w,r","","" +"VPMOVZXBW ymm1, {k}{z}, xmm2/m128","VPMOVZXBW xmm2/m128, {k}{z}, ymm1","vpmovzxbw xmm2/m128, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 30 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPMOVZXBW xmm1, xmm2/m64","VPMOVZXBW xmm2/m64, xmm1","vpmovzxbw xmm2/m64, xmm1","VEX.128.66.0F38.WIG 30 /r","V","V","AVX","","w,r","","" +"VPMOVZXBW xmm1, {k}{z}, xmm2/m64","VPMOVZXBW xmm2/m64, {k}{z}, xmm1","vpmovzxbw xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 30 /r","V","V","AVX512BW+AVX512VL","scale8","w,r,r","","" +"VPMOVZXBW zmm1, {k}{z}, ymm2/m256","VPMOVZXBW ymm2/m256, {k}{z}, zmm1","vpmovzxbw ymm2/m256, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 30 /r","V","V","AVX512BW","scale32","w,r,r","","" +"VPMOVZXDQ ymm1, xmm2/m128","VPMOVZXDQ xmm2/m128, ymm1","vpmovzxdq xmm2/m128, ymm1","VEX.256.66.0F38.WIG 35 /r","V","V","AVX2","","w,r","","" +"VPMOVZXDQ ymm1, {k}{z}, xmm2/m128","VPMOVZXDQ xmm2/m128, {k}{z}, ymm1","vpmovzxdq xmm2/m128, {k}{z}, ymm1","EVEX.256.66.0F38.W0 35 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVZXDQ xmm1, xmm2/m64","VPMOVZXDQ xmm2/m64, xmm1","vpmovzxdq xmm2/m64, xmm1","VEX.128.66.0F38.WIG 35 /r","V","V","AVX","","w,r","","" +"VPMOVZXDQ xmm1, {k}{z}, xmm2/m64","VPMOVZXDQ xmm2/m64, {k}{z}, xmm1","vpmovzxdq xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.W0 35 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVZXDQ zmm1, {k}{z}, ymm2/m256","VPMOVZXDQ ymm2/m256, {k}{z}, zmm1","vpmovzxdq ymm2/m256, {k}{z}, zmm1","EVEX.512.66.0F38.W0 35 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVZXWD ymm1, xmm2/m128","VPMOVZXWD xmm2/m128, ymm1","vpmovzxwd xmm2/m128, ymm1","VEX.256.66.0F38.WIG 33 /r","V","V","AVX2","","w,r","","" +"VPMOVZXWD ymm1, {k}{z}, xmm2/m128","VPMOVZXWD xmm2/m128, {k}{z}, ymm1","vpmovzxwd xmm2/m128, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 33 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r","","" +"VPMOVZXWD xmm1, xmm2/m64","VPMOVZXWD xmm2/m64, xmm1","vpmovzxwd xmm2/m64, xmm1","VEX.128.66.0F38.WIG 33 /r","V","V","AVX","","w,r","","" +"VPMOVZXWD xmm1, {k}{z}, xmm2/m64","VPMOVZXWD xmm2/m64, {k}{z}, xmm1","vpmovzxwd xmm2/m64, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 33 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMOVZXWD zmm1, {k}{z}, ymm2/m256","VPMOVZXWD ymm2/m256, {k}{z}, zmm1","vpmovzxwd ymm2/m256, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 33 /r","V","V","AVX512F","scale32","w,r,r","","" +"VPMOVZXWQ zmm1, {k}{z}, xmm2/m128","VPMOVZXWQ xmm2/m128, {k}{z}, zmm1","vpmovzxwq xmm2/m128, {k}{z}, zmm1","EVEX.512.66.0F38.WIG 34 /r","V","V","AVX512F","scale16","w,r,r","","" +"VPMOVZXWQ xmm1, xmm2/m32","VPMOVZXWQ xmm2/m32, xmm1","vpmovzxwq xmm2/m32, xmm1","VEX.128.66.0F38.WIG 34 /r","V","V","AVX","","w,r","","" +"VPMOVZXWQ xmm1, {k}{z}, xmm2/m32","VPMOVZXWQ xmm2/m32, {k}{z}, xmm1","vpmovzxwq xmm2/m32, {k}{z}, xmm1","EVEX.128.66.0F38.WIG 34 /r","V","V","AVX512F+AVX512VL","scale4","w,r,r","","" +"VPMOVZXWQ ymm1, xmm2/m64","VPMOVZXWQ xmm2/m64, ymm1","vpmovzxwq xmm2/m64, ymm1","VEX.256.66.0F38.WIG 34 /r","V","V","AVX2","","w,r","","" +"VPMOVZXWQ ymm1, {k}{z}, xmm2/m64","VPMOVZXWQ xmm2/m64, {k}{z}, ymm1","vpmovzxwq xmm2/m64, {k}{z}, ymm1","EVEX.256.66.0F38.WIG 34 /r","V","V","AVX512F+AVX512VL","scale8","w,r,r","","" +"VPMULDQ xmm1, xmmV, xmm2/m128","VPMULDQ xmm2/m128, xmmV, xmm1","vpmuldq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 28 /r","V","V","AVX","","w,r,r","","" +"VPMULDQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMULDQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpmuldq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 28 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPMULDQ ymm1, ymmV, ymm2/m256","VPMULDQ ymm2/m256, ymmV, ymm1","vpmuldq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 28 /r","V","V","AVX2","","w,r,r","","" +"VPMULDQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMULDQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpmuldq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 28 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPMULDQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMULDQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpmuldq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 28 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPMULHRSW xmm1, xmmV, xmm2/m128","VPMULHRSW xmm2/m128, xmmV, xmm1","vpmulhrsw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 0B /r","V","V","AVX","","w,r,r","","" +"VPMULHRSW xmm1, {k}{z}, xmmV, xmm2/m128","VPMULHRSW xmm2/m128, xmmV, {k}{z}, xmm1","vpmulhrsw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.WIG 0B /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMULHRSW ymm1, ymmV, ymm2/m256","VPMULHRSW ymm2/m256, ymmV, ymm1","vpmulhrsw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 0B /r","V","V","AVX2","","w,r,r","","" +"VPMULHRSW ymm1, {k}{z}, ymmV, ymm2/m256","VPMULHRSW ymm2/m256, ymmV, {k}{z}, ymm1","vpmulhrsw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.WIG 0B /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMULHRSW zmm1, {k}{z}, zmmV, zmm2/m512","VPMULHRSW zmm2/m512, zmmV, {k}{z}, zmm1","vpmulhrsw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.WIG 0B /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMULHUW xmm1, xmmV, xmm2/m128","VPMULHUW xmm2/m128, xmmV, xmm1","vpmulhuw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG E4 /r","V","V","AVX","","w,r,r","","" +"VPMULHUW xmm1, {k}{z}, xmmV, xmm2/m128","VPMULHUW xmm2/m128, xmmV, {k}{z}, xmm1","vpmulhuw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG E4 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMULHUW ymm1, ymmV, ymm2/m256","VPMULHUW ymm2/m256, ymmV, ymm1","vpmulhuw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG E4 /r","V","V","AVX2","","w,r,r","","" +"VPMULHUW ymm1, {k}{z}, ymmV, ymm2/m256","VPMULHUW ymm2/m256, ymmV, {k}{z}, ymm1","vpmulhuw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG E4 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMULHUW zmm1, {k}{z}, zmmV, zmm2/m512","VPMULHUW zmm2/m512, zmmV, {k}{z}, zmm1","vpmulhuw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG E4 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMULHW xmm1, xmmV, xmm2/m128","VPMULHW xmm2/m128, xmmV, xmm1","vpmulhw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG E5 /r","V","V","AVX","","w,r,r","","" +"VPMULHW xmm1, {k}{z}, xmmV, xmm2/m128","VPMULHW xmm2/m128, xmmV, {k}{z}, xmm1","vpmulhw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG E5 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMULHW ymm1, ymmV, ymm2/m256","VPMULHW ymm2/m256, ymmV, ymm1","vpmulhw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG E5 /r","V","V","AVX2","","w,r,r","","" +"VPMULHW ymm1, {k}{z}, ymmV, ymm2/m256","VPMULHW ymm2/m256, ymmV, {k}{z}, ymm1","vpmulhw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG E5 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMULHW zmm1, {k}{z}, zmmV, zmm2/m512","VPMULHW zmm2/m512, zmmV, {k}{z}, zmm1","vpmulhw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG E5 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMULLD xmm1, xmmV, xmm2/m128","VPMULLD xmm2/m128, xmmV, xmm1","vpmulld xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 40 /r","V","V","AVX","","w,r,r","","" +"VPMULLD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPMULLD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpmulld xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 40 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPMULLD ymm1, ymmV, ymm2/m256","VPMULLD ymm2/m256, ymmV, ymm1","vpmulld ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 40 /r","V","V","AVX2","","w,r,r","","" +"VPMULLD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPMULLD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpmulld ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 40 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPMULLD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPMULLD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpmulld zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 40 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPMULLQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMULLQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpmullq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 40 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPMULLQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMULLQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpmullq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 40 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPMULLQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMULLQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpmullq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 40 /r","V","V","AVX512DQ","bscale8,scale64","w,r,r,r","","" +"VPMULLW xmm1, xmmV, xmm2/m128","VPMULLW xmm2/m128, xmmV, xmm1","vpmullw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG D5 /r","V","V","AVX","","w,r,r","","" +"VPMULLW xmm1, {k}{z}, xmmV, xmm2/m128","VPMULLW xmm2/m128, xmmV, {k}{z}, xmm1","vpmullw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG D5 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPMULLW ymm1, ymmV, ymm2/m256","VPMULLW ymm2/m256, ymmV, ymm1","vpmullw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG D5 /r","V","V","AVX2","","w,r,r","","" +"VPMULLW ymm1, {k}{z}, ymmV, ymm2/m256","VPMULLW ymm2/m256, ymmV, {k}{z}, ymm1","vpmullw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG D5 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPMULLW zmm1, {k}{z}, zmmV, zmm2/m512","VPMULLW zmm2/m512, zmmV, {k}{z}, zmm1","vpmullw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG D5 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPMULTISHIFTQB xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMULTISHIFTQB xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpmultishiftqb xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 83 /r","V","V","AVX512_VBMI+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPMULTISHIFTQB ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMULTISHIFTQB ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpmultishiftqb ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 83 /r","V","V","AVX512_VBMI+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPMULTISHIFTQB zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMULTISHIFTQB zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpmultishiftqb zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 83 /r","V","V","AVX512_VBMI","bscale8,scale64","w,r,r,r","","" +"VPMULUDQ xmm1, xmmV, xmm2/m128","VPMULUDQ xmm2/m128, xmmV, xmm1","vpmuludq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG F4 /r","V","V","AVX","","w,r,r","","" +"VPMULUDQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPMULUDQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpmuludq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 F4 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPMULUDQ ymm1, ymmV, ymm2/m256","VPMULUDQ ymm2/m256, ymmV, ymm1","vpmuludq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG F4 /r","V","V","AVX2","","w,r,r","","" +"VPMULUDQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPMULUDQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpmuludq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 F4 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPMULUDQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPMULUDQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpmuludq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 F4 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPOPCNTB xmm1, {k}{z}, xmm2/m128","VPOPCNTB xmm2/m128, {k}{z}, xmm1","vpopcntb xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.W0 54 /r","V","V","AVX512_BITALG+AVX512VL","scale16","w,r,r","","" +"VPOPCNTB ymm1, {k}{z}, ymm2/m256","VPOPCNTB ymm2/m256, {k}{z}, ymm1","vpopcntb ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.W0 54 /r","V","V","AVX512_BITALG+AVX512VL","scale32","w,r,r","","" +"VPOPCNTB zmm1, {k}{z}, zmm2/m512","VPOPCNTB zmm2/m512, {k}{z}, zmm1","vpopcntb zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.W0 54 /r","V","V","AVX512_BITALG","scale64","w,r,r","","" +"VPOPCNTD xmm1, {k}{z}, xmm2/m128/m32bcst","VPOPCNTD xmm2/m128/m32bcst, {k}{z}, xmm1","vpopcntd xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W0 55 /r","V","V","AVX512_VPOPCNTDQ+AVX512VL","bscale4,scale16","w,r,r","","" +"VPOPCNTD ymm1, {k}{z}, ymm2/m256/m32bcst","VPOPCNTD ymm2/m256/m32bcst, {k}{z}, ymm1","vpopcntd ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W0 55 /r","V","V","AVX512_VPOPCNTDQ+AVX512VL","bscale4,scale32","w,r,r","","" +"VPOPCNTD zmm1, {k}{z}, zmm2/m512/m32bcst","VPOPCNTD zmm2/m512/m32bcst, {k}{z}, zmm1","vpopcntd zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 55 /r","V","V","AVX512_VPOPCNTDQ","bscale4,scale64","w,r,r","","" +"VPOPCNTQ xmm1, {k}{z}, xmm2/m128/m64bcst","VPOPCNTQ xmm2/m128/m64bcst, {k}{z}, xmm1","vpopcntq xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W1 55 /r","V","V","AVX512_VPOPCNTDQ+AVX512VL","bscale8,scale16","w,r,r","","" +"VPOPCNTQ ymm1, {k}{z}, ymm2/m256/m64bcst","VPOPCNTQ ymm2/m256/m64bcst, {k}{z}, ymm1","vpopcntq ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W1 55 /r","V","V","AVX512_VPOPCNTDQ+AVX512VL","bscale8,scale32","w,r,r","","" +"VPOPCNTQ zmm1, {k}{z}, zmm2/m512/m64bcst","VPOPCNTQ zmm2/m512/m64bcst, {k}{z}, zmm1","vpopcntq zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 55 /r","V","V","AVX512_VPOPCNTDQ","bscale8,scale64","w,r,r","","" +"VPOPCNTW xmm1, {k}{z}, xmm2/m128","VPOPCNTW xmm2/m128, {k}{z}, xmm1","vpopcntw xmm2/m128, {k}{z}, xmm1","EVEX.128.66.0F38.W1 54 /r","V","V","AVX512_BITALG+AVX512VL","scale16","w,r,r","","" +"VPOPCNTW ymm1, {k}{z}, ymm2/m256","VPOPCNTW ymm2/m256, {k}{z}, ymm1","vpopcntw ymm2/m256, {k}{z}, ymm1","EVEX.256.66.0F38.W1 54 /r","V","V","AVX512_BITALG+AVX512VL","scale32","w,r,r","","" +"VPOPCNTW zmm1, {k}{z}, zmm2/m512","VPOPCNTW zmm2/m512, {k}{z}, zmm1","vpopcntw zmm2/m512, {k}{z}, zmm1","EVEX.512.66.0F38.W1 54 /r","V","V","AVX512_BITALG","scale64","w,r,r","","" +"VPOR xmm1, xmmV, xmm2/m128","VPOR xmm2/m128, xmmV, xmm1","vpor xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG EB /r","V","V","AVX","","w,r,r","","" +"VPOR ymm1, ymmV, ymm2/m256","VPOR ymm2/m256, ymmV, ymm1","vpor ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG EB /r","V","V","AVX2","","w,r,r","","" +"VPORD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPORD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpord xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 EB /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPORD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPORD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpord ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 EB /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPORD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPORD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpord zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 EB /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPORQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPORQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vporq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 EB /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPORQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPORQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vporq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 EB /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPORQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPORQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vporq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 EB /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPPERM xmm1, xmmV, xmmIH, xmm2/m128","VPPERM xmm2/m128, xmmIH, xmmV, xmm1","vpperm xmm2/m128, xmmIH, xmmV, xmm1","XOP.NDS.128.08.W1 A3 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPPERM xmm1, xmmV, xmm2/m128, xmmIH","VPPERM xmmIH, xmm2/m128, xmmV, xmm1","vpperm xmmIH, xmm2/m128, xmmV, xmm1","XOP.NDS.128.08.W0 A3 /r /is4","V","V","XOP","amd","w,r,r,r","","" +"VPROLD xmmV, {k}{z}, xmm2/m128/m32bcst, imm8u","VPROLD imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","vprold imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W0 72 /1 ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPROLD ymmV, {k}{z}, ymm2/m256/m32bcst, imm8u","VPROLD imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","vprold imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W0 72 /1 ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPROLD zmmV, {k}{z}, zmm2/m512/m32bcst, imm8u","VPROLD imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","vprold imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W0 72 /1 ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPROLQ xmmV, {k}{z}, xmm2/m128/m64bcst, imm8u","VPROLQ imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","vprolq imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W1 72 /1 ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPROLQ ymmV, {k}{z}, ymm2/m256/m64bcst, imm8u","VPROLQ imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","vprolq imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W1 72 /1 ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPROLQ zmmV, {k}{z}, zmm2/m512/m64bcst, imm8u","VPROLQ imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","vprolq imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W1 72 /1 ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPROLVD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPROLVD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vprolvd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 15 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPROLVD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPROLVD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vprolvd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 15 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPROLVD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPROLVD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vprolvd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 15 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPROLVQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPROLVQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vprolvq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 15 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPROLVQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPROLVQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vprolvq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 15 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPROLVQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPROLVQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vprolvq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 15 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPRORD xmmV, {k}{z}, xmm2/m128/m32bcst, imm8u","VPRORD imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","vprord imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W0 72 /0 ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPRORD ymmV, {k}{z}, ymm2/m256/m32bcst, imm8u","VPRORD imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","vprord imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W0 72 /0 ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPRORD zmmV, {k}{z}, zmm2/m512/m32bcst, imm8u","VPRORD imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","vprord imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W0 72 /0 ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPRORQ xmmV, {k}{z}, xmm2/m128/m64bcst, imm8u","VPRORQ imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","vprorq imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W1 72 /0 ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPRORQ ymmV, {k}{z}, ymm2/m256/m64bcst, imm8u","VPRORQ imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","vprorq imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W1 72 /0 ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPRORQ zmmV, {k}{z}, zmm2/m512/m64bcst, imm8u","VPRORQ imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","vprorq imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W1 72 /0 ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPRORVD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPRORVD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vprorvd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 14 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPRORVD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPRORVD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vprorvd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 14 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPRORVD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPRORVD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vprorvd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 14 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPRORVQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPRORVQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vprorvq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 14 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPRORVQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPRORVQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vprorvq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 14 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPRORVQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPRORVQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vprorvq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 14 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPROTB xmm1, xmm2/m128, imm8u","VPROTB imm8u, xmm2/m128, xmm1","vprotb imm8u, xmm2/m128, xmm1","XOP.128.08.W0 C0 /r ib","V","V","XOP","amd","w,r,r","","" +"VPROTB xmm1, xmmV, xmm2/m128","VPROTB xmm2/m128, xmmV, xmm1","vprotb xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 90 /r","V","V","XOP","amd","w,r,r","","" +"VPROTB xmm1, xmm2/m128, xmmV","VPROTB xmmV, xmm2/m128, xmm1","vprotb xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 90 /r","V","V","XOP","amd","w,r,r","","" +"VPROTD xmm1, xmm2/m128, imm8u","VPROTD imm8u, xmm2/m128, xmm1","vprotd imm8u, xmm2/m128, xmm1","XOP.128.08.W0 C2 /r ib","V","V","XOP","amd","w,r,r","","" +"VPROTD xmm1, xmmV, xmm2/m128","VPROTD xmm2/m128, xmmV, xmm1","vprotd xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 92 /r","V","V","XOP","amd","w,r,r","","" +"VPROTD xmm1, xmm2/m128, xmmV","VPROTD xmmV, xmm2/m128, xmm1","vprotd xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 92 /r","V","V","XOP","amd","w,r,r","","" +"VPROTQ xmm1, xmm2/m128, imm8u","VPROTQ imm8u, xmm2/m128, xmm1","vprotq imm8u, xmm2/m128, xmm1","XOP.128.08.W0 C3 /r ib","V","V","XOP","amd","w,r,r","","" +"VPROTQ xmm1, xmmV, xmm2/m128","VPROTQ xmm2/m128, xmmV, xmm1","vprotq xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 93 /r","V","V","XOP","amd","w,r,r","","" +"VPROTQ xmm1, xmm2/m128, xmmV","VPROTQ xmmV, xmm2/m128, xmm1","vprotq xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 93 /r","V","V","XOP","amd","w,r,r","","" +"VPROTW xmm1, xmm2/m128, imm8u","VPROTW imm8u, xmm2/m128, xmm1","vprotw imm8u, xmm2/m128, xmm1","XOP.128.08.W0 C1 /r ib","V","V","XOP","amd","w,r,r","","" +"VPROTW xmm1, xmmV, xmm2/m128","VPROTW xmm2/m128, xmmV, xmm1","vprotw xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 91 /r","V","V","XOP","amd","w,r,r","","" +"VPROTW xmm1, xmm2/m128, xmmV","VPROTW xmmV, xmm2/m128, xmm1","vprotw xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 91 /r","V","V","XOP","amd","w,r,r","","" +"VPSADBW xmm1, xmmV, xmm2/m128","VPSADBW xmm2/m128, xmmV, xmm1","vpsadbw xmm2/m128, xmmV, xmm1","EVEX.NDS.128.66.0F.WIG F6 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPSADBW xmm1, xmmV, xmm2/m128","VPSADBW xmm2/m128, xmmV, xmm1","vpsadbw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG F6 /r","V","V","AVX","","w,r,r","","" +"VPSADBW ymm1, ymmV, ymm2/m256","VPSADBW ymm2/m256, ymmV, ymm1","vpsadbw ymm2/m256, ymmV, ymm1","EVEX.NDS.256.66.0F.WIG F6 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r","","" +"VPSADBW ymm1, ymmV, ymm2/m256","VPSADBW ymm2/m256, ymmV, ymm1","vpsadbw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG F6 /r","V","V","AVX2","","w,r,r","","" +"VPSADBW zmm1, zmmV, zmm2/m512","VPSADBW zmm2/m512, zmmV, zmm1","vpsadbw zmm2/m512, zmmV, zmm1","EVEX.NDS.512.66.0F.WIG F6 /r","V","V","AVX512BW","scale64","w,r,r","","" +"VPSCATTERDD vm32x, {k1-k7}, xmm1","VPSCATTERDD xmm1, {k1-k7}, vm32x","vpscatterdd xmm1, {k1-k7}, vm32x","EVEX.128.66.0F38.W0 A0 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VPSCATTERDD vm32y, {k1-k7}, ymm1","VPSCATTERDD ymm1, {k1-k7}, vm32y","vpscatterdd ymm1, {k1-k7}, vm32y","EVEX.256.66.0F38.W0 A0 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VPSCATTERDD vm32z, {k1-k7}, zmm1","VPSCATTERDD zmm1, {k1-k7}, vm32z","vpscatterdd zmm1, {k1-k7}, vm32z","EVEX.512.66.0F38.W0 A0 /vsib","V","V","AVX512F","modrm_memonly,scale4","w,rw,r","","" +"VPSCATTERDQ vm32x, {k1-k7}, xmm1","VPSCATTERDQ xmm1, {k1-k7}, vm32x","vpscatterdq xmm1, {k1-k7}, vm32x","EVEX.128.66.0F38.W1 A0 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VPSCATTERDQ vm32x, {k1-k7}, ymm1","VPSCATTERDQ ymm1, {k1-k7}, vm32x","vpscatterdq ymm1, {k1-k7}, vm32x","EVEX.256.66.0F38.W1 A0 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VPSCATTERDQ vm32y, {k1-k7}, zmm1","VPSCATTERDQ zmm1, {k1-k7}, vm32y","vpscatterdq zmm1, {k1-k7}, vm32y","EVEX.512.66.0F38.W1 A0 /vsib","V","V","AVX512F","modrm_memonly,scale8","w,rw,r","","" +"VPSCATTERQD vm64x, {k1-k7}, xmm1","VPSCATTERQD xmm1, {k1-k7}, vm64x","vpscatterqd xmm1, {k1-k7}, vm64x","EVEX.128.66.0F38.W0 A1 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VPSCATTERQD vm64y, {k1-k7}, xmm1","VPSCATTERQD xmm1, {k1-k7}, vm64y","vpscatterqd xmm1, {k1-k7}, vm64y","EVEX.256.66.0F38.W0 A1 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VPSCATTERQD vm64z, {k1-k7}, ymm1","VPSCATTERQD ymm1, {k1-k7}, vm64z","vpscatterqd ymm1, {k1-k7}, vm64z","EVEX.512.66.0F38.W0 A1 /vsib","V","V","AVX512F","modrm_memonly,scale4","w,rw,r","","" +"VPSCATTERQQ vm64x, {k1-k7}, xmm1","VPSCATTERQQ xmm1, {k1-k7}, vm64x","vpscatterqq xmm1, {k1-k7}, vm64x","EVEX.128.66.0F38.W1 A1 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VPSCATTERQQ vm64y, {k1-k7}, ymm1","VPSCATTERQQ ymm1, {k1-k7}, vm64y","vpscatterqq ymm1, {k1-k7}, vm64y","EVEX.256.66.0F38.W1 A1 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VPSCATTERQQ vm64z, {k1-k7}, zmm1","VPSCATTERQQ zmm1, {k1-k7}, vm64z","vpscatterqq zmm1, {k1-k7}, vm64z","EVEX.512.66.0F38.W1 A1 /vsib","V","V","AVX512F","modrm_memonly,scale8","w,rw,r","","" +"VPSHAB xmm1, xmmV, xmm2/m128","VPSHAB xmm2/m128, xmmV, xmm1","vpshab xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 98 /r","V","V","XOP","amd","w,r,r","","" +"VPSHAB xmm1, xmm2/m128, xmmV","VPSHAB xmmV, xmm2/m128, xmm1","vpshab xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 98 /r","V","V","XOP","amd","w,r,r","","" +"VPSHAD xmm1, xmmV, xmm2/m128","VPSHAD xmm2/m128, xmmV, xmm1","vpshad xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 9A /r","V","V","XOP","amd","w,r,r","","" +"VPSHAD xmm1, xmm2/m128, xmmV","VPSHAD xmmV, xmm2/m128, xmm1","vpshad xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 9A /r","V","V","XOP","amd","w,r,r","","" +"VPSHAQ xmm1, xmmV, xmm2/m128","VPSHAQ xmm2/m128, xmmV, xmm1","vpshaq xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 9B /r","V","V","XOP","amd","w,r,r","","" +"VPSHAQ xmm1, xmm2/m128, xmmV","VPSHAQ xmmV, xmm2/m128, xmm1","vpshaq xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 9B /r","V","V","XOP","amd","w,r,r","","" +"VPSHAW xmm1, xmmV, xmm2/m128","VPSHAW xmm2/m128, xmmV, xmm1","vpshaw xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 99 /r","V","V","XOP","amd","w,r,r","","" +"VPSHAW xmm1, xmm2/m128, xmmV","VPSHAW xmmV, xmm2/m128, xmm1","vpshaw xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 99 /r","V","V","XOP","amd","w,r,r","","" +"VPSHLB xmm1, xmmV, xmm2/m128","VPSHLB xmm2/m128, xmmV, xmm1","vpshlb xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 94 /r","V","V","XOP","amd","w,r,r","","" +"VPSHLB xmm1, xmm2/m128, xmmV","VPSHLB xmmV, xmm2/m128, xmm1","vpshlb xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 94 /r","V","V","XOP","amd","w,r,r","","" +"VPSHLD xmm1, xmmV, xmm2/m128","VPSHLD xmm2/m128, xmmV, xmm1","vpshld xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 96 /r","V","V","XOP","amd","w,r,r","","" +"VPSHLD xmm1, xmm2/m128, xmmV","VPSHLD xmmV, xmm2/m128, xmm1","vpshld xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 96 /r","V","V","XOP","amd","w,r,r","","" +"VPSHLDD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst, imm8u","VPSHLDD imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpshldd imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W0 71 /r ib","V","V","AVX512_VBMI2+AVX512VL","bscale4,scale16","w,r,r,r,r","","" +"VPSHLDD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u","VPSHLDD imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpshldd imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 71 /r ib","V","V","AVX512_VBMI2+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VPSHLDD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u","VPSHLDD imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpshldd imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 71 /r ib","V","V","AVX512_VBMI2","bscale4,scale64","w,r,r,r,r","","" +"VPSHLDQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u","VPSHLDQ imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpshldq imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W1 71 /r ib","V","V","AVX512_VBMI2+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VPSHLDQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VPSHLDQ imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpshldq imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 71 /r ib","V","V","AVX512_VBMI2+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VPSHLDQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VPSHLDQ imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpshldq imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 71 /r ib","V","V","AVX512_VBMI2","bscale8,scale64","w,r,r,r,r","","" +"VPSHLDVD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPSHLDVD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpshldvd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 71 /r","V","V","AVX512_VBMI2+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPSHLDVD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPSHLDVD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpshldvd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 71 /r","V","V","AVX512_VBMI2+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPSHLDVD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPSHLDVD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpshldvd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 71 /r","V","V","AVX512_VBMI2","bscale4,scale64","rw,r,r,r","","" +"VPSHLDVQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPSHLDVQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpshldvq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 71 /r","V","V","AVX512_VBMI2+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VPSHLDVQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPSHLDVQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpshldvq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 71 /r","V","V","AVX512_VBMI2+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VPSHLDVQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPSHLDVQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpshldvq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 71 /r","V","V","AVX512_VBMI2","bscale8,scale64","rw,r,r,r","","" +"VPSHLDVW xmm1, {k}{z}, xmmV, xmm2/m128","VPSHLDVW xmm2/m128, xmmV, {k}{z}, xmm1","vpshldvw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 70 /r","V","V","AVX512_VBMI2+AVX512VL","scale16","rw,r,r,r","","" +"VPSHLDVW ymm1, {k}{z}, ymmV, ymm2/m256","VPSHLDVW ymm2/m256, ymmV, {k}{z}, ymm1","vpshldvw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 70 /r","V","V","AVX512_VBMI2+AVX512VL","scale32","rw,r,r,r","","" +"VPSHLDVW zmm1, {k}{z}, zmmV, zmm2/m512","VPSHLDVW zmm2/m512, zmmV, {k}{z}, zmm1","vpshldvw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 70 /r","V","V","AVX512_VBMI2","scale64","rw,r,r,r","","" +"VPSHLDW xmm1, {k}{z}, xmmV, xmm2/m128, imm8u","VPSHLDW imm8u, xmm2/m128, xmmV, {k}{z}, xmm1","vpshldw imm8u, xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W1 70 /r ib","V","V","AVX512_VBMI2+AVX512VL","scale16","w,r,r,r,r","","" +"VPSHLDW ymm1, {k}{z}, ymmV, ymm2/m256, imm8u","VPSHLDW imm8u, ymm2/m256, ymmV, {k}{z}, ymm1","vpshldw imm8u, ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 70 /r ib","V","V","AVX512_VBMI2+AVX512VL","scale32","w,r,r,r,r","","" +"VPSHLDW zmm1, {k}{z}, zmmV, zmm2/m512, imm8u","VPSHLDW imm8u, zmm2/m512, zmmV, {k}{z}, zmm1","vpshldw imm8u, zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 70 /r ib","V","V","AVX512_VBMI2","scale64","w,r,r,r,r","","" +"VPSHLQ xmm1, xmmV, xmm2/m128","VPSHLQ xmm2/m128, xmmV, xmm1","vpshlq xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 97 /r","V","V","XOP","amd","w,r,r","","" +"VPSHLQ xmm1, xmm2/m128, xmmV","VPSHLQ xmmV, xmm2/m128, xmm1","vpshlq xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 97 /r","V","V","XOP","amd","w,r,r","","" +"VPSHLW xmm1, xmmV, xmm2/m128","VPSHLW xmm2/m128, xmmV, xmm1","vpshlw xmm2/m128, xmmV, xmm1","XOP.NDS.128.09.W1 95 /r","V","V","XOP","amd","w,r,r","","" +"VPSHLW xmm1, xmm2/m128, xmmV","VPSHLW xmmV, xmm2/m128, xmm1","vpshlw xmmV, xmm2/m128, xmm1","XOP.NDS.128.09.W0 95 /r","V","V","XOP","amd","w,r,r","","" +"VPSHRDD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst, imm8u","VPSHRDD imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpshrdd imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W0 73 /r ib","V","V","AVX512_VBMI2+AVX512VL","bscale4,scale16","w,r,r,r,r","","" +"VPSHRDD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u","VPSHRDD imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpshrdd imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 73 /r ib","V","V","AVX512_VBMI2+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VPSHRDD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u","VPSHRDD imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpshrdd imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 73 /r ib","V","V","AVX512_VBMI2","bscale4,scale64","w,r,r,r,r","","" +"VPSHRDQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u","VPSHRDQ imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpshrdq imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W1 73 /r ib","V","V","AVX512_VBMI2+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VPSHRDQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VPSHRDQ imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpshrdq imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 73 /r ib","V","V","AVX512_VBMI2+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VPSHRDQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VPSHRDQ imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpshrdq imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 73 /r ib","V","V","AVX512_VBMI2","bscale8,scale64","w,r,r,r,r","","" +"VPSHRDVD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPSHRDVD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpshrdvd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W0 73 /r","V","V","AVX512_VBMI2+AVX512VL","bscale4,scale16","rw,r,r,r","","" +"VPSHRDVD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPSHRDVD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpshrdvd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W0 73 /r","V","V","AVX512_VBMI2+AVX512VL","bscale4,scale32","rw,r,r,r","","" +"VPSHRDVD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPSHRDVD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpshrdvd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W0 73 /r","V","V","AVX512_VBMI2","bscale4,scale64","rw,r,r,r","","" +"VPSHRDVQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPSHRDVQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpshrdvq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 73 /r","V","V","AVX512_VBMI2+AVX512VL","bscale8,scale16","rw,r,r,r","","" +"VPSHRDVQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPSHRDVQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpshrdvq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 73 /r","V","V","AVX512_VBMI2+AVX512VL","bscale8,scale32","rw,r,r,r","","" +"VPSHRDVQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPSHRDVQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpshrdvq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 73 /r","V","V","AVX512_VBMI2","bscale8,scale64","rw,r,r,r","","" +"VPSHRDVW xmm1, {k}{z}, xmmV, xmm2/m128","VPSHRDVW xmm2/m128, xmmV, {k}{z}, xmm1","vpshrdvw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F38.W1 72 /r","V","V","AVX512_VBMI2+AVX512VL","scale16","rw,r,r,r","","" +"VPSHRDVW ymm1, {k}{z}, ymmV, ymm2/m256","VPSHRDVW ymm2/m256, ymmV, {k}{z}, ymm1","vpshrdvw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F38.W1 72 /r","V","V","AVX512_VBMI2+AVX512VL","scale32","rw,r,r,r","","" +"VPSHRDVW zmm1, {k}{z}, zmmV, zmm2/m512","VPSHRDVW zmm2/m512, zmmV, {k}{z}, zmm1","vpshrdvw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F38.W1 72 /r","V","V","AVX512_VBMI2","scale64","rw,r,r,r","","" +"VPSHRDW xmm1, {k}{z}, xmmV, xmm2/m128, imm8u","VPSHRDW imm8u, xmm2/m128, xmmV, {k}{z}, xmm1","vpshrdw imm8u, xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W1 72 /r ib","V","V","AVX512_VBMI2+AVX512VL","scale16","w,r,r,r,r","","" +"VPSHRDW ymm1, {k}{z}, ymmV, ymm2/m256, imm8u","VPSHRDW imm8u, ymm2/m256, ymmV, {k}{z}, ymm1","vpshrdw imm8u, ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 72 /r ib","V","V","AVX512_VBMI2+AVX512VL","scale32","w,r,r,r,r","","" +"VPSHRDW zmm1, {k}{z}, zmmV, zmm2/m512, imm8u","VPSHRDW imm8u, zmm2/m512, zmmV, {k}{z}, zmm1","vpshrdw imm8u, zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 72 /r ib","V","V","AVX512_VBMI2","scale64","w,r,r,r,r","","" +"VPSHUFB xmm1, xmmV, xmm2/m128","VPSHUFB xmm2/m128, xmmV, xmm1","vpshufb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 00 /r","V","V","AVX","","w,r,r","","" +"VPSHUFB xmm1, {k}{z}, xmmV, xmm2/m128","VPSHUFB xmm2/m128, xmmV, {k}{z}, xmm1","vpshufb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.WIG 00 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSHUFB ymm1, ymmV, ymm2/m256","VPSHUFB ymm2/m256, ymmV, ymm1","vpshufb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 00 /r","V","V","AVX2","","w,r,r","","" +"VPSHUFB ymm1, {k}{z}, ymmV, ymm2/m256","VPSHUFB ymm2/m256, ymmV, {k}{z}, ymm1","vpshufb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.WIG 00 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSHUFB zmm1, {k}{z}, zmmV, zmm2/m512","VPSHUFB zmm2/m512, zmmV, {k}{z}, zmm1","vpshufb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.WIG 00 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSHUFBITQMB k1, {k}, xmmV, xmm2/m128","VPSHUFBITQMB xmm2/m128, xmmV, {k}, k1","vpshufbitqmb xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F38.W0 8F /r","V","V","AVX512_BITALG+AVX512VL","scale16","w,r,r,r","","" +"VPSHUFBITQMB k1, {k}, ymmV, ymm2/m256","VPSHUFBITQMB ymm2/m256, ymmV, {k}, k1","vpshufbitqmb ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F38.W0 8F /r","V","V","AVX512_BITALG+AVX512VL","scale32","w,r,r,r","","" +"VPSHUFBITQMB k1, {k}, zmmV, zmm2/m512","VPSHUFBITQMB zmm2/m512, zmmV, {k}, k1","vpshufbitqmb zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F38.W0 8F /r","V","V","AVX512_BITALG","scale64","w,r,r,r","","" +"VPSHUFD xmm1, xmm2/m128, imm8u","VPSHUFD imm8u, xmm2/m128, xmm1","vpshufd imm8u, xmm2/m128, xmm1","VEX.128.66.0F.WIG 70 /r ib","V","V","AVX","","w,r,r","","" +"VPSHUFD xmm1, {k}{z}, xmm2/m128/m32bcst, imm8u","VPSHUFD imm8u, xmm2/m128/m32bcst, {k}{z}, xmm1","vpshufd imm8u, xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F.W0 70 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPSHUFD ymm1, ymm2/m256, imm8u","VPSHUFD imm8u, ymm2/m256, ymm1","vpshufd imm8u, ymm2/m256, ymm1","VEX.256.66.0F.WIG 70 /r ib","V","V","AVX2","","w,r,r","","" +"VPSHUFD ymm1, {k}{z}, ymm2/m256/m32bcst, imm8u","VPSHUFD imm8u, ymm2/m256/m32bcst, {k}{z}, ymm1","vpshufd imm8u, ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F.W0 70 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPSHUFD zmm1, {k}{z}, zmm2/m512/m32bcst, imm8u","VPSHUFD imm8u, zmm2/m512/m32bcst, {k}{z}, zmm1","vpshufd imm8u, zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F.W0 70 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPSHUFHW xmm1, xmm2/m128, imm8u","VPSHUFHW imm8u, xmm2/m128, xmm1","vpshufhw imm8u, xmm2/m128, xmm1","VEX.128.F3.0F.WIG 70 /r ib","V","V","AVX","","w,r,r","","" +"VPSHUFHW xmm1, {k}{z}, xmm2/m128, imm8u","VPSHUFHW imm8u, xmm2/m128, {k}{z}, xmm1","vpshufhw imm8u, xmm2/m128, {k}{z}, xmm1","EVEX.128.F3.0F.WIG 70 /r ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSHUFHW ymm1, ymm2/m256, imm8u","VPSHUFHW imm8u, ymm2/m256, ymm1","vpshufhw imm8u, ymm2/m256, ymm1","VEX.256.F3.0F.WIG 70 /r ib","V","V","AVX2","","w,r,r","","" +"VPSHUFHW ymm1, {k}{z}, ymm2/m256, imm8u","VPSHUFHW imm8u, ymm2/m256, {k}{z}, ymm1","vpshufhw imm8u, ymm2/m256, {k}{z}, ymm1","EVEX.256.F3.0F.WIG 70 /r ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSHUFHW zmm1, {k}{z}, zmm2/m512, imm8u","VPSHUFHW imm8u, zmm2/m512, {k}{z}, zmm1","vpshufhw imm8u, zmm2/m512, {k}{z}, zmm1","EVEX.512.F3.0F.WIG 70 /r ib","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSHUFLW xmm1, xmm2/m128, imm8u","VPSHUFLW imm8u, xmm2/m128, xmm1","vpshuflw imm8u, xmm2/m128, xmm1","VEX.128.F2.0F.WIG 70 /r ib","V","V","AVX","","w,r,r","","" +"VPSHUFLW xmm1, {k}{z}, xmm2/m128, imm8u","VPSHUFLW imm8u, xmm2/m128, {k}{z}, xmm1","vpshuflw imm8u, xmm2/m128, {k}{z}, xmm1","EVEX.128.F2.0F.WIG 70 /r ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSHUFLW ymm1, ymm2/m256, imm8u","VPSHUFLW imm8u, ymm2/m256, ymm1","vpshuflw imm8u, ymm2/m256, ymm1","VEX.256.F2.0F.WIG 70 /r ib","V","V","AVX2","","w,r,r","","" +"VPSHUFLW ymm1, {k}{z}, ymm2/m256, imm8u","VPSHUFLW imm8u, ymm2/m256, {k}{z}, ymm1","vpshuflw imm8u, ymm2/m256, {k}{z}, ymm1","EVEX.256.F2.0F.WIG 70 /r ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSHUFLW zmm1, {k}{z}, zmm2/m512, imm8u","VPSHUFLW imm8u, zmm2/m512, {k}{z}, zmm1","vpshuflw imm8u, zmm2/m512, {k}{z}, zmm1","EVEX.512.F2.0F.WIG 70 /r ib","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSIGNB xmm1, xmmV, xmm2/m128","VPSIGNB xmm2/m128, xmmV, xmm1","vpsignb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 08 /r","V","V","AVX","","w,r,r","","" +"VPSIGNB ymm1, ymmV, ymm2/m256","VPSIGNB ymm2/m256, ymmV, ymm1","vpsignb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 08 /r","V","V","AVX2","","w,r,r","","" +"VPSIGND xmm1, xmmV, xmm2/m128","VPSIGND xmm2/m128, xmmV, xmm1","vpsignd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 0A /r","V","V","AVX","","w,r,r","","" +"VPSIGND ymm1, ymmV, ymm2/m256","VPSIGND ymm2/m256, ymmV, ymm1","vpsignd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 0A /r","V","V","AVX2","","w,r,r","","" +"VPSIGNW xmm1, xmmV, xmm2/m128","VPSIGNW xmm2/m128, xmmV, xmm1","vpsignw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.WIG 09 /r","V","V","AVX","","w,r,r","","" +"VPSIGNW ymm1, ymmV, ymm2/m256","VPSIGNW ymm2/m256, ymmV, ymm1","vpsignw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.WIG 09 /r","V","V","AVX2","","w,r,r","","" +"VPSLLD xmmV, xmm2, imm8u","VPSLLD imm8u, xmm2, xmmV","vpslld imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 72 /6 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSLLD xmmV, {k}{z}, xmm2/m128/m32bcst, imm8u","VPSLLD imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","vpslld imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W0 72 /6 ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPSLLD ymmV, ymm2, imm8u","VPSLLD imm8u, ymm2, ymmV","vpslld imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 72 /6 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSLLD ymmV, {k}{z}, ymm2/m256/m32bcst, imm8u","VPSLLD imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","vpslld imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W0 72 /6 ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPSLLD zmmV, {k}{z}, zmm2/m512/m32bcst, imm8u","VPSLLD imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","vpslld imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W0 72 /6 ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPSLLD xmm1, xmmV, xmm2/m128","VPSLLD xmm2/m128, xmmV, xmm1","vpslld xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG F2 /r","V","V","AVX","","w,r,r","","" +"VPSLLD xmm1, {k}{z}, xmmV, xmm2/m128","VPSLLD xmm2/m128, xmmV, {k}{z}, xmm1","vpslld xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 F2 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSLLD ymm1, ymmV, xmm2/m128","VPSLLD xmm2/m128, ymmV, ymm1","vpslld xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F.WIG F2 /r","V","V","AVX2","","w,r,r","","" +"VPSLLD ymm1, {k}{z}, ymmV, xmm2/m128","VPSLLD xmm2/m128, ymmV, {k}{z}, ymm1","vpslld xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 F2 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSLLD zmm1, {k}{z}, zmmV, xmm2/m128","VPSLLD xmm2/m128, zmmV, {k}{z}, zmm1","vpslld xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 F2 /r","V","V","AVX512F","scale16","w,r,r,r","","" +"VPSLLDQ xmmV, xmm2, imm8u","VPSLLDQ imm8u, xmm2, xmmV","vpslldq imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 73 /7 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSLLDQ xmmV, xmm2/m128, imm8u","VPSLLDQ imm8u, xmm2/m128, xmmV","vpslldq imm8u, xmm2/m128, xmmV","EVEX.NDD.128.66.0F.WIG 73 /7 ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPSLLDQ ymmV, ymm2, imm8u","VPSLLDQ imm8u, ymm2, ymmV","vpslldq imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 73 /7 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSLLDQ ymmV, ymm2/m256, imm8u","VPSLLDQ imm8u, ymm2/m256, ymmV","vpslldq imm8u, ymm2/m256, ymmV","EVEX.NDD.256.66.0F.WIG 73 /7 ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r","","" +"VPSLLDQ zmmV, zmm2/m512, imm8u","VPSLLDQ imm8u, zmm2/m512, zmmV","vpslldq imm8u, zmm2/m512, zmmV","EVEX.NDD.512.66.0F.WIG 73 /7 ib","V","V","AVX512BW","scale64","w,r,r","","" +"VPSLLQ xmmV, xmm2, imm8u","VPSLLQ imm8u, xmm2, xmmV","vpsllq imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 73 /6 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSLLQ xmmV, {k}{z}, xmm2/m128/m64bcst, imm8u","VPSLLQ imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","vpsllq imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W1 73 /6 ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPSLLQ ymmV, ymm2, imm8u","VPSLLQ imm8u, ymm2, ymmV","vpsllq imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 73 /6 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSLLQ ymmV, {k}{z}, ymm2/m256/m64bcst, imm8u","VPSLLQ imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","vpsllq imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W1 73 /6 ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPSLLQ zmmV, {k}{z}, zmm2/m512/m64bcst, imm8u","VPSLLQ imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","vpsllq imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W1 73 /6 ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPSLLQ xmm1, xmmV, xmm2/m128","VPSLLQ xmm2/m128, xmmV, xmm1","vpsllq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG F3 /r","V","V","AVX","","w,r,r","","" +"VPSLLQ xmm1, {k}{z}, xmmV, xmm2/m128","VPSLLQ xmm2/m128, xmmV, {k}{z}, xmm1","vpsllq xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 F3 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSLLQ ymm1, ymmV, xmm2/m128","VPSLLQ xmm2/m128, ymmV, ymm1","vpsllq xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F.WIG F3 /r","V","V","AVX2","","w,r,r","","" +"VPSLLQ ymm1, {k}{z}, ymmV, xmm2/m128","VPSLLQ xmm2/m128, ymmV, {k}{z}, ymm1","vpsllq xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 F3 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSLLQ zmm1, {k}{z}, zmmV, xmm2/m128","VPSLLQ xmm2/m128, zmmV, {k}{z}, zmm1","vpsllq xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 F3 /r","V","V","AVX512F","scale16","w,r,r,r","","" +"VPSLLVD xmm1, xmmV, xmm2/m128","VPSLLVD xmm2/m128, xmmV, xmm1","vpsllvd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 47 /r","V","V","AVX2","","w,r,r","","" +"VPSLLVD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPSLLVD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpsllvd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 47 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPSLLVD ymm1, ymmV, ymm2/m256","VPSLLVD ymm2/m256, ymmV, ymm1","vpsllvd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 47 /r","V","V","AVX2","","w,r,r","","" +"VPSLLVD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPSLLVD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpsllvd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 47 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPSLLVD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPSLLVD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpsllvd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 47 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPSLLVQ xmm1, xmmV, xmm2/m128","VPSLLVQ xmm2/m128, xmmV, xmm1","vpsllvq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W1 47 /r","V","V","AVX2","","w,r,r","","" +"VPSLLVQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPSLLVQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpsllvq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 47 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPSLLVQ ymm1, ymmV, ymm2/m256","VPSLLVQ ymm2/m256, ymmV, ymm1","vpsllvq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W1 47 /r","V","V","AVX2","","w,r,r","","" +"VPSLLVQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPSLLVQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpsllvq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 47 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPSLLVQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPSLLVQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpsllvq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 47 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPSLLVW xmm1, {k}{z}, xmmV, xmm2/m128","VPSLLVW xmm2/m128, xmmV, {k}{z}, xmm1","vpsllvw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 12 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSLLVW ymm1, {k}{z}, ymmV, ymm2/m256","VPSLLVW ymm2/m256, ymmV, {k}{z}, ymm1","vpsllvw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 12 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSLLVW zmm1, {k}{z}, zmmV, zmm2/m512","VPSLLVW zmm2/m512, zmmV, {k}{z}, zmm1","vpsllvw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 12 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSLLW xmmV, xmm2, imm8u","VPSLLW imm8u, xmm2, xmmV","vpsllw imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 71 /6 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSLLW xmmV, {k}{z}, xmm2/m128, imm8u","VPSLLW imm8u, xmm2/m128, {k}{z}, xmmV","vpsllw imm8u, xmm2/m128, {k}{z}, xmmV","EVEX.NDD.128.66.0F.WIG 71 /6 ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSLLW ymmV, ymm2, imm8u","VPSLLW imm8u, ymm2, ymmV","vpsllw imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 71 /6 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSLLW ymmV, {k}{z}, ymm2/m256, imm8u","VPSLLW imm8u, ymm2/m256, {k}{z}, ymmV","vpsllw imm8u, ymm2/m256, {k}{z}, ymmV","EVEX.NDD.256.66.0F.WIG 71 /6 ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSLLW zmmV, {k}{z}, zmm2/m512, imm8u","VPSLLW imm8u, zmm2/m512, {k}{z}, zmmV","vpsllw imm8u, zmm2/m512, {k}{z}, zmmV","EVEX.NDD.512.66.0F.WIG 71 /6 ib","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSLLW xmm1, xmmV, xmm2/m128","VPSLLW xmm2/m128, xmmV, xmm1","vpsllw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG F1 /r","V","V","AVX","","w,r,r","","" +"VPSLLW xmm1, {k}{z}, xmmV, xmm2/m128","VPSLLW xmm2/m128, xmmV, {k}{z}, xmm1","vpsllw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG F1 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSLLW ymm1, ymmV, xmm2/m128","VPSLLW xmm2/m128, ymmV, ymm1","vpsllw xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F.WIG F1 /r","V","V","AVX2","","w,r,r","","" +"VPSLLW ymm1, {k}{z}, ymmV, xmm2/m128","VPSLLW xmm2/m128, ymmV, {k}{z}, ymm1","vpsllw xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG F1 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSLLW zmm1, {k}{z}, zmmV, xmm2/m128","VPSLLW xmm2/m128, zmmV, {k}{z}, zmm1","vpsllw xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG F1 /r","V","V","AVX512BW","scale16","w,r,r,r","","" +"VPSRAD xmmV, xmm2, imm8u","VPSRAD imm8u, xmm2, xmmV","vpsrad imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 72 /4 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSRAD xmmV, {k}{z}, xmm2/m128/m32bcst, imm8u","VPSRAD imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","vpsrad imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W0 72 /4 ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPSRAD ymmV, ymm2, imm8u","VPSRAD imm8u, ymm2, ymmV","vpsrad imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 72 /4 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSRAD ymmV, {k}{z}, ymm2/m256/m32bcst, imm8u","VPSRAD imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","vpsrad imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W0 72 /4 ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPSRAD zmmV, {k}{z}, zmm2/m512/m32bcst, imm8u","VPSRAD imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","vpsrad imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W0 72 /4 ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPSRAD xmm1, xmmV, xmm2/m128","VPSRAD xmm2/m128, xmmV, xmm1","vpsrad xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG E2 /r","V","V","AVX","","w,r,r","","" +"VPSRAD xmm1, {k}{z}, xmmV, xmm2/m128","VPSRAD xmm2/m128, xmmV, {k}{z}, xmm1","vpsrad xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 E2 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSRAD ymm1, ymmV, xmm2/m128","VPSRAD xmm2/m128, ymmV, ymm1","vpsrad xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F.WIG E2 /r","V","V","AVX2","","w,r,r","","" +"VPSRAD ymm1, {k}{z}, ymmV, xmm2/m128","VPSRAD xmm2/m128, ymmV, {k}{z}, ymm1","vpsrad xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 E2 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSRAD zmm1, {k}{z}, zmmV, xmm2/m128","VPSRAD xmm2/m128, zmmV, {k}{z}, zmm1","vpsrad xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 E2 /r","V","V","AVX512F","scale16","w,r,r,r","","" +"VPSRAQ xmmV, {k}{z}, xmm2/m128/m64bcst, imm8u","VPSRAQ imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","vpsraq imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W1 72 /4 ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPSRAQ ymmV, {k}{z}, ymm2/m256/m64bcst, imm8u","VPSRAQ imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","vpsraq imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W1 72 /4 ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPSRAQ zmmV, {k}{z}, zmm2/m512/m64bcst, imm8u","VPSRAQ imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","vpsraq imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W1 72 /4 ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPSRAQ xmm1, {k}{z}, xmmV, xmm2/m128","VPSRAQ xmm2/m128, xmmV, {k}{z}, xmm1","vpsraq xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 E2 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSRAQ ymm1, {k}{z}, ymmV, xmm2/m128","VPSRAQ xmm2/m128, ymmV, {k}{z}, ymm1","vpsraq xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 E2 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSRAQ zmm1, {k}{z}, zmmV, xmm2/m128","VPSRAQ xmm2/m128, zmmV, {k}{z}, zmm1","vpsraq xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 E2 /r","V","V","AVX512F","scale16","w,r,r,r","","" +"VPSRAVD xmm1, xmmV, xmm2/m128","VPSRAVD xmm2/m128, xmmV, xmm1","vpsravd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 46 /r","V","V","AVX2","","w,r,r","","" +"VPSRAVD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPSRAVD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpsravd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 46 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPSRAVD ymm1, ymmV, ymm2/m256","VPSRAVD ymm2/m256, ymmV, ymm1","vpsravd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 46 /r","V","V","AVX2","","w,r,r","","" +"VPSRAVD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPSRAVD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpsravd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 46 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPSRAVD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPSRAVD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpsravd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 46 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPSRAVQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPSRAVQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpsravq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 46 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPSRAVQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPSRAVQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpsravq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 46 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPSRAVQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPSRAVQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpsravq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 46 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPSRAVW xmm1, {k}{z}, xmmV, xmm2/m128","VPSRAVW xmm2/m128, xmmV, {k}{z}, xmm1","vpsravw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 11 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSRAVW ymm1, {k}{z}, ymmV, ymm2/m256","VPSRAVW ymm2/m256, ymmV, {k}{z}, ymm1","vpsravw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 11 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSRAVW zmm1, {k}{z}, zmmV, zmm2/m512","VPSRAVW zmm2/m512, zmmV, {k}{z}, zmm1","vpsravw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 11 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSRAW xmmV, xmm2, imm8u","VPSRAW imm8u, xmm2, xmmV","vpsraw imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 71 /4 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSRAW xmmV, {k}{z}, xmm2/m128, imm8u","VPSRAW imm8u, xmm2/m128, {k}{z}, xmmV","vpsraw imm8u, xmm2/m128, {k}{z}, xmmV","EVEX.NDD.128.66.0F.WIG 71 /4 ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSRAW ymmV, ymm2, imm8u","VPSRAW imm8u, ymm2, ymmV","vpsraw imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 71 /4 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSRAW ymmV, {k}{z}, ymm2/m256, imm8u","VPSRAW imm8u, ymm2/m256, {k}{z}, ymmV","vpsraw imm8u, ymm2/m256, {k}{z}, ymmV","EVEX.NDD.256.66.0F.WIG 71 /4 ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSRAW zmmV, {k}{z}, zmm2/m512, imm8u","VPSRAW imm8u, zmm2/m512, {k}{z}, zmmV","vpsraw imm8u, zmm2/m512, {k}{z}, zmmV","EVEX.NDD.512.66.0F.WIG 71 /4 ib","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSRAW xmm1, xmmV, xmm2/m128","VPSRAW xmm2/m128, xmmV, xmm1","vpsraw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG E1 /r","V","V","AVX","","w,r,r","","" +"VPSRAW xmm1, {k}{z}, xmmV, xmm2/m128","VPSRAW xmm2/m128, xmmV, {k}{z}, xmm1","vpsraw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG E1 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSRAW ymm1, ymmV, xmm2/m128","VPSRAW xmm2/m128, ymmV, ymm1","vpsraw xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F.WIG E1 /r","V","V","AVX2","","w,r,r","","" +"VPSRAW ymm1, {k}{z}, ymmV, xmm2/m128","VPSRAW xmm2/m128, ymmV, {k}{z}, ymm1","vpsraw xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG E1 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSRAW zmm1, {k}{z}, zmmV, xmm2/m128","VPSRAW xmm2/m128, zmmV, {k}{z}, zmm1","vpsraw xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG E1 /r","V","V","AVX512BW","scale16","w,r,r,r","","" +"VPSRLD xmmV, xmm2, imm8u","VPSRLD imm8u, xmm2, xmmV","vpsrld imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 72 /2 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSRLD xmmV, {k}{z}, xmm2/m128/m32bcst, imm8u","VPSRLD imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","vpsrld imm8u, xmm2/m128/m32bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W0 72 /2 ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPSRLD ymmV, ymm2, imm8u","VPSRLD imm8u, ymm2, ymmV","vpsrld imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 72 /2 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSRLD ymmV, {k}{z}, ymm2/m256/m32bcst, imm8u","VPSRLD imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","vpsrld imm8u, ymm2/m256/m32bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W0 72 /2 ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPSRLD zmmV, {k}{z}, zmm2/m512/m32bcst, imm8u","VPSRLD imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","vpsrld imm8u, zmm2/m512/m32bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W0 72 /2 ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPSRLD xmm1, xmmV, xmm2/m128","VPSRLD xmm2/m128, xmmV, xmm1","vpsrld xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG D2 /r","V","V","AVX","","w,r,r","","" +"VPSRLD xmm1, {k}{z}, xmmV, xmm2/m128","VPSRLD xmm2/m128, xmmV, {k}{z}, xmm1","vpsrld xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 D2 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSRLD ymm1, ymmV, xmm2/m128","VPSRLD xmm2/m128, ymmV, ymm1","vpsrld xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F.WIG D2 /r","V","V","AVX2","","w,r,r","","" +"VPSRLD ymm1, {k}{z}, ymmV, xmm2/m128","VPSRLD xmm2/m128, ymmV, {k}{z}, ymm1","vpsrld xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 D2 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSRLD zmm1, {k}{z}, zmmV, xmm2/m128","VPSRLD xmm2/m128, zmmV, {k}{z}, zmm1","vpsrld xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 D2 /r","V","V","AVX512F","scale16","w,r,r,r","","" +"VPSRLDQ xmmV, xmm2, imm8u","VPSRLDQ imm8u, xmm2, xmmV","vpsrldq imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 73 /3 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSRLDQ xmmV, xmm2/m128, imm8u","VPSRLDQ imm8u, xmm2/m128, xmmV","vpsrldq imm8u, xmm2/m128, xmmV","EVEX.NDD.128.66.0F.WIG 73 /3 ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r","","" +"VPSRLDQ ymmV, ymm2, imm8u","VPSRLDQ imm8u, ymm2, ymmV","vpsrldq imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 73 /3 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSRLDQ ymmV, ymm2/m256, imm8u","VPSRLDQ imm8u, ymm2/m256, ymmV","vpsrldq imm8u, ymm2/m256, ymmV","EVEX.NDD.256.66.0F.WIG 73 /3 ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r","","" +"VPSRLDQ zmmV, zmm2/m512, imm8u","VPSRLDQ imm8u, zmm2/m512, zmmV","vpsrldq imm8u, zmm2/m512, zmmV","EVEX.NDD.512.66.0F.WIG 73 /3 ib","V","V","AVX512BW","scale64","w,r,r","","" +"VPSRLQ xmmV, xmm2, imm8u","VPSRLQ imm8u, xmm2, xmmV","vpsrlq imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 73 /2 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSRLQ xmmV, {k}{z}, xmm2/m128/m64bcst, imm8u","VPSRLQ imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","vpsrlq imm8u, xmm2/m128/m64bcst, {k}{z}, xmmV","EVEX.NDD.128.66.0F.W1 73 /2 ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPSRLQ ymmV, ymm2, imm8u","VPSRLQ imm8u, ymm2, ymmV","vpsrlq imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 73 /2 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSRLQ ymmV, {k}{z}, ymm2/m256/m64bcst, imm8u","VPSRLQ imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","vpsrlq imm8u, ymm2/m256/m64bcst, {k}{z}, ymmV","EVEX.NDD.256.66.0F.W1 73 /2 ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPSRLQ zmmV, {k}{z}, zmm2/m512/m64bcst, imm8u","VPSRLQ imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","vpsrlq imm8u, zmm2/m512/m64bcst, {k}{z}, zmmV","EVEX.NDD.512.66.0F.W1 73 /2 ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPSRLQ xmm1, xmmV, xmm2/m128","VPSRLQ xmm2/m128, xmmV, xmm1","vpsrlq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG D3 /r","V","V","AVX","","w,r,r","","" +"VPSRLQ xmm1, {k}{z}, xmmV, xmm2/m128","VPSRLQ xmm2/m128, xmmV, {k}{z}, xmm1","vpsrlq xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 D3 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSRLQ ymm1, ymmV, xmm2/m128","VPSRLQ xmm2/m128, ymmV, ymm1","vpsrlq xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F.WIG D3 /r","V","V","AVX2","","w,r,r","","" +"VPSRLQ ymm1, {k}{z}, ymmV, xmm2/m128","VPSRLQ xmm2/m128, ymmV, {k}{z}, ymm1","vpsrlq xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 D3 /r","V","V","AVX512F+AVX512VL","scale16","w,r,r,r","","" +"VPSRLQ zmm1, {k}{z}, zmmV, xmm2/m128","VPSRLQ xmm2/m128, zmmV, {k}{z}, zmm1","vpsrlq xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 D3 /r","V","V","AVX512F","scale16","w,r,r,r","","" +"VPSRLVD xmm1, xmmV, xmm2/m128","VPSRLVD xmm2/m128, xmmV, xmm1","vpsrlvd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W0 45 /r","V","V","AVX2","","w,r,r","","" +"VPSRLVD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPSRLVD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpsrlvd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 45 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPSRLVD ymm1, ymmV, ymm2/m256","VPSRLVD ymm2/m256, ymmV, ymm1","vpsrlvd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W0 45 /r","V","V","AVX2","","w,r,r","","" +"VPSRLVD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPSRLVD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpsrlvd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 45 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPSRLVD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPSRLVD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpsrlvd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 45 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPSRLVQ xmm1, xmmV, xmm2/m128","VPSRLVQ xmm2/m128, xmmV, xmm1","vpsrlvq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F38.W1 45 /r","V","V","AVX2","","w,r,r","","" +"VPSRLVQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPSRLVQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpsrlvq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 45 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPSRLVQ ymm1, ymmV, ymm2/m256","VPSRLVQ ymm2/m256, ymmV, ymm1","vpsrlvq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F38.W1 45 /r","V","V","AVX2","","w,r,r","","" +"VPSRLVQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPSRLVQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpsrlvq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 45 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPSRLVQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPSRLVQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpsrlvq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 45 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPSRLVW xmm1, {k}{z}, xmmV, xmm2/m128","VPSRLVW xmm2/m128, xmmV, {k}{z}, xmm1","vpsrlvw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 10 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSRLVW ymm1, {k}{z}, ymmV, ymm2/m256","VPSRLVW ymm2/m256, ymmV, {k}{z}, ymm1","vpsrlvw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 10 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSRLVW zmm1, {k}{z}, zmmV, zmm2/m512","VPSRLVW zmm2/m512, zmmV, {k}{z}, zmm1","vpsrlvw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 10 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSRLW xmmV, xmm2, imm8u","VPSRLW imm8u, xmm2, xmmV","vpsrlw imm8u, xmm2, xmmV","VEX.NDD.128.66.0F.WIG 71 /2 ib","V","V","AVX","modrm_regonly","w,r,r","","" +"VPSRLW xmmV, {k}{z}, xmm2/m128, imm8u","VPSRLW imm8u, xmm2/m128, {k}{z}, xmmV","vpsrlw imm8u, xmm2/m128, {k}{z}, xmmV","EVEX.NDD.128.66.0F.WIG 71 /2 ib","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSRLW ymmV, ymm2, imm8u","VPSRLW imm8u, ymm2, ymmV","vpsrlw imm8u, ymm2, ymmV","VEX.NDD.256.66.0F.WIG 71 /2 ib","V","V","AVX2","modrm_regonly","w,r,r","","" +"VPSRLW ymmV, {k}{z}, ymm2/m256, imm8u","VPSRLW imm8u, ymm2/m256, {k}{z}, ymmV","vpsrlw imm8u, ymm2/m256, {k}{z}, ymmV","EVEX.NDD.256.66.0F.WIG 71 /2 ib","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSRLW zmmV, {k}{z}, zmm2/m512, imm8u","VPSRLW imm8u, zmm2/m512, {k}{z}, zmmV","vpsrlw imm8u, zmm2/m512, {k}{z}, zmmV","EVEX.NDD.512.66.0F.WIG 71 /2 ib","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSRLW xmm1, xmmV, xmm2/m128","VPSRLW xmm2/m128, xmmV, xmm1","vpsrlw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG D1 /r","V","V","AVX","","w,r,r","","" +"VPSRLW xmm1, {k}{z}, xmmV, xmm2/m128","VPSRLW xmm2/m128, xmmV, {k}{z}, xmm1","vpsrlw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG D1 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSRLW ymm1, ymmV, xmm2/m128","VPSRLW xmm2/m128, ymmV, ymm1","vpsrlw xmm2/m128, ymmV, ymm1","VEX.NDS.256.66.0F.WIG D1 /r","V","V","AVX2","","w,r,r","","" +"VPSRLW ymm1, {k}{z}, ymmV, xmm2/m128","VPSRLW xmm2/m128, ymmV, {k}{z}, ymm1","vpsrlw xmm2/m128, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG D1 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSRLW zmm1, {k}{z}, zmmV, xmm2/m128","VPSRLW xmm2/m128, zmmV, {k}{z}, zmm1","vpsrlw xmm2/m128, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG D1 /r","V","V","AVX512BW","scale16","w,r,r,r","","" +"VPSUBB xmm1, xmmV, xmm2/m128","VPSUBB xmm2/m128, xmmV, xmm1","vpsubb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG F8 /r","V","V","AVX","","w,r,r","","" +"VPSUBB xmm1, {k}{z}, xmmV, xmm2/m128","VPSUBB xmm2/m128, xmmV, {k}{z}, xmm1","vpsubb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG F8 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSUBB ymm1, ymmV, ymm2/m256","VPSUBB ymm2/m256, ymmV, ymm1","vpsubb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG F8 /r","V","V","AVX2","","w,r,r","","" +"VPSUBB ymm1, {k}{z}, ymmV, ymm2/m256","VPSUBB ymm2/m256, ymmV, {k}{z}, ymm1","vpsubb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG F8 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSUBB zmm1, {k}{z}, zmmV, zmm2/m512","VPSUBB zmm2/m512, zmmV, {k}{z}, zmm1","vpsubb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG F8 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSUBD xmm1, xmmV, xmm2/m128","VPSUBD xmm2/m128, xmmV, xmm1","vpsubd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG FA /r","V","V","AVX","","w,r,r","","" +"VPSUBD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPSUBD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpsubd xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 FA /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPSUBD ymm1, ymmV, ymm2/m256","VPSUBD ymm2/m256, ymmV, ymm1","vpsubd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG FA /r","V","V","AVX2","","w,r,r","","" +"VPSUBD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPSUBD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpsubd ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 FA /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPSUBD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPSUBD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpsubd zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 FA /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPSUBQ xmm1, xmmV, xmm2/m128","VPSUBQ xmm2/m128, xmmV, xmm1","vpsubq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG FB /r","V","V","AVX","","w,r,r","","" +"VPSUBQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPSUBQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpsubq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 FB /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPSUBQ ymm1, ymmV, ymm2/m256","VPSUBQ ymm2/m256, ymmV, ymm1","vpsubq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG FB /r","V","V","AVX2","","w,r,r","","" +"VPSUBQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPSUBQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpsubq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 FB /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPSUBQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPSUBQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpsubq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 FB /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPSUBSB xmm1, xmmV, xmm2/m128","VPSUBSB xmm2/m128, xmmV, xmm1","vpsubsb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG E8 /r","V","V","AVX","","w,r,r","","" +"VPSUBSB xmm1, {k}{z}, xmmV, xmm2/m128","VPSUBSB xmm2/m128, xmmV, {k}{z}, xmm1","vpsubsb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG E8 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSUBSB ymm1, ymmV, ymm2/m256","VPSUBSB ymm2/m256, ymmV, ymm1","vpsubsb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG E8 /r","V","V","AVX2","","w,r,r","","" +"VPSUBSB ymm1, {k}{z}, ymmV, ymm2/m256","VPSUBSB ymm2/m256, ymmV, {k}{z}, ymm1","vpsubsb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG E8 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSUBSB zmm1, {k}{z}, zmmV, zmm2/m512","VPSUBSB zmm2/m512, zmmV, {k}{z}, zmm1","vpsubsb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG E8 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSUBSW xmm1, xmmV, xmm2/m128","VPSUBSW xmm2/m128, xmmV, xmm1","vpsubsw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG E9 /r","V","V","AVX","","w,r,r","","" +"VPSUBSW xmm1, {k}{z}, xmmV, xmm2/m128","VPSUBSW xmm2/m128, xmmV, {k}{z}, xmm1","vpsubsw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG E9 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSUBSW ymm1, ymmV, ymm2/m256","VPSUBSW ymm2/m256, ymmV, ymm1","vpsubsw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG E9 /r","V","V","AVX2","","w,r,r","","" +"VPSUBSW ymm1, {k}{z}, ymmV, ymm2/m256","VPSUBSW ymm2/m256, ymmV, {k}{z}, ymm1","vpsubsw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG E9 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSUBSW zmm1, {k}{z}, zmmV, zmm2/m512","VPSUBSW zmm2/m512, zmmV, {k}{z}, zmm1","vpsubsw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG E9 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSUBUSB xmm1, xmmV, xmm2/m128","VPSUBUSB xmm2/m128, xmmV, xmm1","vpsubusb xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG D8 /r","V","V","AVX","","w,r,r","","" +"VPSUBUSB xmm1, {k}{z}, xmmV, xmm2/m128","VPSUBUSB xmm2/m128, xmmV, {k}{z}, xmm1","vpsubusb xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG D8 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSUBUSB ymm1, ymmV, ymm2/m256","VPSUBUSB ymm2/m256, ymmV, ymm1","vpsubusb ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG D8 /r","V","V","AVX2","","w,r,r","","" +"VPSUBUSB ymm1, {k}{z}, ymmV, ymm2/m256","VPSUBUSB ymm2/m256, ymmV, {k}{z}, ymm1","vpsubusb ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG D8 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSUBUSB zmm1, {k}{z}, zmmV, zmm2/m512","VPSUBUSB zmm2/m512, zmmV, {k}{z}, zmm1","vpsubusb zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG D8 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSUBUSW xmm1, xmmV, xmm2/m128","VPSUBUSW xmm2/m128, xmmV, xmm1","vpsubusw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG D9 /r","V","V","AVX","","w,r,r","","" +"VPSUBUSW xmm1, {k}{z}, xmmV, xmm2/m128","VPSUBUSW xmm2/m128, xmmV, {k}{z}, xmm1","vpsubusw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG D9 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSUBUSW ymm1, ymmV, ymm2/m256","VPSUBUSW ymm2/m256, ymmV, ymm1","vpsubusw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG D9 /r","V","V","AVX2","","w,r,r","","" +"VPSUBUSW ymm1, {k}{z}, ymmV, ymm2/m256","VPSUBUSW ymm2/m256, ymmV, {k}{z}, ymm1","vpsubusw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG D9 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSUBUSW zmm1, {k}{z}, zmmV, zmm2/m512","VPSUBUSW zmm2/m512, zmmV, {k}{z}, zmm1","vpsubusw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG D9 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPSUBW xmm1, xmmV, xmm2/m128","VPSUBW xmm2/m128, xmmV, xmm1","vpsubw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG F9 /r","V","V","AVX","","w,r,r","","" +"VPSUBW xmm1, {k}{z}, xmmV, xmm2/m128","VPSUBW xmm2/m128, xmmV, {k}{z}, xmm1","vpsubw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG F9 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPSUBW ymm1, ymmV, ymm2/m256","VPSUBW ymm2/m256, ymmV, ymm1","vpsubw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG F9 /r","V","V","AVX2","","w,r,r","","" +"VPSUBW ymm1, {k}{z}, ymmV, ymm2/m256","VPSUBW ymm2/m256, ymmV, {k}{z}, ymm1","vpsubw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG F9 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPSUBW zmm1, {k}{z}, zmmV, zmm2/m512","VPSUBW zmm2/m512, zmmV, {k}{z}, zmm1","vpsubw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG F9 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPTERNLOGD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst, imm8u","VPTERNLOGD imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpternlogd imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F3A.W0 25 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","rw,r,r,r,r","","" +"VPTERNLOGD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u","VPTERNLOGD imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpternlogd imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F3A.W0 25 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","rw,r,r,r,r","","" +"VPTERNLOGD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u","VPTERNLOGD imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpternlogd imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F3A.W0 25 /r ib","V","V","AVX512F","bscale4,scale64","rw,r,r,r,r","","" +"VPTERNLOGQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u","VPTERNLOGQ imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpternlogq imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.DDS.128.66.0F3A.W1 25 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","rw,r,r,r,r","","" +"VPTERNLOGQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VPTERNLOGQ imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpternlogq imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.DDS.256.66.0F3A.W1 25 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","rw,r,r,r,r","","" +"VPTERNLOGQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VPTERNLOGQ imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpternlogq imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.DDS.512.66.0F3A.W1 25 /r ib","V","V","AVX512F","bscale8,scale64","rw,r,r,r,r","","" +"VPTEST xmm1, xmm2/m128","VPTEST xmm2/m128, xmm1","vptest xmm2/m128, xmm1","VEX.128.66.0F38.WIG 17 /r","V","V","AVX","","r,r","","" +"VPTEST ymm1, ymm2/m256","VPTEST ymm2/m256, ymm1","vptest ymm2/m256, ymm1","VEX.256.66.0F38.WIG 17 /r","V","V","AVX","","r,r","","" +"VPTESTMB k1, {k}, xmmV, xmm2/m128","VPTESTMB xmm2/m128, xmmV, {k}, k1","vptestmb xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F38.W0 26 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPTESTMB k1, {k}, ymmV, ymm2/m256","VPTESTMB ymm2/m256, ymmV, {k}, k1","vptestmb ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F38.W0 26 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPTESTMB k1, {k}, zmmV, zmm2/m512","VPTESTMB zmm2/m512, zmmV, {k}, k1","vptestmb zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F38.W0 26 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPTESTMD k1, {k}, xmmV, xmm2/m128/m32bcst","VPTESTMD xmm2/m128/m32bcst, xmmV, {k}, k1","vptestmd xmm2/m128/m32bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F38.W0 27 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPTESTMD k1, {k}, ymmV, ymm2/m256/m32bcst","VPTESTMD ymm2/m256/m32bcst, ymmV, {k}, k1","vptestmd ymm2/m256/m32bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F38.W0 27 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPTESTMD k1, {k}, zmmV, zmm2/m512/m32bcst","VPTESTMD zmm2/m512/m32bcst, zmmV, {k}, k1","vptestmd zmm2/m512/m32bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F38.W0 27 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPTESTMQ k1, {k}, xmmV, xmm2/m128/m64bcst","VPTESTMQ xmm2/m128/m64bcst, xmmV, {k}, k1","vptestmq xmm2/m128/m64bcst, xmmV, {k}, k1","EVEX.NDS.128.66.0F38.W1 27 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPTESTMQ k1, {k}, ymmV, ymm2/m256/m64bcst","VPTESTMQ ymm2/m256/m64bcst, ymmV, {k}, k1","vptestmq ymm2/m256/m64bcst, ymmV, {k}, k1","EVEX.NDS.256.66.0F38.W1 27 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPTESTMQ k1, {k}, zmmV, zmm2/m512/m64bcst","VPTESTMQ zmm2/m512/m64bcst, zmmV, {k}, k1","vptestmq zmm2/m512/m64bcst, zmmV, {k}, k1","EVEX.NDS.512.66.0F38.W1 27 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPTESTMW k1, {k}, xmmV, xmm2/m128","VPTESTMW xmm2/m128, xmmV, {k}, k1","vptestmw xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.66.0F38.W1 26 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPTESTMW k1, {k}, ymmV, ymm2/m256","VPTESTMW ymm2/m256, ymmV, {k}, k1","vptestmw ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.66.0F38.W1 26 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPTESTMW k1, {k}, zmmV, zmm2/m512","VPTESTMW zmm2/m512, zmmV, {k}, k1","vptestmw zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.66.0F38.W1 26 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPTESTNMB k1, {k}, xmmV, xmm2/m128","VPTESTNMB xmm2/m128, xmmV, {k}, k1","vptestnmb xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.F3.0F38.W0 26 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPTESTNMB k1, {k}, ymmV, ymm2/m256","VPTESTNMB ymm2/m256, ymmV, {k}, k1","vptestnmb ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.F3.0F38.W0 26 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPTESTNMB k1, {k}, zmmV, zmm2/m512","VPTESTNMB zmm2/m512, zmmV, {k}, k1","vptestnmb zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.F3.0F38.W0 26 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPTESTNMD k1, {k}, xmmV, xmm2/m128/m32bcst","VPTESTNMD xmm2/m128/m32bcst, xmmV, {k}, k1","vptestnmd xmm2/m128/m32bcst, xmmV, {k}, k1","EVEX.NDS.128.F3.0F38.W0 27 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPTESTNMD k1, {k}, ymmV, ymm2/m256/m32bcst","VPTESTNMD ymm2/m256/m32bcst, ymmV, {k}, k1","vptestnmd ymm2/m256/m32bcst, ymmV, {k}, k1","EVEX.NDS.256.F3.0F38.W0 27 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPTESTNMD k1, {k}, zmmV, zmm2/m512/m32bcst","VPTESTNMD zmm2/m512/m32bcst, zmmV, {k}, k1","vptestnmd zmm2/m512/m32bcst, zmmV, {k}, k1","EVEX.NDS.512.F3.0F38.W0 27 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPTESTNMQ k1, {k}, xmmV, xmm2/m128/m64bcst","VPTESTNMQ xmm2/m128/m64bcst, xmmV, {k}, k1","vptestnmq xmm2/m128/m64bcst, xmmV, {k}, k1","EVEX.NDS.128.F3.0F38.W1 27 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPTESTNMQ k1, {k}, ymmV, ymm2/m256/m64bcst","VPTESTNMQ ymm2/m256/m64bcst, ymmV, {k}, k1","vptestnmq ymm2/m256/m64bcst, ymmV, {k}, k1","EVEX.NDS.256.F3.0F38.W1 27 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPTESTNMQ k1, {k}, zmmV, zmm2/m512/m64bcst","VPTESTNMQ zmm2/m512/m64bcst, zmmV, {k}, k1","vptestnmq zmm2/m512/m64bcst, zmmV, {k}, k1","EVEX.NDS.512.F3.0F38.W1 27 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPTESTNMW k1, {k}, xmmV, xmm2/m128","VPTESTNMW xmm2/m128, xmmV, {k}, k1","vptestnmw xmm2/m128, xmmV, {k}, k1","EVEX.NDS.128.F3.0F38.W1 26 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPTESTNMW k1, {k}, ymmV, ymm2/m256","VPTESTNMW ymm2/m256, ymmV, {k}, k1","vptestnmw ymm2/m256, ymmV, {k}, k1","EVEX.NDS.256.F3.0F38.W1 26 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPTESTNMW k1, {k}, zmmV, zmm2/m512","VPTESTNMW zmm2/m512, zmmV, {k}, k1","vptestnmw zmm2/m512, zmmV, {k}, k1","EVEX.NDS.512.F3.0F38.W1 26 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPUNPCKHBW xmm1, xmmV, xmm2/m128","VPUNPCKHBW xmm2/m128, xmmV, xmm1","vpunpckhbw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 68 /r","V","V","AVX","","w,r,r","","" +"VPUNPCKHBW xmm1, {k}{z}, xmmV, xmm2/m128","VPUNPCKHBW xmm2/m128, xmmV, {k}{z}, xmm1","vpunpckhbw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG 68 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPUNPCKHBW ymm1, ymmV, ymm2/m256","VPUNPCKHBW ymm2/m256, ymmV, ymm1","vpunpckhbw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 68 /r","V","V","AVX2","","w,r,r","","" +"VPUNPCKHBW ymm1, {k}{z}, ymmV, ymm2/m256","VPUNPCKHBW ymm2/m256, ymmV, {k}{z}, ymm1","vpunpckhbw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG 68 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPUNPCKHBW zmm1, {k}{z}, zmmV, zmm2/m512","VPUNPCKHBW zmm2/m512, zmmV, {k}{z}, zmm1","vpunpckhbw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG 68 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPUNPCKHDQ xmm1, xmmV, xmm2/m128","VPUNPCKHDQ xmm2/m128, xmmV, xmm1","vpunpckhdq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 6A /r","V","V","AVX","","w,r,r","","" +"VPUNPCKHDQ xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPUNPCKHDQ xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpunpckhdq xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 6A /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPUNPCKHDQ ymm1, ymmV, ymm2/m256","VPUNPCKHDQ ymm2/m256, ymmV, ymm1","vpunpckhdq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 6A /r","V","V","AVX2","","w,r,r","","" +"VPUNPCKHDQ ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPUNPCKHDQ ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpunpckhdq ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 6A /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPUNPCKHDQ zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPUNPCKHDQ zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpunpckhdq zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 6A /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPUNPCKHQDQ xmm1, xmmV, xmm2/m128","VPUNPCKHQDQ xmm2/m128, xmmV, xmm1","vpunpckhqdq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 6D /r","V","V","AVX","","w,r,r","","" +"VPUNPCKHQDQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPUNPCKHQDQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpunpckhqdq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 6D /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPUNPCKHQDQ ymm1, ymmV, ymm2/m256","VPUNPCKHQDQ ymm2/m256, ymmV, ymm1","vpunpckhqdq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 6D /r","V","V","AVX2","","w,r,r","","" +"VPUNPCKHQDQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPUNPCKHQDQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpunpckhqdq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 6D /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPUNPCKHQDQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPUNPCKHQDQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpunpckhqdq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 6D /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPUNPCKHWD xmm1, xmmV, xmm2/m128","VPUNPCKHWD xmm2/m128, xmmV, xmm1","vpunpckhwd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 69 /r","V","V","AVX","","w,r,r","","" +"VPUNPCKHWD xmm1, {k}{z}, xmmV, xmm2/m128","VPUNPCKHWD xmm2/m128, xmmV, {k}{z}, xmm1","vpunpckhwd xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG 69 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPUNPCKHWD ymm1, ymmV, ymm2/m256","VPUNPCKHWD ymm2/m256, ymmV, ymm1","vpunpckhwd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 69 /r","V","V","AVX2","","w,r,r","","" +"VPUNPCKHWD ymm1, {k}{z}, ymmV, ymm2/m256","VPUNPCKHWD ymm2/m256, ymmV, {k}{z}, ymm1","vpunpckhwd ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG 69 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPUNPCKHWD zmm1, {k}{z}, zmmV, zmm2/m512","VPUNPCKHWD zmm2/m512, zmmV, {k}{z}, zmm1","vpunpckhwd zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG 69 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPUNPCKLBW xmm1, xmmV, xmm2/m128","VPUNPCKLBW xmm2/m128, xmmV, xmm1","vpunpcklbw xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 60 /r","V","V","AVX","","w,r,r","","" +"VPUNPCKLBW xmm1, {k}{z}, xmmV, xmm2/m128","VPUNPCKLBW xmm2/m128, xmmV, {k}{z}, xmm1","vpunpcklbw xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG 60 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPUNPCKLBW ymm1, ymmV, ymm2/m256","VPUNPCKLBW ymm2/m256, ymmV, ymm1","vpunpcklbw ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 60 /r","V","V","AVX2","","w,r,r","","" +"VPUNPCKLBW ymm1, {k}{z}, ymmV, ymm2/m256","VPUNPCKLBW ymm2/m256, ymmV, {k}{z}, ymm1","vpunpcklbw ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG 60 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPUNPCKLBW zmm1, {k}{z}, zmmV, zmm2/m512","VPUNPCKLBW zmm2/m512, zmmV, {k}{z}, zmm1","vpunpcklbw zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG 60 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPUNPCKLDQ xmm1, xmmV, xmm2/m128","VPUNPCKLDQ xmm2/m128, xmmV, xmm1","vpunpckldq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 62 /r","V","V","AVX","","w,r,r","","" +"VPUNPCKLDQ xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPUNPCKLDQ xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpunpckldq xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 62 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPUNPCKLDQ ymm1, ymmV, ymm2/m256","VPUNPCKLDQ ymm2/m256, ymmV, ymm1","vpunpckldq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 62 /r","V","V","AVX2","","w,r,r","","" +"VPUNPCKLDQ ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPUNPCKLDQ ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpunpckldq ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 62 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPUNPCKLDQ zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPUNPCKLDQ zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpunpckldq zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 62 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPUNPCKLQDQ xmm1, xmmV, xmm2/m128","VPUNPCKLQDQ xmm2/m128, xmmV, xmm1","vpunpcklqdq xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 6C /r","V","V","AVX","","w,r,r","","" +"VPUNPCKLQDQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPUNPCKLQDQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpunpcklqdq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 6C /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPUNPCKLQDQ ymm1, ymmV, ymm2/m256","VPUNPCKLQDQ ymm2/m256, ymmV, ymm1","vpunpcklqdq ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 6C /r","V","V","AVX2","","w,r,r","","" +"VPUNPCKLQDQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPUNPCKLQDQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpunpcklqdq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 6C /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPUNPCKLQDQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPUNPCKLQDQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpunpcklqdq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 6C /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VPUNPCKLWD xmm1, xmmV, xmm2/m128","VPUNPCKLWD xmm2/m128, xmmV, xmm1","vpunpcklwd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 61 /r","V","V","AVX","","w,r,r","","" +"VPUNPCKLWD xmm1, {k}{z}, xmmV, xmm2/m128","VPUNPCKLWD xmm2/m128, xmmV, {k}{z}, xmm1","vpunpcklwd xmm2/m128, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.WIG 61 /r","V","V","AVX512BW+AVX512VL","scale16","w,r,r,r","","" +"VPUNPCKLWD ymm1, ymmV, ymm2/m256","VPUNPCKLWD ymm2/m256, ymmV, ymm1","vpunpcklwd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 61 /r","V","V","AVX2","","w,r,r","","" +"VPUNPCKLWD ymm1, {k}{z}, ymmV, ymm2/m256","VPUNPCKLWD ymm2/m256, ymmV, {k}{z}, ymm1","vpunpcklwd ymm2/m256, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.WIG 61 /r","V","V","AVX512BW+AVX512VL","scale32","w,r,r,r","","" +"VPUNPCKLWD zmm1, {k}{z}, zmmV, zmm2/m512","VPUNPCKLWD zmm2/m512, zmmV, {k}{z}, zmm1","vpunpcklwd zmm2/m512, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.WIG 61 /r","V","V","AVX512BW","scale64","w,r,r,r","","" +"VPXOR xmm1, xmmV, xmm2/m128","VPXOR xmm2/m128, xmmV, xmm1","vpxor xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG EF /r","V","V","AVX","","w,r,r","","" +"VPXOR ymm1, ymmV, ymm2/m256","VPXOR ymm2/m256, ymmV, ymm1","vpxor ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG EF /r","V","V","AVX2","","w,r,r","","" +"VPXORD xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VPXORD xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vpxord xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W0 EF /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VPXORD ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VPXORD ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vpxord ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W0 EF /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VPXORD zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VPXORD zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vpxord zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W0 EF /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VPXORQ xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VPXORQ xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vpxorq xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 EF /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VPXORQ ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VPXORQ ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vpxorq ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 EF /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VPXORQ zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VPXORQ zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vpxorq zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 EF /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VRANGEPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u:4","VRANGEPD imm8u:4, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vrangepd imm8u:4, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W1 50 /r ib","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VRANGEPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u:4","VRANGEPD imm8u:4, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vrangepd imm8u:4, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 50 /r ib","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VRANGEPD zmm1{sae}, {k}{z}, zmmV, zmm2, imm8u:4","VRANGEPD imm8u:4, zmm2, zmmV, {k}{z}, zmm1{sae}","vrangepd imm8u:4, zmm2, zmmV, {k}{z}, zmm1{sae}","EVEX.NDS.512.66.0F3A.W1 50 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r,r,r","","" +"VRANGEPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u:4","VRANGEPD imm8u:4, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vrangepd imm8u:4, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 50 /r ib","V","V","AVX512DQ","bscale8,scale64","w,r,r,r,r","","" +"VRANGEPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst, imm8u:4","VRANGEPS imm8u:4, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vrangeps imm8u:4, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F3A.W0 50 /r ib","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r,r,r","","" +"VRANGEPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u:4","VRANGEPS imm8u:4, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vrangeps imm8u:4, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 50 /r ib","V","V","AVX512DQ+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VRANGEPS zmm1{sae}, {k}{z}, zmmV, zmm2, imm8u:4","VRANGEPS imm8u:4, zmm2, zmmV, {k}{z}, zmm1{sae}","vrangeps imm8u:4, zmm2, zmmV, {k}{z}, zmm1{sae}","EVEX.NDS.512.66.0F3A.W0 50 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r,r,r","","" +"VRANGEPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u:4","VRANGEPS imm8u:4, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vrangeps imm8u:4, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 50 /r ib","V","V","AVX512DQ","bscale4,scale64","w,r,r,r,r","","" +"VRANGESD xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u:4","VRANGESD imm8u:4, xmm2, xmmV, {k}{z}, xmm1{sae}","vrangesd imm8u:4, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F3A.W1 51 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r,r,r","","" +"VRANGESD xmm1, {k}{z}, xmmV, xmm2/m64, imm8u:4","VRANGESD imm8u:4, xmm2/m64, xmmV, {k}{z}, xmm1","vrangesd imm8u:4, xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F3A.W1 51 /r ib","V","V","AVX512DQ","scale8","w,r,r,r,r","","" +"VRANGESS xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u:4","VRANGESS imm8u:4, xmm2, xmmV, {k}{z}, xmm1{sae}","vrangess imm8u:4, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F3A.W0 51 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r,r,r","","" +"VRANGESS xmm1, {k}{z}, xmmV, xmm2/m32, imm8u:4","VRANGESS imm8u:4, xmm2/m32, xmmV, {k}{z}, xmm1","vrangess imm8u:4, xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F3A.W0 51 /r ib","V","V","AVX512DQ","scale4","w,r,r,r,r","","" +"VRCP14PD xmm1, {k}{z}, xmm2/m128/m64bcst","VRCP14PD xmm2/m128/m64bcst, {k}{z}, xmm1","vrcp14pd xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W1 4C /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","","" +"VRCP14PD ymm1, {k}{z}, ymm2/m256/m64bcst","VRCP14PD ymm2/m256/m64bcst, {k}{z}, ymm1","vrcp14pd ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W1 4C /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","","" +"VRCP14PD zmm1, {k}{z}, zmm2/m512/m64bcst","VRCP14PD zmm2/m512/m64bcst, {k}{z}, zmm1","vrcp14pd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 4C /r","V","V","AVX512F","bscale8,scale64","w,r,r","","" +"VRCP14PS xmm1, {k}{z}, xmm2/m128/m32bcst","VRCP14PS xmm2/m128/m32bcst, {k}{z}, xmm1","vrcp14ps xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W0 4C /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VRCP14PS ymm1, {k}{z}, ymm2/m256/m32bcst","VRCP14PS ymm2/m256/m32bcst, {k}{z}, ymm1","vrcp14ps ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W0 4C /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VRCP14PS zmm1, {k}{z}, zmm2/m512/m32bcst","VRCP14PS zmm2/m512/m32bcst, {k}{z}, zmm1","vrcp14ps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 4C /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VRCP14SD xmm1, {k}{z}, xmmV, xmm2/m64","VRCP14SD xmm2/m64, xmmV, {k}{z}, xmm1","vrcp14sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W1 4D /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VRCP14SS xmm1, {k}{z}, xmmV, xmm2/m32","VRCP14SS xmm2/m32, xmmV, {k}{z}, xmm1","vrcp14ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W0 4D /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VRCP28PD zmm1{sae}, {k}{z}, zmm2","VRCP28PD zmm2, {k}{z}, zmm1{sae}","vrcp28pd zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W1 CA /r","V","V","AVX512ER","modrm_regonly","w,r,r","","" +"VRCP28PD zmm1, {k}{z}, zmm2/m512/m64bcst","VRCP28PD zmm2/m512/m64bcst, {k}{z}, zmm1","vrcp28pd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 CA /r","V","V","AVX512ER","bscale8,scale64","w,r,r","","" +"VRCP28PS zmm1{sae}, {k}{z}, zmm2","VRCP28PS zmm2, {k}{z}, zmm1{sae}","vrcp28ps zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W0 CA /r","V","V","AVX512ER","modrm_regonly","w,r,r","","" +"VRCP28PS zmm1, {k}{z}, zmm2/m512/m32bcst","VRCP28PS zmm2/m512/m32bcst, {k}{z}, zmm1","vrcp28ps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 CA /r","V","V","AVX512ER","bscale4,scale64","w,r,r","","" +"VRCP28SD xmm1{sae}, {k}{z}, xmmV, xmm2","VRCP28SD xmm2, xmmV, {k}{z}, xmm1{sae}","vrcp28sd xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F38.W1 CB /r","V","V","AVX512ER","modrm_regonly","w,r,r,r","","" +"VRCP28SD xmm1, {k}{z}, xmmV, xmm2/m64","VRCP28SD xmm2/m64, xmmV, {k}{z}, xmm1","vrcp28sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W1 CB /r","V","V","AVX512ER","scale8","w,r,r,r","","" +"VRCP28SS xmm1{sae}, {k}{z}, xmmV, xmm2","VRCP28SS xmm2, xmmV, {k}{z}, xmm1{sae}","vrcp28ss xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F38.W0 CB /r","V","V","AVX512ER","modrm_regonly","w,r,r,r","","" +"VRCP28SS xmm1, {k}{z}, xmmV, xmm2/m32","VRCP28SS xmm2/m32, xmmV, {k}{z}, xmm1","vrcp28ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W0 CB /r","V","V","AVX512ER","scale4","w,r,r,r","","" +"VRCPPS xmm1, xmm2/m128","VRCPPS xmm2/m128, xmm1","vrcpps xmm2/m128, xmm1","VEX.128.0F.WIG 53 /r","V","V","AVX","","w,r","","" +"VRCPPS ymm1, ymm2/m256","VRCPPS ymm2/m256, ymm1","vrcpps ymm2/m256, ymm1","VEX.256.0F.WIG 53 /r","V","V","AVX","","w,r","","" +"VRCPSS xmm1, xmmV, xmm2/m32","VRCPSS xmm2/m32, xmmV, xmm1","vrcpss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 53 /r","V","V","AVX","","w,r,r","","" +"VREDUCEPD xmm1, {k}{z}, xmm2/m128/m64bcst, imm8u","VREDUCEPD imm8u, xmm2/m128/m64bcst, {k}{z}, xmm1","vreducepd imm8u, xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F3A.W1 56 /r ib","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VREDUCEPD ymm1, {k}{z}, ymm2/m256/m64bcst, imm8u","VREDUCEPD imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","vreducepd imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W1 56 /r ib","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VREDUCEPD zmm1{sae}, {k}{z}, zmm2, imm8u","VREDUCEPD imm8u, zmm2, {k}{z}, zmm1{sae}","vreducepd imm8u, zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F3A.W1 56 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r,r","","" +"VREDUCEPD zmm1, {k}{z}, zmm2/m512/m64bcst, imm8u","VREDUCEPD imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","vreducepd imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W1 56 /r ib","V","V","AVX512DQ","bscale8,scale64","w,r,r,r","","" +"VREDUCEPS xmm1, {k}{z}, xmm2/m128/m32bcst, imm8u","VREDUCEPS imm8u, xmm2/m128/m32bcst, {k}{z}, xmm1","vreduceps imm8u, xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F3A.W0 56 /r ib","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VREDUCEPS ymm1, {k}{z}, ymm2/m256/m32bcst, imm8u","VREDUCEPS imm8u, ymm2/m256/m32bcst, {k}{z}, ymm1","vreduceps imm8u, ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W0 56 /r ib","V","V","AVX512DQ+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VREDUCEPS zmm1{sae}, {k}{z}, zmm2, imm8u","VREDUCEPS imm8u, zmm2, {k}{z}, zmm1{sae}","vreduceps imm8u, zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F3A.W0 56 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r,r","","" +"VREDUCEPS zmm1, {k}{z}, zmm2/m512/m32bcst, imm8u","VREDUCEPS imm8u, zmm2/m512/m32bcst, {k}{z}, zmm1","vreduceps imm8u, zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W0 56 /r ib","V","V","AVX512DQ","bscale4,scale64","w,r,r,r","","" +"VREDUCESD xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u","VREDUCESD imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","vreducesd imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F3A.W1 57 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r,r,r","","" +"VREDUCESD xmm1, {k}{z}, xmmV, xmm2/m64, imm8u","VREDUCESD imm8u, xmm2/m64, xmmV, {k}{z}, xmm1","vreducesd imm8u, xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F3A.W1 57 /r ib","V","V","AVX512DQ","scale8","w,r,r,r,r","","" +"VREDUCESS xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u","VREDUCESS imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","vreducess imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F3A.W0 57 /r ib","V","V","AVX512DQ","modrm_regonly","w,r,r,r,r","","" +"VREDUCESS xmm1, {k}{z}, xmmV, xmm2/m32, imm8u","VREDUCESS imm8u, xmm2/m32, xmmV, {k}{z}, xmm1","vreducess imm8u, xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F3A.W0 57 /r ib","V","V","AVX512DQ","scale4","w,r,r,r,r","","" +"VRNDSCALEPD xmm1, {k}{z}, xmm2/m128/m64bcst, imm8u","VRNDSCALEPD imm8u, xmm2/m128/m64bcst, {k}{z}, xmm1","vrndscalepd imm8u, xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F3A.W1 09 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VRNDSCALEPD ymm1, {k}{z}, ymm2/m256/m64bcst, imm8u","VRNDSCALEPD imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","vrndscalepd imm8u, ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W1 09 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VRNDSCALEPD zmm1{sae}, {k}{z}, zmm2, imm8u","VRNDSCALEPD imm8u, zmm2, {k}{z}, zmm1{sae}","vrndscalepd imm8u, zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F3A.W1 09 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VRNDSCALEPD zmm1, {k}{z}, zmm2/m512/m64bcst, imm8u","VRNDSCALEPD imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","vrndscalepd imm8u, zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W1 09 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VRNDSCALEPS xmm1, {k}{z}, xmm2/m128/m32bcst, imm8u","VRNDSCALEPS imm8u, xmm2/m128/m32bcst, {k}{z}, xmm1","vrndscaleps imm8u, xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F3A.W0 08 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VRNDSCALEPS ymm1, {k}{z}, ymm2/m256/m32bcst, imm8u","VRNDSCALEPS imm8u, ymm2/m256/m32bcst, {k}{z}, ymm1","vrndscaleps imm8u, ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F3A.W0 08 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VRNDSCALEPS zmm1{sae}, {k}{z}, zmm2, imm8u","VRNDSCALEPS imm8u, zmm2, {k}{z}, zmm1{sae}","vrndscaleps imm8u, zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F3A.W0 08 /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VRNDSCALEPS zmm1, {k}{z}, zmm2/m512/m32bcst, imm8u","VRNDSCALEPS imm8u, zmm2/m512/m32bcst, {k}{z}, zmm1","vrndscaleps imm8u, zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F3A.W0 08 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VRNDSCALESD xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u","VRNDSCALESD imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","vrndscalesd imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F3A.W1 0B /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r,r","","" +"VRNDSCALESD xmm1, {k}{z}, xmmV, xmm2/m64, imm8u","VRNDSCALESD imm8u, xmm2/m64, xmmV, {k}{z}, xmm1","vrndscalesd imm8u, xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F3A.W1 0B /r ib","V","V","AVX512F","scale8","w,r,r,r,r","","" +"VRNDSCALESS xmm1{sae}, {k}{z}, xmmV, xmm2, imm8u","VRNDSCALESS imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","vrndscaless imm8u, xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F3A.W0 0A /r ib","V","V","AVX512F","modrm_regonly","w,r,r,r,r","","" +"VRNDSCALESS xmm1, {k}{z}, xmmV, xmm2/m32, imm8u","VRNDSCALESS imm8u, xmm2/m32, xmmV, {k}{z}, xmm1","vrndscaless imm8u, xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F3A.W0 0A /r ib","V","V","AVX512F","scale4","w,r,r,r,r","","" +"VROUNDPD xmm1, xmm2/m128, imm8u","VROUNDPD imm8u, xmm2/m128, xmm1","vroundpd imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.WIG 09 /r ib","V","V","AVX","","w,r,r","","" +"VROUNDPD ymm1, ymm2/m256, imm8u","VROUNDPD imm8u, ymm2/m256, ymm1","vroundpd imm8u, ymm2/m256, ymm1","VEX.256.66.0F3A.WIG 09 /r ib","V","V","AVX","","w,r,r","","" +"VROUNDPS xmm1, xmm2/m128, imm8u","VROUNDPS imm8u, xmm2/m128, xmm1","vroundps imm8u, xmm2/m128, xmm1","VEX.128.66.0F3A.WIG 08 /r ib","V","V","AVX","","w,r,r","","" +"VROUNDPS ymm1, ymm2/m256, imm8u","VROUNDPS imm8u, ymm2/m256, ymm1","vroundps imm8u, ymm2/m256, ymm1","VEX.256.66.0F3A.WIG 08 /r ib","V","V","AVX","","w,r,r","","" +"VROUNDSD xmm1, xmmV, xmm2/m64, imm8u","VROUNDSD imm8u, xmm2/m64, xmmV, xmm1","vroundsd imm8u, xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.WIG 0B /r ib","V","V","AVX","","w,r,r,r","","" +"VROUNDSS xmm1, xmmV, xmm2/m32, imm8u","VROUNDSS imm8u, xmm2/m32, xmmV, xmm1","vroundss imm8u, xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.66.0F3A.WIG 0A /r ib","V","V","AVX","","w,r,r,r","","" +"VRSQRT14PD xmm1, {k}{z}, xmm2/m128/m64bcst","VRSQRT14PD xmm2/m128/m64bcst, {k}{z}, xmm1","vrsqrt14pd xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W1 4E /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","","" +"VRSQRT14PD ymm1, {k}{z}, ymm2/m256/m64bcst","VRSQRT14PD ymm2/m256/m64bcst, {k}{z}, ymm1","vrsqrt14pd ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W1 4E /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","","" +"VRSQRT14PD zmm1, {k}{z}, zmm2/m512/m64bcst","VRSQRT14PD zmm2/m512/m64bcst, {k}{z}, zmm1","vrsqrt14pd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 4E /r","V","V","AVX512F","bscale8,scale64","w,r,r","","" +"VRSQRT14PS xmm1, {k}{z}, xmm2/m128/m32bcst","VRSQRT14PS xmm2/m128/m32bcst, {k}{z}, xmm1","vrsqrt14ps xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.66.0F38.W0 4E /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VRSQRT14PS ymm1, {k}{z}, ymm2/m256/m32bcst","VRSQRT14PS ymm2/m256/m32bcst, {k}{z}, ymm1","vrsqrt14ps ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.66.0F38.W0 4E /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VRSQRT14PS zmm1, {k}{z}, zmm2/m512/m32bcst","VRSQRT14PS zmm2/m512/m32bcst, {k}{z}, zmm1","vrsqrt14ps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 4E /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VRSQRT14SD xmm1, {k}{z}, xmmV, xmm2/m64","VRSQRT14SD xmm2/m64, xmmV, {k}{z}, xmm1","vrsqrt14sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W1 4F /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VRSQRT14SS xmm1, {k}{z}, xmmV, xmm2/m32","VRSQRT14SS xmm2/m32, xmmV, {k}{z}, xmm1","vrsqrt14ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W0 4F /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VRSQRT28PD zmm1{sae}, {k}{z}, zmm2","VRSQRT28PD zmm2, {k}{z}, zmm1{sae}","vrsqrt28pd zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W1 CC /r","V","V","AVX512ER","modrm_regonly","w,r,r","","" +"VRSQRT28PD zmm1, {k}{z}, zmm2/m512/m64bcst","VRSQRT28PD zmm2/m512/m64bcst, {k}{z}, zmm1","vrsqrt28pd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W1 CC /r","V","V","AVX512ER","bscale8,scale64","w,r,r","","" +"VRSQRT28PS zmm1{sae}, {k}{z}, zmm2","VRSQRT28PS zmm2, {k}{z}, zmm1{sae}","vrsqrt28ps zmm2, {k}{z}, zmm1{sae}","EVEX.512.66.0F38.W0 CC /r","V","V","AVX512ER","modrm_regonly","w,r,r","","" +"VRSQRT28PS zmm1, {k}{z}, zmm2/m512/m32bcst","VRSQRT28PS zmm2/m512/m32bcst, {k}{z}, zmm1","vrsqrt28ps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.66.0F38.W0 CC /r","V","V","AVX512ER","bscale4,scale64","w,r,r","","" +"VRSQRT28SD xmm1{sae}, {k}{z}, xmmV, xmm2","VRSQRT28SD xmm2, xmmV, {k}{z}, xmm1{sae}","vrsqrt28sd xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F38.W1 CD /r","V","V","AVX512ER","modrm_regonly","w,r,r,r","","" +"VRSQRT28SD xmm1, {k}{z}, xmmV, xmm2/m64","VRSQRT28SD xmm2/m64, xmmV, {k}{z}, xmm1","vrsqrt28sd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W1 CD /r","V","V","AVX512ER","scale8","w,r,r,r","","" +"VRSQRT28SS xmm1{sae}, {k}{z}, xmmV, xmm2","VRSQRT28SS xmm2, xmmV, {k}{z}, xmm1{sae}","vrsqrt28ss xmm2, xmmV, {k}{z}, xmm1{sae}","EVEX.NDS.128.66.0F38.W0 CD /r","V","V","AVX512ER","modrm_regonly","w,r,r,r","","" +"VRSQRT28SS xmm1, {k}{z}, xmmV, xmm2/m32","VRSQRT28SS xmm2/m32, xmmV, {k}{z}, xmm1","vrsqrt28ss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W0 CD /r","V","V","AVX512ER","scale4","w,r,r,r","","" +"VRSQRTPS xmm1, xmm2/m128","VRSQRTPS xmm2/m128, xmm1","vrsqrtps xmm2/m128, xmm1","VEX.128.0F.WIG 52 /r","V","V","AVX","","w,r","","" +"VRSQRTPS ymm1, ymm2/m256","VRSQRTPS ymm2/m256, ymm1","vrsqrtps ymm2/m256, ymm1","VEX.256.0F.WIG 52 /r","V","V","AVX","","w,r","","" +"VRSQRTSS xmm1, xmmV, xmm2/m32","VRSQRTSS xmm2/m32, xmmV, xmm1","vrsqrtss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 52 /r","V","V","AVX","","w,r,r","","" +"VSCALEFPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VSCALEFPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vscalefpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W1 2C /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VSCALEFPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VSCALEFPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vscalefpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W1 2C /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VSCALEFPD zmm1{er}, {k}{z}, zmmV, zmm2","VSCALEFPD zmm2, zmmV, {k}{z}, zmm1{er}","vscalefpd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.66.0F38.W1 2C /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSCALEFPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VSCALEFPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vscalefpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W1 2C /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VSCALEFPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VSCALEFPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vscalefps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F38.W0 2C /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VSCALEFPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VSCALEFPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vscalefps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F38.W0 2C /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VSCALEFPS zmm1{er}, {k}{z}, zmmV, zmm2","VSCALEFPS zmm2, zmmV, {k}{z}, zmm1{er}","vscalefps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.66.0F38.W0 2C /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSCALEFPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VSCALEFPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vscalefps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F38.W0 2C /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VSCALEFSD xmm1{er}, {k}{z}, xmmV, xmm2","VSCALEFSD xmm2, xmmV, {k}{z}, xmm1{er}","vscalefsd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.66.0F38.W1 2D /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSCALEFSD xmm1, {k}{z}, xmmV, xmm2/m64","VSCALEFSD xmm2/m64, xmmV, {k}{z}, xmm1","vscalefsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W1 2D /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VSCALEFSS xmm1{er}, {k}{z}, xmmV, xmm2","VSCALEFSS xmm2, xmmV, {k}{z}, xmm1{er}","vscalefss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.66.0F38.W0 2D /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSCALEFSS xmm1, {k}{z}, xmmV, xmm2/m32","VSCALEFSS xmm2/m32, xmmV, {k}{z}, xmm1","vscalefss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.66.0F38.W0 2D /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VSCATTERDPD vm32x, {k1-k7}, xmm1","VSCATTERDPD xmm1, {k1-k7}, vm32x","vscatterdpd xmm1, {k1-k7}, vm32x","EVEX.128.66.0F38.W1 A2 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VSCATTERDPD vm32x, {k1-k7}, ymm1","VSCATTERDPD ymm1, {k1-k7}, vm32x","vscatterdpd ymm1, {k1-k7}, vm32x","EVEX.256.66.0F38.W1 A2 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VSCATTERDPD vm32y, {k1-k7}, zmm1","VSCATTERDPD zmm1, {k1-k7}, vm32y","vscatterdpd zmm1, {k1-k7}, vm32y","EVEX.512.66.0F38.W1 A2 /vsib","V","V","AVX512F","modrm_memonly,scale8","w,rw,r","","" +"VSCATTERDPS vm32x, {k1-k7}, xmm1","VSCATTERDPS xmm1, {k1-k7}, vm32x","vscatterdps xmm1, {k1-k7}, vm32x","EVEX.128.66.0F38.W0 A2 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VSCATTERDPS vm32y, {k1-k7}, ymm1","VSCATTERDPS ymm1, {k1-k7}, vm32y","vscatterdps ymm1, {k1-k7}, vm32y","EVEX.256.66.0F38.W0 A2 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VSCATTERDPS vm32z, {k1-k7}, zmm1","VSCATTERDPS zmm1, {k1-k7}, vm32z","vscatterdps zmm1, {k1-k7}, vm32z","EVEX.512.66.0F38.W0 A2 /vsib","V","V","AVX512F","modrm_memonly,scale4","w,rw,r","","" +"VSCATTERPF0DPD vm32y, {k1-k7}","VSCATTERPF0DPD {k1-k7}, vm32y","vscatterpf0dpd {k1-k7}, vm32y","EVEX.512.66.0F38.W1 C6 /5","V","V","AVX512PF","modrm_memonly,scale8","r,rw","","" +"VSCATTERPF0DPS vm32z, {k1-k7}","VSCATTERPF0DPS {k1-k7}, vm32z","vscatterpf0dps {k1-k7}, vm32z","EVEX.512.66.0F38.W0 C6 /5","V","V","AVX512PF","modrm_memonly,scale4","r,rw","","" +"VSCATTERPF0QPD vm64z, {k1-k7}","VSCATTERPF0QPD {k1-k7}, vm64z","vscatterpf0qpd {k1-k7}, vm64z","EVEX.512.66.0F38.W1 C7 /5","V","V","AVX512PF","modrm_memonly,scale8","r,rw","","" +"VSCATTERPF0QPS vm64z, {k1-k7}","VSCATTERPF0QPS {k1-k7}, vm64z","vscatterpf0qps {k1-k7}, vm64z","EVEX.512.66.0F38.W0 C7 /5","V","V","AVX512PF","modrm_memonly,scale4","r,rw","","" +"VSCATTERPF1DPD vm32y, {k1-k7}","VSCATTERPF1DPD {k1-k7}, vm32y","vscatterpf1dpd {k1-k7}, vm32y","EVEX.512.66.0F38.W1 C6 /6","V","V","AVX512PF","modrm_memonly,scale8","r,rw","","" +"VSCATTERPF1DPS vm32z, {k1-k7}","VSCATTERPF1DPS {k1-k7}, vm32z","vscatterpf1dps {k1-k7}, vm32z","EVEX.512.66.0F38.W0 C6 /6","V","V","AVX512PF","modrm_memonly,scale4","r,rw","","" +"VSCATTERPF1QPD vm64z, {k1-k7}","VSCATTERPF1QPD {k1-k7}, vm64z","vscatterpf1qpd {k1-k7}, vm64z","EVEX.512.66.0F38.W1 C7 /6","V","V","AVX512PF","modrm_memonly,scale8","r,rw","","" +"VSCATTERPF1QPS vm64z, {k1-k7}","VSCATTERPF1QPS {k1-k7}, vm64z","vscatterpf1qps {k1-k7}, vm64z","EVEX.512.66.0F38.W0 C7 /6","V","V","AVX512PF","modrm_memonly,scale4","r,rw","","" +"VSCATTERQPD vm64x, {k1-k7}, xmm1","VSCATTERQPD xmm1, {k1-k7}, vm64x","vscatterqpd xmm1, {k1-k7}, vm64x","EVEX.128.66.0F38.W1 A3 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VSCATTERQPD vm64y, {k1-k7}, ymm1","VSCATTERQPD ymm1, {k1-k7}, vm64y","vscatterqpd ymm1, {k1-k7}, vm64y","EVEX.256.66.0F38.W1 A3 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale8","w,rw,r","","" +"VSCATTERQPD vm64z, {k1-k7}, zmm1","VSCATTERQPD zmm1, {k1-k7}, vm64z","vscatterqpd zmm1, {k1-k7}, vm64z","EVEX.512.66.0F38.W1 A3 /vsib","V","V","AVX512F","modrm_memonly,scale8","w,rw,r","","" +"VSCATTERQPS vm64x, {k1-k7}, xmm1","VSCATTERQPS xmm1, {k1-k7}, vm64x","vscatterqps xmm1, {k1-k7}, vm64x","EVEX.128.66.0F38.W0 A3 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VSCATTERQPS vm64y, {k1-k7}, xmm1","VSCATTERQPS xmm1, {k1-k7}, vm64y","vscatterqps xmm1, {k1-k7}, vm64y","EVEX.256.66.0F38.W0 A3 /vsib","V","V","AVX512F+AVX512VL","modrm_memonly,scale4","w,rw,r","","" +"VSCATTERQPS vm64z, {k1-k7}, ymm1","VSCATTERQPS ymm1, {k1-k7}, vm64z","vscatterqps ymm1, {k1-k7}, vm64z","EVEX.512.66.0F38.W0 A3 /vsib","V","V","AVX512F","modrm_memonly,scale4","w,rw,r","","" +"VSHUFF32X4 ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u","VSHUFF32X4 imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vshuff32x4 imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 23 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VSHUFF32X4 zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u","VSHUFF32X4 imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vshuff32x4 imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 23 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r,r","","" +"VSHUFF64X2 ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VSHUFF64X2 imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vshuff64x2 imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 23 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VSHUFF64X2 zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VSHUFF64X2 imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vshuff64x2 imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 23 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VSHUFI32X4 ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u","VSHUFI32X4 imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vshufi32x4 imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W0 43 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VSHUFI32X4 zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u","VSHUFI32X4 imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vshufi32x4 imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W0 43 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r,r","","" +"VSHUFI64X2 ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VSHUFI64X2 imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vshufi64x2 imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F3A.W1 43 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VSHUFI64X2 zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VSHUFI64X2 imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vshufi64x2 imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F3A.W1 43 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VSHUFPD xmm1, xmmV, xmm2/m128, imm8u","VSHUFPD imm8u, xmm2/m128, xmmV, xmm1","vshufpd imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG C6 /r ib","V","V","AVX","","w,r,r,r","","" +"VSHUFPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst, imm8u","VSHUFPD imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vshufpd imm8u, xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 C6 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r,r","","" +"VSHUFPD ymm1, ymmV, ymm2/m256, imm8u","VSHUFPD imm8u, ymm2/m256, ymmV, ymm1","vshufpd imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG C6 /r ib","V","V","AVX","","w,r,r,r","","" +"VSHUFPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst, imm8u","VSHUFPD imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vshufpd imm8u, ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 C6 /r ib","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r,r","","" +"VSHUFPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst, imm8u","VSHUFPD imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vshufpd imm8u, zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 C6 /r ib","V","V","AVX512F","bscale8,scale64","w,r,r,r,r","","" +"VSHUFPS xmm1, xmmV, xmm2/m128, imm8u","VSHUFPS imm8u, xmm2/m128, xmmV, xmm1","vshufps imm8u, xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG C6 /r ib","V","V","AVX","","w,r,r,r","","" +"VSHUFPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst, imm8u","VSHUFPS imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vshufps imm8u, xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 C6 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r,r","","" +"VSHUFPS ymm1, ymmV, ymm2/m256, imm8u","VSHUFPS imm8u, ymm2/m256, ymmV, ymm1","vshufps imm8u, ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG C6 /r ib","V","V","AVX","","w,r,r,r","","" +"VSHUFPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst, imm8u","VSHUFPS imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vshufps imm8u, ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 C6 /r ib","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r,r","","" +"VSHUFPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst, imm8u","VSHUFPS imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vshufps imm8u, zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 C6 /r ib","V","V","AVX512F","bscale4,scale64","w,r,r,r,r","","" +"VSQRTPD xmm1, xmm2/m128","VSQRTPD xmm2/m128, xmm1","vsqrtpd xmm2/m128, xmm1","VEX.128.66.0F.WIG 51 /r","V","V","AVX","","w,r","","" +"VSQRTPD xmm1, {k}{z}, xmm2/m128/m64bcst","VSQRTPD xmm2/m128/m64bcst, {k}{z}, xmm1","vsqrtpd xmm2/m128/m64bcst, {k}{z}, xmm1","EVEX.128.66.0F.W1 51 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r","","" +"VSQRTPD ymm1, ymm2/m256","VSQRTPD ymm2/m256, ymm1","vsqrtpd ymm2/m256, ymm1","VEX.256.66.0F.WIG 51 /r","V","V","AVX","","w,r","","" +"VSQRTPD ymm1, {k}{z}, ymm2/m256/m64bcst","VSQRTPD ymm2/m256/m64bcst, {k}{z}, ymm1","vsqrtpd ymm2/m256/m64bcst, {k}{z}, ymm1","EVEX.256.66.0F.W1 51 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r","","" +"VSQRTPD zmm1{er}, {k}{z}, zmm2","VSQRTPD zmm2, {k}{z}, zmm1{er}","vsqrtpd zmm2, {k}{z}, zmm1{er}","EVEX.512.66.0F.W1 51 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VSQRTPD zmm1, {k}{z}, zmm2/m512/m64bcst","VSQRTPD zmm2/m512/m64bcst, {k}{z}, zmm1","vsqrtpd zmm2/m512/m64bcst, {k}{z}, zmm1","EVEX.512.66.0F.W1 51 /r","V","V","AVX512F","bscale8,scale64","w,r,r","","" +"VSQRTPS xmm1, xmm2/m128","VSQRTPS xmm2/m128, xmm1","vsqrtps xmm2/m128, xmm1","VEX.128.0F.WIG 51 /r","V","V","AVX","","w,r","","" +"VSQRTPS xmm1, {k}{z}, xmm2/m128/m32bcst","VSQRTPS xmm2/m128/m32bcst, {k}{z}, xmm1","vsqrtps xmm2/m128/m32bcst, {k}{z}, xmm1","EVEX.128.0F.W0 51 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r","","" +"VSQRTPS ymm1, ymm2/m256","VSQRTPS ymm2/m256, ymm1","vsqrtps ymm2/m256, ymm1","VEX.256.0F.WIG 51 /r","V","V","AVX","","w,r","","" +"VSQRTPS ymm1, {k}{z}, ymm2/m256/m32bcst","VSQRTPS ymm2/m256/m32bcst, {k}{z}, ymm1","vsqrtps ymm2/m256/m32bcst, {k}{z}, ymm1","EVEX.256.0F.W0 51 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r","","" +"VSQRTPS zmm1{er}, {k}{z}, zmm2","VSQRTPS zmm2, {k}{z}, zmm1{er}","vsqrtps zmm2, {k}{z}, zmm1{er}","EVEX.512.0F.W0 51 /r","V","V","AVX512F","modrm_regonly","w,r,r","","" +"VSQRTPS zmm1, {k}{z}, zmm2/m512/m32bcst","VSQRTPS zmm2/m512/m32bcst, {k}{z}, zmm1","vsqrtps zmm2/m512/m32bcst, {k}{z}, zmm1","EVEX.512.0F.W0 51 /r","V","V","AVX512F","bscale4,scale64","w,r,r","","" +"VSQRTSD xmm1{er}, {k}{z}, xmmV, xmm2","VSQRTSD xmm2, xmmV, {k}{z}, xmm1{er}","vsqrtsd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F2.0F.W1 51 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSQRTSD xmm1, xmmV, xmm2/m64","VSQRTSD xmm2/m64, xmmV, xmm1","vsqrtsd xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 51 /r","V","V","AVX","","w,r,r","","" +"VSQRTSD xmm1, {k}{z}, xmmV, xmm2/m64","VSQRTSD xmm2/m64, xmmV, {k}{z}, xmm1","vsqrtsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 51 /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VSQRTSS xmm1{er}, {k}{z}, xmmV, xmm2","VSQRTSS xmm2, xmmV, {k}{z}, xmm1{er}","vsqrtss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F3.0F.W0 51 /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSQRTSS xmm1, xmmV, xmm2/m32","VSQRTSS xmm2/m32, xmmV, xmm1","vsqrtss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 51 /r","V","V","AVX","","w,r,r","","" +"VSQRTSS xmm1, {k}{z}, xmmV, xmm2/m32","VSQRTSS xmm2/m32, xmmV, {k}{z}, xmm1","vsqrtss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 51 /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VSTMXCSR m32","VSTMXCSR m32","vstmxcsr m32","VEX.128.0F.WIG AE /3","V","V","AVX","modrm_memonly","w","","" +"VSUBPD xmm1, xmmV, xmm2/m128","VSUBPD xmm2/m128, xmmV, xmm1","vsubpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 5C /r","V","V","AVX","","w,r,r","","" +"VSUBPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VSUBPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vsubpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 5C /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VSUBPD ymm1, ymmV, ymm2/m256","VSUBPD ymm2/m256, ymmV, ymm1","vsubpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 5C /r","V","V","AVX","","w,r,r","","" +"VSUBPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VSUBPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vsubpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 5C /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VSUBPD zmm1{er}, {k}{z}, zmmV, zmm2","VSUBPD zmm2, zmmV, {k}{z}, zmm1{er}","vsubpd zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.66.0F.W1 5C /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSUBPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VSUBPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vsubpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 5C /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VSUBPS xmm1, xmmV, xmm2/m128","VSUBPS xmm2/m128, xmmV, xmm1","vsubps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 5C /r","V","V","AVX","","w,r,r","","" +"VSUBPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VSUBPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vsubps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 5C /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VSUBPS ymm1, ymmV, ymm2/m256","VSUBPS ymm2/m256, ymmV, ymm1","vsubps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 5C /r","V","V","AVX","","w,r,r","","" +"VSUBPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VSUBPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vsubps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 5C /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VSUBPS zmm1{er}, {k}{z}, zmmV, zmm2","VSUBPS zmm2, zmmV, {k}{z}, zmm1{er}","vsubps zmm2, zmmV, {k}{z}, zmm1{er}","EVEX.NDS.512.0F.W0 5C /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSUBPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VSUBPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vsubps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 5C /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VSUBSD xmm1{er}, {k}{z}, xmmV, xmm2","VSUBSD xmm2, xmmV, {k}{z}, xmm1{er}","vsubsd xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F2.0F.W1 5C /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSUBSD xmm1, xmmV, xmm2/m64","VSUBSD xmm2/m64, xmmV, xmm1","vsubsd xmm2/m64, xmmV, xmm1","VEX.NDS.LIG.F2.0F.WIG 5C /r","V","V","AVX","","w,r,r","","" +"VSUBSD xmm1, {k}{z}, xmmV, xmm2/m64","VSUBSD xmm2/m64, xmmV, {k}{z}, xmm1","vsubsd xmm2/m64, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F2.0F.W1 5C /r","V","V","AVX512F","scale8","w,r,r,r","","" +"VSUBSS xmm1{er}, {k}{z}, xmmV, xmm2","VSUBSS xmm2, xmmV, {k}{z}, xmm1{er}","vsubss xmm2, xmmV, {k}{z}, xmm1{er}","EVEX.NDS.128.F3.0F.W0 5C /r","V","V","AVX512F","modrm_regonly","w,r,r,r","","" +"VSUBSS xmm1, xmmV, xmm2/m32","VSUBSS xmm2/m32, xmmV, xmm1","vsubss xmm2/m32, xmmV, xmm1","VEX.NDS.LIG.F3.0F.WIG 5C /r","V","V","AVX","","w,r,r","","" +"VSUBSS xmm1, {k}{z}, xmmV, xmm2/m32","VSUBSS xmm2/m32, xmmV, {k}{z}, xmm1","vsubss xmm2/m32, xmmV, {k}{z}, xmm1","EVEX.NDS.LIG.F3.0F.W0 5C /r","V","V","AVX512F","scale4","w,r,r,r","","" +"VTESTPD xmm1, xmm2/m128","VTESTPD xmm2/m128, xmm1","vtestpd xmm2/m128, xmm1","VEX.128.66.0F38.W0 0F /r","V","V","AVX","","r,r","","" +"VTESTPD ymm1, ymm2/m256","VTESTPD ymm2/m256, ymm1","vtestpd ymm2/m256, ymm1","VEX.256.66.0F38.W0 0F /r","V","V","AVX","","r,r","","" +"VTESTPS xmm1, xmm2/m128","VTESTPS xmm2/m128, xmm1","vtestps xmm2/m128, xmm1","VEX.128.66.0F38.W0 0E /r","V","V","AVX","","r,r","","" +"VTESTPS ymm1, ymm2/m256","VTESTPS ymm2/m256, ymm1","vtestps ymm2/m256, ymm1","VEX.256.66.0F38.W0 0E /r","V","V","AVX","","r,r","","" +"VUCOMISD xmm1{sae}, xmm2","VUCOMISD xmm2, xmm1{sae}","vucomisd xmm2, xmm1{sae}","EVEX.128.66.0F.W1 2E /r","V","V","AVX512F","modrm_regonly","r,r","","" +"VUCOMISD xmm1, xmm2/m64","VUCOMISD xmm2/m64, xmm1","vucomisd xmm2/m64, xmm1","EVEX.LIG.66.0F.W1 2E /r","V","V","AVX512F","scale8","r,r","","" +"VUCOMISD xmm1, xmm2/m64","VUCOMISD xmm2/m64, xmm1","vucomisd xmm2/m64, xmm1","VEX.LIG.66.0F.WIG 2E /r","V","V","AVX","","r,r","","" +"VUCOMISS xmm1{sae}, xmm2","VUCOMISS xmm2, xmm1{sae}","vucomiss xmm2, xmm1{sae}","EVEX.128.0F.W0 2E /r","V","V","AVX512F","modrm_regonly","r,r","","" +"VUCOMISS xmm1, xmm2/m32","VUCOMISS xmm2/m32, xmm1","vucomiss xmm2/m32, xmm1","EVEX.LIG.0F.W0 2E /r","V","V","AVX512F","scale4","r,r","","" +"VUCOMISS xmm1, xmm2/m32","VUCOMISS xmm2/m32, xmm1","vucomiss xmm2/m32, xmm1","VEX.LIG.0F.WIG 2E /r","V","V","AVX","","r,r","","" +"VUNPCKHPD xmm1, xmmV, xmm2/m128","VUNPCKHPD xmm2/m128, xmmV, xmm1","vunpckhpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 15 /r","V","V","AVX","","w,r,r","","" +"VUNPCKHPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VUNPCKHPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vunpckhpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 15 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VUNPCKHPD ymm1, ymmV, ymm2/m256","VUNPCKHPD ymm2/m256, ymmV, ymm1","vunpckhpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 15 /r","V","V","AVX","","w,r,r","","" +"VUNPCKHPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VUNPCKHPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vunpckhpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 15 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VUNPCKHPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VUNPCKHPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vunpckhpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 15 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VUNPCKHPS xmm1, xmmV, xmm2/m128","VUNPCKHPS xmm2/m128, xmmV, xmm1","vunpckhps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 15 /r","V","V","AVX","","w,r,r","","" +"VUNPCKHPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VUNPCKHPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vunpckhps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 15 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VUNPCKHPS ymm1, ymmV, ymm2/m256","VUNPCKHPS ymm2/m256, ymmV, ymm1","vunpckhps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 15 /r","V","V","AVX","","w,r,r","","" +"VUNPCKHPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VUNPCKHPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vunpckhps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 15 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VUNPCKHPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VUNPCKHPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vunpckhps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 15 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VUNPCKLPD xmm1, xmmV, xmm2/m128","VUNPCKLPD xmm2/m128, xmmV, xmm1","vunpcklpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 14 /r","V","V","AVX","","w,r,r","","" +"VUNPCKLPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VUNPCKLPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vunpcklpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 14 /r","V","V","AVX512F+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VUNPCKLPD ymm1, ymmV, ymm2/m256","VUNPCKLPD ymm2/m256, ymmV, ymm1","vunpcklpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 14 /r","V","V","AVX","","w,r,r","","" +"VUNPCKLPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VUNPCKLPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vunpcklpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 14 /r","V","V","AVX512F+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VUNPCKLPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VUNPCKLPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vunpcklpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 14 /r","V","V","AVX512F","bscale8,scale64","w,r,r,r","","" +"VUNPCKLPS xmm1, xmmV, xmm2/m128","VUNPCKLPS xmm2/m128, xmmV, xmm1","vunpcklps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 14 /r","V","V","AVX","","w,r,r","","" +"VUNPCKLPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VUNPCKLPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vunpcklps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 14 /r","V","V","AVX512F+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VUNPCKLPS ymm1, ymmV, ymm2/m256","VUNPCKLPS ymm2/m256, ymmV, ymm1","vunpcklps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 14 /r","V","V","AVX","","w,r,r","","" +"VUNPCKLPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VUNPCKLPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vunpcklps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 14 /r","V","V","AVX512F+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VUNPCKLPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VUNPCKLPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vunpcklps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 14 /r","V","V","AVX512F","bscale4,scale64","w,r,r,r","","" +"VXORPD xmm1, xmmV, xmm2/m128","VXORPD xmm2/m128, xmmV, xmm1","vxorpd xmm2/m128, xmmV, xmm1","VEX.NDS.128.66.0F.WIG 57 /r","V","V","AVX","","w,r,r","","" +"VXORPD xmm1, {k}{z}, xmmV, xmm2/m128/m64bcst","VXORPD xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","vxorpd xmm2/m128/m64bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.66.0F.W1 57 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale16","w,r,r,r","","" +"VXORPD ymm1, ymmV, ymm2/m256","VXORPD ymm2/m256, ymmV, ymm1","vxorpd ymm2/m256, ymmV, ymm1","VEX.NDS.256.66.0F.WIG 57 /r","V","V","AVX","","w,r,r","","" +"VXORPD ymm1, {k}{z}, ymmV, ymm2/m256/m64bcst","VXORPD ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","vxorpd ymm2/m256/m64bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.66.0F.W1 57 /r","V","V","AVX512DQ+AVX512VL","bscale8,scale32","w,r,r,r","","" +"VXORPD zmm1, {k}{z}, zmmV, zmm2/m512/m64bcst","VXORPD zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","vxorpd zmm2/m512/m64bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.66.0F.W1 57 /r","V","V","AVX512DQ","bscale8,scale64","w,r,r,r","","" +"VXORPS xmm1, xmmV, xmm2/m128","VXORPS xmm2/m128, xmmV, xmm1","vxorps xmm2/m128, xmmV, xmm1","VEX.NDS.128.0F.WIG 57 /r","V","V","AVX","","w,r,r","","" +"VXORPS xmm1, {k}{z}, xmmV, xmm2/m128/m32bcst","VXORPS xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","vxorps xmm2/m128/m32bcst, xmmV, {k}{z}, xmm1","EVEX.NDS.128.0F.W0 57 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale16","w,r,r,r","","" +"VXORPS ymm1, ymmV, ymm2/m256","VXORPS ymm2/m256, ymmV, ymm1","vxorps ymm2/m256, ymmV, ymm1","VEX.NDS.256.0F.WIG 57 /r","V","V","AVX","","w,r,r","","" +"VXORPS ymm1, {k}{z}, ymmV, ymm2/m256/m32bcst","VXORPS ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","vxorps ymm2/m256/m32bcst, ymmV, {k}{z}, ymm1","EVEX.NDS.256.0F.W0 57 /r","V","V","AVX512DQ+AVX512VL","bscale4,scale32","w,r,r,r","","" +"VXORPS zmm1, {k}{z}, zmmV, zmm2/m512/m32bcst","VXORPS zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","vxorps zmm2/m512/m32bcst, zmmV, {k}{z}, zmm1","EVEX.NDS.512.0F.W0 57 /r","V","V","AVX512DQ","bscale4,scale64","w,r,r,r","","" +"VZEROALL","VZEROALL","vzeroall","VEX.256.0F.WIG 77","V","V","AVX","","","","" +"VZEROUPPER","VZEROUPPER","vzeroupper","VEX.128.0F.WIG 77","V","V","AVX","","","","" +"WAIT","WAIT","wait","9B","V","V","","pseudo","","","" +"WBINVD","WBINVD","wbinvd","0F 09","V","V","486","","","","" +"WRFSBASE rmr32","WRFSBASE rmr32","wrfsbase rmr32","F3 0F AE /2","N.S.","V","FSGSBASE","modrm_regonly,operand16,operand32","r","Y","32" +"WRFSBASE rmr64","WRFSBASE rmr64","wrfsbase rmr64","F3 REX.W 0F AE /2","N.S.","V","FSGSBASE","modrm_regonly","r","Y","64" +"WRGSBASE rmr32","WRGSBASE rmr32","wrgsbase rmr32","F3 0F AE /3","N.S.","V","FSGSBASE","modrm_regonly,operand16,operand32","r","Y","32" +"WRGSBASE rmr64","WRGSBASE rmr64","wrgsbase rmr64","F3 REX.W 0F AE /3","N.S.","V","FSGSBASE","modrm_regonly","r","Y","64" +"WRMSR","WRMSR","wrmsr","0F 30","V","V","Pentium","","","","" +"WRPKRU","WRPKRU","wrpkru","0F 01 EF","V","V","PKU","","","","" +"WRSSD m32, r32","WRSSD r32, m32","wrssd r32, m32","0F 38 F6 /r","V","V","CET","modrm_memonly,operand16,operand32","w,r","","" +"WRSSQ m64, r64","WRSSQ r64, m64","wrssq r64, m64","REX.W 0F 38 F6 /r","N.S.","V","CET","modrm_memonly","w,r","","" +"WRUSSD m32, r32","WRUSSD r32, m32","wrussd r32, m32","66 0F 38 F5 /r","V","V","CET","modrm_memonly,operand16,operand32","w,r","","" +"WRUSSQ m64, r64","WRUSSQ r64, m64","wrussq r64, m64","66 REX.W 0F 38 F5 /r","N.S.","V","CET","modrm_memonly","w,r","","" +"XABORT imm8u","XABORT imm8u","xabort imm8u","C6 F8 ib","V","V","RTM","modrm_regonly","r","","" +"XACQUIRE","XACQUIRE","xacquire","F2","V","V","HLE","pseudo","","","" +"XADD r/m8, r8","XADDB r8, r/m8","xaddb r8, r/m8","0F C0 /r","V","V","486","","rw,rw","Y","8" +"XADD r/m8, r8","XADDB r8, r/m8","xaddb r8, r/m8","REX 0F C0 /r","N.E.","V","","pseudo64","rw,w","Y","8" +"XADD r/m32, r32","XADDL r32, r/m32","xaddl r32, r/m32","0F C1 /r","V","V","486","operand32","rw,rw","Y","32" +"XADD r/m64, r64","XADDQ r64, r/m64","xaddq r64, r/m64","REX.W 0F C1 /r","N.S.","V","486","","rw,rw","Y","64" +"XADD r/m16, r16","XADDW r16, r/m16","xaddw r16, r/m16","0F C1 /r","V","V","486","operand16","rw,rw","Y","16" +"XBEGIN rel16","XBEGIN rel16","xbegin rel16","C7 F8 cw","V","V","RTM","modrm_regonly,operand16","r","","" +"XBEGIN rel32","XBEGIN rel32","xbegin rel32","C7 F8 cd","V","V","RTM","modrm_regonly,operand32,operand64","r","","" +"XCHG r8, r/m8","XCHGB r/m8, r8","xchgb r/m8, r8","86 /r","V","V","","pseudo","w,r","Y","8" +"XCHG r8, r/m8","XCHGB r/m8, r8","xchgb r/m8, r8","REX 86 /r","N.E.","V","","pseudo","w,r","Y","8" +"XCHG r/m8, r8","XCHGB r8, r/m8","xchgb r8, r/m8","86 /r","V","V","","","rw,rw","Y","8" +"XCHG r/m8, r8","XCHGB r8, r/m8","xchgb r8, r/m8","REX 86 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"XCHG r32op, EAX","XCHGL EAX, r32op","xchgl EAX, r32op","90+rd","V","V","","operand32","rw,rw","Y","32" +"XCHG r32, r/m32","XCHGL r/m32, r32","xchgl r/m32, r32","87 /r","V","V","","operand32,pseudo","w,r","Y","32" +"XCHG r/m32, r32","XCHGL r32, r/m32","xchgl r32, r/m32","87 /r","V","V","","operand32","rw,rw","Y","32" +"XCHG EAX, r32op","XCHGL r32op, EAX","xchgl r32op, EAX","90+rd","V","V","","operand32,pseudo","rw,rw","Y","32" +"XCHG r64op, RAX","XCHGQ RAX, r64op","xchgq RAX, r64op","REX.W 90+ro","N.S.","V","","","rw,rw","Y","64" +"XCHG r64, r/m64","XCHGQ r/m64, r64","xchgq r/m64, r64","REX.W 87 /r","N.E.","V","","pseudo","w,r","Y","64" +"XCHG r/m64, r64","XCHGQ r64, r/m64","xchgq r64, r/m64","REX.W 87 /r","N.S.","V","","","rw,rw","Y","64" +"XCHG RAX, r64op","XCHGQ r64op, RAX","xchgq r64op, RAX","REX.W 90+rd","N.E.","V","","pseudo","rw,rw","Y","64" +"XCHG r16op, AX","XCHGW AX, r16op","xchgw AX, r16op","90+rw","V","V","","operand16","rw,rw","Y","16" +"XCHG r16, r/m16","XCHGW r/m16, r16","xchgw r/m16, r16","87 /r","V","V","","operand16,pseudo","w,r","Y","16" +"XCHG r/m16, r16","XCHGW r16, r/m16","xchgw r16, r/m16","87 /r","V","V","","operand16","rw,rw","Y","16" +"XCHG AX, r16op","XCHGW r16op, AX","xchgw r16op, AX","90+rw","V","V","","operand16,pseudo","rw,rw","Y","16" +"XEND","XEND","xend","0F 01 D5","V","V","RTM","","","","" +"XGETBV","XGETBV","xgetbv","0F 01 D0","V","V","XSAVE","","","","" +"XLATB","XLAT","xlat","D7","V","V","","","","","" +"XLATB","XLAT","xlat","REX.W D7","N.E.","V","","pseudo","","","" +"XOR r/m8, imm8","XORB imm8, r/m8","xorb imm8, r/m8","REX 80 /6 ib","N.E.","V","","pseudo64","rw,r","Y","8" +"XOR AL, imm8u","XORB imm8u, AL","xorb imm8u, AL","34 ib","V","V","","","rw,r","Y","8" +"XOR r/m8, imm8u","XORB imm8u, r/m8","xorb imm8u, r/m8","80 /6 ib","V","V","","","rw,r","Y","8" +"XOR r/m8, imm8u","XORB imm8u, r/m8","xorb imm8u, r/m8","82 /6 ib","V","N.S.","","","rw,r","Y","8" +"XOR r8, r/m8","XORB r/m8, r8","xorb r/m8, r8","32 /r","V","V","","","rw,r","Y","8" +"XOR r8, r/m8","XORB r/m8, r8","xorb r/m8, r8","REX 32 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"XOR r/m8, r8","XORB r8, r/m8","xorb r8, r/m8","30 /r","V","V","","","rw,r","Y","8" +"XOR r/m8, r8","XORB r8, r/m8","xorb r8, r/m8","REX 30 /r","N.E.","V","","pseudo64","rw,r","Y","8" +"XOR EAX, imm32","XORL imm32, EAX","xorl imm32, EAX","35 id","V","V","","operand32","rw,r","Y","32" +"XOR r/m32, imm32","XORL imm32, r/m32","xorl imm32, r/m32","81 /6 id","V","V","","operand32","rw,r","Y","32" +"XOR r/m32, imm8","XORL imm8, r/m32","xorl imm8, r/m32","83 /6 ib","V","V","","operand32","rw,r","Y","32" +"XOR r32, r/m32","XORL r/m32, r32","xorl r/m32, r32","33 /r","V","V","","operand32","rw,r","Y","32" +"XOR r/m32, r32","XORL r32, r/m32","xorl r32, r/m32","31 /r","V","V","","operand32","rw,r","Y","32" +"XORPD xmm1, xmm2/m128","XORPD xmm2/m128, xmm1","xorpd xmm2/m128, xmm1","66 0F 57 /r","V","V","SSE2","","rw,r","","" +"XORPS xmm1, xmm2/m128","XORPS xmm2/m128, xmm1","xorps xmm2/m128, xmm1","0F 57 /r","V","V","SSE","","rw,r","","" +"XOR RAX, imm32","XORQ imm32, RAX","xorq imm32, RAX","REX.W 35 id","N.S.","V","","","rw,r","Y","64" +"XOR r/m64, imm32","XORQ imm32, r/m64","xorq imm32, r/m64","REX.W 81 /6 id","N.S.","V","","","rw,r","Y","64" +"XOR r/m64, imm8","XORQ imm8, r/m64","xorq imm8, r/m64","REX.W 83 /6 ib","N.S.","V","","","rw,r","Y","64" +"XOR r64, r/m64","XORQ r/m64, r64","xorq r/m64, r64","REX.W 33 /r","N.S.","V","","","rw,r","Y","64" +"XOR r/m64, r64","XORQ r64, r/m64","xorq r64, r/m64","REX.W 31 /r","N.S.","V","","","rw,r","Y","64" +"XOR AX, imm16","XORW imm16, AX","xorw imm16, AX","35 iw","V","V","","operand16","rw,r","Y","16" +"XOR r/m16, imm16","XORW imm16, r/m16","xorw imm16, r/m16","81 /6 iw","V","V","","operand16","rw,r","Y","16" +"XOR r/m16, imm8","XORW imm8, r/m16","xorw imm8, r/m16","83 /6 ib","V","V","","operand16","rw,r","Y","16" +"XOR r16, r/m16","XORW r/m16, r16","xorw r/m16, r16","33 /r","V","V","","operand16","rw,r","Y","16" +"XOR r/m16, r16","XORW r16, r/m16","xorw r16, r/m16","31 /r","V","V","","operand16","rw,r","Y","16" +"XRELEASE","XRELEASE","xrelease","F3","V","V","HLE","pseudo","","","" +"XRSTOR mem","XRSTOR mem","xrstor mem","0F AE /5","V","V","XSAVE","modrm_memonly,operand16,operand32","r","","" +"XRSTOR64 mem","XRSTOR64 mem","xrstor64 mem","REX.W 0F AE /5","N.S.","V","XSAVE","modrm_memonly","r","","" +"XRSTORS mem","XRSTORS mem","xrstors mem","0F C7 /3","V","V","XSAVES","modrm_memonly,operand16,operand32","r","","" +"XRSTORS64 mem","XRSTORS64 mem","xrstors64 mem","REX.W 0F C7 /3","N.S.","V","XSAVES","modrm_memonly","r","","" +"XSAVE mem","XSAVE mem","xsave mem","0F AE /4","V","V","XSAVE","modrm_memonly,operand16,operand32","w","","" +"XSAVE64 mem","XSAVE64 mem","xsave64 mem","REX.W 0F AE /4","N.S.","V","XSAVE","modrm_memonly","w","","" +"XSAVEC mem","XSAVEC mem","xsavec mem","0F C7 /4","V","V","XSAVEC","modrm_memonly,operand16,operand32","w","","" +"XSAVEC64 mem","XSAVEC64 mem","xsavec64 mem","REX.W 0F C7 /4","N.S.","V","XSAVEC","modrm_memonly","w","","" +"XSAVEOPT mem","XSAVEOPT mem","xsaveopt mem","0F AE /6","V","V","XSAVEOPT","modrm_memonly,operand16,operand32","w","","" +"XSAVEOPT64 mem","XSAVEOPT64 mem","xsaveopt64 mem","REX.W 0F AE /6","N.S.","V","XSAVEOPT","modrm_memonly","w","","" +"XSAVES mem","XSAVES mem","xsaves mem","0F C7 /5","V","V","XSAVES","modrm_memonly,operand16,operand32","w","","" +"XSAVES64 mem","XSAVES64 mem","xsaves64 mem","REX.W 0F C7 /5","N.S.","V","XSAVES","modrm_memonly","w","","" +"XSETBV","XSETBV","xsetbv","0F 01 D1","V","V","XSAVE","","","","" +"XTEST","XTEST","xtest","0F 01 D6","V","V","HLE or RTM","","","","" diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target index 61d9bb426e..6177fd845a 100644 --- a/tests/tcg/x86_64/Makefile.target +++ b/tests/tcg/x86_64/Makefile.target @@ -16,6 +16,7 @@ TESTS=$(MULTIARCH_TESTS) endif run-test-i386-ssse3: QEMU_OPTS += -cpu max +run-test-avx: QEMU_OPTS += -cpu max run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max test-x86_64: LDFLAGS+=-lm -lc From 3dd116e32e8624dcfa966570a7806e92e19dc380 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 26 Aug 2022 23:15:33 +0200 Subject: [PATCH 0281/1020] target/i386: do not use MOVL to move data between SSE registers Write down explicitly the load/store sequence. Extracted from a patch by Paul Brook . Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index b7972f0ff5..3237c1d8f9 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3295,8 +3295,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(3))); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)), - offsetof(CPUX86State,xmm_regs[rm].ZMM_L(0))); + tcg_gen_ld_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, xmm_regs[rm].ZMM_L(0))); + tcg_gen_st_i32(s->tmp2_i32, cpu_env, + offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0))); } break; case 0x310: /* movsd xmm, ea */ From da1a7edb5d790757b266462ab5d5e80b6a98214e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 26 Aug 2022 23:15:49 +0200 Subject: [PATCH 0282/1020] target/i386: formatting fixes Extracted from a patch by Paul Brook . Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 3237c1d8f9..25a2539d59 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3314,7 +3314,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } else { rm = (modrm & 7) | REX_B(s); gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)), - offsetof(CPUX86State,xmm_regs[rm].ZMM_Q(0))); + offsetof(CPUX86State, xmm_regs[rm].ZMM_Q(0))); } break; case 0x012: /* movlps */ @@ -4463,7 +4463,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, /* 32 bit access */ gen_op_ld_v(s, MO_32, s->T0, s->A0); tcg_gen_st32_tl(s->T0, cpu_env, - offsetof(CPUX86State,xmm_t0.ZMM_L(0))); + offsetof(CPUX86State, xmm_t0.ZMM_L(0))); break; case 3: /* 64 bit access */ @@ -4523,8 +4523,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, break; case 0xf7: /* maskmov : we must prepare A0 */ - if (mod != 3) + if (mod != 3) { goto illegal_op; + } tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]); gen_extu(s->aflag, s->A0); gen_add_A0_ds_seg(s); From 36fc7ee299cf7901e372fec31b46b5367b55f9f5 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:30 +0100 Subject: [PATCH 0283/1020] target/i386: Add ZMM_OFFSET macro Add a convenience macro to get the address of an xmm_regs element within CPUX86State. This was originally going to be the basis of an implementation that broke operations into 128 bit chunks. I scrapped that idea, so this is now a purely cosmetic change. But I think a worthwhile one - it reduces the number of function calls that need to be split over multiple lines. No functional changes. Signed-off-by: Paul Brook Reviewed-by: Richard Henderson Message-Id: <20220424220204.2493824-9-paul@nowt.org> Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 60 +++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 25a2539d59..cba862746b 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2777,6 +2777,8 @@ static inline void gen_op_movq_env_0(DisasContext *s, int d_offset) tcg_gen_st_i64(s->tmp1_i64, cpu_env, d_offset); } +#define ZMM_OFFSET(reg) offsetof(CPUX86State, xmm_regs[reg]) + typedef void (*SSEFunc_i_ep)(TCGv_i32 val, TCGv_ptr env, TCGv_ptr reg); typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg); typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val); @@ -3198,13 +3200,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, if (mod == 3) goto illegal_op; gen_lea_modrm(env, s, modrm); - gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); + gen_sto_env_A0(s, ZMM_OFFSET(reg)); break; case 0x3f0: /* lddqu */ if (mod == 3) goto illegal_op; gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); + gen_ldo_env_A0(s, ZMM_OFFSET(reg)); break; case 0x22b: /* movntss */ case 0x32b: /* movntsd */ @@ -3240,15 +3242,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, #ifdef TARGET_X86_64 if (s->dflag == MO_64) { gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0); - tcg_gen_addi_ptr(s->ptr0, cpu_env, - offsetof(CPUX86State,xmm_regs[reg])); + tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(reg)); gen_helper_movq_mm_T0_xmm(s->ptr0, s->T0); } else #endif { gen_ldst_modrm(env, s, modrm, MO_32, OR_TMP0, 0); - tcg_gen_addi_ptr(s->ptr0, cpu_env, - offsetof(CPUX86State,xmm_regs[reg])); + tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(reg)); tcg_gen_trunc_tl_i32(s->tmp2_i32, s->T0); gen_helper_movl_mm_T0_xmm(s->ptr0, s->tmp2_i32); } @@ -3273,11 +3273,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x26f: /* movdqu xmm, ea */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); + gen_ldo_env_A0(s, ZMM_OFFSET(reg)); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movo(s, offsetof(CPUX86State, xmm_regs[reg]), - offsetof(CPUX86State,xmm_regs[rm])); + gen_op_movo(s, ZMM_OFFSET(reg), ZMM_OFFSET(rm)); } break; case 0x210: /* movss xmm, ea */ @@ -3333,7 +3332,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x212: /* movsldup */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); + gen_ldo_env_A0(s, ZMM_OFFSET(reg)); } else { rm = (modrm & 7) | REX_B(s); gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)), @@ -3375,7 +3374,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x216: /* movshdup */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); + gen_ldo_env_A0(s, ZMM_OFFSET(reg)); } else { rm = (modrm & 7) | REX_B(s); gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)), @@ -3397,8 +3396,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto illegal_op; field_length = x86_ldub_code(env, s) & 0x3F; bit_index = x86_ldub_code(env, s) & 0x3F; - tcg_gen_addi_ptr(s->ptr0, cpu_env, - offsetof(CPUX86State,xmm_regs[reg])); + tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(reg)); if (b1 == 1) gen_helper_extrq_i(cpu_env, s->ptr0, tcg_const_i32(bit_index), @@ -3467,11 +3465,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x27f: /* movdqu ea, xmm */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_sto_env_A0(s, offsetof(CPUX86State, xmm_regs[reg])); + gen_sto_env_A0(s, ZMM_OFFSET(reg)); } else { rm = (modrm & 7) | REX_B(s); - gen_op_movo(s, offsetof(CPUX86State, xmm_regs[rm]), - offsetof(CPUX86State,xmm_regs[reg])); + gen_op_movo(s, ZMM_OFFSET(rm), ZMM_OFFSET(reg)); } break; case 0x211: /* movss ea, xmm */ @@ -3549,7 +3546,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } if (is_xmm) { rm = (modrm & 7) | REX_B(s); - op2_offset = offsetof(CPUX86State,xmm_regs[rm]); + op2_offset = ZMM_OFFSET(rm); } else { rm = (modrm & 7); op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); @@ -3560,15 +3557,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, break; case 0x050: /* movmskps */ rm = (modrm & 7) | REX_B(s); - tcg_gen_addi_ptr(s->ptr0, cpu_env, - offsetof(CPUX86State,xmm_regs[rm])); + tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm)); gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0); tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); break; case 0x150: /* movmskpd */ rm = (modrm & 7) | REX_B(s); - tcg_gen_addi_ptr(s->ptr0, cpu_env, - offsetof(CPUX86State,xmm_regs[rm])); + tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm)); gen_helper_movmskpd(s->tmp2_i32, cpu_env, s->ptr0); tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); break; @@ -3583,7 +3578,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, rm = (modrm & 7); op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); } - op1_offset = offsetof(CPUX86State,xmm_regs[reg]); + op1_offset = ZMM_OFFSET(reg); tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); switch(b >> 8) { @@ -3600,7 +3595,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x32a: /* cvtsi2sd */ ot = mo_64_32(s->dflag); gen_ldst_modrm(env, s, modrm, ot, OR_TMP0, 0); - op1_offset = offsetof(CPUX86State,xmm_regs[reg]); + op1_offset = ZMM_OFFSET(reg); tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); if (ot == MO_32) { SSEFunc_0_epi sse_fn_epi = sse_op_table3ai[(b >> 8) & 1]; @@ -3626,7 +3621,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldo_env_A0(s, op2_offset); } else { rm = (modrm & 7) | REX_B(s); - op2_offset = offsetof(CPUX86State,xmm_regs[rm]); + op2_offset = ZMM_OFFSET(rm); } op1_offset = offsetof(CPUX86State,fpregs[reg & 7].mmx); tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); @@ -3663,7 +3658,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, op2_offset = offsetof(CPUX86State,xmm_t0); } else { rm = (modrm & 7) | REX_B(s); - op2_offset = offsetof(CPUX86State,xmm_regs[rm]); + op2_offset = ZMM_OFFSET(rm); } tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset); if (ot == MO_32) { @@ -3749,8 +3744,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto illegal_op; if (b1) { rm = (modrm & 7) | REX_B(s); - tcg_gen_addi_ptr(s->ptr0, cpu_env, - offsetof(CPUX86State, xmm_regs[rm])); + tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm)); gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0); } else { rm = (modrm & 7); @@ -3782,9 +3776,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, goto illegal_op; if (b1) { - op1_offset = offsetof(CPUX86State,xmm_regs[reg]); + op1_offset = ZMM_OFFSET(reg); if (mod == 3) { - op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]); + op2_offset = ZMM_OFFSET(rm | REX_B(s)); } else { op2_offset = offsetof(CPUX86State,xmm_t0); gen_lea_modrm(env, s, modrm); @@ -4347,9 +4341,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } if (b1) { - op1_offset = offsetof(CPUX86State,xmm_regs[reg]); + op1_offset = ZMM_OFFSET(reg); if (mod == 3) { - op2_offset = offsetof(CPUX86State,xmm_regs[rm | REX_B(s)]); + op2_offset = ZMM_OFFSET(rm | REX_B(s)); } else { op2_offset = offsetof(CPUX86State,xmm_t0); gen_lea_modrm(env, s, modrm); @@ -4429,7 +4423,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, break; } if (is_xmm) { - op1_offset = offsetof(CPUX86State,xmm_regs[reg]); + op1_offset = ZMM_OFFSET(reg); if (mod != 3) { int sz = 4; @@ -4476,7 +4470,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } } else { rm = (modrm & 7) | REX_B(s); - op2_offset = offsetof(CPUX86State,xmm_regs[rm]); + op2_offset = ZMM_OFFSET(rm); } } else { op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); From f2dbc28947026d8c55a28774f04d96d5612cf6dd Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:26 +0100 Subject: [PATCH 0284/1020] target/i386: Rework sse_op_table1 Add a flags field to each row in sse_op_table1. Initially this is only used as a replacement for the magic SSE_SPECIAL and SSE_DUMMY pointers, the other flags are mostly relevant for the AVX implementation but can be applied to SSE as well. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-5-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 311 +++++++++++++++++++++--------------- 1 file changed, 182 insertions(+), 129 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index cba862746b..7332bbcf44 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2790,146 +2790,193 @@ typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val); typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv val); -#define SSE_SPECIAL ((void *)1) -#define SSE_DUMMY ((void *)2) +#define SSE_OPF_CMP (1 << 1) /* does not write for first operand */ +#define SSE_OPF_SPECIAL (1 << 3) /* magic */ +#define SSE_OPF_3DNOW (1 << 4) /* 3DNow! instruction */ +#define SSE_OPF_MMX (1 << 5) /* MMX/integer/AVX2 instruction */ +#define SSE_OPF_SCALAR (1 << 6) /* Has SSE scalar variants */ +#define SSE_OPF_SHUF (1 << 9) /* pshufx/shufpx */ -#define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm } -#define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \ - gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, } +#define OP(op, flags, a, b, c, d) \ + {flags, {a, b, c, d} } -static const SSEFunc_0_epp sse_op_table1[256][4] = { +#define MMX_OP(x) OP(op1, SSE_OPF_MMX, \ + gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm, NULL, NULL) + +#define SSE_FOP(name) OP(op1, SSE_OPF_SCALAR, \ + gen_helper_##name##ps, gen_helper_##name##pd, \ + gen_helper_##name##ss, gen_helper_##name##sd) +#define SSE_OP(sname, dname, op, flags) OP(op, flags, \ + gen_helper_##sname##_xmm, gen_helper_##dname##_xmm, NULL, NULL) + +struct SSEOpHelper_table1 { + int flags; + SSEFunc_0_epp op[4]; +}; + +#define SSE_3DNOW { SSE_OPF_3DNOW } +#define SSE_SPECIAL { SSE_OPF_SPECIAL } + +static const struct SSEOpHelper_table1 sse_op_table1[256] = { /* 3DNow! extensions */ - [0x0e] = { SSE_DUMMY }, /* femms */ - [0x0f] = { SSE_DUMMY }, /* pf... */ + [0x0e] = SSE_SPECIAL, /* femms */ + [0x0f] = SSE_3DNOW, /* pf... (sse_op_table5) */ /* pure SSE operations */ - [0x10] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ - [0x11] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movups, movupd, movss, movsd */ - [0x12] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd, movsldup, movddup */ - [0x13] = { SSE_SPECIAL, SSE_SPECIAL }, /* movlps, movlpd */ - [0x14] = { gen_helper_punpckldq_xmm, gen_helper_punpcklqdq_xmm }, - [0x15] = { gen_helper_punpckhdq_xmm, gen_helper_punpckhqdq_xmm }, - [0x16] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd, movshdup */ - [0x17] = { SSE_SPECIAL, SSE_SPECIAL }, /* movhps, movhpd */ + [0x10] = SSE_SPECIAL, /* movups, movupd, movss, movsd */ + [0x11] = SSE_SPECIAL, /* movups, movupd, movss, movsd */ + [0x12] = SSE_SPECIAL, /* movlps, movlpd, movsldup, movddup */ + [0x13] = SSE_SPECIAL, /* movlps, movlpd */ + [0x14] = SSE_OP(punpckldq, punpcklqdq, op1, 0), /* unpcklps, unpcklpd */ + [0x15] = SSE_OP(punpckhdq, punpckhqdq, op1, 0), /* unpckhps, unpckhpd */ + [0x16] = SSE_SPECIAL, /* movhps, movhpd, movshdup */ + [0x17] = SSE_SPECIAL, /* movhps, movhpd */ - [0x28] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */ - [0x29] = { SSE_SPECIAL, SSE_SPECIAL }, /* movaps, movapd */ - [0x2a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */ - [0x2b] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movntps, movntpd, movntss, movntsd */ - [0x2c] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */ - [0x2d] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */ - [0x2e] = { gen_helper_ucomiss, gen_helper_ucomisd }, - [0x2f] = { gen_helper_comiss, gen_helper_comisd }, - [0x50] = { SSE_SPECIAL, SSE_SPECIAL }, /* movmskps, movmskpd */ - [0x51] = SSE_FOP(sqrt), - [0x52] = { gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL }, - [0x53] = { gen_helper_rcpps, NULL, gen_helper_rcpss, NULL }, - [0x54] = { gen_helper_pand_xmm, gen_helper_pand_xmm }, /* andps, andpd */ - [0x55] = { gen_helper_pandn_xmm, gen_helper_pandn_xmm }, /* andnps, andnpd */ - [0x56] = { gen_helper_por_xmm, gen_helper_por_xmm }, /* orps, orpd */ - [0x57] = { gen_helper_pxor_xmm, gen_helper_pxor_xmm }, /* xorps, xorpd */ + [0x28] = SSE_SPECIAL, /* movaps, movapd */ + [0x29] = SSE_SPECIAL, /* movaps, movapd */ + [0x2a] = SSE_SPECIAL, /* cvtpi2ps, cvtpi2pd, cvtsi2ss, cvtsi2sd */ + [0x2b] = SSE_SPECIAL, /* movntps, movntpd, movntss, movntsd */ + [0x2c] = SSE_SPECIAL, /* cvttps2pi, cvttpd2pi, cvttsd2si, cvttss2si */ + [0x2d] = SSE_SPECIAL, /* cvtps2pi, cvtpd2pi, cvtsd2si, cvtss2si */ + [0x2e] = OP(op1, SSE_OPF_CMP | SSE_OPF_SCALAR, + gen_helper_ucomiss, gen_helper_ucomisd, NULL, NULL), + [0x2f] = OP(op1, SSE_OPF_CMP | SSE_OPF_SCALAR, + gen_helper_comiss, gen_helper_comisd, NULL, NULL), + [0x50] = SSE_SPECIAL, /* movmskps, movmskpd */ + [0x51] = OP(op1, SSE_OPF_SCALAR, + gen_helper_sqrtps, gen_helper_sqrtpd, + gen_helper_sqrtss, gen_helper_sqrtsd), + [0x52] = OP(op1, SSE_OPF_SCALAR, + gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL), + [0x53] = OP(op1, SSE_OPF_SCALAR, + gen_helper_rcpps, NULL, gen_helper_rcpss, NULL), + [0x54] = SSE_OP(pand, pand, op1, 0), /* andps, andpd */ + [0x55] = SSE_OP(pandn, pandn, op1, 0), /* andnps, andnpd */ + [0x56] = SSE_OP(por, por, op1, 0), /* orps, orpd */ + [0x57] = SSE_OP(pxor, pxor, op1, 0), /* xorps, xorpd */ [0x58] = SSE_FOP(add), [0x59] = SSE_FOP(mul), - [0x5a] = { gen_helper_cvtps2pd, gen_helper_cvtpd2ps, - gen_helper_cvtss2sd, gen_helper_cvtsd2ss }, - [0x5b] = { gen_helper_cvtdq2ps, gen_helper_cvtps2dq, gen_helper_cvttps2dq }, + [0x5a] = OP(op1, SSE_OPF_SCALAR, + gen_helper_cvtps2pd, gen_helper_cvtpd2ps, + gen_helper_cvtss2sd, gen_helper_cvtsd2ss), + [0x5b] = OP(op1, 0, + gen_helper_cvtdq2ps, gen_helper_cvtps2dq, + gen_helper_cvttps2dq, NULL), [0x5c] = SSE_FOP(sub), [0x5d] = SSE_FOP(min), [0x5e] = SSE_FOP(div), [0x5f] = SSE_FOP(max), - [0xc2] = SSE_FOP(cmpeq), - [0xc6] = { (SSEFunc_0_epp)gen_helper_shufps, - (SSEFunc_0_epp)gen_helper_shufpd }, /* XXX: casts */ + [0xc2] = SSE_FOP(cmpeq), /* sse_op_table4 */ + [0xc6] = OP(dummy, SSE_OPF_SHUF, (SSEFunc_0_epp)gen_helper_shufps, + (SSEFunc_0_epp)gen_helper_shufpd, NULL, NULL), /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */ - [0x38] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, - [0x3a] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, + [0x38] = SSE_SPECIAL, + [0x3a] = SSE_SPECIAL, /* MMX ops and their SSE extensions */ - [0x60] = MMX_OP2(punpcklbw), - [0x61] = MMX_OP2(punpcklwd), - [0x62] = MMX_OP2(punpckldq), - [0x63] = MMX_OP2(packsswb), - [0x64] = MMX_OP2(pcmpgtb), - [0x65] = MMX_OP2(pcmpgtw), - [0x66] = MMX_OP2(pcmpgtl), - [0x67] = MMX_OP2(packuswb), - [0x68] = MMX_OP2(punpckhbw), - [0x69] = MMX_OP2(punpckhwd), - [0x6a] = MMX_OP2(punpckhdq), - [0x6b] = MMX_OP2(packssdw), - [0x6c] = { NULL, gen_helper_punpcklqdq_xmm }, - [0x6d] = { NULL, gen_helper_punpckhqdq_xmm }, - [0x6e] = { SSE_SPECIAL, SSE_SPECIAL }, /* movd mm, ea */ - [0x6f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, , movqdu */ - [0x70] = { (SSEFunc_0_epp)gen_helper_pshufw_mmx, - (SSEFunc_0_epp)gen_helper_pshufd_xmm, - (SSEFunc_0_epp)gen_helper_pshufhw_xmm, - (SSEFunc_0_epp)gen_helper_pshuflw_xmm }, /* XXX: casts */ - [0x71] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftw */ - [0x72] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftd */ - [0x73] = { SSE_SPECIAL, SSE_SPECIAL }, /* shiftq */ - [0x74] = MMX_OP2(pcmpeqb), - [0x75] = MMX_OP2(pcmpeqw), - [0x76] = MMX_OP2(pcmpeql), - [0x77] = { SSE_DUMMY }, /* emms */ - [0x78] = { NULL, SSE_SPECIAL, NULL, SSE_SPECIAL }, /* extrq_i, insertq_i */ - [0x79] = { NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r }, - [0x7c] = { NULL, gen_helper_haddpd, NULL, gen_helper_haddps }, - [0x7d] = { NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps }, - [0x7e] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movd, movd, , movq */ - [0x7f] = { SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, /* movq, movdqa, movdqu */ - [0xc4] = { SSE_SPECIAL, SSE_SPECIAL }, /* pinsrw */ - [0xc5] = { SSE_SPECIAL, SSE_SPECIAL }, /* pextrw */ - [0xd0] = { NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps }, - [0xd1] = MMX_OP2(psrlw), - [0xd2] = MMX_OP2(psrld), - [0xd3] = MMX_OP2(psrlq), - [0xd4] = MMX_OP2(paddq), - [0xd5] = MMX_OP2(pmullw), - [0xd6] = { NULL, SSE_SPECIAL, SSE_SPECIAL, SSE_SPECIAL }, - [0xd7] = { SSE_SPECIAL, SSE_SPECIAL }, /* pmovmskb */ - [0xd8] = MMX_OP2(psubusb), - [0xd9] = MMX_OP2(psubusw), - [0xda] = MMX_OP2(pminub), - [0xdb] = MMX_OP2(pand), - [0xdc] = MMX_OP2(paddusb), - [0xdd] = MMX_OP2(paddusw), - [0xde] = MMX_OP2(pmaxub), - [0xdf] = MMX_OP2(pandn), - [0xe0] = MMX_OP2(pavgb), - [0xe1] = MMX_OP2(psraw), - [0xe2] = MMX_OP2(psrad), - [0xe3] = MMX_OP2(pavgw), - [0xe4] = MMX_OP2(pmulhuw), - [0xe5] = MMX_OP2(pmulhw), - [0xe6] = { NULL, gen_helper_cvttpd2dq, gen_helper_cvtdq2pd, gen_helper_cvtpd2dq }, - [0xe7] = { SSE_SPECIAL , SSE_SPECIAL }, /* movntq, movntq */ - [0xe8] = MMX_OP2(psubsb), - [0xe9] = MMX_OP2(psubsw), - [0xea] = MMX_OP2(pminsw), - [0xeb] = MMX_OP2(por), - [0xec] = MMX_OP2(paddsb), - [0xed] = MMX_OP2(paddsw), - [0xee] = MMX_OP2(pmaxsw), - [0xef] = MMX_OP2(pxor), - [0xf0] = { NULL, NULL, NULL, SSE_SPECIAL }, /* lddqu */ - [0xf1] = MMX_OP2(psllw), - [0xf2] = MMX_OP2(pslld), - [0xf3] = MMX_OP2(psllq), - [0xf4] = MMX_OP2(pmuludq), - [0xf5] = MMX_OP2(pmaddwd), - [0xf6] = MMX_OP2(psadbw), - [0xf7] = { (SSEFunc_0_epp)gen_helper_maskmov_mmx, - (SSEFunc_0_epp)gen_helper_maskmov_xmm }, /* XXX: casts */ - [0xf8] = MMX_OP2(psubb), - [0xf9] = MMX_OP2(psubw), - [0xfa] = MMX_OP2(psubl), - [0xfb] = MMX_OP2(psubq), - [0xfc] = MMX_OP2(paddb), - [0xfd] = MMX_OP2(paddw), - [0xfe] = MMX_OP2(paddl), + [0x60] = MMX_OP(punpcklbw), + [0x61] = MMX_OP(punpcklwd), + [0x62] = MMX_OP(punpckldq), + [0x63] = MMX_OP(packsswb), + [0x64] = MMX_OP(pcmpgtb), + [0x65] = MMX_OP(pcmpgtw), + [0x66] = MMX_OP(pcmpgtl), + [0x67] = MMX_OP(packuswb), + [0x68] = MMX_OP(punpckhbw), + [0x69] = MMX_OP(punpckhwd), + [0x6a] = MMX_OP(punpckhdq), + [0x6b] = MMX_OP(packssdw), + [0x6c] = OP(op1, SSE_OPF_MMX, + NULL, gen_helper_punpcklqdq_xmm, NULL, NULL), + [0x6d] = OP(op1, SSE_OPF_MMX, + NULL, gen_helper_punpckhqdq_xmm, NULL, NULL), + [0x6e] = SSE_SPECIAL, /* movd mm, ea */ + [0x6f] = SSE_SPECIAL, /* movq, movdqa, , movqdu */ + [0x70] = OP(op1i, SSE_OPF_SHUF | SSE_OPF_MMX, + (SSEFunc_0_epp)gen_helper_pshufw_mmx, + (SSEFunc_0_epp)gen_helper_pshufd_xmm, + (SSEFunc_0_epp)gen_helper_pshufhw_xmm, + (SSEFunc_0_epp)gen_helper_pshuflw_xmm), + [0x71] = SSE_SPECIAL, /* shiftw */ + [0x72] = SSE_SPECIAL, /* shiftd */ + [0x73] = SSE_SPECIAL, /* shiftq */ + [0x74] = MMX_OP(pcmpeqb), + [0x75] = MMX_OP(pcmpeqw), + [0x76] = MMX_OP(pcmpeql), + [0x77] = SSE_SPECIAL, /* emms */ + [0x78] = SSE_SPECIAL, /* extrq_i, insertq_i (sse4a) */ + [0x79] = OP(op1, 0, + NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r), + [0x7c] = OP(op1, 0, + NULL, gen_helper_haddpd, NULL, gen_helper_haddps), + [0x7d] = OP(op1, 0, + NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps), + [0x7e] = SSE_SPECIAL, /* movd, movd, , movq */ + [0x7f] = SSE_SPECIAL, /* movq, movdqa, movdqu */ + [0xc4] = SSE_SPECIAL, /* pinsrw */ + [0xc5] = SSE_SPECIAL, /* pextrw */ + [0xd0] = OP(op1, 0, + NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps), + [0xd1] = MMX_OP(psrlw), + [0xd2] = MMX_OP(psrld), + [0xd3] = MMX_OP(psrlq), + [0xd4] = MMX_OP(paddq), + [0xd5] = MMX_OP(pmullw), + [0xd6] = SSE_SPECIAL, + [0xd7] = SSE_SPECIAL, /* pmovmskb */ + [0xd8] = MMX_OP(psubusb), + [0xd9] = MMX_OP(psubusw), + [0xda] = MMX_OP(pminub), + [0xdb] = MMX_OP(pand), + [0xdc] = MMX_OP(paddusb), + [0xdd] = MMX_OP(paddusw), + [0xde] = MMX_OP(pmaxub), + [0xdf] = MMX_OP(pandn), + [0xe0] = MMX_OP(pavgb), + [0xe1] = MMX_OP(psraw), + [0xe2] = MMX_OP(psrad), + [0xe3] = MMX_OP(pavgw), + [0xe4] = MMX_OP(pmulhuw), + [0xe5] = MMX_OP(pmulhw), + [0xe6] = OP(op1, 0, + NULL, gen_helper_cvttpd2dq, + gen_helper_cvtdq2pd, gen_helper_cvtpd2dq), + [0xe7] = SSE_SPECIAL, /* movntq, movntq */ + [0xe8] = MMX_OP(psubsb), + [0xe9] = MMX_OP(psubsw), + [0xea] = MMX_OP(pminsw), + [0xeb] = MMX_OP(por), + [0xec] = MMX_OP(paddsb), + [0xed] = MMX_OP(paddsw), + [0xee] = MMX_OP(pmaxsw), + [0xef] = MMX_OP(pxor), + [0xf0] = SSE_SPECIAL, /* lddqu */ + [0xf1] = MMX_OP(psllw), + [0xf2] = MMX_OP(pslld), + [0xf3] = MMX_OP(psllq), + [0xf4] = MMX_OP(pmuludq), + [0xf5] = MMX_OP(pmaddwd), + [0xf6] = MMX_OP(psadbw), + [0xf7] = OP(op1t, SSE_OPF_MMX, + (SSEFunc_0_epp)gen_helper_maskmov_mmx, + (SSEFunc_0_epp)gen_helper_maskmov_xmm, NULL, NULL), + [0xf8] = MMX_OP(psubb), + [0xf9] = MMX_OP(psubw), + [0xfa] = MMX_OP(psubl), + [0xfb] = MMX_OP(psubq), + [0xfc] = MMX_OP(paddb), + [0xfd] = MMX_OP(paddw), + [0xfe] = MMX_OP(paddl), }; +#undef MMX_OP +#undef OP +#undef SSE_FOP +#undef SSE_OP +#undef SSE_SPECIAL + +#define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm } +#define SSE_SPECIAL_FN ((void *)1) static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = { [0 + 2] = MMX_OP2(psrlw), @@ -2972,6 +3019,8 @@ static const SSEFunc_l_ep sse_op_table3bq[] = { }; #endif +#define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \ + gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, } static const SSEFunc_0_epp sse_op_table4[8][4] = { SSE_FOP(cmpeq), SSE_FOP(cmplt), @@ -2982,6 +3031,7 @@ static const SSEFunc_0_epp sse_op_table4[8][4] = { SSE_FOP(cmpnle), SSE_FOP(cmpord), }; +#undef SSE_FOP static const SSEFunc_0_epp sse_op_table5[256] = { [0x0c] = gen_helper_pi2fw, @@ -3023,7 +3073,7 @@ struct SSEOpHelper_eppi { #define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 } #define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 } #define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 } -#define SSE41_SPECIAL { { NULL, SSE_SPECIAL }, CPUID_EXT_SSE41 } +#define SSE41_SPECIAL { { NULL, SSE_SPECIAL_FN }, CPUID_EXT_SSE41 } #define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \ CPUID_EXT_PCLMULQDQ } #define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES } @@ -3114,6 +3164,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, { int b1, op1_offset, op2_offset, is_xmm, val; int modrm, mod, rm, reg; + int sse_op_flags; SSEFunc_0_epp sse_fn_epp; SSEFunc_0_eppi sse_fn_eppi; SSEFunc_0_ppi sse_fn_ppi; @@ -3129,8 +3180,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, b1 = 3; else b1 = 0; - sse_fn_epp = sse_op_table1[b][b1]; - if (!sse_fn_epp) { + sse_op_flags = sse_op_table1[b].flags; + sse_fn_epp = sse_op_table1[b].op[b1]; + if ((sse_op_flags & (SSE_OPF_SPECIAL | SSE_OPF_3DNOW)) == 0 + && !sse_fn_epp) { goto unknown_op; } if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) { @@ -3184,7 +3237,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, reg |= REX_R(s); } mod = (modrm >> 6) & 3; - if (sse_fn_epp == SSE_SPECIAL) { + if (sse_op_flags & SSE_OPF_SPECIAL) { b |= (b1 << 8); switch(b) { case 0x0e7: /* movntq */ @@ -3819,7 +3872,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldq_env_A0(s, op2_offset); } } - if (sse_fn_epp == SSE_SPECIAL) { + if (sse_fn_epp == SSE_SPECIAL_FN) { goto unknown_op; } @@ -4205,7 +4258,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, s->rip_offset = 1; - if (sse_fn_eppi == SSE_SPECIAL) { + if (sse_fn_eppi == SSE_SPECIAL_FN) { ot = mo_64_32(s->dflag); rm = (modrm & 7) | REX_B(s); if (mod != 3) From 491f0f1962f3ac6d2968cbf2a5f192ac613abbcf Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:27 +0100 Subject: [PATCH 0285/1020] target/i386: Rework sse_op_table6/7 Add a flags field each row in sse_op_table6 and sse_op_table7. Initially this is only used as a replacement for the magic SSE41_SPECIAL pointer. The other flags are mostly relevant for the AVX implementation but can be applied to SSE as well. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-6-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 230 ++++++++++++++++++++---------------- 1 file changed, 131 insertions(+), 99 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 7332bbcf44..b7321b7588 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2976,7 +2976,6 @@ static const struct SSEOpHelper_table1 sse_op_table1[256] = { #undef SSE_SPECIAL #define MMX_OP2(x) { gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm } -#define SSE_SPECIAL_FN ((void *)1) static const SSEFunc_0_epp sse_op_table2[3 * 8][2] = { [0 + 2] = MMX_OP2(psrlw), @@ -3060,113 +3059,134 @@ static const SSEFunc_0_epp sse_op_table5[256] = { [0xbf] = gen_helper_pavgb_mmx /* pavgusb */ }; -struct SSEOpHelper_epp { +struct SSEOpHelper_table6 { SSEFunc_0_epp op[2]; uint32_t ext_mask; + int flags; }; -struct SSEOpHelper_eppi { +struct SSEOpHelper_table7 { SSEFunc_0_eppi op[2]; uint32_t ext_mask; + int flags; }; -#define SSSE3_OP(x) { MMX_OP2(x), CPUID_EXT_SSSE3 } -#define SSE41_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE41 } -#define SSE42_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_SSE42 } -#define SSE41_SPECIAL { { NULL, SSE_SPECIAL_FN }, CPUID_EXT_SSE41 } -#define PCLMULQDQ_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, \ - CPUID_EXT_PCLMULQDQ } -#define AESNI_OP(x) { { NULL, gen_helper_ ## x ## _xmm }, CPUID_EXT_AES } +#define gen_helper_special_xmm NULL -static const struct SSEOpHelper_epp sse_op_table6[256] = { - [0x00] = SSSE3_OP(pshufb), - [0x01] = SSSE3_OP(phaddw), - [0x02] = SSSE3_OP(phaddd), - [0x03] = SSSE3_OP(phaddsw), - [0x04] = SSSE3_OP(pmaddubsw), - [0x05] = SSSE3_OP(phsubw), - [0x06] = SSSE3_OP(phsubd), - [0x07] = SSSE3_OP(phsubsw), - [0x08] = SSSE3_OP(psignb), - [0x09] = SSSE3_OP(psignw), - [0x0a] = SSSE3_OP(psignd), - [0x0b] = SSSE3_OP(pmulhrsw), - [0x10] = SSE41_OP(pblendvb), - [0x14] = SSE41_OP(blendvps), - [0x15] = SSE41_OP(blendvpd), - [0x17] = SSE41_OP(ptest), - [0x1c] = SSSE3_OP(pabsb), - [0x1d] = SSSE3_OP(pabsw), - [0x1e] = SSSE3_OP(pabsd), - [0x20] = SSE41_OP(pmovsxbw), - [0x21] = SSE41_OP(pmovsxbd), - [0x22] = SSE41_OP(pmovsxbq), - [0x23] = SSE41_OP(pmovsxwd), - [0x24] = SSE41_OP(pmovsxwq), - [0x25] = SSE41_OP(pmovsxdq), - [0x28] = SSE41_OP(pmuldq), - [0x29] = SSE41_OP(pcmpeqq), - [0x2a] = SSE41_SPECIAL, /* movntqda */ - [0x2b] = SSE41_OP(packusdw), - [0x30] = SSE41_OP(pmovzxbw), - [0x31] = SSE41_OP(pmovzxbd), - [0x32] = SSE41_OP(pmovzxbq), - [0x33] = SSE41_OP(pmovzxwd), - [0x34] = SSE41_OP(pmovzxwq), - [0x35] = SSE41_OP(pmovzxdq), - [0x37] = SSE42_OP(pcmpgtq), - [0x38] = SSE41_OP(pminsb), - [0x39] = SSE41_OP(pminsd), - [0x3a] = SSE41_OP(pminuw), - [0x3b] = SSE41_OP(pminud), - [0x3c] = SSE41_OP(pmaxsb), - [0x3d] = SSE41_OP(pmaxsd), - [0x3e] = SSE41_OP(pmaxuw), - [0x3f] = SSE41_OP(pmaxud), - [0x40] = SSE41_OP(pmulld), - [0x41] = SSE41_OP(phminposuw), - [0xdb] = AESNI_OP(aesimc), - [0xdc] = AESNI_OP(aesenc), - [0xdd] = AESNI_OP(aesenclast), - [0xde] = AESNI_OP(aesdec), - [0xdf] = AESNI_OP(aesdeclast), +#define OP(name, op, flags, ext, mmx_name) \ + {{mmx_name, gen_helper_ ## name ## _xmm}, CPUID_EXT_ ## ext, flags} +#define BINARY_OP_MMX(name, ext) \ + OP(name, op1, SSE_OPF_MMX, ext, gen_helper_ ## name ## _mmx) +#define BINARY_OP(name, ext, flags) \ + OP(name, op1, flags, ext, NULL) +#define UNARY_OP_MMX(name, ext) \ + OP(name, op1, SSE_OPF_MMX, ext, gen_helper_ ## name ## _mmx) +#define UNARY_OP(name, ext, flags) \ + OP(name, op1, flags, ext, NULL) +#define BLENDV_OP(name, ext, flags) OP(name, op1, 0, ext, NULL) +#define CMP_OP(name, ext) OP(name, op1, SSE_OPF_CMP, ext, NULL) +#define SPECIAL_OP(ext) OP(special, op1, SSE_OPF_SPECIAL, ext, NULL) + +/* prefix [66] 0f 38 */ +static const struct SSEOpHelper_table6 sse_op_table6[256] = { + [0x00] = BINARY_OP_MMX(pshufb, SSSE3), + [0x01] = BINARY_OP_MMX(phaddw, SSSE3), + [0x02] = BINARY_OP_MMX(phaddd, SSSE3), + [0x03] = BINARY_OP_MMX(phaddsw, SSSE3), + [0x04] = BINARY_OP_MMX(pmaddubsw, SSSE3), + [0x05] = BINARY_OP_MMX(phsubw, SSSE3), + [0x06] = BINARY_OP_MMX(phsubd, SSSE3), + [0x07] = BINARY_OP_MMX(phsubsw, SSSE3), + [0x08] = BINARY_OP_MMX(psignb, SSSE3), + [0x09] = BINARY_OP_MMX(psignw, SSSE3), + [0x0a] = BINARY_OP_MMX(psignd, SSSE3), + [0x0b] = BINARY_OP_MMX(pmulhrsw, SSSE3), + [0x10] = BLENDV_OP(pblendvb, SSE41, SSE_OPF_MMX), + [0x14] = BLENDV_OP(blendvps, SSE41, 0), + [0x15] = BLENDV_OP(blendvpd, SSE41, 0), + [0x17] = CMP_OP(ptest, SSE41), + [0x1c] = UNARY_OP_MMX(pabsb, SSSE3), + [0x1d] = UNARY_OP_MMX(pabsw, SSSE3), + [0x1e] = UNARY_OP_MMX(pabsd, SSSE3), + [0x20] = UNARY_OP(pmovsxbw, SSE41, SSE_OPF_MMX), + [0x21] = UNARY_OP(pmovsxbd, SSE41, SSE_OPF_MMX), + [0x22] = UNARY_OP(pmovsxbq, SSE41, SSE_OPF_MMX), + [0x23] = UNARY_OP(pmovsxwd, SSE41, SSE_OPF_MMX), + [0x24] = UNARY_OP(pmovsxwq, SSE41, SSE_OPF_MMX), + [0x25] = UNARY_OP(pmovsxdq, SSE41, SSE_OPF_MMX), + [0x28] = BINARY_OP(pmuldq, SSE41, SSE_OPF_MMX), + [0x29] = BINARY_OP(pcmpeqq, SSE41, SSE_OPF_MMX), + [0x2a] = SPECIAL_OP(SSE41), /* movntqda */ + [0x2b] = BINARY_OP(packusdw, SSE41, SSE_OPF_MMX), + [0x30] = UNARY_OP(pmovzxbw, SSE41, SSE_OPF_MMX), + [0x31] = UNARY_OP(pmovzxbd, SSE41, SSE_OPF_MMX), + [0x32] = UNARY_OP(pmovzxbq, SSE41, SSE_OPF_MMX), + [0x33] = UNARY_OP(pmovzxwd, SSE41, SSE_OPF_MMX), + [0x34] = UNARY_OP(pmovzxwq, SSE41, SSE_OPF_MMX), + [0x35] = UNARY_OP(pmovzxdq, SSE41, SSE_OPF_MMX), + [0x37] = BINARY_OP(pcmpgtq, SSE41, SSE_OPF_MMX), + [0x38] = BINARY_OP(pminsb, SSE41, SSE_OPF_MMX), + [0x39] = BINARY_OP(pminsd, SSE41, SSE_OPF_MMX), + [0x3a] = BINARY_OP(pminuw, SSE41, SSE_OPF_MMX), + [0x3b] = BINARY_OP(pminud, SSE41, SSE_OPF_MMX), + [0x3c] = BINARY_OP(pmaxsb, SSE41, SSE_OPF_MMX), + [0x3d] = BINARY_OP(pmaxsd, SSE41, SSE_OPF_MMX), + [0x3e] = BINARY_OP(pmaxuw, SSE41, SSE_OPF_MMX), + [0x3f] = BINARY_OP(pmaxud, SSE41, SSE_OPF_MMX), + [0x40] = BINARY_OP(pmulld, SSE41, SSE_OPF_MMX), + [0x41] = UNARY_OP(phminposuw, SSE41, 0), + [0xdb] = UNARY_OP(aesimc, AES, 0), + [0xdc] = BINARY_OP(aesenc, AES, 0), + [0xdd] = BINARY_OP(aesenclast, AES, 0), + [0xde] = BINARY_OP(aesdec, AES, 0), + [0xdf] = BINARY_OP(aesdeclast, AES, 0), }; -static const struct SSEOpHelper_eppi sse_op_table7[256] = { - [0x08] = SSE41_OP(roundps), - [0x09] = SSE41_OP(roundpd), - [0x0a] = SSE41_OP(roundss), - [0x0b] = SSE41_OP(roundsd), - [0x0c] = SSE41_OP(blendps), - [0x0d] = SSE41_OP(blendpd), - [0x0e] = SSE41_OP(pblendw), - [0x0f] = SSSE3_OP(palignr), - [0x14] = SSE41_SPECIAL, /* pextrb */ - [0x15] = SSE41_SPECIAL, /* pextrw */ - [0x16] = SSE41_SPECIAL, /* pextrd/pextrq */ - [0x17] = SSE41_SPECIAL, /* extractps */ - [0x20] = SSE41_SPECIAL, /* pinsrb */ - [0x21] = SSE41_SPECIAL, /* insertps */ - [0x22] = SSE41_SPECIAL, /* pinsrd/pinsrq */ - [0x40] = SSE41_OP(dpps), - [0x41] = SSE41_OP(dppd), - [0x42] = SSE41_OP(mpsadbw), - [0x44] = PCLMULQDQ_OP(pclmulqdq), - [0x60] = SSE42_OP(pcmpestrm), - [0x61] = SSE42_OP(pcmpestri), - [0x62] = SSE42_OP(pcmpistrm), - [0x63] = SSE42_OP(pcmpistri), - [0xdf] = AESNI_OP(aeskeygenassist), +/* prefix [66] 0f 3a */ +static const struct SSEOpHelper_table7 sse_op_table7[256] = { + [0x08] = UNARY_OP(roundps, SSE41, 0), + [0x09] = UNARY_OP(roundpd, SSE41, 0), + [0x0a] = UNARY_OP(roundss, SSE41, SSE_OPF_SCALAR), + [0x0b] = UNARY_OP(roundsd, SSE41, SSE_OPF_SCALAR), + [0x0c] = BINARY_OP(blendps, SSE41, 0), + [0x0d] = BINARY_OP(blendpd, SSE41, 0), + [0x0e] = BINARY_OP(pblendw, SSE41, SSE_OPF_MMX), + [0x0f] = BINARY_OP_MMX(palignr, SSSE3), + [0x14] = SPECIAL_OP(SSE41), /* pextrb */ + [0x15] = SPECIAL_OP(SSE41), /* pextrw */ + [0x16] = SPECIAL_OP(SSE41), /* pextrd/pextrq */ + [0x17] = SPECIAL_OP(SSE41), /* extractps */ + [0x20] = SPECIAL_OP(SSE41), /* pinsrb */ + [0x21] = SPECIAL_OP(SSE41), /* insertps */ + [0x22] = SPECIAL_OP(SSE41), /* pinsrd/pinsrq */ + [0x40] = BINARY_OP(dpps, SSE41, 0), + [0x41] = BINARY_OP(dppd, SSE41, 0), + [0x42] = BINARY_OP(mpsadbw, SSE41, SSE_OPF_MMX), + [0x44] = BINARY_OP(pclmulqdq, PCLMULQDQ, 0), + [0x60] = CMP_OP(pcmpestrm, SSE42), + [0x61] = CMP_OP(pcmpestri, SSE42), + [0x62] = CMP_OP(pcmpistrm, SSE42), + [0x63] = CMP_OP(pcmpistri, SSE42), + [0xdf] = UNARY_OP(aeskeygenassist, AES, 0), }; +#undef OP +#undef BINARY_OP_MMX +#undef BINARY_OP +#undef UNARY_OP_MMX +#undef UNARY_OP +#undef BLENDV_OP +#undef SPECIAL_OP + static void gen_sse(CPUX86State *env, DisasContext *s, int b, target_ulong pc_start) { int b1, op1_offset, op2_offset, is_xmm, val; int modrm, mod, rm, reg; int sse_op_flags; + const struct SSEOpHelper_table6 *op6; + const struct SSEOpHelper_table7 *op7; SSEFunc_0_epp sse_fn_epp; - SSEFunc_0_eppi sse_fn_eppi; SSEFunc_0_ppi sse_fn_ppi; SSEFunc_0_eppt sse_fn_eppt; MemOp ot; @@ -3821,12 +3841,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, mod = (modrm >> 6) & 3; assert(b1 < 2); - sse_fn_epp = sse_op_table6[b].op[b1]; - if (!sse_fn_epp) { + op6 = &sse_op_table6[b]; + if (op6->ext_mask == 0) { goto unknown_op; } - if (!(s->cpuid_ext_features & sse_op_table6[b].ext_mask)) + if (!(s->cpuid_ext_features & op6->ext_mask)) { goto illegal_op; + } if (b1) { op1_offset = ZMM_OFFSET(reg); @@ -3863,6 +3884,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } } } else { + if ((op6->flags & SSE_OPF_MMX) == 0) { + goto unknown_op; + } op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); if (mod == 3) { op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); @@ -3872,13 +3896,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldq_env_A0(s, op2_offset); } } - if (sse_fn_epp == SSE_SPECIAL_FN) { - goto unknown_op; + if (!op6->op[b1]) { + goto illegal_op; } tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); - sse_fn_epp(cpu_env, s->ptr0, s->ptr1); + op6->op[b1](cpu_env, s->ptr0, s->ptr1); if (b == 0x17) { set_cc_op(s, CC_OP_EFLAGS); @@ -4249,16 +4273,21 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, mod = (modrm >> 6) & 3; assert(b1 < 2); - sse_fn_eppi = sse_op_table7[b].op[b1]; - if (!sse_fn_eppi) { + op7 = &sse_op_table7[b]; + if (op7->ext_mask == 0) { goto unknown_op; } - if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask)) + if (!(s->cpuid_ext_features & op7->ext_mask)) { goto illegal_op; + } s->rip_offset = 1; - if (sse_fn_eppi == SSE_SPECIAL_FN) { + if (op7->flags & SSE_OPF_SPECIAL) { + /* None of the "special" ops are valid on mmx registers */ + if (b1 == 0) { + goto illegal_op; + } ot = mo_64_32(s->dflag); rm = (modrm & 7) | REX_B(s); if (mod != 3) @@ -4403,6 +4432,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldo_env_A0(s, op2_offset); } } else { + if ((op7->flags & SSE_OPF_MMX) == 0) { + goto illegal_op; + } op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); if (mod == 3) { op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); @@ -4425,7 +4457,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); - sse_fn_eppi(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val)); + op7->op[b1](cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val)); break; case 0x33a: From 622ef8f29123a4048d93ae78303b52a4fca51e03 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:46 +0100 Subject: [PATCH 0286/1020] target/i386: Move 3DNOW decoder Handle 3DNOW instructions early to avoid complicating the MMX/SSE logic. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-25-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index b7321b7588..c76f6dba11 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3216,6 +3216,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, is_xmm = 1; } } + if (sse_op_flags & SSE_OPF_3DNOW) { + if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) { + goto illegal_op; + } + } /* simple MMX/SSE operation */ if (s->flags & HF_TS_MASK) { gen_exception(s, EXCP07_PREX, pc_start - s->cs_base); @@ -4567,21 +4572,20 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, rm = (modrm & 7); op2_offset = offsetof(CPUX86State,fpregs[rm].mmx); } + if (sse_op_flags & SSE_OPF_3DNOW) { + /* 3DNow! data insns */ + val = x86_ldub_code(env, s); + SSEFunc_0_epp op_3dnow = sse_op_table5[val]; + if (!op_3dnow) { + goto unknown_op; + } + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + op_3dnow(cpu_env, s->ptr0, s->ptr1); + return; + } } switch(b) { - case 0x0f: /* 3DNow! data insns */ - val = x86_ldub_code(env, s); - sse_fn_epp = sse_op_table5[val]; - if (!sse_fn_epp) { - goto unknown_op; - } - if (!(s->cpuid_ext2_features & CPUID_EXT2_3DNOW)) { - goto illegal_op; - } - tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); - sse_fn_epp(cpu_env, s->ptr0, s->ptr1); - break; case 0x70: /* pshufx insn */ case 0xc6: /* pshufx insn */ val = x86_ldub_code(env, s); From 2607e76ffde4b0620428500a00c354c58578a933 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 27 Aug 2022 00:13:40 +0200 Subject: [PATCH 0287/1020] target/i386: check SSE table flags instead of hardcoding opcodes Put more flags to work to avoid hardcoding lists of opcodes. The op7 case for SSE_OPF_CMP is included for homogeneity and because AVX needs it, but it is never used by SSE or MMX. Extracted from a patch by Paul Brook . Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 75 +++++++++++++++---------------------- 1 file changed, 31 insertions(+), 44 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index c76f6dba11..849c40b685 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3909,7 +3909,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); op6->op[b1](cpu_env, s->ptr0, s->ptr1); - if (b == 0x17) { + if (op6->flags & SSE_OPF_CMP) { set_cc_op(s, CC_OP_EFLAGS); } break; @@ -4463,6 +4463,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); op7->op[b1](cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val)); + if (op7->flags & SSE_OPF_CMP) { + set_cc_op(s, CC_OP_EFLAGS); + } break; case 0x33a: @@ -4518,28 +4521,24 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, int sz = 4; gen_lea_modrm(env, s, modrm); - op2_offset = offsetof(CPUX86State,xmm_t0); + op2_offset = offsetof(CPUX86State, xmm_t0); - switch (b) { - case 0x50 ... 0x5a: - case 0x5c ... 0x5f: - case 0xc2: - /* Most sse scalar operations. */ - if (b1 == 2) { - sz = 2; - } else if (b1 == 3) { - sz = 3; - } - break; - - case 0x2e: /* ucomis[sd] */ - case 0x2f: /* comis[sd] */ - if (b1 == 0) { - sz = 2; + if (sse_op_flags & SSE_OPF_SCALAR) { + if (sse_op_flags & SSE_OPF_CMP) { + /* ucomis[sd], comis[sd] */ + if (b1 == 0) { + sz = 2; + } else { + sz = 3; + } } else { - sz = 3; + /* Most sse scalar operations. */ + if (b1 == 2) { + sz = 2; + } else if (b1 == 3) { + sz = 3; + } } - break; } switch (sz) { @@ -4585,26 +4584,14 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, return; } } - switch(b) { - case 0x70: /* pshufx insn */ - case 0xc6: /* pshufx insn */ + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + if (sse_op_flags & SSE_OPF_SHUF) { val = x86_ldub_code(env, s); - tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); /* XXX: introduce a new table? */ sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp; sse_fn_ppi(s->ptr0, s->ptr1, tcg_const_i32(val)); - break; - case 0xc2: - /* compare insns, bits 7:3 (7:5 for AVX) are ignored */ - val = x86_ldub_code(env, s) & 7; - sse_fn_epp = sse_op_table4[val][b1]; - - tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); - sse_fn_epp(cpu_env, s->ptr0, s->ptr1); - break; - case 0xf7: + } else if (b == 0xf7) { /* maskmov : we must prepare A0 */ if (mod != 3) { goto illegal_op; @@ -4613,19 +4600,19 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_extu(s->aflag, s->A0); gen_add_A0_ds_seg(s); - tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); /* XXX: introduce a new table? */ sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp; sse_fn_eppt(cpu_env, s->ptr0, s->ptr1, s->A0); - break; - default: - tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + } else if (b == 0xc2) { + /* compare insns, bits 7:3 (7:5 for AVX) are ignored */ + val = x86_ldub_code(env, s) & 7; + sse_fn_epp = sse_op_table4[val][b1]; + sse_fn_epp(cpu_env, s->ptr0, s->ptr1); + } else { sse_fn_epp(cpu_env, s->ptr0, s->ptr1); - break; } - if (b == 0x2e || b == 0x2f) { + + if (sse_op_flags & SSE_OPF_CMP) { set_cc_op(s, CC_OP_EFLAGS); } } From d7a851f89ac60379087b7d29c4ba09e1c6e11265 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 27 Aug 2022 00:44:38 +0200 Subject: [PATCH 0288/1020] target/i386: isolate MMX code more Extracted from a patch by Paul Brook . Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 52 +++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 19 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 849c40b685..097c895ef1 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3888,6 +3888,12 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldo_env_A0(s, op2_offset); } } + if (!op6->op[b1]) { + goto illegal_op; + } + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + op6->op[b1](cpu_env, s->ptr0, s->ptr1); } else { if ((op6->flags & SSE_OPF_MMX) == 0) { goto unknown_op; @@ -3900,14 +3906,10 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_lea_modrm(env, s, modrm); gen_ldq_env_A0(s, op2_offset); } + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + op6->op[0](cpu_env, s->ptr0, s->ptr1); } - if (!op6->op[b1]) { - goto illegal_op; - } - - tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); - tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); - op6->op[b1](cpu_env, s->ptr0, s->ptr1); if (op6->flags & SSE_OPF_CMP) { set_cc_op(s, CC_OP_EFLAGS); @@ -4427,16 +4429,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, return; } - if (b1) { - op1_offset = ZMM_OFFSET(reg); - if (mod == 3) { - op2_offset = ZMM_OFFSET(rm | REX_B(s)); - } else { - op2_offset = offsetof(CPUX86State,xmm_t0); - gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, op2_offset); - } - } else { + if (b1 == 0) { + /* MMX */ if ((op7->flags & SSE_OPF_MMX) == 0) { goto illegal_op; } @@ -4448,9 +4442,29 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_lea_modrm(env, s, modrm); gen_ldq_env_A0(s, op2_offset); } - } - val = x86_ldub_code(env, s); + val = x86_ldub_code(env, s); + tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + /* We only actually have one MMX instuction (palignr) */ + assert(b == 0x0f); + + op7->op[0](cpu_env, s->ptr0, s->ptr1, + tcg_const_i32(val)); + break; + } + + /* SSE */ + op1_offset = ZMM_OFFSET(reg); + if (mod == 3) { + op2_offset = ZMM_OFFSET(rm | REX_B(s)); + } else { + op2_offset = offsetof(CPUX86State, xmm_t0); + gen_lea_modrm(env, s, modrm); + gen_ldo_env_A0(s, op2_offset); + } + + val = x86_ldub_code(env, s); if ((b & 0xfc) == 0x60) { /* pcmpXstrX */ set_cc_op(s, CC_OP_EFLAGS); From ce4fa29f949595666ecea52eadc84ca899ccf2a4 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 27 Aug 2022 00:49:31 +0200 Subject: [PATCH 0289/1020] target/i386: Add size suffix to vector FP helpers For AVX we're going to need both 128 bit (xmm) and 256 bit (ymm) variants of floating point helpers. Add the register type suffix to the existing *PS and *PD helpers (SS and SD variants are only valid on 128 bit vectors) No functional changes. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-15-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 48 ++++++++++++++++++------------------ target/i386/ops_sse_header.h | 48 ++++++++++++++++++------------------ target/i386/tcg/translate.c | 37 +++++++++++++-------------- 3 files changed, 67 insertions(+), 66 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index b12b271fcd..f603981ab8 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -537,7 +537,7 @@ void glue(helper_pshufw, SUFFIX)(Reg *d, Reg *s, int order) MOVE(*d, r); } #else -void helper_shufps(Reg *d, Reg *s, int order) +void glue(helper_shufps, SUFFIX)(Reg *d, Reg *s, int order) { Reg r; @@ -548,7 +548,7 @@ void helper_shufps(Reg *d, Reg *s, int order) MOVE(*d, r); } -void helper_shufpd(Reg *d, Reg *s, int order) +void glue(helper_shufpd, SUFFIX)(Reg *d, Reg *s, int order) { Reg r; @@ -598,7 +598,7 @@ void glue(helper_pshufhw, SUFFIX)(Reg *d, Reg *s, int order) /* XXX: not accurate */ #define SSE_HELPER_S(name, F) \ - void helper_ ## name ## ps(CPUX86State *env, Reg *d, Reg *s) \ + void glue(helper_ ## name ## ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)\ { \ d->ZMM_S(0) = F(32, d->ZMM_S(0), s->ZMM_S(0)); \ d->ZMM_S(1) = F(32, d->ZMM_S(1), s->ZMM_S(1)); \ @@ -611,7 +611,7 @@ void glue(helper_pshufhw, SUFFIX)(Reg *d, Reg *s, int order) d->ZMM_S(0) = F(32, d->ZMM_S(0), s->ZMM_S(0)); \ } \ \ - void helper_ ## name ## pd(CPUX86State *env, Reg *d, Reg *s) \ + void glue(helper_ ## name ## pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)\ { \ d->ZMM_D(0) = F(64, d->ZMM_D(0), s->ZMM_D(0)); \ d->ZMM_D(1) = F(64, d->ZMM_D(1), s->ZMM_D(1)); \ @@ -647,7 +647,7 @@ SSE_HELPER_S(sqrt, FPU_SQRT) /* float to float conversions */ -void helper_cvtps2pd(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_cvtps2pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { float32 s0, s1; @@ -657,7 +657,7 @@ void helper_cvtps2pd(CPUX86State *env, Reg *d, Reg *s) d->ZMM_D(1) = float32_to_float64(s1, &env->sse_status); } -void helper_cvtpd2ps(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_cvtpd2ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->ZMM_S(0) = float64_to_float32(s->ZMM_D(0), &env->sse_status); d->ZMM_S(1) = float64_to_float32(s->ZMM_D(1), &env->sse_status); @@ -675,7 +675,7 @@ void helper_cvtsd2ss(CPUX86State *env, Reg *d, Reg *s) } /* integer to float */ -void helper_cvtdq2ps(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_cvtdq2ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { d->ZMM_S(0) = int32_to_float32(s->ZMM_L(0), &env->sse_status); d->ZMM_S(1) = int32_to_float32(s->ZMM_L(1), &env->sse_status); @@ -683,7 +683,7 @@ void helper_cvtdq2ps(CPUX86State *env, Reg *d, Reg *s) d->ZMM_S(3) = int32_to_float32(s->ZMM_L(3), &env->sse_status); } -void helper_cvtdq2pd(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_cvtdq2pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int32_t l0, l1; @@ -760,7 +760,7 @@ WRAP_FLOATCONV(int64_t, float32_to_int64_round_to_zero, float32, INT64_MIN) WRAP_FLOATCONV(int64_t, float64_to_int64, float64, INT64_MIN) WRAP_FLOATCONV(int64_t, float64_to_int64_round_to_zero, float64, INT64_MIN) -void helper_cvtps2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_cvtps2dq, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { d->ZMM_L(0) = x86_float32_to_int32(s->ZMM_S(0), &env->sse_status); d->ZMM_L(1) = x86_float32_to_int32(s->ZMM_S(1), &env->sse_status); @@ -768,7 +768,7 @@ void helper_cvtps2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s) d->ZMM_L(3) = x86_float32_to_int32(s->ZMM_S(3), &env->sse_status); } -void helper_cvtpd2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_cvtpd2dq, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { d->ZMM_L(0) = x86_float64_to_int32(s->ZMM_D(0), &env->sse_status); d->ZMM_L(1) = x86_float64_to_int32(s->ZMM_D(1), &env->sse_status); @@ -810,7 +810,7 @@ int64_t helper_cvtsd2sq(CPUX86State *env, ZMMReg *s) #endif /* float to integer truncated */ -void helper_cvttps2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_cvttps2dq, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { d->ZMM_L(0) = x86_float32_to_int32_round_to_zero(s->ZMM_S(0), &env->sse_status); d->ZMM_L(1) = x86_float32_to_int32_round_to_zero(s->ZMM_S(1), &env->sse_status); @@ -818,7 +818,7 @@ void helper_cvttps2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s) d->ZMM_L(3) = x86_float32_to_int32_round_to_zero(s->ZMM_S(3), &env->sse_status); } -void helper_cvttpd2dq(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_cvttpd2dq, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { d->ZMM_L(0) = x86_float64_to_int32_round_to_zero(s->ZMM_D(0), &env->sse_status); d->ZMM_L(1) = x86_float64_to_int32_round_to_zero(s->ZMM_D(1), &env->sse_status); @@ -859,7 +859,7 @@ int64_t helper_cvttsd2sq(CPUX86State *env, ZMMReg *s) } #endif -void helper_rsqrtps(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_rsqrtps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { uint8_t old_flags = get_float_exception_flags(&env->sse_status); d->ZMM_S(0) = float32_div(float32_one, @@ -886,7 +886,7 @@ void helper_rsqrtss(CPUX86State *env, ZMMReg *d, ZMMReg *s) set_float_exception_flags(old_flags, &env->sse_status); } -void helper_rcpps(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_rcpps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { uint8_t old_flags = get_float_exception_flags(&env->sse_status); d->ZMM_S(0) = float32_div(float32_one, s->ZMM_S(0), &env->sse_status); @@ -947,7 +947,7 @@ void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length) d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), index, length); } -void helper_haddps(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_haddps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { ZMMReg r; @@ -958,7 +958,7 @@ void helper_haddps(CPUX86State *env, ZMMReg *d, ZMMReg *s) MOVE(*d, r); } -void helper_haddpd(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_haddpd, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { ZMMReg r; @@ -967,7 +967,7 @@ void helper_haddpd(CPUX86State *env, ZMMReg *d, ZMMReg *s) MOVE(*d, r); } -void helper_hsubps(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_hsubps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { ZMMReg r; @@ -978,7 +978,7 @@ void helper_hsubps(CPUX86State *env, ZMMReg *d, ZMMReg *s) MOVE(*d, r); } -void helper_hsubpd(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_hsubpd, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { ZMMReg r; @@ -987,7 +987,7 @@ void helper_hsubpd(CPUX86State *env, ZMMReg *d, ZMMReg *s) MOVE(*d, r); } -void helper_addsubps(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_addsubps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { d->ZMM_S(0) = float32_sub(d->ZMM_S(0), s->ZMM_S(0), &env->sse_status); d->ZMM_S(1) = float32_add(d->ZMM_S(1), s->ZMM_S(1), &env->sse_status); @@ -995,7 +995,7 @@ void helper_addsubps(CPUX86State *env, ZMMReg *d, ZMMReg *s) d->ZMM_S(3) = float32_add(d->ZMM_S(3), s->ZMM_S(3), &env->sse_status); } -void helper_addsubpd(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_addsubpd, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { d->ZMM_D(0) = float64_sub(d->ZMM_D(0), s->ZMM_D(0), &env->sse_status); d->ZMM_D(1) = float64_add(d->ZMM_D(1), s->ZMM_D(1), &env->sse_status); @@ -1003,7 +1003,7 @@ void helper_addsubpd(CPUX86State *env, ZMMReg *d, ZMMReg *s) /* XXX: unordered */ #define SSE_HELPER_CMP(name, F) \ - void helper_ ## name ## ps(CPUX86State *env, Reg *d, Reg *s) \ + void glue(helper_ ## name ## ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)\ { \ d->ZMM_L(0) = F(32, d->ZMM_S(0), s->ZMM_S(0)); \ d->ZMM_L(1) = F(32, d->ZMM_S(1), s->ZMM_S(1)); \ @@ -1016,7 +1016,7 @@ void helper_addsubpd(CPUX86State *env, ZMMReg *d, ZMMReg *s) d->ZMM_L(0) = F(32, d->ZMM_S(0), s->ZMM_S(0)); \ } \ \ - void helper_ ## name ## pd(CPUX86State *env, Reg *d, Reg *s) \ + void glue(helper_ ## name ## pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)\ { \ d->ZMM_Q(0) = F(64, d->ZMM_D(0), s->ZMM_D(0)); \ d->ZMM_Q(1) = F(64, d->ZMM_D(1), s->ZMM_D(1)); \ @@ -1099,7 +1099,7 @@ void helper_comisd(CPUX86State *env, Reg *d, Reg *s) CC_SRC = comis_eflags[ret + 1]; } -uint32_t helper_movmskps(CPUX86State *env, Reg *s) +uint32_t glue(helper_movmskps, SUFFIX)(CPUX86State *env, Reg *s) { int b0, b1, b2, b3; @@ -1110,7 +1110,7 @@ uint32_t helper_movmskps(CPUX86State *env, Reg *s) return b0 | (b1 << 1) | (b2 << 2) | (b3 << 3); } -uint32_t helper_movmskpd(CPUX86State *env, Reg *s) +uint32_t glue(helper_movmskpd, SUFFIX)(CPUX86State *env, Reg *s) { int b0, b1; diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h index cef28f2aae..fc697536a0 100644 --- a/target/i386/ops_sse_header.h +++ b/target/i386/ops_sse_header.h @@ -122,8 +122,8 @@ DEF_HELPER_2(glue(movq_mm_T0, SUFFIX), void, Reg, i64) #if SHIFT == 0 DEF_HELPER_3(glue(pshufw, SUFFIX), void, Reg, Reg, int) #else -DEF_HELPER_3(shufps, void, Reg, Reg, int) -DEF_HELPER_3(shufpd, void, Reg, Reg, int) +DEF_HELPER_3(glue(shufps, SUFFIX), void, Reg, Reg, int) +DEF_HELPER_3(glue(shufpd, SUFFIX), void, Reg, Reg, int) DEF_HELPER_3(glue(pshufd, SUFFIX), void, Reg, Reg, int) DEF_HELPER_3(glue(pshuflw, SUFFIX), void, Reg, Reg, int) DEF_HELPER_3(glue(pshufhw, SUFFIX), void, Reg, Reg, int) @@ -134,9 +134,9 @@ DEF_HELPER_3(glue(pshufhw, SUFFIX), void, Reg, Reg, int) /* XXX: not accurate */ #define SSE_HELPER_S(name, F) \ - DEF_HELPER_3(name ## ps, void, env, Reg, Reg) \ + DEF_HELPER_3(glue(name ## ps, SUFFIX), void, env, Reg, Reg) \ DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \ - DEF_HELPER_3(name ## pd, void, env, Reg, Reg) \ + DEF_HELPER_3(glue(name ## pd, SUFFIX), void, env, Reg, Reg) \ DEF_HELPER_3(name ## sd, void, env, Reg, Reg) SSE_HELPER_S(add, FPU_ADD) @@ -148,12 +148,12 @@ SSE_HELPER_S(max, FPU_MAX) SSE_HELPER_S(sqrt, FPU_SQRT) -DEF_HELPER_3(cvtps2pd, void, env, Reg, Reg) -DEF_HELPER_3(cvtpd2ps, void, env, Reg, Reg) +DEF_HELPER_3(glue(cvtps2pd, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(cvtpd2ps, SUFFIX), void, env, Reg, Reg) DEF_HELPER_3(cvtss2sd, void, env, Reg, Reg) DEF_HELPER_3(cvtsd2ss, void, env, Reg, Reg) -DEF_HELPER_3(cvtdq2ps, void, env, Reg, Reg) -DEF_HELPER_3(cvtdq2pd, void, env, Reg, Reg) +DEF_HELPER_3(glue(cvtdq2ps, SUFFIX), void, env, Reg, Reg) +DEF_HELPER_3(glue(cvtdq2pd, SUFFIX), void, env, Reg, Reg) DEF_HELPER_3(cvtpi2ps, void, env, ZMMReg, MMXReg) DEF_HELPER_3(cvtpi2pd, void, env, ZMMReg, MMXReg) DEF_HELPER_3(cvtsi2ss, void, env, ZMMReg, i32) @@ -164,8 +164,8 @@ DEF_HELPER_3(cvtsq2ss, void, env, ZMMReg, i64) DEF_HELPER_3(cvtsq2sd, void, env, ZMMReg, i64) #endif -DEF_HELPER_3(cvtps2dq, void, env, ZMMReg, ZMMReg) -DEF_HELPER_3(cvtpd2dq, void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(cvtps2dq, SUFFIX), void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(cvtpd2dq, SUFFIX), void, env, ZMMReg, ZMMReg) DEF_HELPER_3(cvtps2pi, void, env, MMXReg, ZMMReg) DEF_HELPER_3(cvtpd2pi, void, env, MMXReg, ZMMReg) DEF_HELPER_2(cvtss2si, s32, env, ZMMReg) @@ -175,8 +175,8 @@ DEF_HELPER_2(cvtss2sq, s64, env, ZMMReg) DEF_HELPER_2(cvtsd2sq, s64, env, ZMMReg) #endif -DEF_HELPER_3(cvttps2dq, void, env, ZMMReg, ZMMReg) -DEF_HELPER_3(cvttpd2dq, void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(cvttps2dq, SUFFIX), void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(cvttpd2dq, SUFFIX), void, env, ZMMReg, ZMMReg) DEF_HELPER_3(cvttps2pi, void, env, MMXReg, ZMMReg) DEF_HELPER_3(cvttpd2pi, void, env, MMXReg, ZMMReg) DEF_HELPER_2(cvttss2si, s32, env, ZMMReg) @@ -186,25 +186,25 @@ DEF_HELPER_2(cvttss2sq, s64, env, ZMMReg) DEF_HELPER_2(cvttsd2sq, s64, env, ZMMReg) #endif -DEF_HELPER_3(rsqrtps, void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(rsqrtps, SUFFIX), void, env, ZMMReg, ZMMReg) DEF_HELPER_3(rsqrtss, void, env, ZMMReg, ZMMReg) -DEF_HELPER_3(rcpps, void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(rcpps, SUFFIX), void, env, ZMMReg, ZMMReg) DEF_HELPER_3(rcpss, void, env, ZMMReg, ZMMReg) DEF_HELPER_3(extrq_r, void, env, ZMMReg, ZMMReg) DEF_HELPER_4(extrq_i, void, env, ZMMReg, int, int) DEF_HELPER_3(insertq_r, void, env, ZMMReg, ZMMReg) DEF_HELPER_4(insertq_i, void, env, ZMMReg, int, int) -DEF_HELPER_3(haddps, void, env, ZMMReg, ZMMReg) -DEF_HELPER_3(haddpd, void, env, ZMMReg, ZMMReg) -DEF_HELPER_3(hsubps, void, env, ZMMReg, ZMMReg) -DEF_HELPER_3(hsubpd, void, env, ZMMReg, ZMMReg) -DEF_HELPER_3(addsubps, void, env, ZMMReg, ZMMReg) -DEF_HELPER_3(addsubpd, void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(haddps, SUFFIX), void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(haddpd, SUFFIX), void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(hsubps, SUFFIX), void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(hsubpd, SUFFIX), void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(addsubps, SUFFIX), void, env, ZMMReg, ZMMReg) +DEF_HELPER_3(glue(addsubpd, SUFFIX), void, env, ZMMReg, ZMMReg) #define SSE_HELPER_CMP(name, F) \ - DEF_HELPER_3(name ## ps, void, env, Reg, Reg) \ + DEF_HELPER_3(glue(name ## ps, SUFFIX), void, env, Reg, Reg) \ DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \ - DEF_HELPER_3(name ## pd, void, env, Reg, Reg) \ + DEF_HELPER_3(glue(name ## pd, SUFFIX), void, env, Reg, Reg) \ DEF_HELPER_3(name ## sd, void, env, Reg, Reg) SSE_HELPER_CMP(cmpeq, FPU_CMPEQ) @@ -220,8 +220,8 @@ DEF_HELPER_3(ucomiss, void, env, Reg, Reg) DEF_HELPER_3(comiss, void, env, Reg, Reg) DEF_HELPER_3(ucomisd, void, env, Reg, Reg) DEF_HELPER_3(comisd, void, env, Reg, Reg) -DEF_HELPER_2(movmskps, i32, env, Reg) -DEF_HELPER_2(movmskpd, i32, env, Reg) +DEF_HELPER_2(glue(movmskps, SUFFIX), i32, env, Reg) +DEF_HELPER_2(glue(movmskpd, SUFFIX), i32, env, Reg) #endif DEF_HELPER_2(glue(pmovmskb, SUFFIX), i32, env, Reg) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 097c895ef1..16db155c94 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2804,7 +2804,7 @@ typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm, NULL, NULL) #define SSE_FOP(name) OP(op1, SSE_OPF_SCALAR, \ - gen_helper_##name##ps, gen_helper_##name##pd, \ + gen_helper_##name##ps##_xmm, gen_helper_##name##pd##_xmm, \ gen_helper_##name##ss, gen_helper_##name##sd) #define SSE_OP(sname, dname, op, flags) OP(op, flags, \ gen_helper_##sname##_xmm, gen_helper_##dname##_xmm, NULL, NULL) @@ -2843,12 +2843,12 @@ static const struct SSEOpHelper_table1 sse_op_table1[256] = { gen_helper_comiss, gen_helper_comisd, NULL, NULL), [0x50] = SSE_SPECIAL, /* movmskps, movmskpd */ [0x51] = OP(op1, SSE_OPF_SCALAR, - gen_helper_sqrtps, gen_helper_sqrtpd, + gen_helper_sqrtps_xmm, gen_helper_sqrtpd_xmm, gen_helper_sqrtss, gen_helper_sqrtsd), [0x52] = OP(op1, SSE_OPF_SCALAR, - gen_helper_rsqrtps, NULL, gen_helper_rsqrtss, NULL), + gen_helper_rsqrtps_xmm, NULL, gen_helper_rsqrtss, NULL), [0x53] = OP(op1, SSE_OPF_SCALAR, - gen_helper_rcpps, NULL, gen_helper_rcpss, NULL), + gen_helper_rcpps_xmm, NULL, gen_helper_rcpss, NULL), [0x54] = SSE_OP(pand, pand, op1, 0), /* andps, andpd */ [0x55] = SSE_OP(pandn, pandn, op1, 0), /* andnps, andnpd */ [0x56] = SSE_OP(por, por, op1, 0), /* orps, orpd */ @@ -2856,19 +2856,19 @@ static const struct SSEOpHelper_table1 sse_op_table1[256] = { [0x58] = SSE_FOP(add), [0x59] = SSE_FOP(mul), [0x5a] = OP(op1, SSE_OPF_SCALAR, - gen_helper_cvtps2pd, gen_helper_cvtpd2ps, + gen_helper_cvtps2pd_xmm, gen_helper_cvtpd2ps_xmm, gen_helper_cvtss2sd, gen_helper_cvtsd2ss), [0x5b] = OP(op1, 0, - gen_helper_cvtdq2ps, gen_helper_cvtps2dq, - gen_helper_cvttps2dq, NULL), + gen_helper_cvtdq2ps_xmm, gen_helper_cvtps2dq_xmm, + gen_helper_cvttps2dq_xmm, NULL), [0x5c] = SSE_FOP(sub), [0x5d] = SSE_FOP(min), [0x5e] = SSE_FOP(div), [0x5f] = SSE_FOP(max), [0xc2] = SSE_FOP(cmpeq), /* sse_op_table4 */ - [0xc6] = OP(dummy, SSE_OPF_SHUF, (SSEFunc_0_epp)gen_helper_shufps, - (SSEFunc_0_epp)gen_helper_shufpd, NULL, NULL), + [0xc6] = OP(dummy, SSE_OPF_SHUF, (SSEFunc_0_epp)gen_helper_shufps_xmm, + (SSEFunc_0_epp)gen_helper_shufpd_xmm, NULL, NULL), /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */ [0x38] = SSE_SPECIAL, @@ -2909,15 +2909,15 @@ static const struct SSEOpHelper_table1 sse_op_table1[256] = { [0x79] = OP(op1, 0, NULL, gen_helper_extrq_r, NULL, gen_helper_insertq_r), [0x7c] = OP(op1, 0, - NULL, gen_helper_haddpd, NULL, gen_helper_haddps), + NULL, gen_helper_haddpd_xmm, NULL, gen_helper_haddps_xmm), [0x7d] = OP(op1, 0, - NULL, gen_helper_hsubpd, NULL, gen_helper_hsubps), + NULL, gen_helper_hsubpd_xmm, NULL, gen_helper_hsubps_xmm), [0x7e] = SSE_SPECIAL, /* movd, movd, , movq */ [0x7f] = SSE_SPECIAL, /* movq, movdqa, movdqu */ [0xc4] = SSE_SPECIAL, /* pinsrw */ [0xc5] = SSE_SPECIAL, /* pextrw */ [0xd0] = OP(op1, 0, - NULL, gen_helper_addsubpd, NULL, gen_helper_addsubps), + NULL, gen_helper_addsubpd_xmm, NULL, gen_helper_addsubps_xmm), [0xd1] = MMX_OP(psrlw), [0xd2] = MMX_OP(psrld), [0xd3] = MMX_OP(psrlq), @@ -2940,8 +2940,8 @@ static const struct SSEOpHelper_table1 sse_op_table1[256] = { [0xe4] = MMX_OP(pmulhuw), [0xe5] = MMX_OP(pmulhw), [0xe6] = OP(op1, 0, - NULL, gen_helper_cvttpd2dq, - gen_helper_cvtdq2pd, gen_helper_cvtpd2dq), + NULL, gen_helper_cvttpd2dq_xmm, + gen_helper_cvtdq2pd_xmm, gen_helper_cvtpd2dq_xmm), [0xe7] = SSE_SPECIAL, /* movntq, movntq */ [0xe8] = MMX_OP(psubsb), [0xe9] = MMX_OP(psubsw), @@ -3018,8 +3018,9 @@ static const SSEFunc_l_ep sse_op_table3bq[] = { }; #endif -#define SSE_FOP(x) { gen_helper_ ## x ## ps, gen_helper_ ## x ## pd, \ - gen_helper_ ## x ## ss, gen_helper_ ## x ## sd, } +#define SSE_FOP(x) { \ + gen_helper_ ## x ## ps ## _xmm, gen_helper_ ## x ## pd ## _xmm, \ + gen_helper_ ## x ## ss, gen_helper_ ## x ## sd} static const SSEFunc_0_epp sse_op_table4[8][4] = { SSE_FOP(cmpeq), SSE_FOP(cmplt), @@ -3636,13 +3637,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x050: /* movmskps */ rm = (modrm & 7) | REX_B(s); tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm)); - gen_helper_movmskps(s->tmp2_i32, cpu_env, s->ptr0); + gen_helper_movmskps_xmm(s->tmp2_i32, cpu_env, s->ptr0); tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); break; case 0x150: /* movmskpd */ rm = (modrm & 7) | REX_B(s); tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm)); - gen_helper_movmskpd(s->tmp2_i32, cpu_env, s->ptr0); + gen_helper_movmskpd_xmm(s->tmp2_i32, cpu_env, s->ptr0); tcg_gen_extu_i32_tl(cpu_regs[reg], s->tmp2_i32); break; case 0x02a: /* cvtpi2ps */ From 7f326902433052e97a6aa9539f45d5a8a1fdd172 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 26 Aug 2022 23:09:27 +0200 Subject: [PATCH 0290/1020] target/i386: do not cast gen_helper_* function pointers Use a union to store the various possible kinds of function pointers, and access the correct one based on the flags. SSEOpHelper_table6 and SSEOpHelper_table7 right now only have one case, but this would change with AVX's 3- and 4-argument operations. Use unions there too, to keep the code more similar for the three tables. Extracted from a patch by Paul Brook . Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 75 ++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 38 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 16db155c94..c6a9a5b1d4 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2784,6 +2784,8 @@ typedef void (*SSEFunc_l_ep)(TCGv_i64 val, TCGv_ptr env, TCGv_ptr reg); typedef void (*SSEFunc_0_epi)(TCGv_ptr env, TCGv_ptr reg, TCGv_i32 val); typedef void (*SSEFunc_0_epl)(TCGv_ptr env, TCGv_ptr reg, TCGv_i64 val); typedef void (*SSEFunc_0_epp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b); +typedef void (*SSEFunc_0_eppp)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, + TCGv_ptr reg_c); typedef void (*SSEFunc_0_eppi)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val); typedef void (*SSEFunc_0_ppi)(TCGv_ptr reg_a, TCGv_ptr reg_b, TCGv_i32 val); @@ -2798,7 +2800,7 @@ typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, #define SSE_OPF_SHUF (1 << 9) /* pshufx/shufpx */ #define OP(op, flags, a, b, c, d) \ - {flags, {a, b, c, d} } + {flags, {{.op = a}, {.op = b}, {.op = c}, {.op = d} } } #define MMX_OP(x) OP(op1, SSE_OPF_MMX, \ gen_helper_ ## x ## _mmx, gen_helper_ ## x ## _xmm, NULL, NULL) @@ -2809,9 +2811,15 @@ typedef void (*SSEFunc_0_eppt)(TCGv_ptr env, TCGv_ptr reg_a, TCGv_ptr reg_b, #define SSE_OP(sname, dname, op, flags) OP(op, flags, \ gen_helper_##sname##_xmm, gen_helper_##dname##_xmm, NULL, NULL) +typedef union SSEFuncs { + SSEFunc_0_epp op1; + SSEFunc_0_ppi op1i; + SSEFunc_0_eppt op1t; +} SSEFuncs; + struct SSEOpHelper_table1 { int flags; - SSEFunc_0_epp op[4]; + SSEFuncs fn[4]; }; #define SSE_3DNOW { SSE_OPF_3DNOW } @@ -2867,8 +2875,7 @@ static const struct SSEOpHelper_table1 sse_op_table1[256] = { [0x5f] = SSE_FOP(max), [0xc2] = SSE_FOP(cmpeq), /* sse_op_table4 */ - [0xc6] = OP(dummy, SSE_OPF_SHUF, (SSEFunc_0_epp)gen_helper_shufps_xmm, - (SSEFunc_0_epp)gen_helper_shufpd_xmm, NULL, NULL), + [0xc6] = SSE_OP(shufps, shufpd, op1i, SSE_OPF_SHUF), /* SSSE3, SSE4, MOVBE, CRC32, BMI1, BMI2, ADX. */ [0x38] = SSE_SPECIAL, @@ -2894,10 +2901,8 @@ static const struct SSEOpHelper_table1 sse_op_table1[256] = { [0x6e] = SSE_SPECIAL, /* movd mm, ea */ [0x6f] = SSE_SPECIAL, /* movq, movdqa, , movqdu */ [0x70] = OP(op1i, SSE_OPF_SHUF | SSE_OPF_MMX, - (SSEFunc_0_epp)gen_helper_pshufw_mmx, - (SSEFunc_0_epp)gen_helper_pshufd_xmm, - (SSEFunc_0_epp)gen_helper_pshufhw_xmm, - (SSEFunc_0_epp)gen_helper_pshuflw_xmm), + gen_helper_pshufw_mmx, gen_helper_pshufd_xmm, + gen_helper_pshufhw_xmm, gen_helper_pshuflw_xmm), [0x71] = SSE_SPECIAL, /* shiftw */ [0x72] = SSE_SPECIAL, /* shiftd */ [0x73] = SSE_SPECIAL, /* shiftq */ @@ -2959,8 +2964,7 @@ static const struct SSEOpHelper_table1 sse_op_table1[256] = { [0xf5] = MMX_OP(pmaddwd), [0xf6] = MMX_OP(psadbw), [0xf7] = OP(op1t, SSE_OPF_MMX, - (SSEFunc_0_epp)gen_helper_maskmov_mmx, - (SSEFunc_0_epp)gen_helper_maskmov_xmm, NULL, NULL), + gen_helper_maskmov_mmx, gen_helper_maskmov_xmm, NULL, NULL), [0xf8] = MMX_OP(psubb), [0xf9] = MMX_OP(psubw), [0xfa] = MMX_OP(psubl), @@ -3057,17 +3061,19 @@ static const SSEFunc_0_epp sse_op_table5[256] = { [0xb6] = gen_helper_movq, /* pfrcpit2 */ [0xb7] = gen_helper_pmulhrw_mmx, [0xbb] = gen_helper_pswapd, - [0xbf] = gen_helper_pavgb_mmx /* pavgusb */ + [0xbf] = gen_helper_pavgb_mmx, }; struct SSEOpHelper_table6 { - SSEFunc_0_epp op[2]; + SSEFuncs fn[2]; uint32_t ext_mask; int flags; }; struct SSEOpHelper_table7 { - SSEFunc_0_eppi op[2]; + union { + SSEFunc_0_eppi op1; + } fn[2]; uint32_t ext_mask; int flags; }; @@ -3075,7 +3081,8 @@ struct SSEOpHelper_table7 { #define gen_helper_special_xmm NULL #define OP(name, op, flags, ext, mmx_name) \ - {{mmx_name, gen_helper_ ## name ## _xmm}, CPUID_EXT_ ## ext, flags} + {{{.op = mmx_name}, {.op = gen_helper_ ## name ## _xmm} }, \ + CPUID_EXT_ ## ext, flags} #define BINARY_OP_MMX(name, ext) \ OP(name, op1, SSE_OPF_MMX, ext, gen_helper_ ## name ## _mmx) #define BINARY_OP(name, ext, flags) \ @@ -3185,11 +3192,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, int b1, op1_offset, op2_offset, is_xmm, val; int modrm, mod, rm, reg; int sse_op_flags; + SSEFuncs sse_op_fn; const struct SSEOpHelper_table6 *op6; const struct SSEOpHelper_table7 *op7; - SSEFunc_0_epp sse_fn_epp; - SSEFunc_0_ppi sse_fn_ppi; - SSEFunc_0_eppt sse_fn_eppt; MemOp ot; b &= 0xff; @@ -3202,9 +3207,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, else b1 = 0; sse_op_flags = sse_op_table1[b].flags; - sse_fn_epp = sse_op_table1[b].op[b1]; + sse_op_fn = sse_op_table1[b].fn[b1]; if ((sse_op_flags & (SSE_OPF_SPECIAL | SSE_OPF_3DNOW)) == 0 - && !sse_fn_epp) { + && !sse_op_fn.op1) { goto unknown_op; } if ((b <= 0x5f && b >= 0x10) || b == 0xc6 || b == 0xc2) { @@ -3618,9 +3623,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, op1_offset = offsetof(CPUX86State,mmx_t0); } assert(b1 < 2); - sse_fn_epp = sse_op_table2[((b - 1) & 3) * 8 + + SSEFunc_0_epp fn = sse_op_table2[((b - 1) & 3) * 8 + (((modrm >> 3)) & 7)][b1]; - if (!sse_fn_epp) { + if (!fn) { goto unknown_op; } if (is_xmm) { @@ -3632,7 +3637,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } tcg_gen_addi_ptr(s->ptr0, cpu_env, op2_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op1_offset); - sse_fn_epp(cpu_env, s->ptr0, s->ptr1); + fn(cpu_env, s->ptr0, s->ptr1); break; case 0x050: /* movmskps */ rm = (modrm & 7) | REX_B(s); @@ -3889,12 +3894,12 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_ldo_env_A0(s, op2_offset); } } - if (!op6->op[b1]) { + if (!op6->fn[b1].op1) { goto illegal_op; } tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); - op6->op[b1](cpu_env, s->ptr0, s->ptr1); + op6->fn[b1].op1(cpu_env, s->ptr0, s->ptr1); } else { if ((op6->flags & SSE_OPF_MMX) == 0) { goto unknown_op; @@ -3909,7 +3914,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); - op6->op[0](cpu_env, s->ptr0, s->ptr1); + op6->fn[0].op1(cpu_env, s->ptr0, s->ptr1); } if (op6->flags & SSE_OPF_CMP) { @@ -4450,8 +4455,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, /* We only actually have one MMX instuction (palignr) */ assert(b == 0x0f); - op7->op[0](cpu_env, s->ptr0, s->ptr1, - tcg_const_i32(val)); + op7->fn[0].op1(cpu_env, s->ptr0, s->ptr1, + tcg_const_i32(val)); break; } @@ -4477,7 +4482,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(s->ptr0, cpu_env, op1_offset); tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); - op7->op[b1](cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val)); + op7->fn[b1].op1(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(val)); if (op7->flags & SSE_OPF_CMP) { set_cc_op(s, CC_OP_EFLAGS); } @@ -4603,9 +4608,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); if (sse_op_flags & SSE_OPF_SHUF) { val = x86_ldub_code(env, s); - /* XXX: introduce a new table? */ - sse_fn_ppi = (SSEFunc_0_ppi)sse_fn_epp; - sse_fn_ppi(s->ptr0, s->ptr1, tcg_const_i32(val)); + sse_op_fn.op1i(s->ptr0, s->ptr1, tcg_const_i32(val)); } else if (b == 0xf7) { /* maskmov : we must prepare A0 */ if (mod != 3) { @@ -4614,17 +4617,13 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_mov_tl(s->A0, cpu_regs[R_EDI]); gen_extu(s->aflag, s->A0); gen_add_A0_ds_seg(s); - - /* XXX: introduce a new table? */ - sse_fn_eppt = (SSEFunc_0_eppt)sse_fn_epp; - sse_fn_eppt(cpu_env, s->ptr0, s->ptr1, s->A0); + sse_op_fn.op1t(cpu_env, s->ptr0, s->ptr1, s->A0); } else if (b == 0xc2) { /* compare insns, bits 7:3 (7:5 for AVX) are ignored */ val = x86_ldub_code(env, s) & 7; - sse_fn_epp = sse_op_table4[val][b1]; - sse_fn_epp(cpu_env, s->ptr0, s->ptr1); + sse_op_table4[val][b1](cpu_env, s->ptr0, s->ptr1); } else { - sse_fn_epp(cpu_env, s->ptr0, s->ptr1); + sse_op_fn.op1(cpu_env, s->ptr0, s->ptr1); } if (sse_op_flags & SSE_OPF_CMP) { From 71964f1b692addde852a3eb05e2298cbd80882ae Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:28 +0100 Subject: [PATCH 0291/1020] target/i386: Add CHECK_NO_VEX Reject invalid VEX encodings on MMX instructions. Signed-off-by: Paul Brook Reviewed-by: Richard Henderson Message-Id: <20220424220204.2493824-7-paul@nowt.org> Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index c6a9a5b1d4..99c84473f4 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3186,6 +3186,12 @@ static const struct SSEOpHelper_table7 sse_op_table7[256] = { #undef BLENDV_OP #undef SPECIAL_OP +/* VEX prefix not allowed */ +#define CHECK_NO_VEX(s) do { \ + if (s->prefix & PREFIX_VEX) \ + goto illegal_op; \ + } while (0) + static void gen_sse(CPUX86State *env, DisasContext *s, int b, target_ulong pc_start) { @@ -3272,6 +3278,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, b |= (b1 << 8); switch(b) { case 0x0e7: /* movntq */ + CHECK_NO_VEX(s); if (mod == 3) { goto illegal_op; } @@ -3307,6 +3314,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } break; case 0x6e: /* movd mm, ea */ + CHECK_NO_VEX(s); #ifdef TARGET_X86_64 if (s->dflag == MO_64) { gen_ldst_modrm(env, s, modrm, MO_64, OR_TMP0, 0); @@ -3338,6 +3346,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } break; case 0x6f: /* movq mm, ea */ + CHECK_NO_VEX(s); if (mod != 3) { gen_lea_modrm(env, s, modrm); gen_ldq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx)); @@ -3473,6 +3482,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, break; case 0x178: case 0x378: + CHECK_NO_VEX(s); { int bit_index, field_length; @@ -3492,6 +3502,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } break; case 0x7e: /* movd ea, mm */ + CHECK_NO_VEX(s); #ifdef TARGET_X86_64 if (s->dflag == MO_64) { tcg_gen_ld_i64(s->T0, cpu_env, @@ -3532,6 +3543,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1))); break; case 0x7f: /* movq ea, mm */ + CHECK_NO_VEX(s); if (mod != 3) { gen_lea_modrm(env, s, modrm); gen_stq_env_A0(s, offsetof(CPUX86State, fpregs[reg].mmx)); @@ -3614,6 +3626,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, offsetof(CPUX86State, xmm_t0.ZMM_L(1))); op1_offset = offsetof(CPUX86State,xmm_t0); } else { + CHECK_NO_VEX(s); tcg_gen_movi_tl(s->T0, val); tcg_gen_st32_tl(s->T0, cpu_env, offsetof(CPUX86State, mmx_t0.MMX_L(0))); @@ -3653,6 +3666,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, break; case 0x02a: /* cvtpi2ps */ case 0x12a: /* cvtpi2pd */ + CHECK_NO_VEX(s); gen_helper_enter_mmx(cpu_env); if (mod != 3) { gen_lea_modrm(env, s, modrm); @@ -3698,6 +3712,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x12c: /* cvttpd2pi */ case 0x02d: /* cvtps2pi */ case 0x12d: /* cvtpd2pi */ + CHECK_NO_VEX(s); gen_helper_enter_mmx(cpu_env); if (mod != 3) { gen_lea_modrm(env, s, modrm); @@ -3771,6 +3786,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_st16_tl(s->T0, cpu_env, offsetof(CPUX86State,xmm_regs[reg].ZMM_W(val))); } else { + CHECK_NO_VEX(s); val &= 3; tcg_gen_st16_tl(s->T0, cpu_env, offsetof(CPUX86State,fpregs[reg].mmx.MMX_W(val))); @@ -3810,6 +3826,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } break; case 0x2d6: /* movq2dq */ + CHECK_NO_VEX(s); gen_helper_enter_mmx(cpu_env); rm = (modrm & 7); gen_op_movq(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(0)), @@ -3817,6 +3834,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_op_movq_env_0(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_Q(1))); break; case 0x3d6: /* movdq2q */ + CHECK_NO_VEX(s); gen_helper_enter_mmx(cpu_env); rm = (modrm & 7) | REX_B(s); gen_op_movq(s, offsetof(CPUX86State, fpregs[reg & 7].mmx), @@ -3831,6 +3849,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(s->ptr0, cpu_env, ZMM_OFFSET(rm)); gen_helper_pmovmskb_xmm(s->tmp2_i32, cpu_env, s->ptr0); } else { + CHECK_NO_VEX(s); rm = (modrm & 7); tcg_gen_addi_ptr(s->ptr0, cpu_env, offsetof(CPUX86State, fpregs[rm].mmx)); @@ -3901,6 +3920,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); op6->fn[b1].op1(cpu_env, s->ptr0, s->ptr1); } else { + CHECK_NO_VEX(s); if ((op6->flags & SSE_OPF_MMX) == 0) { goto unknown_op; } @@ -3934,6 +3954,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x3f0: /* crc32 Gd,Eb */ case 0x3f1: /* crc32 Gd,Ey */ do_crc32: + CHECK_NO_VEX(s); if (!(s->cpuid_ext_features & CPUID_EXT_SSE42)) { goto illegal_op; } @@ -3956,6 +3977,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x1f0: /* crc32 or movbe */ case 0x1f1: + CHECK_NO_VEX(s); /* For these insns, the f3 prefix is supposed to have priority over the 66 prefix, but that's not what we implement above setting b1. */ @@ -3965,6 +3987,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, /* FALLTHRU */ case 0x0f0: /* movbe Gy,My */ case 0x0f1: /* movbe My,Gy */ + CHECK_NO_VEX(s); if (!(s->cpuid_ext_features & CPUID_EXT_MOVBE)) { goto illegal_op; } @@ -4131,6 +4154,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x1f6: /* adcx Gy, Ey */ case 0x2f6: /* adox Gy, Ey */ + CHECK_NO_VEX(s); if (!(s->cpuid_7_0_ebx_features & CPUID_7_0_EBX_ADX)) { goto illegal_op; } else { @@ -4436,6 +4460,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } if (b1 == 0) { + CHECK_NO_VEX(s); /* MMX */ if ((op7->flags & SSE_OPF_MMX) == 0) { goto illegal_op; @@ -4582,6 +4607,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, op2_offset = ZMM_OFFSET(rm); } } else { + CHECK_NO_VEX(s); op1_offset = offsetof(CPUX86State,fpregs[reg].mmx); if (mod != 3) { gen_lea_modrm(env, s, modrm); From 25bdec79c629b49fbcf134f9eca063aaba6d4094 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 1 Sep 2022 08:19:35 +0200 Subject: [PATCH 0292/1020] target/i386: rewrite destructive 3DNow operations Remove use of the MOVE macro, since it will be purged from MMX/SSE as well. Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index f603981ab8..2c0090a647 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -1327,11 +1327,11 @@ void helper_pf2iw(CPUX86State *env, MMXReg *d, MMXReg *s) void helper_pfacc(CPUX86State *env, MMXReg *d, MMXReg *s) { - MMXReg r; + float32 r; - r.MMX_S(0) = float32_add(d->MMX_S(0), d->MMX_S(1), &env->mmx_status); - r.MMX_S(1) = float32_add(s->MMX_S(0), s->MMX_S(1), &env->mmx_status); - MOVE(*d, r); + r = float32_add(d->MMX_S(0), d->MMX_S(1), &env->mmx_status); + d->MMX_S(1) = float32_add(s->MMX_S(0), s->MMX_S(1), &env->mmx_status); + d->MMX_S(0) = r; } void helper_pfadd(CPUX86State *env, MMXReg *d, MMXReg *s) @@ -1392,20 +1392,20 @@ void helper_pfmul(CPUX86State *env, MMXReg *d, MMXReg *s) void helper_pfnacc(CPUX86State *env, MMXReg *d, MMXReg *s) { - MMXReg r; + float32 r; - r.MMX_S(0) = float32_sub(d->MMX_S(0), d->MMX_S(1), &env->mmx_status); - r.MMX_S(1) = float32_sub(s->MMX_S(0), s->MMX_S(1), &env->mmx_status); - MOVE(*d, r); + r = float32_sub(d->MMX_S(0), d->MMX_S(1), &env->mmx_status); + d->MMX_S(1) = float32_sub(s->MMX_S(0), s->MMX_S(1), &env->mmx_status); + d->MMX_S(0) = r; } void helper_pfpnacc(CPUX86State *env, MMXReg *d, MMXReg *s) { - MMXReg r; + float32 r; - r.MMX_S(0) = float32_sub(d->MMX_S(0), d->MMX_S(1), &env->mmx_status); - r.MMX_S(1) = float32_add(s->MMX_S(0), s->MMX_S(1), &env->mmx_status); - MOVE(*d, r); + r = float32_sub(d->MMX_S(0), d->MMX_S(1), &env->mmx_status); + d->MMX_S(1) = float32_add(s->MMX_S(0), s->MMX_S(1), &env->mmx_status); + d->MMX_S(0) = r; } void helper_pfrcp(CPUX86State *env, MMXReg *d, MMXReg *s) @@ -1438,11 +1438,11 @@ void helper_pfsubr(CPUX86State *env, MMXReg *d, MMXReg *s) void helper_pswapd(CPUX86State *env, MMXReg *d, MMXReg *s) { - MMXReg r; + uint32_t r; - r.MMX_L(0) = s->MMX_L(1); - r.MMX_L(1) = s->MMX_L(0); - MOVE(*d, r); + r = s->MMX_L(0); + d->MMX_L(0) = s->MMX_L(1); + d->MMX_L(1) = r; } #endif From 18592d2ec2dddff3b08568d29aa82d96e0369b88 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:32 +0100 Subject: [PATCH 0293/1020] target/i386: Rewrite vector shift helper Rewrite the vector shift helpers in preperation for AVX support (3 operand form and 256 bit vectors). For now keep the existing two operand interface. No functional changes to existing helpers. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-11-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 247 +++++++++++++++++++----------------------- 1 file changed, 112 insertions(+), 135 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 2c0090a647..a4a09226e3 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -40,6 +40,8 @@ #define SUFFIX _xmm #endif +#define LANE_WIDTH (SHIFT ? 16 : 8) + /* * Copy the relevant parts of a Reg value around. In the case where * sizeof(Reg) > SIZE, these helpers operate only on the lower bytes of @@ -56,198 +58,173 @@ #define MOVE(d, r) memcpy(&(d).B(0), &(r).B(0), SIZE) #endif -void glue(helper_psrlw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - int shift; +#if SHIFT == 0 +#define FPSRL(x, c) ((x) >> shift) +#define FPSRAW(x, c) ((int16_t)(x) >> shift) +#define FPSRAL(x, c) ((int32_t)(x) >> shift) +#define FPSLL(x, c) ((x) << shift) +#endif - if (s->Q(0) > 15) { - d->Q(0) = 0; -#if SHIFT == 1 - d->Q(1) = 0; -#endif +void glue(helper_psrlw, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) +{ + Reg *s = d; + int shift; + if (c->Q(0) > 15) { + for (int i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } } else { - shift = s->B(0); - d->W(0) >>= shift; - d->W(1) >>= shift; - d->W(2) >>= shift; - d->W(3) >>= shift; -#if SHIFT == 1 - d->W(4) >>= shift; - d->W(5) >>= shift; - d->W(6) >>= shift; - d->W(7) >>= shift; -#endif + shift = c->B(0); + for (int i = 0; i < 4 << SHIFT; i++) { + d->W(i) = FPSRL(s->W(i), shift); + } } } -void glue(helper_psraw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_psllw, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) { + Reg *s = d; int shift; + if (c->Q(0) > 15) { + for (int i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } + } else { + shift = c->B(0); + for (int i = 0; i < 4 << SHIFT; i++) { + d->W(i) = FPSLL(s->W(i), shift); + } + } +} - if (s->Q(0) > 15) { +void glue(helper_psraw, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) +{ + Reg *s = d; + int shift; + if (c->Q(0) > 15) { shift = 15; } else { - shift = s->B(0); + shift = c->B(0); + } + for (int i = 0; i < 4 << SHIFT; i++) { + d->W(i) = FPSRAW(s->W(i), shift); } - d->W(0) = (int16_t)d->W(0) >> shift; - d->W(1) = (int16_t)d->W(1) >> shift; - d->W(2) = (int16_t)d->W(2) >> shift; - d->W(3) = (int16_t)d->W(3) >> shift; -#if SHIFT == 1 - d->W(4) = (int16_t)d->W(4) >> shift; - d->W(5) = (int16_t)d->W(5) >> shift; - d->W(6) = (int16_t)d->W(6) >> shift; - d->W(7) = (int16_t)d->W(7) >> shift; -#endif } -void glue(helper_psllw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_psrld, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) { + Reg *s = d; int shift; - - if (s->Q(0) > 15) { - d->Q(0) = 0; -#if SHIFT == 1 - d->Q(1) = 0; -#endif + if (c->Q(0) > 31) { + for (int i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } } else { - shift = s->B(0); - d->W(0) <<= shift; - d->W(1) <<= shift; - d->W(2) <<= shift; - d->W(3) <<= shift; -#if SHIFT == 1 - d->W(4) <<= shift; - d->W(5) <<= shift; - d->W(6) <<= shift; - d->W(7) <<= shift; -#endif + shift = c->B(0); + for (int i = 0; i < 2 << SHIFT; i++) { + d->L(i) = FPSRL(s->L(i), shift); + } } } -void glue(helper_psrld, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_pslld, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) { + Reg *s = d; int shift; - - if (s->Q(0) > 31) { - d->Q(0) = 0; -#if SHIFT == 1 - d->Q(1) = 0; -#endif + if (c->Q(0) > 31) { + for (int i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } } else { - shift = s->B(0); - d->L(0) >>= shift; - d->L(1) >>= shift; -#if SHIFT == 1 - d->L(2) >>= shift; - d->L(3) >>= shift; -#endif + shift = c->B(0); + for (int i = 0; i < 2 << SHIFT; i++) { + d->L(i) = FPSLL(s->L(i), shift); + } } } -void glue(helper_psrad, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_psrad, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) { + Reg *s = d; int shift; - - if (s->Q(0) > 31) { + if (c->Q(0) > 31) { shift = 31; } else { - shift = s->B(0); + shift = c->B(0); + } + for (int i = 0; i < 2 << SHIFT; i++) { + d->L(i) = FPSRAL(s->L(i), shift); } - d->L(0) = (int32_t)d->L(0) >> shift; - d->L(1) = (int32_t)d->L(1) >> shift; -#if SHIFT == 1 - d->L(2) = (int32_t)d->L(2) >> shift; - d->L(3) = (int32_t)d->L(3) >> shift; -#endif } -void glue(helper_pslld, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_psrlq, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) { + Reg *s = d; int shift; - - if (s->Q(0) > 31) { - d->Q(0) = 0; -#if SHIFT == 1 - d->Q(1) = 0; -#endif + if (c->Q(0) > 63) { + for (int i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } } else { - shift = s->B(0); - d->L(0) <<= shift; - d->L(1) <<= shift; -#if SHIFT == 1 - d->L(2) <<= shift; - d->L(3) <<= shift; -#endif + shift = c->B(0); + for (int i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = FPSRL(s->Q(i), shift); + } } } -void glue(helper_psrlq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_psllq, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) { + Reg *s = d; int shift; - - if (s->Q(0) > 63) { - d->Q(0) = 0; -#if SHIFT == 1 - d->Q(1) = 0; -#endif + if (c->Q(0) > 63) { + for (int i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } } else { - shift = s->B(0); - d->Q(0) >>= shift; -#if SHIFT == 1 - d->Q(1) >>= shift; -#endif + shift = c->B(0); + for (int i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = FPSLL(s->Q(i), shift); + } } } -void glue(helper_psllq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +#if SHIFT >= 1 +void glue(helper_psrldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) { - int shift; + Reg *s = d; + int shift, i, j; - if (s->Q(0) > 63) { - d->Q(0) = 0; -#if SHIFT == 1 - d->Q(1) = 0; -#endif - } else { - shift = s->B(0); - d->Q(0) <<= shift; -#if SHIFT == 1 - d->Q(1) <<= shift; -#endif - } -} - -#if SHIFT == 1 -void glue(helper_psrldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - int shift, i; - - shift = s->L(0); + shift = c->L(0); if (shift > 16) { shift = 16; } - for (i = 0; i < 16 - shift; i++) { - d->B(i) = d->B(i + shift); - } - for (i = 16 - shift; i < 16; i++) { - d->B(i) = 0; + for (j = 0; j < 8 << SHIFT; j += LANE_WIDTH) { + for (i = 0; i < 16 - shift; i++) { + d->B(j + i) = s->B(j + i + shift); + } + for (i = 16 - shift; i < 16; i++) { + d->B(j + i) = 0; + } } } -void glue(helper_pslldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +void glue(helper_pslldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) { - int shift, i; + Reg *s = d; + int shift, i, j; - shift = s->L(0); + shift = c->L(0); if (shift > 16) { shift = 16; } - for (i = 15; i >= shift; i--) { - d->B(i) = d->B(i - shift); - } - for (i = 0; i < shift; i++) { - d->B(i) = 0; + for (j = 0; j < 8 << SHIFT; j += LANE_WIDTH) { + for (i = 15; i >= shift; i--) { + d->B(j + i) = s->B(j + i - shift); + } + for (i = 0; i < shift; i++) { + d->B(j + i) = 0; + } } } #endif From ee04a3c86dc125bbbdb04abaf4188dbafe612891 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:33 +0100 Subject: [PATCH 0294/1020] target/i386: Rewrite simple integer vector helpers Rewrite the "simple" vector integer helpers in preperation for AVX support. While the current code is able to use the same prototype for unary (a = F(b)) and binary (a = F(b, c)) operations, future changes will cause them to diverge. No functional changes to existing helpers Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-12-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 83 +++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 55 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index a4a09226e3..ce03362810 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -229,63 +229,36 @@ void glue(helper_pslldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *c) } #endif -#define SSE_HELPER_B(name, F) \ +#define SSE_HELPER_1(name, elem, num, F) \ void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ { \ - d->B(0) = F(d->B(0), s->B(0)); \ - d->B(1) = F(d->B(1), s->B(1)); \ - d->B(2) = F(d->B(2), s->B(2)); \ - d->B(3) = F(d->B(3), s->B(3)); \ - d->B(4) = F(d->B(4), s->B(4)); \ - d->B(5) = F(d->B(5), s->B(5)); \ - d->B(6) = F(d->B(6), s->B(6)); \ - d->B(7) = F(d->B(7), s->B(7)); \ - XMM_ONLY( \ - d->B(8) = F(d->B(8), s->B(8)); \ - d->B(9) = F(d->B(9), s->B(9)); \ - d->B(10) = F(d->B(10), s->B(10)); \ - d->B(11) = F(d->B(11), s->B(11)); \ - d->B(12) = F(d->B(12), s->B(12)); \ - d->B(13) = F(d->B(13), s->B(13)); \ - d->B(14) = F(d->B(14), s->B(14)); \ - d->B(15) = F(d->B(15), s->B(15)); \ - ) \ - } + int n = num; \ + for (int i = 0; i < n; i++) { \ + d->elem(i) = F(s->elem(i)); \ + } \ + } + +#define SSE_HELPER_2(name, elem, num, F) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ + { \ + Reg *v = d; \ + int n = num; \ + for (int i = 0; i < n; i++) { \ + d->elem(i) = F(v->elem(i), s->elem(i)); \ + } \ + } + +#define SSE_HELPER_B(name, F) \ + SSE_HELPER_2(name, B, 8 << SHIFT, F) #define SSE_HELPER_W(name, F) \ - void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ - { \ - d->W(0) = F(d->W(0), s->W(0)); \ - d->W(1) = F(d->W(1), s->W(1)); \ - d->W(2) = F(d->W(2), s->W(2)); \ - d->W(3) = F(d->W(3), s->W(3)); \ - XMM_ONLY( \ - d->W(4) = F(d->W(4), s->W(4)); \ - d->W(5) = F(d->W(5), s->W(5)); \ - d->W(6) = F(d->W(6), s->W(6)); \ - d->W(7) = F(d->W(7), s->W(7)); \ - ) \ - } + SSE_HELPER_2(name, W, 4 << SHIFT, F) #define SSE_HELPER_L(name, F) \ - void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ - { \ - d->L(0) = F(d->L(0), s->L(0)); \ - d->L(1) = F(d->L(1), s->L(1)); \ - XMM_ONLY( \ - d->L(2) = F(d->L(2), s->L(2)); \ - d->L(3) = F(d->L(3), s->L(3)); \ - ) \ - } + SSE_HELPER_2(name, L, 2 << SHIFT, F) #define SSE_HELPER_Q(name, F) \ - void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ - { \ - d->Q(0) = F(d->Q(0), s->Q(0)); \ - XMM_ONLY( \ - d->Q(1) = F(d->Q(1), s->Q(1)); \ - ) \ - } + SSE_HELPER_2(name, Q, 1 << SHIFT, F) #if SHIFT == 0 static inline int satub(int x) @@ -1544,12 +1517,12 @@ void glue(helper_phsubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) MOVE(*d, r); } -#define FABSB(_, x) (x > INT8_MAX ? -(int8_t)x : x) -#define FABSW(_, x) (x > INT16_MAX ? -(int16_t)x : x) -#define FABSL(_, x) (x > INT32_MAX ? -(int32_t)x : x) -SSE_HELPER_B(helper_pabsb, FABSB) -SSE_HELPER_W(helper_pabsw, FABSW) -SSE_HELPER_L(helper_pabsd, FABSL) +#define FABSB(x) (x > INT8_MAX ? -(int8_t)x : x) +#define FABSW(x) (x > INT16_MAX ? -(int16_t)x : x) +#define FABSL(x) (x > INT32_MAX ? -(int32_t)x : x) +SSE_HELPER_1(helper_pabsb, B, 8 << SHIFT, FABSB) +SSE_HELPER_1(helper_pabsw, W, 4 << SHIFT, FABSW) +SSE_HELPER_1(helper_pabsd, L, 2 << SHIFT, FABSL) #define FMULHRSW(d, s) (((int16_t) d * (int16_t)s + 0x4000) >> 15) SSE_HELPER_W(helper_pmulhrsw, FMULHRSW) From e894bae8cbfdf08c0f006234badf297857aed3cd Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:34 +0100 Subject: [PATCH 0295/1020] target/i386: Misc integer AVX helper prep More preparatory work for AVX support in various integer vector helpers No functional changes to existing helpers. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-13-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 164 +++++++++++++++++++++--------------------- 1 file changed, 80 insertions(+), 84 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index ce03362810..557cc7ce7d 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -390,19 +390,22 @@ SSE_HELPER_W(helper_pavgw, FAVG) void glue(helper_pmuludq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->Q(0) = (uint64_t)s->L(0) * (uint64_t)d->L(0); -#if SHIFT == 1 - d->Q(1) = (uint64_t)s->L(2) * (uint64_t)d->L(2); -#endif + Reg *v = d; + int i; + + for (i = 0; i < (1 << SHIFT); i++) { + d->Q(i) = (uint64_t)s->L(i * 2) * (uint64_t)v->L(i * 2); + } } void glue(helper_pmaddwd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { + Reg *v = d; int i; for (i = 0; i < (2 << SHIFT); i++) { - d->L(i) = (int16_t)s->W(2 * i) * (int16_t)d->W(2 * i) + - (int16_t)s->W(2 * i + 1) * (int16_t)d->W(2 * i + 1); + d->L(i) = (int16_t)s->W(2 * i) * (int16_t)v->W(2 * i) + + (int16_t)s->W(2 * i + 1) * (int16_t)v->W(2 * i + 1); } } @@ -416,32 +419,24 @@ static inline int abs1(int a) } } #endif + void glue(helper_psadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - unsigned int val; + Reg *v = d; + int i; - val = 0; - val += abs1(d->B(0) - s->B(0)); - val += abs1(d->B(1) - s->B(1)); - val += abs1(d->B(2) - s->B(2)); - val += abs1(d->B(3) - s->B(3)); - val += abs1(d->B(4) - s->B(4)); - val += abs1(d->B(5) - s->B(5)); - val += abs1(d->B(6) - s->B(6)); - val += abs1(d->B(7) - s->B(7)); - d->Q(0) = val; -#if SHIFT == 1 - val = 0; - val += abs1(d->B(8) - s->B(8)); - val += abs1(d->B(9) - s->B(9)); - val += abs1(d->B(10) - s->B(10)); - val += abs1(d->B(11) - s->B(11)); - val += abs1(d->B(12) - s->B(12)); - val += abs1(d->B(13) - s->B(13)); - val += abs1(d->B(14) - s->B(14)); - val += abs1(d->B(15) - s->B(15)); - d->Q(1) = val; -#endif + for (i = 0; i < (1 << SHIFT); i++) { + unsigned int val = 0; + val += abs1(v->B(8 * i + 0) - s->B(8 * i + 0)); + val += abs1(v->B(8 * i + 1) - s->B(8 * i + 1)); + val += abs1(v->B(8 * i + 2) - s->B(8 * i + 2)); + val += abs1(v->B(8 * i + 3) - s->B(8 * i + 3)); + val += abs1(v->B(8 * i + 4) - s->B(8 * i + 4)); + val += abs1(v->B(8 * i + 5) - s->B(8 * i + 5)); + val += abs1(v->B(8 * i + 6) - s->B(8 * i + 6)); + val += abs1(v->B(8 * i + 7) - s->B(8 * i + 7)); + d->Q(i) = val; + } } void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, @@ -458,20 +453,24 @@ void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, void glue(helper_movl_mm_T0, SUFFIX)(Reg *d, uint32_t val) { + int i; + d->L(0) = val; d->L(1) = 0; -#if SHIFT == 1 - d->Q(1) = 0; -#endif + for (i = 1; i < (1 << SHIFT); i++) { + d->Q(i) = 0; + } } #ifdef TARGET_X86_64 void glue(helper_movq_mm_T0, SUFFIX)(Reg *d, uint64_t val) { + int i; + d->Q(0) = val; -#if SHIFT == 1 - d->Q(1) = 0; -#endif + for (i = 1; i < (1 << SHIFT); i++) { + d->Q(i) = 0; + } } #endif @@ -1074,26 +1073,21 @@ uint32_t glue(helper_movmskpd, SUFFIX)(CPUX86State *env, Reg *s) uint32_t glue(helper_pmovmskb, SUFFIX)(CPUX86State *env, Reg *s) { uint32_t val; + int i; val = 0; - val |= (s->B(0) >> 7); - val |= (s->B(1) >> 6) & 0x02; - val |= (s->B(2) >> 5) & 0x04; - val |= (s->B(3) >> 4) & 0x08; - val |= (s->B(4) >> 3) & 0x10; - val |= (s->B(5) >> 2) & 0x20; - val |= (s->B(6) >> 1) & 0x40; - val |= (s->B(7)) & 0x80; -#if SHIFT == 1 - val |= (s->B(8) << 1) & 0x0100; - val |= (s->B(9) << 2) & 0x0200; - val |= (s->B(10) << 3) & 0x0400; - val |= (s->B(11) << 4) & 0x0800; - val |= (s->B(12) << 5) & 0x1000; - val |= (s->B(13) << 6) & 0x2000; - val |= (s->B(14) << 7) & 0x4000; - val |= (s->B(15) << 8) & 0x8000; -#endif + for (i = 0; i < (1 << SHIFT); i++) { + uint8_t byte = 0; + byte |= (s->B(8 * i + 0) >> 7); + byte |= (s->B(8 * i + 1) >> 6) & 0x02; + byte |= (s->B(8 * i + 2) >> 5) & 0x04; + byte |= (s->B(8 * i + 3) >> 4) & 0x08; + byte |= (s->B(8 * i + 4) >> 3) & 0x10; + byte |= (s->B(8 * i + 5) >> 2) & 0x20; + byte |= (s->B(8 * i + 6) >> 1) & 0x40; + byte |= (s->B(8 * i + 7)) & 0x80; + val |= byte << (8 * i); + } return val; } @@ -1638,46 +1632,48 @@ SSE_HELPER_V(helper_blendvpd, Q, 2, FBLENDVPD) void glue(helper_ptest, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - uint64_t zf = (s->Q(0) & d->Q(0)) | (s->Q(1) & d->Q(1)); - uint64_t cf = (s->Q(0) & ~d->Q(0)) | (s->Q(1) & ~d->Q(1)); + uint64_t zf = 0, cf = 0; + int i; + for (i = 0; i < 1 << SHIFT; i++) { + zf |= (s->Q(i) & d->Q(i)); + cf |= (s->Q(i) & ~d->Q(i)); + } CC_SRC = (zf ? 0 : CC_Z) | (cf ? 0 : CC_C); } -#define SSE_HELPER_F(name, elem, num, F) \ - void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ - { \ - if (num > 2) { \ - if (num > 4) { \ - d->elem(7) = F(7); \ - d->elem(6) = F(6); \ - d->elem(5) = F(5); \ - d->elem(4) = F(4); \ - } \ - d->elem(3) = F(3); \ - d->elem(2) = F(2); \ - } \ - d->elem(1) = F(1); \ - d->elem(0) = F(0); \ +#define SSE_HELPER_F(name, elem, num, F) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ + { \ + int n = num; \ + for (int i = n; --i >= 0; ) { \ + d->elem(i) = F(i); \ + } \ } -SSE_HELPER_F(helper_pmovsxbw, W, 8, (int8_t) s->B) -SSE_HELPER_F(helper_pmovsxbd, L, 4, (int8_t) s->B) -SSE_HELPER_F(helper_pmovsxbq, Q, 2, (int8_t) s->B) -SSE_HELPER_F(helper_pmovsxwd, L, 4, (int16_t) s->W) -SSE_HELPER_F(helper_pmovsxwq, Q, 2, (int16_t) s->W) -SSE_HELPER_F(helper_pmovsxdq, Q, 2, (int32_t) s->L) -SSE_HELPER_F(helper_pmovzxbw, W, 8, s->B) -SSE_HELPER_F(helper_pmovzxbd, L, 4, s->B) -SSE_HELPER_F(helper_pmovzxbq, Q, 2, s->B) -SSE_HELPER_F(helper_pmovzxwd, L, 4, s->W) -SSE_HELPER_F(helper_pmovzxwq, Q, 2, s->W) -SSE_HELPER_F(helper_pmovzxdq, Q, 2, s->L) +#if SHIFT > 0 +SSE_HELPER_F(helper_pmovsxbw, W, 4 << SHIFT, (int8_t) s->B) +SSE_HELPER_F(helper_pmovsxbd, L, 2 << SHIFT, (int8_t) s->B) +SSE_HELPER_F(helper_pmovsxbq, Q, 1 << SHIFT, (int8_t) s->B) +SSE_HELPER_F(helper_pmovsxwd, L, 2 << SHIFT, (int16_t) s->W) +SSE_HELPER_F(helper_pmovsxwq, Q, 1 << SHIFT, (int16_t) s->W) +SSE_HELPER_F(helper_pmovsxdq, Q, 1 << SHIFT, (int32_t) s->L) +SSE_HELPER_F(helper_pmovzxbw, W, 4 << SHIFT, s->B) +SSE_HELPER_F(helper_pmovzxbd, L, 2 << SHIFT, s->B) +SSE_HELPER_F(helper_pmovzxbq, Q, 1 << SHIFT, s->B) +SSE_HELPER_F(helper_pmovzxwd, L, 2 << SHIFT, s->W) +SSE_HELPER_F(helper_pmovzxwq, Q, 1 << SHIFT, s->W) +SSE_HELPER_F(helper_pmovzxdq, Q, 1 << SHIFT, s->L) +#endif void glue(helper_pmuldq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->Q(0) = (int64_t)(int32_t) d->L(0) * (int32_t) s->L(0); - d->Q(1) = (int64_t)(int32_t) d->L(2) * (int32_t) s->L(2); + Reg *v = d; + int i; + + for (i = 0; i < 1 << SHIFT; i++) { + d->Q(i) = (int64_t)(int32_t) v->L(2 * i) * (int32_t) s->L(2 * i); + } } #define FCMPEQQ(d, s) (d == s ? -1 : 0) From d45b0de63d545aad2a2d91fde7b816ee3641d8d4 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:35 +0100 Subject: [PATCH 0296/1020] target/i386: Destructive vector helpers for AVX These helpers need to take special care to avoid overwriting source values before the wole result has been calculated. Currently they use a dummy Reg typed variable to store the result then assign the whole register. This will cause 128 bit operations to corrupt the upper half of the register, so replace it with explicit temporaries and element assignments. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-14-paul@nowt.org> Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 556 ++++++++++++++++++++---------------------- 1 file changed, 262 insertions(+), 294 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 557cc7ce7d..bb50ca6f8d 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -41,6 +41,7 @@ #endif #define LANE_WIDTH (SHIFT ? 16 : 8) +#define PACK_WIDTH (LANE_WIDTH / 2) /* * Copy the relevant parts of a Reg value around. In the case where @@ -474,71 +475,81 @@ void glue(helper_movq_mm_T0, SUFFIX)(Reg *d, uint64_t val) } #endif +#define SHUFFLE4(F, a, b, offset) do { \ + r0 = a->F((order & 3) + offset); \ + r1 = a->F(((order >> 2) & 3) + offset); \ + r2 = b->F(((order >> 4) & 3) + offset); \ + r3 = b->F(((order >> 6) & 3) + offset); \ + d->F(offset) = r0; \ + d->F(offset + 1) = r1; \ + d->F(offset + 2) = r2; \ + d->F(offset + 3) = r3; \ + } while (0) + #if SHIFT == 0 void glue(helper_pshufw, SUFFIX)(Reg *d, Reg *s, int order) { - Reg r; + uint16_t r0, r1, r2, r3; - r.W(0) = s->W(order & 3); - r.W(1) = s->W((order >> 2) & 3); - r.W(2) = s->W((order >> 4) & 3); - r.W(3) = s->W((order >> 6) & 3); - MOVE(*d, r); + SHUFFLE4(W, s, s, 0); } #else void glue(helper_shufps, SUFFIX)(Reg *d, Reg *s, int order) { - Reg r; + Reg *v = d; + uint32_t r0, r1, r2, r3; + int i; - r.L(0) = d->L(order & 3); - r.L(1) = d->L((order >> 2) & 3); - r.L(2) = s->L((order >> 4) & 3); - r.L(3) = s->L((order >> 6) & 3); - MOVE(*d, r); + for (i = 0; i < 2 << SHIFT; i += 4) { + SHUFFLE4(L, v, s, i); + } } void glue(helper_shufpd, SUFFIX)(Reg *d, Reg *s, int order) { - Reg r; + Reg *v = d; + uint64_t r0, r1; + int i; - r.Q(0) = d->Q(order & 1); - r.Q(1) = s->Q((order >> 1) & 1); - MOVE(*d, r); + for (i = 0; i < 1 << SHIFT; i += 2) { + r0 = v->Q(((order & 1) & 1) + i); + r1 = s->Q(((order >> 1) & 1) + i); + d->Q(i) = r0; + d->Q(i + 1) = r1; + order >>= 2; + } } void glue(helper_pshufd, SUFFIX)(Reg *d, Reg *s, int order) { - Reg r; + uint32_t r0, r1, r2, r3; + int i; - r.L(0) = s->L(order & 3); - r.L(1) = s->L((order >> 2) & 3); - r.L(2) = s->L((order >> 4) & 3); - r.L(3) = s->L((order >> 6) & 3); - MOVE(*d, r); + for (i = 0; i < 2 << SHIFT; i += 4) { + SHUFFLE4(L, s, s, i); + } } void glue(helper_pshuflw, SUFFIX)(Reg *d, Reg *s, int order) { - Reg r; + uint16_t r0, r1, r2, r3; + int i, j; - r.W(0) = s->W(order & 3); - r.W(1) = s->W((order >> 2) & 3); - r.W(2) = s->W((order >> 4) & 3); - r.W(3) = s->W((order >> 6) & 3); - r.Q(1) = s->Q(1); - MOVE(*d, r); + for (i = 0, j = 1; j < 1 << SHIFT; i += 8, j += 2) { + SHUFFLE4(W, s, s, i); + d->Q(j) = s->Q(j); + } } void glue(helper_pshufhw, SUFFIX)(Reg *d, Reg *s, int order) { - Reg r; + uint16_t r0, r1, r2, r3; + int i, j; - r.Q(0) = s->Q(0); - r.W(4) = s->W(4 + (order & 3)); - r.W(5) = s->W(4 + ((order >> 2) & 3)); - r.W(6) = s->W(4 + ((order >> 4) & 3)); - r.W(7) = s->W(4 + ((order >> 6) & 3)); - MOVE(*d, r); + for (i = 4, j = 0; j < 1 << SHIFT; i += 8, j += 2) { + d->Q(j) = s->Q(j); + SHUFFLE4(W, s, s, i); + } } #endif @@ -1091,156 +1102,132 @@ uint32_t glue(helper_pmovmskb, SUFFIX)(CPUX86State *env, Reg *s) return val; } -void glue(helper_packsswb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - Reg r; - - r.B(0) = satsb((int16_t)d->W(0)); - r.B(1) = satsb((int16_t)d->W(1)); - r.B(2) = satsb((int16_t)d->W(2)); - r.B(3) = satsb((int16_t)d->W(3)); -#if SHIFT == 1 - r.B(4) = satsb((int16_t)d->W(4)); - r.B(5) = satsb((int16_t)d->W(5)); - r.B(6) = satsb((int16_t)d->W(6)); - r.B(7) = satsb((int16_t)d->W(7)); -#endif - r.B((4 << SHIFT) + 0) = satsb((int16_t)s->W(0)); - r.B((4 << SHIFT) + 1) = satsb((int16_t)s->W(1)); - r.B((4 << SHIFT) + 2) = satsb((int16_t)s->W(2)); - r.B((4 << SHIFT) + 3) = satsb((int16_t)s->W(3)); -#if SHIFT == 1 - r.B(12) = satsb((int16_t)s->W(4)); - r.B(13) = satsb((int16_t)s->W(5)); - r.B(14) = satsb((int16_t)s->W(6)); - r.B(15) = satsb((int16_t)s->W(7)); -#endif - MOVE(*d, r); +#define PACK_HELPER_B(name, F) \ +void glue(helper_pack ## name, SUFFIX)(CPUX86State *env, \ + Reg *d, Reg *s) \ +{ \ + Reg *v = d; \ + uint8_t r[PACK_WIDTH * 2]; \ + int j, k; \ + for (j = 0; j < 4 << SHIFT; j += PACK_WIDTH) { \ + for (k = 0; k < PACK_WIDTH; k++) { \ + r[k] = F((int16_t)v->W(j + k)); \ + } \ + for (k = 0; k < PACK_WIDTH; k++) { \ + r[PACK_WIDTH + k] = F((int16_t)s->W(j + k)); \ + } \ + for (k = 0; k < PACK_WIDTH * 2; k++) { \ + d->B(2 * j + k) = r[k]; \ + } \ + } \ } -void glue(helper_packuswb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - Reg r; - - r.B(0) = satub((int16_t)d->W(0)); - r.B(1) = satub((int16_t)d->W(1)); - r.B(2) = satub((int16_t)d->W(2)); - r.B(3) = satub((int16_t)d->W(3)); -#if SHIFT == 1 - r.B(4) = satub((int16_t)d->W(4)); - r.B(5) = satub((int16_t)d->W(5)); - r.B(6) = satub((int16_t)d->W(6)); - r.B(7) = satub((int16_t)d->W(7)); -#endif - r.B((4 << SHIFT) + 0) = satub((int16_t)s->W(0)); - r.B((4 << SHIFT) + 1) = satub((int16_t)s->W(1)); - r.B((4 << SHIFT) + 2) = satub((int16_t)s->W(2)); - r.B((4 << SHIFT) + 3) = satub((int16_t)s->W(3)); -#if SHIFT == 1 - r.B(12) = satub((int16_t)s->W(4)); - r.B(13) = satub((int16_t)s->W(5)); - r.B(14) = satub((int16_t)s->W(6)); - r.B(15) = satub((int16_t)s->W(7)); -#endif - MOVE(*d, r); -} +PACK_HELPER_B(sswb, satsb) +PACK_HELPER_B(uswb, satub) void glue(helper_packssdw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - Reg r; + Reg *v = d; + uint16_t r[PACK_WIDTH]; + int j, k; - r.W(0) = satsw(d->L(0)); - r.W(1) = satsw(d->L(1)); -#if SHIFT == 1 - r.W(2) = satsw(d->L(2)); - r.W(3) = satsw(d->L(3)); -#endif - r.W((2 << SHIFT) + 0) = satsw(s->L(0)); - r.W((2 << SHIFT) + 1) = satsw(s->L(1)); -#if SHIFT == 1 - r.W(6) = satsw(s->L(2)); - r.W(7) = satsw(s->L(3)); -#endif - MOVE(*d, r); + for (j = 0; j < 2 << SHIFT; j += PACK_WIDTH / 2) { + for (k = 0; k < PACK_WIDTH / 2; k++) { + r[k] = satsw(v->L(j + k)); + } + for (k = 0; k < PACK_WIDTH / 2; k++) { + r[PACK_WIDTH / 2 + k] = satsw(s->L(j + k)); + } + for (k = 0; k < PACK_WIDTH; k++) { + d->W(2 * j + k) = r[k]; + } + } } #define UNPCK_OP(base_name, base) \ \ void glue(helper_punpck ## base_name ## bw, SUFFIX)(CPUX86State *env,\ - Reg *d, Reg *s) \ + Reg *d, Reg *s) \ { \ - Reg r; \ + Reg *v = d; \ + uint8_t r[PACK_WIDTH * 2]; \ + int j, i; \ \ - r.B(0) = d->B((base << (SHIFT + 2)) + 0); \ - r.B(1) = s->B((base << (SHIFT + 2)) + 0); \ - r.B(2) = d->B((base << (SHIFT + 2)) + 1); \ - r.B(3) = s->B((base << (SHIFT + 2)) + 1); \ - r.B(4) = d->B((base << (SHIFT + 2)) + 2); \ - r.B(5) = s->B((base << (SHIFT + 2)) + 2); \ - r.B(6) = d->B((base << (SHIFT + 2)) + 3); \ - r.B(7) = s->B((base << (SHIFT + 2)) + 3); \ - XMM_ONLY( \ - r.B(8) = d->B((base << (SHIFT + 2)) + 4); \ - r.B(9) = s->B((base << (SHIFT + 2)) + 4); \ - r.B(10) = d->B((base << (SHIFT + 2)) + 5); \ - r.B(11) = s->B((base << (SHIFT + 2)) + 5); \ - r.B(12) = d->B((base << (SHIFT + 2)) + 6); \ - r.B(13) = s->B((base << (SHIFT + 2)) + 6); \ - r.B(14) = d->B((base << (SHIFT + 2)) + 7); \ - r.B(15) = s->B((base << (SHIFT + 2)) + 7); \ - ) \ - MOVE(*d, r); \ + for (j = 0; j < 8 << SHIFT; ) { \ + int k = j + base * PACK_WIDTH; \ + for (i = 0; i < PACK_WIDTH; i++) { \ + r[2 * i] = v->B(k + i); \ + r[2 * i + 1] = s->B(k + i); \ + } \ + for (i = 0; i < PACK_WIDTH * 2; i++, j++) { \ + d->B(j) = r[i]; \ + } \ + } \ } \ \ void glue(helper_punpck ## base_name ## wd, SUFFIX)(CPUX86State *env,\ - Reg *d, Reg *s) \ + Reg *d, Reg *s) \ { \ - Reg r; \ + Reg *v = d; \ + uint16_t r[PACK_WIDTH]; \ + int j, i; \ \ - r.W(0) = d->W((base << (SHIFT + 1)) + 0); \ - r.W(1) = s->W((base << (SHIFT + 1)) + 0); \ - r.W(2) = d->W((base << (SHIFT + 1)) + 1); \ - r.W(3) = s->W((base << (SHIFT + 1)) + 1); \ - XMM_ONLY( \ - r.W(4) = d->W((base << (SHIFT + 1)) + 2); \ - r.W(5) = s->W((base << (SHIFT + 1)) + 2); \ - r.W(6) = d->W((base << (SHIFT + 1)) + 3); \ - r.W(7) = s->W((base << (SHIFT + 1)) + 3); \ - ) \ - MOVE(*d, r); \ + for (j = 0; j < 4 << SHIFT; ) { \ + int k = j + base * PACK_WIDTH / 2; \ + for (i = 0; i < PACK_WIDTH / 2; i++) { \ + r[2 * i] = v->W(k + i); \ + r[2 * i + 1] = s->W(k + i); \ + } \ + for (i = 0; i < PACK_WIDTH; i++, j++) { \ + d->W(j) = r[i]; \ + } \ + } \ } \ \ void glue(helper_punpck ## base_name ## dq, SUFFIX)(CPUX86State *env,\ - Reg *d, Reg *s) \ + Reg *d, Reg *s) \ { \ - Reg r; \ + Reg *v = d; \ + uint32_t r[PACK_WIDTH / 2]; \ + int j, i; \ \ - r.L(0) = d->L((base << SHIFT) + 0); \ - r.L(1) = s->L((base << SHIFT) + 0); \ - XMM_ONLY( \ - r.L(2) = d->L((base << SHIFT) + 1); \ - r.L(3) = s->L((base << SHIFT) + 1); \ - ) \ - MOVE(*d, r); \ + for (j = 0; j < 2 << SHIFT; ) { \ + int k = j + base * PACK_WIDTH / 4; \ + for (i = 0; i < PACK_WIDTH / 4; i++) { \ + r[2 * i] = v->L(k + i); \ + r[2 * i + 1] = s->L(k + i); \ + } \ + for (i = 0; i < PACK_WIDTH / 2; i++, j++) { \ + d->L(j) = r[i]; \ + } \ + } \ } \ \ XMM_ONLY( \ - void glue(helper_punpck ## base_name ## qdq, SUFFIX)(CPUX86State \ - *env, \ - Reg *d, \ - Reg *s) \ + void glue(helper_punpck ## base_name ## qdq, SUFFIX)( \ + CPUX86State *env, Reg *d, Reg *s) \ { \ - Reg r; \ + Reg *v = d; \ + uint64_t r[2]; \ + int i; \ \ - r.Q(0) = d->Q(base); \ - r.Q(1) = s->Q(base); \ - MOVE(*d, r); \ + for (i = 0; i < 1 << SHIFT; i += 2) { \ + r[0] = v->Q(base + i); \ + r[1] = s->Q(base + i); \ + d->Q(i) = r[0]; \ + d->Q(i + 1) = r[1]; \ + } \ } \ ) UNPCK_OP(l, 0) UNPCK_OP(h, 1) +#undef PACK_WIDTH +#undef PACK_HELPER_B +#undef UNPCK_OP + + /* 3DNow! float ops */ #if SHIFT == 0 void helper_pi2fd(CPUX86State *env, MMXReg *d, MMXReg *s) @@ -1393,122 +1380,86 @@ void helper_pswapd(CPUX86State *env, MMXReg *d, MMXReg *s) /* SSSE3 op helpers */ void glue(helper_pshufb, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { + Reg *v = d; int i; - Reg r; +#if SHIFT == 0 + uint8_t r[8]; - for (i = 0; i < (8 << SHIFT); i++) { - r.B(i) = (s->B(i) & 0x80) ? 0 : (d->B(s->B(i) & ((8 << SHIFT) - 1))); + for (i = 0; i < 8; i++) { + r[i] = (s->B(i) & 0x80) ? 0 : (v->B(s->B(i) & 7)); } + for (i = 0; i < 8; i++) { + d->B(i) = r[i]; + } +#else + uint8_t r[8 << SHIFT]; - MOVE(*d, r); -} - -void glue(helper_phaddw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - - Reg r; - - r.W(0) = (int16_t)d->W(0) + (int16_t)d->W(1); - r.W(1) = (int16_t)d->W(2) + (int16_t)d->W(3); - XMM_ONLY(r.W(2) = (int16_t)d->W(4) + (int16_t)d->W(5)); - XMM_ONLY(r.W(3) = (int16_t)d->W(6) + (int16_t)d->W(7)); - r.W((2 << SHIFT) + 0) = (int16_t)s->W(0) + (int16_t)s->W(1); - r.W((2 << SHIFT) + 1) = (int16_t)s->W(2) + (int16_t)s->W(3); - XMM_ONLY(r.W(6) = (int16_t)s->W(4) + (int16_t)s->W(5)); - XMM_ONLY(r.W(7) = (int16_t)s->W(6) + (int16_t)s->W(7)); - - MOVE(*d, r); -} - -void glue(helper_phaddd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - Reg r; - - r.L(0) = (int32_t)d->L(0) + (int32_t)d->L(1); - XMM_ONLY(r.L(1) = (int32_t)d->L(2) + (int32_t)d->L(3)); - r.L((1 << SHIFT) + 0) = (int32_t)s->L(0) + (int32_t)s->L(1); - XMM_ONLY(r.L(3) = (int32_t)s->L(2) + (int32_t)s->L(3)); - - MOVE(*d, r); -} - -void glue(helper_phaddsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - Reg r; - - r.W(0) = satsw((int16_t)d->W(0) + (int16_t)d->W(1)); - r.W(1) = satsw((int16_t)d->W(2) + (int16_t)d->W(3)); - XMM_ONLY(r.W(2) = satsw((int16_t)d->W(4) + (int16_t)d->W(5))); - XMM_ONLY(r.W(3) = satsw((int16_t)d->W(6) + (int16_t)d->W(7))); - r.W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) + (int16_t)s->W(1)); - r.W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) + (int16_t)s->W(3)); - XMM_ONLY(r.W(6) = satsw((int16_t)s->W(4) + (int16_t)s->W(5))); - XMM_ONLY(r.W(7) = satsw((int16_t)s->W(6) + (int16_t)s->W(7))); - - MOVE(*d, r); -} - -void glue(helper_pmaddubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - d->W(0) = satsw((int8_t)s->B(0) * (uint8_t)d->B(0) + - (int8_t)s->B(1) * (uint8_t)d->B(1)); - d->W(1) = satsw((int8_t)s->B(2) * (uint8_t)d->B(2) + - (int8_t)s->B(3) * (uint8_t)d->B(3)); - d->W(2) = satsw((int8_t)s->B(4) * (uint8_t)d->B(4) + - (int8_t)s->B(5) * (uint8_t)d->B(5)); - d->W(3) = satsw((int8_t)s->B(6) * (uint8_t)d->B(6) + - (int8_t)s->B(7) * (uint8_t)d->B(7)); -#if SHIFT == 1 - d->W(4) = satsw((int8_t)s->B(8) * (uint8_t)d->B(8) + - (int8_t)s->B(9) * (uint8_t)d->B(9)); - d->W(5) = satsw((int8_t)s->B(10) * (uint8_t)d->B(10) + - (int8_t)s->B(11) * (uint8_t)d->B(11)); - d->W(6) = satsw((int8_t)s->B(12) * (uint8_t)d->B(12) + - (int8_t)s->B(13) * (uint8_t)d->B(13)); - d->W(7) = satsw((int8_t)s->B(14) * (uint8_t)d->B(14) + - (int8_t)s->B(15) * (uint8_t)d->B(15)); + for (i = 0; i < 8 << SHIFT; i++) { + int j = i & ~0xf; + r[i] = (s->B(i) & 0x80) ? 0 : v->B(j | (s->B(i) & 0xf)); + } + for (i = 0; i < 8 << SHIFT; i++) { + d->B(i) = r[i]; + } #endif } -void glue(helper_phsubw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - Reg r; - - r.W(0) = (int16_t)d->W(0) - (int16_t)d->W(1); - r.W(1) = (int16_t)d->W(2) - (int16_t)d->W(3); - XMM_ONLY(r.W(2) = (int16_t)d->W(4) - (int16_t)d->W(5)); - XMM_ONLY(r.W(3) = (int16_t)d->W(6) - (int16_t)d->W(7)); - r.W((2 << SHIFT) + 0) = (int16_t)s->W(0) - (int16_t)s->W(1); - r.W((2 << SHIFT) + 1) = (int16_t)s->W(2) - (int16_t)s->W(3); - XMM_ONLY(r.W(6) = (int16_t)s->W(4) - (int16_t)s->W(5)); - XMM_ONLY(r.W(7) = (int16_t)s->W(6) - (int16_t)s->W(7)); - MOVE(*d, r); +#define SSE_HELPER_HW(name, F) \ +void glue(helper_ ## name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ +{ \ + Reg *v = d; \ + uint16_t r[4 << SHIFT]; \ + int i, j, k; \ + for (k = 0; k < 4 << SHIFT; k += LANE_WIDTH / 2) { \ + for (i = j = 0; j < LANE_WIDTH / 2; i++, j += 2) { \ + r[i + k] = F(v->W(j + k), v->W(j + k + 1)); \ + } \ + for (j = 0; j < LANE_WIDTH / 2; i++, j += 2) { \ + r[i + k] = F(s->W(j + k), s->W(j + k + 1)); \ + } \ + } \ + for (i = 0; i < 4 << SHIFT; i++) { \ + d->W(i) = r[i]; \ + } \ } -void glue(helper_phsubd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - Reg r; - - r.L(0) = (int32_t)d->L(0) - (int32_t)d->L(1); - XMM_ONLY(r.L(1) = (int32_t)d->L(2) - (int32_t)d->L(3)); - r.L((1 << SHIFT) + 0) = (int32_t)s->L(0) - (int32_t)s->L(1); - XMM_ONLY(r.L(3) = (int32_t)s->L(2) - (int32_t)s->L(3)); - MOVE(*d, r); +#define SSE_HELPER_HL(name, F) \ +void glue(helper_ ## name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ +{ \ + Reg *v = d; \ + uint32_t r[2 << SHIFT]; \ + int i, j, k; \ + for (k = 0; k < 2 << SHIFT; k += LANE_WIDTH / 4) { \ + for (i = j = 0; j < LANE_WIDTH / 4; i++, j += 2) { \ + r[i + k] = F(v->L(j + k), v->L(j + k + 1)); \ + } \ + for (j = 0; j < LANE_WIDTH / 4; i++, j += 2) { \ + r[i + k] = F(s->L(j + k), s->L(j + k + 1)); \ + } \ + } \ + for (i = 0; i < 2 << SHIFT; i++) { \ + d->L(i) = r[i]; \ + } \ } -void glue(helper_phsubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) -{ - Reg r; +SSE_HELPER_HW(phaddw, FADD) +SSE_HELPER_HW(phsubw, FSUB) +SSE_HELPER_HW(phaddsw, FADDSW) +SSE_HELPER_HW(phsubsw, FSUBSW) +SSE_HELPER_HL(phaddd, FADD) +SSE_HELPER_HL(phsubd, FSUB) - r.W(0) = satsw((int16_t)d->W(0) - (int16_t)d->W(1)); - r.W(1) = satsw((int16_t)d->W(2) - (int16_t)d->W(3)); - XMM_ONLY(r.W(2) = satsw((int16_t)d->W(4) - (int16_t)d->W(5))); - XMM_ONLY(r.W(3) = satsw((int16_t)d->W(6) - (int16_t)d->W(7))); - r.W((2 << SHIFT) + 0) = satsw((int16_t)s->W(0) - (int16_t)s->W(1)); - r.W((2 << SHIFT) + 1) = satsw((int16_t)s->W(2) - (int16_t)s->W(3)); - XMM_ONLY(r.W(6) = satsw((int16_t)s->W(4) - (int16_t)s->W(5))); - XMM_ONLY(r.W(7) = satsw((int16_t)s->W(6) - (int16_t)s->W(7))); - MOVE(*d, r); +#undef SSE_HELPER_HW +#undef SSE_HELPER_HL + +void glue(helper_pmaddubsw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +{ + Reg *v = d; + int i; + for (i = 0; i < 4 << SHIFT; i++) { + d->W(i) = satsw((int8_t)s->B(i * 2) * (uint8_t)v->B(i * 2) + + (int8_t)s->B(i * 2 + 1) * (uint8_t)v->B(i * 2 + 1)); + } } #define FABSB(x) (x > INT8_MAX ? -(int8_t)x : x) @@ -1531,32 +1482,38 @@ SSE_HELPER_L(helper_psignd, FSIGNL) void glue(helper_palignr, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, int32_t shift) { - Reg r; + Reg *v = d; + int i; /* XXX could be checked during translation */ - if (shift >= (16 << SHIFT)) { - r.Q(0) = 0; - XMM_ONLY(r.Q(1) = 0); + if (shift >= (SHIFT ? 32 : 16)) { + for (i = 0; i < (1 << SHIFT); i++) { + d->Q(i) = 0; + } } else { shift <<= 3; #define SHR(v, i) (i < 64 && i > -64 ? i > 0 ? v >> (i) : (v << -(i)) : 0) #if SHIFT == 0 - r.Q(0) = SHR(s->Q(0), shift - 0) | - SHR(d->Q(0), shift - 64); + d->Q(0) = SHR(s->Q(0), shift - 0) | + SHR(v->Q(0), shift - 64); #else - r.Q(0) = SHR(s->Q(0), shift - 0) | - SHR(s->Q(1), shift - 64) | - SHR(d->Q(0), shift - 128) | - SHR(d->Q(1), shift - 192); - r.Q(1) = SHR(s->Q(0), shift + 64) | - SHR(s->Q(1), shift - 0) | - SHR(d->Q(0), shift - 64) | - SHR(d->Q(1), shift - 128); + for (i = 0; i < (1 << SHIFT); i += 2) { + uint64_t r0, r1; + + r0 = SHR(s->Q(i), shift - 0) | + SHR(s->Q(i + 1), shift - 64) | + SHR(v->Q(i), shift - 128) | + SHR(v->Q(i + 1), shift - 192); + r1 = SHR(s->Q(i), shift + 64) | + SHR(s->Q(i + 1), shift - 0) | + SHR(v->Q(i), shift - 64) | + SHR(v->Q(i + 1), shift - 128); + d->Q(i) = r0; + d->Q(i + 1) = r1; + } #endif #undef SHR } - - MOVE(*d, r); } #define XMM0 (env->xmm_regs[0]) @@ -1681,17 +1638,23 @@ SSE_HELPER_Q(helper_pcmpeqq, FCMPEQQ) void glue(helper_packusdw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - Reg r; + Reg *v = d; + uint16_t r[8]; + int i, j, k; - r.W(0) = satuw((int32_t) d->L(0)); - r.W(1) = satuw((int32_t) d->L(1)); - r.W(2) = satuw((int32_t) d->L(2)); - r.W(3) = satuw((int32_t) d->L(3)); - r.W(4) = satuw((int32_t) s->L(0)); - r.W(5) = satuw((int32_t) s->L(1)); - r.W(6) = satuw((int32_t) s->L(2)); - r.W(7) = satuw((int32_t) s->L(3)); - MOVE(*d, r); + for (i = 0, j = 0; i <= 2 << SHIFT; i += 8, j += 4) { + r[0] = satuw(v->L(j)); + r[1] = satuw(v->L(j + 1)); + r[2] = satuw(v->L(j + 2)); + r[3] = satuw(v->L(j + 3)); + r[4] = satuw(s->L(j)); + r[5] = satuw(s->L(j + 1)); + r[6] = satuw(s->L(j + 2)); + r[7] = satuw(s->L(j + 3)); + for (k = 0; k < 8; k++) { + d->W(i + k) = r[k]; + } + } } #define FMINSB(d, s) MIN((int8_t)d, (int8_t)s) @@ -1947,20 +1910,25 @@ void glue(helper_dppd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) void glue(helper_mpsadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t offset) { - int s0 = (offset & 3) << 2; - int d0 = (offset & 4) << 0; - int i; - Reg r; + Reg *v = d; + int i, j; + uint16_t r[8]; - for (i = 0; i < 8; i++, d0++) { - r.W(i) = 0; - r.W(i) += abs1(d->B(d0 + 0) - s->B(s0 + 0)); - r.W(i) += abs1(d->B(d0 + 1) - s->B(s0 + 1)); - r.W(i) += abs1(d->B(d0 + 2) - s->B(s0 + 2)); - r.W(i) += abs1(d->B(d0 + 3) - s->B(s0 + 3)); + for (j = 0; j < 4 << SHIFT; ) { + int s0 = (j * 2) + ((offset & 3) << 2); + int d0 = (j * 2) + ((offset & 4) << 0); + for (i = 0; i < LANE_WIDTH / 2; i++, d0++) { + r[i] = 0; + r[i] += abs1(v->B(d0 + 0) - s->B(s0 + 0)); + r[i] += abs1(v->B(d0 + 1) - s->B(s0 + 1)); + r[i] += abs1(v->B(d0 + 2) - s->B(s0 + 2)); + r[i] += abs1(v->B(d0 + 3) - s->B(s0 + 3)); + } + for (i = 0; i < LANE_WIDTH / 2; i++, j++) { + d->W(j) = r[i]; + } + offset >>= 3; } - - MOVE(*d, r); } /* SSE4.2 op helpers */ From 3403cafeeef30f41afee42c655573675286b3238 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:37 +0100 Subject: [PATCH 0297/1020] target/i386: Floating point arithmetic helper AVX prep Prepare the "easy" floating point vector helpers for AVX No functional changes to existing helpers. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-16-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 138 ++++++++++++++++++++++++++++-------------- 1 file changed, 92 insertions(+), 46 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index bb50ca6f8d..86ca74492e 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -553,40 +553,58 @@ void glue(helper_pshufhw, SUFFIX)(Reg *d, Reg *s, int order) } #endif -#if SHIFT == 1 +#if SHIFT >= 1 /* FPU ops */ /* XXX: not accurate */ -#define SSE_HELPER_S(name, F) \ - void glue(helper_ ## name ## ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)\ +#define SSE_HELPER_P(name, F) \ + void glue(helper_ ## name ## ps, SUFFIX)(CPUX86State *env, \ + Reg *d, Reg *s) \ { \ - d->ZMM_S(0) = F(32, d->ZMM_S(0), s->ZMM_S(0)); \ - d->ZMM_S(1) = F(32, d->ZMM_S(1), s->ZMM_S(1)); \ - d->ZMM_S(2) = F(32, d->ZMM_S(2), s->ZMM_S(2)); \ - d->ZMM_S(3) = F(32, d->ZMM_S(3), s->ZMM_S(3)); \ + Reg *v = d; \ + int i; \ + for (i = 0; i < 2 << SHIFT; i++) { \ + d->ZMM_S(i) = F(32, v->ZMM_S(i), s->ZMM_S(i)); \ + } \ } \ \ - void helper_ ## name ## ss(CPUX86State *env, Reg *d, Reg *s) \ + void glue(helper_ ## name ## pd, SUFFIX)(CPUX86State *env, \ + Reg *d, Reg *s) \ { \ - d->ZMM_S(0) = F(32, d->ZMM_S(0), s->ZMM_S(0)); \ - } \ - \ - void glue(helper_ ## name ## pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)\ - { \ - d->ZMM_D(0) = F(64, d->ZMM_D(0), s->ZMM_D(0)); \ - d->ZMM_D(1) = F(64, d->ZMM_D(1), s->ZMM_D(1)); \ - } \ - \ - void helper_ ## name ## sd(CPUX86State *env, Reg *d, Reg *s) \ - { \ - d->ZMM_D(0) = F(64, d->ZMM_D(0), s->ZMM_D(0)); \ + Reg *v = d; \ + int i; \ + for (i = 0; i < 1 << SHIFT; i++) { \ + d->ZMM_D(i) = F(64, v->ZMM_D(i), s->ZMM_D(i)); \ + } \ } +#if SHIFT == 1 + +#define SSE_HELPER_S(name, F) \ + SSE_HELPER_P(name, F) \ + \ + void helper_ ## name ## ss(CPUX86State *env, Reg *d, Reg *s)\ + { \ + Reg *v = d; \ + d->ZMM_S(0) = F(32, v->ZMM_S(0), s->ZMM_S(0)); \ + } \ + \ + void helper_ ## name ## sd(CPUX86State *env, Reg *d, Reg *s)\ + { \ + Reg *v = d; \ + d->ZMM_D(0) = F(64, v->ZMM_D(0), s->ZMM_D(0)); \ + } + +#else + +#define SSE_HELPER_S(name, F) SSE_HELPER_P(name, F) + +#endif + #define FPU_ADD(size, a, b) float ## size ## _add(a, b, &env->sse_status) #define FPU_SUB(size, a, b) float ## size ## _sub(a, b, &env->sse_status) #define FPU_MUL(size, a, b) float ## size ## _mul(a, b, &env->sse_status) #define FPU_DIV(size, a, b) float ## size ## _div(a, b, &env->sse_status) -#define FPU_SQRT(size, a, b) float ## size ## _sqrt(b, &env->sse_status) /* Note that the choice of comparison op here is important to get the * special cases right: for min and max Intel specifies that (-0,0), @@ -603,8 +621,34 @@ SSE_HELPER_S(mul, FPU_MUL) SSE_HELPER_S(div, FPU_DIV) SSE_HELPER_S(min, FPU_MIN) SSE_HELPER_S(max, FPU_MAX) -SSE_HELPER_S(sqrt, FPU_SQRT) +void glue(helper_sqrtps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +{ + int i; + for (i = 0; i < 2 << SHIFT; i++) { + d->ZMM_S(i) = float32_sqrt(s->ZMM_S(i), &env->sse_status); + } +} + +void glue(helper_sqrtpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) +{ + int i; + for (i = 0; i < 1 << SHIFT; i++) { + d->ZMM_D(i) = float64_sqrt(s->ZMM_D(i), &env->sse_status); + } +} + +#if SHIFT == 1 +void helper_sqrtss(CPUX86State *env, Reg *d, Reg *s) +{ + d->ZMM_S(0) = float32_sqrt(s->ZMM_S(0), &env->sse_status); +} + +void helper_sqrtsd(CPUX86State *env, Reg *d, Reg *s) +{ + d->ZMM_D(0) = float64_sqrt(s->ZMM_D(0), &env->sse_status); +} +#endif /* float to float conversions */ void glue(helper_cvtps2pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) @@ -822,18 +866,12 @@ int64_t helper_cvttsd2sq(CPUX86State *env, ZMMReg *s) void glue(helper_rsqrtps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { uint8_t old_flags = get_float_exception_flags(&env->sse_status); - d->ZMM_S(0) = float32_div(float32_one, - float32_sqrt(s->ZMM_S(0), &env->sse_status), - &env->sse_status); - d->ZMM_S(1) = float32_div(float32_one, - float32_sqrt(s->ZMM_S(1), &env->sse_status), - &env->sse_status); - d->ZMM_S(2) = float32_div(float32_one, - float32_sqrt(s->ZMM_S(2), &env->sse_status), - &env->sse_status); - d->ZMM_S(3) = float32_div(float32_one, - float32_sqrt(s->ZMM_S(3), &env->sse_status), - &env->sse_status); + int i; + for (i = 0; i < 2 << SHIFT; i++) { + d->ZMM_S(i) = float32_div(float32_one, + float32_sqrt(s->ZMM_S(i), &env->sse_status), + &env->sse_status); + } set_float_exception_flags(old_flags, &env->sse_status); } @@ -849,10 +887,10 @@ void helper_rsqrtss(CPUX86State *env, ZMMReg *d, ZMMReg *s) void glue(helper_rcpps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { uint8_t old_flags = get_float_exception_flags(&env->sse_status); - d->ZMM_S(0) = float32_div(float32_one, s->ZMM_S(0), &env->sse_status); - d->ZMM_S(1) = float32_div(float32_one, s->ZMM_S(1), &env->sse_status); - d->ZMM_S(2) = float32_div(float32_one, s->ZMM_S(2), &env->sse_status); - d->ZMM_S(3) = float32_div(float32_one, s->ZMM_S(3), &env->sse_status); + int i; + for (i = 0; i < 2 << SHIFT; i++) { + d->ZMM_S(i) = float32_div(float32_one, s->ZMM_S(i), &env->sse_status); + } set_float_exception_flags(old_flags, &env->sse_status); } @@ -947,18 +985,24 @@ void glue(helper_hsubpd, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) MOVE(*d, r); } -void glue(helper_addsubps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_addsubps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->ZMM_S(0) = float32_sub(d->ZMM_S(0), s->ZMM_S(0), &env->sse_status); - d->ZMM_S(1) = float32_add(d->ZMM_S(1), s->ZMM_S(1), &env->sse_status); - d->ZMM_S(2) = float32_sub(d->ZMM_S(2), s->ZMM_S(2), &env->sse_status); - d->ZMM_S(3) = float32_add(d->ZMM_S(3), s->ZMM_S(3), &env->sse_status); + Reg *v = d; + int i; + for (i = 0; i < 2 << SHIFT; i += 2) { + d->ZMM_S(i) = float32_sub(v->ZMM_S(i), s->ZMM_S(i), &env->sse_status); + d->ZMM_S(i+1) = float32_add(v->ZMM_S(i+1), s->ZMM_S(i+1), &env->sse_status); + } } -void glue(helper_addsubpd, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) +void glue(helper_addsubpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->ZMM_D(0) = float64_sub(d->ZMM_D(0), s->ZMM_D(0), &env->sse_status); - d->ZMM_D(1) = float64_add(d->ZMM_D(1), s->ZMM_D(1), &env->sse_status); + Reg *v = d; + int i; + for (i = 0; i < 1 << SHIFT; i += 2) { + d->ZMM_D(i) = float64_sub(v->ZMM_D(i), s->ZMM_D(i), &env->sse_status); + d->ZMM_D(i+1) = float64_add(v->ZMM_D(i+1), s->ZMM_D(i+1), &env->sse_status); + } } /* XXX: unordered */ @@ -2258,6 +2302,8 @@ void glue(helper_aeskeygenassist, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, } #endif +#undef SSE_HELPER_S + #undef SHIFT #undef XMM_ONLY #undef Reg From cbf4ad5498039105db7c41e16e116b5b6584a786 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Thu, 25 Aug 2022 23:58:15 +0200 Subject: [PATCH 0298/1020] target/i386: reimplement AVX comparison helpers AVX includes an additional set of comparison predicates, some of which our softfloat implementation does not expose as separate functions. Rewrite the helpers in terms of floatN_compare for future extensibility. Signed-off-by: Paul Brook Reviewed-by: Richard Henderson Message-Id: <20220424220204.2493824-24-paul@nowt.org> Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 97 ++++++++++++++++++++---------------- target/i386/ops_sse_header.h | 24 ++++----- target/i386/tcg/translate.c | 20 ++++---- 3 files changed, 75 insertions(+), 66 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 86ca74492e..7463ff1599 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -1005,57 +1005,66 @@ void glue(helper_addsubpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) } } -/* XXX: unordered */ -#define SSE_HELPER_CMP(name, F) \ - void glue(helper_ ## name ## ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)\ +#define SSE_HELPER_CMP_P(name, F, C) \ + void glue(helper_ ## name ## ps, SUFFIX)(CPUX86State *env, \ + Reg *d, Reg *s) \ { \ - d->ZMM_L(0) = F(32, d->ZMM_S(0), s->ZMM_S(0)); \ - d->ZMM_L(1) = F(32, d->ZMM_S(1), s->ZMM_S(1)); \ - d->ZMM_L(2) = F(32, d->ZMM_S(2), s->ZMM_S(2)); \ - d->ZMM_L(3) = F(32, d->ZMM_S(3), s->ZMM_S(3)); \ + Reg *v = d; \ + int i; \ + for (i = 0; i < 2 << SHIFT; i++) { \ + d->ZMM_L(i) = C(F(32, v->ZMM_S(i), s->ZMM_S(i))) ? -1 : 0; \ + } \ } \ \ - void helper_ ## name ## ss(CPUX86State *env, Reg *d, Reg *s) \ + void glue(helper_ ## name ## pd, SUFFIX)(CPUX86State *env, \ + Reg *d, Reg *s) \ { \ - d->ZMM_L(0) = F(32, d->ZMM_S(0), s->ZMM_S(0)); \ - } \ - \ - void glue(helper_ ## name ## pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)\ - { \ - d->ZMM_Q(0) = F(64, d->ZMM_D(0), s->ZMM_D(0)); \ - d->ZMM_Q(1) = F(64, d->ZMM_D(1), s->ZMM_D(1)); \ - } \ - \ - void helper_ ## name ## sd(CPUX86State *env, Reg *d, Reg *s) \ - { \ - d->ZMM_Q(0) = F(64, d->ZMM_D(0), s->ZMM_D(0)); \ + Reg *v = d; \ + int i; \ + for (i = 0; i < 1 << SHIFT; i++) { \ + d->ZMM_Q(i) = C(F(64, v->ZMM_D(i), s->ZMM_D(i))) ? -1 : 0; \ + } \ } -#define FPU_CMPEQ(size, a, b) \ - (float ## size ## _eq_quiet(a, b, &env->sse_status) ? -1 : 0) -#define FPU_CMPLT(size, a, b) \ - (float ## size ## _lt(a, b, &env->sse_status) ? -1 : 0) -#define FPU_CMPLE(size, a, b) \ - (float ## size ## _le(a, b, &env->sse_status) ? -1 : 0) -#define FPU_CMPUNORD(size, a, b) \ - (float ## size ## _unordered_quiet(a, b, &env->sse_status) ? -1 : 0) -#define FPU_CMPNEQ(size, a, b) \ - (float ## size ## _eq_quiet(a, b, &env->sse_status) ? 0 : -1) -#define FPU_CMPNLT(size, a, b) \ - (float ## size ## _lt(a, b, &env->sse_status) ? 0 : -1) -#define FPU_CMPNLE(size, a, b) \ - (float ## size ## _le(a, b, &env->sse_status) ? 0 : -1) -#define FPU_CMPORD(size, a, b) \ - (float ## size ## _unordered_quiet(a, b, &env->sse_status) ? 0 : -1) +#if SHIFT == 1 +#define SSE_HELPER_CMP(name, F, C) \ + SSE_HELPER_CMP_P(name, F, C) \ + void helper_ ## name ## ss(CPUX86State *env, Reg *d, Reg *s) \ + { \ + Reg *v = d; \ + d->ZMM_L(0) = C(F(32, v->ZMM_S(0), s->ZMM_S(0))) ? -1 : 0; \ + } \ + \ + void helper_ ## name ## sd(CPUX86State *env, Reg *d, Reg *s) \ + { \ + Reg *v = d; \ + d->ZMM_Q(0) = C(F(64, v->ZMM_D(0), s->ZMM_D(0))) ? -1 : 0; \ + } -SSE_HELPER_CMP(cmpeq, FPU_CMPEQ) -SSE_HELPER_CMP(cmplt, FPU_CMPLT) -SSE_HELPER_CMP(cmple, FPU_CMPLE) -SSE_HELPER_CMP(cmpunord, FPU_CMPUNORD) -SSE_HELPER_CMP(cmpneq, FPU_CMPNEQ) -SSE_HELPER_CMP(cmpnlt, FPU_CMPNLT) -SSE_HELPER_CMP(cmpnle, FPU_CMPNLE) -SSE_HELPER_CMP(cmpord, FPU_CMPORD) +#define FPU_EQ(x) (x == float_relation_equal) +#define FPU_LT(x) (x == float_relation_less) +#define FPU_LE(x) (x <= float_relation_equal) +#define FPU_UNORD(x) (x == float_relation_unordered) + +#define FPU_CMPQ(size, a, b) \ + float ## size ## _compare_quiet(a, b, &env->sse_status) +#define FPU_CMPS(size, a, b) \ + float ## size ## _compare(a, b, &env->sse_status) + +#else +#define SSE_HELPER_CMP(name, F, C) SSE_HELPER_CMP_P(name, F, C) +#endif + +SSE_HELPER_CMP(cmpeq, FPU_CMPQ, FPU_EQ) +SSE_HELPER_CMP(cmplt, FPU_CMPS, FPU_LT) +SSE_HELPER_CMP(cmple, FPU_CMPS, FPU_LE) +SSE_HELPER_CMP(cmpunord, FPU_CMPQ, FPU_UNORD) +SSE_HELPER_CMP(cmpneq, FPU_CMPQ, !FPU_EQ) +SSE_HELPER_CMP(cmpnlt, FPU_CMPS, !FPU_LT) +SSE_HELPER_CMP(cmpnle, FPU_CMPS, !FPU_LE) +SSE_HELPER_CMP(cmpord, FPU_CMPQ, !FPU_UNORD) + +#undef SSE_HELPER_CMP static const int comis_eflags[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h index fc697536a0..d99464afb0 100644 --- a/target/i386/ops_sse_header.h +++ b/target/i386/ops_sse_header.h @@ -201,20 +201,20 @@ DEF_HELPER_3(glue(hsubpd, SUFFIX), void, env, ZMMReg, ZMMReg) DEF_HELPER_3(glue(addsubps, SUFFIX), void, env, ZMMReg, ZMMReg) DEF_HELPER_3(glue(addsubpd, SUFFIX), void, env, ZMMReg, ZMMReg) -#define SSE_HELPER_CMP(name, F) \ - DEF_HELPER_3(glue(name ## ps, SUFFIX), void, env, Reg, Reg) \ - DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \ - DEF_HELPER_3(glue(name ## pd, SUFFIX), void, env, Reg, Reg) \ +#define SSE_HELPER_CMP(name, F, C) \ + DEF_HELPER_3(glue(name ## ps, SUFFIX), void, env, Reg, Reg) \ + DEF_HELPER_3(name ## ss, void, env, Reg, Reg) \ + DEF_HELPER_3(glue(name ## pd, SUFFIX), void, env, Reg, Reg) \ DEF_HELPER_3(name ## sd, void, env, Reg, Reg) -SSE_HELPER_CMP(cmpeq, FPU_CMPEQ) -SSE_HELPER_CMP(cmplt, FPU_CMPLT) -SSE_HELPER_CMP(cmple, FPU_CMPLE) -SSE_HELPER_CMP(cmpunord, FPU_CMPUNORD) -SSE_HELPER_CMP(cmpneq, FPU_CMPNEQ) -SSE_HELPER_CMP(cmpnlt, FPU_CMPNLT) -SSE_HELPER_CMP(cmpnle, FPU_CMPNLE) -SSE_HELPER_CMP(cmpord, FPU_CMPORD) +SSE_HELPER_CMP(cmpeq, FPU_CMPQ, FPU_EQ) +SSE_HELPER_CMP(cmplt, FPU_CMPS, FPU_LT) +SSE_HELPER_CMP(cmple, FPU_CMPS, FPU_LE) +SSE_HELPER_CMP(cmpunord, FPU_CMPQ, FPU_UNORD) +SSE_HELPER_CMP(cmpneq, FPU_CMPQ, !FPU_EQ) +SSE_HELPER_CMP(cmpnlt, FPU_CMPS, !FPU_LT) +SSE_HELPER_CMP(cmpnle, FPU_CMPS, !FPU_LE) +SSE_HELPER_CMP(cmpord, FPU_CMPQ, !FPU_UNORD) DEF_HELPER_3(ucomiss, void, env, Reg, Reg) DEF_HELPER_3(comiss, void, env, Reg, Reg) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 99c84473f4..fc081e6ad6 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3022,20 +3022,20 @@ static const SSEFunc_l_ep sse_op_table3bq[] = { }; #endif -#define SSE_FOP(x) { \ +#define SSE_CMP(x) { \ gen_helper_ ## x ## ps ## _xmm, gen_helper_ ## x ## pd ## _xmm, \ gen_helper_ ## x ## ss, gen_helper_ ## x ## sd} static const SSEFunc_0_epp sse_op_table4[8][4] = { - SSE_FOP(cmpeq), - SSE_FOP(cmplt), - SSE_FOP(cmple), - SSE_FOP(cmpunord), - SSE_FOP(cmpneq), - SSE_FOP(cmpnlt), - SSE_FOP(cmpnle), - SSE_FOP(cmpord), + SSE_CMP(cmpeq), + SSE_CMP(cmplt), + SSE_CMP(cmple), + SSE_CMP(cmpunord), + SSE_CMP(cmpneq), + SSE_CMP(cmpnlt), + SSE_CMP(cmpnle), + SSE_CMP(cmpord), }; -#undef SSE_FOP +#undef SSE_CMP static const SSEFunc_0_epp sse_op_table5[256] = { [0x0c] = gen_helper_pi2fw, From 6f218d6e994bd8b229d6522899b6ac6cd98bdb47 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:38 +0100 Subject: [PATCH 0299/1020] target/i386: Dot product AVX helper prep Make the dpps and dppd helpers AVX-ready I can't see any obvious reason why dppd shouldn't work on 256 bit ymm registers, but both AMD and Intel agree that it's xmm only. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-17-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 80 ++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 7463ff1599..c9737e16b9 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -1903,55 +1903,64 @@ SSE_HELPER_I(helper_blendps, L, 4, FBLENDP) SSE_HELPER_I(helper_blendpd, Q, 2, FBLENDP) SSE_HELPER_I(helper_pblendw, W, 8, FBLENDP) -void glue(helper_dpps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) +void glue(helper_dpps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t mask) { + Reg *v = d; float32 prod1, prod2, temp2, temp3, temp4; + int i; - /* - * We must evaluate (A+B)+(C+D), not ((A+B)+C)+D - * to correctly round the intermediate results - */ - if (mask & (1 << 4)) { - prod1 = float32_mul(d->ZMM_S(0), s->ZMM_S(0), &env->sse_status); - } else { - prod1 = float32_zero; - } - if (mask & (1 << 5)) { - prod2 = float32_mul(d->ZMM_S(1), s->ZMM_S(1), &env->sse_status); - } else { - prod2 = float32_zero; - } - temp2 = float32_add(prod1, prod2, &env->sse_status); - if (mask & (1 << 6)) { - prod1 = float32_mul(d->ZMM_S(2), s->ZMM_S(2), &env->sse_status); - } else { - prod1 = float32_zero; - } - if (mask & (1 << 7)) { - prod2 = float32_mul(d->ZMM_S(3), s->ZMM_S(3), &env->sse_status); - } else { - prod2 = float32_zero; - } - temp3 = float32_add(prod1, prod2, &env->sse_status); - temp4 = float32_add(temp2, temp3, &env->sse_status); + for (i = 0; i < 2 << SHIFT; i += 4) { + /* + * We must evaluate (A+B)+(C+D), not ((A+B)+C)+D + * to correctly round the intermediate results + */ + if (mask & (1 << 4)) { + prod1 = float32_mul(v->ZMM_S(i), s->ZMM_S(i), &env->sse_status); + } else { + prod1 = float32_zero; + } + if (mask & (1 << 5)) { + prod2 = float32_mul(v->ZMM_S(i+1), s->ZMM_S(i+1), &env->sse_status); + } else { + prod2 = float32_zero; + } + temp2 = float32_add(prod1, prod2, &env->sse_status); + if (mask & (1 << 6)) { + prod1 = float32_mul(v->ZMM_S(i+2), s->ZMM_S(i+2), &env->sse_status); + } else { + prod1 = float32_zero; + } + if (mask & (1 << 7)) { + prod2 = float32_mul(v->ZMM_S(i+3), s->ZMM_S(i+3), &env->sse_status); + } else { + prod2 = float32_zero; + } + temp3 = float32_add(prod1, prod2, &env->sse_status); + temp4 = float32_add(temp2, temp3, &env->sse_status); - d->ZMM_S(0) = (mask & (1 << 0)) ? temp4 : float32_zero; - d->ZMM_S(1) = (mask & (1 << 1)) ? temp4 : float32_zero; - d->ZMM_S(2) = (mask & (1 << 2)) ? temp4 : float32_zero; - d->ZMM_S(3) = (mask & (1 << 3)) ? temp4 : float32_zero; + d->ZMM_S(i) = (mask & (1 << 0)) ? temp4 : float32_zero; + d->ZMM_S(i+1) = (mask & (1 << 1)) ? temp4 : float32_zero; + d->ZMM_S(i+2) = (mask & (1 << 2)) ? temp4 : float32_zero; + d->ZMM_S(i+3) = (mask & (1 << 3)) ? temp4 : float32_zero; + } } -void glue(helper_dppd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) +#if SHIFT == 1 +/* Oddly, there is no ymm version of dppd */ +void glue(helper_dppd, SUFFIX)(CPUX86State *env, + Reg *d, Reg *s, uint32_t mask) { + Reg *v = d; float64 prod1, prod2, temp2; if (mask & (1 << 4)) { - prod1 = float64_mul(d->ZMM_D(0), s->ZMM_D(0), &env->sse_status); + prod1 = float64_mul(v->ZMM_D(0), s->ZMM_D(0), &env->sse_status); } else { prod1 = float64_zero; } if (mask & (1 << 5)) { - prod2 = float64_mul(d->ZMM_D(1), s->ZMM_D(1), &env->sse_status); + prod2 = float64_mul(v->ZMM_D(1), s->ZMM_D(1), &env->sse_status); } else { prod2 = float64_zero; } @@ -1959,6 +1968,7 @@ void glue(helper_dppd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) d->ZMM_D(0) = (mask & (1 << 0)) ? temp2 : float64_zero; d->ZMM_D(1) = (mask & (1 << 1)) ? temp2 : float64_zero; } +#endif void glue(helper_mpsadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t offset) From 6567ffb4f259d9937ff74f21e96cdac905440620 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:39 +0100 Subject: [PATCH 0300/1020] target/i386: Destructive FP helpers for AVX Perpare the horizontal atithmetic vector helpers for AVX These currently use a dummy Reg typed variable to store the result then assign the whole register. This will cause 128 bit operations to corrupt the upper half of the register, so replace it with explicit temporaries and element assignments. Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-18-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 91 ++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 53 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index c9737e16b9..c6dba9572d 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -22,7 +22,6 @@ #if SHIFT == 0 #define Reg MMXReg -#define SIZE 8 #define XMM_ONLY(...) #define B(n) MMX_B(n) #define W(n) MMX_W(n) @@ -31,7 +30,6 @@ #define SUFFIX _mmx #else #define Reg ZMMReg -#define SIZE 16 #define XMM_ONLY(...) __VA_ARGS__ #define B(n) ZMM_B(n) #define W(n) ZMM_W(n) @@ -43,22 +41,6 @@ #define LANE_WIDTH (SHIFT ? 16 : 8) #define PACK_WIDTH (LANE_WIDTH / 2) -/* - * Copy the relevant parts of a Reg value around. In the case where - * sizeof(Reg) > SIZE, these helpers operate only on the lower bytes of - * a 64 byte ZMMReg, so we must copy only those and keep the top bytes - * untouched in the guest-visible destination destination register. - * Note that the "lower bytes" are placed last in memory on big-endian - * hosts, which store the vector backwards in memory. In that case the - * copy *starts* at B(SIZE - 1) and ends at B(0), the opposite of - * the little-endian case. - */ -#if HOST_BIG_ENDIAN -#define MOVE(d, r) memcpy(&((d).B(SIZE - 1)), &(r).B(SIZE - 1), SIZE) -#else -#define MOVE(d, r) memcpy(&(d).B(0), &(r).B(0), SIZE) -#endif - #if SHIFT == 0 #define FPSRL(x, c) ((x) >> shift) #define FPSRAW(x, c) ((int16_t)(x) >> shift) @@ -945,45 +927,49 @@ void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length) d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), index, length); } -void glue(helper_haddps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) -{ - ZMMReg r; - - r.ZMM_S(0) = float32_add(d->ZMM_S(0), d->ZMM_S(1), &env->sse_status); - r.ZMM_S(1) = float32_add(d->ZMM_S(2), d->ZMM_S(3), &env->sse_status); - r.ZMM_S(2) = float32_add(s->ZMM_S(0), s->ZMM_S(1), &env->sse_status); - r.ZMM_S(3) = float32_add(s->ZMM_S(2), s->ZMM_S(3), &env->sse_status); - MOVE(*d, r); +#define SSE_HELPER_HPS(name, F) \ +void glue(helper_ ## name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ +{ \ + Reg *v = d; \ + float32 r[2 << SHIFT]; \ + int i, j, k; \ + for (k = 0; k < 2 << SHIFT; k += LANE_WIDTH / 4) { \ + for (i = j = 0; j < 4; i++, j += 2) { \ + r[i + k] = F(v->ZMM_S(j + k), v->ZMM_S(j + k + 1), &env->sse_status); \ + } \ + for (j = 0; j < 4; i++, j += 2) { \ + r[i + k] = F(s->ZMM_S(j + k), s->ZMM_S(j + k + 1), &env->sse_status); \ + } \ + } \ + for (i = 0; i < 2 << SHIFT; i++) { \ + d->ZMM_S(i) = r[i]; \ + } \ } -void glue(helper_haddpd, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) -{ - ZMMReg r; +SSE_HELPER_HPS(haddps, float32_add) +SSE_HELPER_HPS(hsubps, float32_sub) - r.ZMM_D(0) = float64_add(d->ZMM_D(0), d->ZMM_D(1), &env->sse_status); - r.ZMM_D(1) = float64_add(s->ZMM_D(0), s->ZMM_D(1), &env->sse_status); - MOVE(*d, r); +#define SSE_HELPER_HPD(name, F) \ +void glue(helper_ ## name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ +{ \ + Reg *v = d; \ + float64 r[1 << SHIFT]; \ + int i, j, k; \ + for (k = 0; k < 1 << SHIFT; k += LANE_WIDTH / 8) { \ + for (i = j = 0; j < 2; i++, j += 2) { \ + r[i + k] = F(v->ZMM_D(j + k), v->ZMM_D(j + k + 1), &env->sse_status); \ + } \ + for (j = 0; j < 2; i++, j += 2) { \ + r[i + k] = F(s->ZMM_D(j + k), s->ZMM_D(j + k + 1), &env->sse_status); \ + } \ + } \ + for (i = 0; i < 1 << SHIFT; i++) { \ + d->ZMM_D(i) = r[i]; \ + } \ } -void glue(helper_hsubps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) -{ - ZMMReg r; - - r.ZMM_S(0) = float32_sub(d->ZMM_S(0), d->ZMM_S(1), &env->sse_status); - r.ZMM_S(1) = float32_sub(d->ZMM_S(2), d->ZMM_S(3), &env->sse_status); - r.ZMM_S(2) = float32_sub(s->ZMM_S(0), s->ZMM_S(1), &env->sse_status); - r.ZMM_S(3) = float32_sub(s->ZMM_S(2), s->ZMM_S(3), &env->sse_status); - MOVE(*d, r); -} - -void glue(helper_hsubpd, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) -{ - ZMMReg r; - - r.ZMM_D(0) = float64_sub(d->ZMM_D(0), d->ZMM_D(1), &env->sse_status); - r.ZMM_D(1) = float64_sub(s->ZMM_D(0), s->ZMM_D(1), &env->sse_status); - MOVE(*d, r); -} +SSE_HELPER_HPD(haddpd, float64_add) +SSE_HELPER_HPD(hsubpd, float64_sub) void glue(helper_addsubps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { @@ -2331,4 +2317,3 @@ void glue(helper_aeskeygenassist, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, #undef L #undef Q #undef SUFFIX -#undef SIZE From fd17264ad153824204e1b5b88ebb3b597321b012 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:40 +0100 Subject: [PATCH 0301/1020] target/i386: Misc AVX helper prep Fixup various vector helpers that either trivially exten to 256 bit, or don't have 256 bit variants. No functional changes to existing helpers Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-19-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 143 +++++++++++++++++++++++++++--------------- 1 file changed, 94 insertions(+), 49 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index c6dba9572d..0c4257dee7 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -422,6 +422,7 @@ void glue(helper_psadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) } } +#if SHIFT < 2 void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, target_ulong a0) { @@ -433,6 +434,7 @@ void glue(helper_maskmov, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, } } } +#endif void glue(helper_movl_mm_T0, SUFFIX)(Reg *d, uint32_t val) { @@ -635,21 +637,24 @@ void helper_sqrtsd(CPUX86State *env, Reg *d, Reg *s) /* float to float conversions */ void glue(helper_cvtps2pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - float32 s0, s1; - - s0 = s->ZMM_S(0); - s1 = s->ZMM_S(1); - d->ZMM_D(0) = float32_to_float64(s0, &env->sse_status); - d->ZMM_D(1) = float32_to_float64(s1, &env->sse_status); + int i; + for (i = 1 << SHIFT; --i >= 0; ) { + d->ZMM_D(i) = float32_to_float64(s->ZMM_S(i), &env->sse_status); + } } void glue(helper_cvtpd2ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->ZMM_S(0) = float64_to_float32(s->ZMM_D(0), &env->sse_status); - d->ZMM_S(1) = float64_to_float32(s->ZMM_D(1), &env->sse_status); - d->Q(1) = 0; + int i; + for (i = 0; i < 1 << SHIFT; i++) { + d->ZMM_S(i) = float64_to_float32(s->ZMM_D(i), &env->sse_status); + } + for (i >>= 1; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } } +#if SHIFT == 1 void helper_cvtss2sd(CPUX86State *env, Reg *d, Reg *s) { d->ZMM_D(0) = float32_to_float64(s->ZMM_S(0), &env->sse_status); @@ -659,26 +664,27 @@ void helper_cvtsd2ss(CPUX86State *env, Reg *d, Reg *s) { d->ZMM_S(0) = float64_to_float32(s->ZMM_D(0), &env->sse_status); } +#endif /* integer to float */ void glue(helper_cvtdq2ps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - d->ZMM_S(0) = int32_to_float32(s->ZMM_L(0), &env->sse_status); - d->ZMM_S(1) = int32_to_float32(s->ZMM_L(1), &env->sse_status); - d->ZMM_S(2) = int32_to_float32(s->ZMM_L(2), &env->sse_status); - d->ZMM_S(3) = int32_to_float32(s->ZMM_L(3), &env->sse_status); + int i; + for (i = 0; i < 2 << SHIFT; i++) { + d->ZMM_S(i) = int32_to_float32(s->ZMM_L(i), &env->sse_status); + } } void glue(helper_cvtdq2pd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { - int32_t l0, l1; - - l0 = (int32_t)s->ZMM_L(0); - l1 = (int32_t)s->ZMM_L(1); - d->ZMM_D(0) = int32_to_float64(l0, &env->sse_status); - d->ZMM_D(1) = int32_to_float64(l1, &env->sse_status); + int i; + for (i = 1 << SHIFT; --i >= 0; ) { + int32_t l = s->ZMM_L(i); + d->ZMM_D(i) = int32_to_float64(l, &env->sse_status); + } } +#if SHIFT == 1 void helper_cvtpi2ps(CPUX86State *env, ZMMReg *d, MMXReg *s) { d->ZMM_S(0) = int32_to_float32(s->MMX_L(0), &env->sse_status); @@ -713,8 +719,11 @@ void helper_cvtsq2sd(CPUX86State *env, ZMMReg *d, uint64_t val) } #endif +#endif + /* float to integer */ +#if SHIFT == 1 /* * x86 mandates that we return the indefinite integer value for the result * of any float-to-integer conversion that raises the 'invalid' exception. @@ -745,22 +754,28 @@ WRAP_FLOATCONV(int64_t, float32_to_int64, float32, INT64_MIN) WRAP_FLOATCONV(int64_t, float32_to_int64_round_to_zero, float32, INT64_MIN) WRAP_FLOATCONV(int64_t, float64_to_int64, float64, INT64_MIN) WRAP_FLOATCONV(int64_t, float64_to_int64_round_to_zero, float64, INT64_MIN) +#endif void glue(helper_cvtps2dq, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { - d->ZMM_L(0) = x86_float32_to_int32(s->ZMM_S(0), &env->sse_status); - d->ZMM_L(1) = x86_float32_to_int32(s->ZMM_S(1), &env->sse_status); - d->ZMM_L(2) = x86_float32_to_int32(s->ZMM_S(2), &env->sse_status); - d->ZMM_L(3) = x86_float32_to_int32(s->ZMM_S(3), &env->sse_status); + int i; + for (i = 0; i < 2 << SHIFT; i++) { + d->ZMM_L(i) = x86_float32_to_int32(s->ZMM_S(i), &env->sse_status); + } } void glue(helper_cvtpd2dq, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { - d->ZMM_L(0) = x86_float64_to_int32(s->ZMM_D(0), &env->sse_status); - d->ZMM_L(1) = x86_float64_to_int32(s->ZMM_D(1), &env->sse_status); - d->ZMM_Q(1) = 0; + int i; + for (i = 0; i < 1 << SHIFT; i++) { + d->ZMM_L(i) = x86_float64_to_int32(s->ZMM_D(i), &env->sse_status); + } + for (i >>= 1; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } } +#if SHIFT == 1 void helper_cvtps2pi(CPUX86State *env, MMXReg *d, ZMMReg *s) { d->MMX_L(0) = x86_float32_to_int32(s->ZMM_S(0), &env->sse_status); @@ -794,23 +809,31 @@ int64_t helper_cvtsd2sq(CPUX86State *env, ZMMReg *s) return x86_float64_to_int64(s->ZMM_D(0), &env->sse_status); } #endif +#endif /* float to integer truncated */ void glue(helper_cvttps2dq, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { - d->ZMM_L(0) = x86_float32_to_int32_round_to_zero(s->ZMM_S(0), &env->sse_status); - d->ZMM_L(1) = x86_float32_to_int32_round_to_zero(s->ZMM_S(1), &env->sse_status); - d->ZMM_L(2) = x86_float32_to_int32_round_to_zero(s->ZMM_S(2), &env->sse_status); - d->ZMM_L(3) = x86_float32_to_int32_round_to_zero(s->ZMM_S(3), &env->sse_status); + int i; + for (i = 0; i < 2 << SHIFT; i++) { + d->ZMM_L(i) = x86_float32_to_int32_round_to_zero(s->ZMM_S(i), + &env->sse_status); + } } void glue(helper_cvttpd2dq, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { - d->ZMM_L(0) = x86_float64_to_int32_round_to_zero(s->ZMM_D(0), &env->sse_status); - d->ZMM_L(1) = x86_float64_to_int32_round_to_zero(s->ZMM_D(1), &env->sse_status); - d->ZMM_Q(1) = 0; + int i; + for (i = 0; i < 1 << SHIFT; i++) { + d->ZMM_L(i) = x86_float64_to_int32_round_to_zero(s->ZMM_D(i), + &env->sse_status); + } + for (i >>= 1; i < 1 << SHIFT; i++) { + d->Q(i) = 0; + } } +#if SHIFT == 1 void helper_cvttps2pi(CPUX86State *env, MMXReg *d, ZMMReg *s) { d->MMX_L(0) = x86_float32_to_int32_round_to_zero(s->ZMM_S(0), &env->sse_status); @@ -844,6 +867,7 @@ int64_t helper_cvttsd2sq(CPUX86State *env, ZMMReg *s) return x86_float64_to_int64_round_to_zero(s->ZMM_D(0), &env->sse_status); } #endif +#endif void glue(helper_rsqrtps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { @@ -857,6 +881,7 @@ void glue(helper_rsqrtps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) set_float_exception_flags(old_flags, &env->sse_status); } +#if SHIFT == 1 void helper_rsqrtss(CPUX86State *env, ZMMReg *d, ZMMReg *s) { uint8_t old_flags = get_float_exception_flags(&env->sse_status); @@ -865,6 +890,7 @@ void helper_rsqrtss(CPUX86State *env, ZMMReg *d, ZMMReg *s) &env->sse_status); set_float_exception_flags(old_flags, &env->sse_status); } +#endif void glue(helper_rcpps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) { @@ -876,13 +902,16 @@ void glue(helper_rcpps, SUFFIX)(CPUX86State *env, ZMMReg *d, ZMMReg *s) set_float_exception_flags(old_flags, &env->sse_status); } +#if SHIFT == 1 void helper_rcpss(CPUX86State *env, ZMMReg *d, ZMMReg *s) { uint8_t old_flags = get_float_exception_flags(&env->sse_status); d->ZMM_S(0) = float32_div(float32_one, s->ZMM_S(0), &env->sse_status); set_float_exception_flags(old_flags, &env->sse_status); } +#endif +#if SHIFT == 1 static inline uint64_t helper_extrq(uint64_t src, int shift, int len) { uint64_t mask; @@ -926,6 +955,7 @@ void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length) { d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), index, length); } +#endif #define SSE_HELPER_HPS(name, F) \ void glue(helper_ ## name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ @@ -1052,6 +1082,7 @@ SSE_HELPER_CMP(cmpord, FPU_CMPQ, !FPU_UNORD) #undef SSE_HELPER_CMP +#if SHIFT == 1 static const int comis_eflags[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C}; void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s) @@ -1097,25 +1128,30 @@ void helper_comisd(CPUX86State *env, Reg *d, Reg *s) ret = float64_compare(d0, d1, &env->sse_status); CC_SRC = comis_eflags[ret + 1]; } +#endif uint32_t glue(helper_movmskps, SUFFIX)(CPUX86State *env, Reg *s) { - int b0, b1, b2, b3; + uint32_t mask; + int i; - b0 = s->ZMM_L(0) >> 31; - b1 = s->ZMM_L(1) >> 31; - b2 = s->ZMM_L(2) >> 31; - b3 = s->ZMM_L(3) >> 31; - return b0 | (b1 << 1) | (b2 << 2) | (b3 << 3); + mask = 0; + for (i = 0; i < 2 << SHIFT; i++) { + mask |= (s->ZMM_L(i) >> (31 - i)) & (1 << i); + } + return mask; } uint32_t glue(helper_movmskpd, SUFFIX)(CPUX86State *env, Reg *s) { - int b0, b1; + uint32_t mask; + int i; - b0 = s->ZMM_L(1) >> 31; - b1 = s->ZMM_L(3) >> 31; - return b0 | (b1 << 1); + mask = 0; + for (i = 0; i < 1 << SHIFT; i++) { + mask |= (s->ZMM_Q(i) >> (63 - i)) & (1 << i); + } + return mask; } #endif @@ -1712,6 +1748,7 @@ SSE_HELPER_L(helper_pmaxud, MAX) #define FMULLD(d, s) ((int32_t)d * (int32_t)s) SSE_HELPER_L(helper_pmulld, FMULLD) +#if SHIFT == 1 void glue(helper_phminposuw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int idx = 0; @@ -1743,12 +1780,14 @@ void glue(helper_phminposuw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) d->L(1) = 0; d->Q(1) = 0; } +#endif void glue(helper_roundps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mode) { uint8_t old_flags = get_float_exception_flags(&env->sse_status); signed char prev_rounding_mode; + int i; prev_rounding_mode = env->sse_status.float_rounding_mode; if (!(mode & (1 << 2))) { @@ -1768,10 +1807,9 @@ void glue(helper_roundps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, } } - d->ZMM_S(0) = float32_round_to_int(s->ZMM_S(0), &env->sse_status); - d->ZMM_S(1) = float32_round_to_int(s->ZMM_S(1), &env->sse_status); - d->ZMM_S(2) = float32_round_to_int(s->ZMM_S(2), &env->sse_status); - d->ZMM_S(3) = float32_round_to_int(s->ZMM_S(3), &env->sse_status); + for (i = 0; i < 2 << SHIFT; i++) { + d->ZMM_S(i) = float32_round_to_int(s->ZMM_S(i), &env->sse_status); + } if (mode & (1 << 3) && !(old_flags & float_flag_inexact)) { set_float_exception_flags(get_float_exception_flags(&env->sse_status) & @@ -1786,6 +1824,7 @@ void glue(helper_roundpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, { uint8_t old_flags = get_float_exception_flags(&env->sse_status); signed char prev_rounding_mode; + int i; prev_rounding_mode = env->sse_status.float_rounding_mode; if (!(mode & (1 << 2))) { @@ -1805,8 +1844,9 @@ void glue(helper_roundpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, } } - d->ZMM_D(0) = float64_round_to_int(s->ZMM_D(0), &env->sse_status); - d->ZMM_D(1) = float64_round_to_int(s->ZMM_D(1), &env->sse_status); + for (i = 0; i < 1 << SHIFT; i++) { + d->ZMM_D(i) = float64_round_to_int(s->ZMM_D(i), &env->sse_status); + } if (mode & (1 << 3) && !(old_flags & float_flag_inexact)) { set_float_exception_flags(get_float_exception_flags(&env->sse_status) & @@ -1816,6 +1856,7 @@ void glue(helper_roundpd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, env->sse_status.float_rounding_mode = prev_rounding_mode; } +#if SHIFT == 1 void glue(helper_roundss, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mode) { @@ -1883,6 +1924,7 @@ void glue(helper_roundsd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, } env->sse_status.float_rounding_mode = prev_rounding_mode; } +#endif #define FBLENDP(d, s, m) (m ? s : d) SSE_HELPER_I(helper_blendps, L, 4, FBLENDP) @@ -1984,6 +2026,7 @@ void glue(helper_mpsadbw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, #define FCMPGTQ(d, s) ((int64_t)d > (int64_t)s ? -1 : 0) SSE_HELPER_Q(helper_pcmpgtq, FCMPGTQ) +#if SHIFT == 1 static inline int pcmp_elen(CPUX86State *env, int reg, uint32_t ctrl) { target_long val, limit; @@ -2204,6 +2247,8 @@ target_ulong helper_crc32(uint32_t crc1, target_ulong msg, uint32_t len) return crc; } +#endif + void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t ctrl) { From 0e29cea589ac870f9bfcc33514ccce14dbd8f098 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:41 +0100 Subject: [PATCH 0302/1020] target/i386: Rewrite blendv helpers Rewrite the blendv helpers so that they can easily be extended to support the AVX encodings, which make all 4 arguments explicit. No functional changes to the existing helpers Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-20-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 86 ++++++++++++------------------------------- 1 file changed, 24 insertions(+), 62 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 0c4257dee7..5241663227 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -1591,76 +1591,38 @@ void glue(helper_palignr, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, } } -#define XMM0 (env->xmm_regs[0]) +#if SHIFT >= 1 -#if SHIFT == 1 #define SSE_HELPER_V(name, elem, num, F) \ - void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \ { \ - d->elem(0) = F(d->elem(0), s->elem(0), XMM0.elem(0)); \ - d->elem(1) = F(d->elem(1), s->elem(1), XMM0.elem(1)); \ - if (num > 2) { \ - d->elem(2) = F(d->elem(2), s->elem(2), XMM0.elem(2)); \ - d->elem(3) = F(d->elem(3), s->elem(3), XMM0.elem(3)); \ - if (num > 4) { \ - d->elem(4) = F(d->elem(4), s->elem(4), XMM0.elem(4)); \ - d->elem(5) = F(d->elem(5), s->elem(5), XMM0.elem(5)); \ - d->elem(6) = F(d->elem(6), s->elem(6), XMM0.elem(6)); \ - d->elem(7) = F(d->elem(7), s->elem(7), XMM0.elem(7)); \ - if (num > 8) { \ - d->elem(8) = F(d->elem(8), s->elem(8), XMM0.elem(8)); \ - d->elem(9) = F(d->elem(9), s->elem(9), XMM0.elem(9)); \ - d->elem(10) = F(d->elem(10), s->elem(10), XMM0.elem(10)); \ - d->elem(11) = F(d->elem(11), s->elem(11), XMM0.elem(11)); \ - d->elem(12) = F(d->elem(12), s->elem(12), XMM0.elem(12)); \ - d->elem(13) = F(d->elem(13), s->elem(13), XMM0.elem(13)); \ - d->elem(14) = F(d->elem(14), s->elem(14), XMM0.elem(14)); \ - d->elem(15) = F(d->elem(15), s->elem(15), XMM0.elem(15)); \ - } \ - } \ + Reg *v = d; \ + Reg *m = &env->xmm_regs[0]; \ + int i; \ + for (i = 0; i < num; i++) { \ + d->elem(i) = F(v->elem(i), s->elem(i), m->elem(i)); \ } \ } #define SSE_HELPER_I(name, elem, num, F) \ - void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t imm) \ + void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, \ + uint32_t imm) \ { \ - d->elem(0) = F(d->elem(0), s->elem(0), ((imm >> 0) & 1)); \ - d->elem(1) = F(d->elem(1), s->elem(1), ((imm >> 1) & 1)); \ - if (num > 2) { \ - d->elem(2) = F(d->elem(2), s->elem(2), ((imm >> 2) & 1)); \ - d->elem(3) = F(d->elem(3), s->elem(3), ((imm >> 3) & 1)); \ - if (num > 4) { \ - d->elem(4) = F(d->elem(4), s->elem(4), ((imm >> 4) & 1)); \ - d->elem(5) = F(d->elem(5), s->elem(5), ((imm >> 5) & 1)); \ - d->elem(6) = F(d->elem(6), s->elem(6), ((imm >> 6) & 1)); \ - d->elem(7) = F(d->elem(7), s->elem(7), ((imm >> 7) & 1)); \ - if (num > 8) { \ - d->elem(8) = F(d->elem(8), s->elem(8), ((imm >> 8) & 1)); \ - d->elem(9) = F(d->elem(9), s->elem(9), ((imm >> 9) & 1)); \ - d->elem(10) = F(d->elem(10), s->elem(10), \ - ((imm >> 10) & 1)); \ - d->elem(11) = F(d->elem(11), s->elem(11), \ - ((imm >> 11) & 1)); \ - d->elem(12) = F(d->elem(12), s->elem(12), \ - ((imm >> 12) & 1)); \ - d->elem(13) = F(d->elem(13), s->elem(13), \ - ((imm >> 13) & 1)); \ - d->elem(14) = F(d->elem(14), s->elem(14), \ - ((imm >> 14) & 1)); \ - d->elem(15) = F(d->elem(15), s->elem(15), \ - ((imm >> 15) & 1)); \ - } \ - } \ + Reg *v = d; \ + int i; \ + for (i = 0; i < num; i++) { \ + int j = i & 7; \ + d->elem(i) = F(v->elem(i), s->elem(i), (imm >> j) & 1); \ } \ } /* SSE4.1 op helpers */ -#define FBLENDVB(d, s, m) ((m & 0x80) ? s : d) -#define FBLENDVPS(d, s, m) ((m & 0x80000000) ? s : d) -#define FBLENDVPD(d, s, m) ((m & 0x8000000000000000LL) ? s : d) -SSE_HELPER_V(helper_pblendvb, B, 16, FBLENDVB) -SSE_HELPER_V(helper_blendvps, L, 4, FBLENDVPS) -SSE_HELPER_V(helper_blendvpd, Q, 2, FBLENDVPD) +#define FBLENDVB(v, s, m) ((m & 0x80) ? s : v) +#define FBLENDVPS(v, s, m) ((m & 0x80000000) ? s : v) +#define FBLENDVPD(v, s, m) ((m & 0x8000000000000000LL) ? s : v) +SSE_HELPER_V(helper_pblendvb, B, 8 << SHIFT, FBLENDVB) +SSE_HELPER_V(helper_blendvps, L, 2 << SHIFT, FBLENDVPS) +SSE_HELPER_V(helper_blendvpd, Q, 1 << SHIFT, FBLENDVPD) void glue(helper_ptest, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { @@ -1926,10 +1888,10 @@ void glue(helper_roundsd, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, } #endif -#define FBLENDP(d, s, m) (m ? s : d) -SSE_HELPER_I(helper_blendps, L, 4, FBLENDP) -SSE_HELPER_I(helper_blendpd, Q, 2, FBLENDP) -SSE_HELPER_I(helper_pblendw, W, 8, FBLENDP) +#define FBLENDP(v, s, m) (m ? s : v) +SSE_HELPER_I(helper_blendps, L, 2 << SHIFT, FBLENDP) +SSE_HELPER_I(helper_blendpd, Q, 1 << SHIFT, FBLENDP) +SSE_HELPER_I(helper_pblendw, W, 4 << SHIFT, FBLENDP) void glue(helper_dpps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, uint32_t mask) From 5a09df21f7478f18e2ec59bac78a85c60e15604b Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:42 +0100 Subject: [PATCH 0303/1020] target/i386: AVX pclmulqdq prep Make the pclmulqdq helper AVX ready Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-21-paul@nowt.org> Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 5241663227..c791e86af7 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -2211,14 +2211,14 @@ target_ulong helper_crc32(uint32_t crc1, target_ulong msg, uint32_t len) #endif -void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, - uint32_t ctrl) +#if SHIFT == 1 +static void clmulq(uint64_t *dest_l, uint64_t *dest_h, + uint64_t a, uint64_t b) { - uint64_t ah, al, b, resh, resl; + uint64_t al, ah, resh, resl; ah = 0; - al = d->Q((ctrl & 1) != 0); - b = s->Q((ctrl & 16) != 0); + al = a; resh = resl = 0; while (b) { @@ -2231,8 +2231,23 @@ void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, b >>= 1; } - d->Q(0) = resl; - d->Q(1) = resh; + *dest_l = resl; + *dest_h = resh; +} +#endif + +void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t ctrl) +{ + Reg *v = d; + uint64_t a, b; + int i; + + for (i = 0; i < 1 << SHIFT; i += 2) { + a = v->Q(((ctrl & 1) != 0) + i); + b = s->Q(((ctrl & 16) != 0) + i); + clmulq(&d->Q(i), &d->Q(i + 1), a, b); + } } void glue(helper_aesdec, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) From a64fc269198e09d422da0e89e606f6f12b40af1f Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Sun, 24 Apr 2022 23:01:43 +0100 Subject: [PATCH 0304/1020] target/i386: AVX+AES helpers prep Make the AES vector helpers AVX ready No functional changes to existing helpers Signed-off-by: Paul Brook Message-Id: <20220424220204.2493824-22-paul@nowt.org> Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index c791e86af7..c0766de18d 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -2256,11 +2256,12 @@ void glue(helper_aesdec, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) Reg st = *d; Reg rk = *s; - for (i = 0 ; i < 4 ; i++) { - d->L(i) = rk.L(i) ^ bswap32(AES_Td0[st.B(AES_ishifts[4*i+0])] ^ - AES_Td1[st.B(AES_ishifts[4*i+1])] ^ - AES_Td2[st.B(AES_ishifts[4*i+2])] ^ - AES_Td3[st.B(AES_ishifts[4*i+3])]); + for (i = 0 ; i < 2 << SHIFT ; i++) { + int j = i & 3; + d->L(i) = rk.L(i) ^ bswap32(AES_Td0[st.B(AES_ishifts[4 * j + 0])] ^ + AES_Td1[st.B(AES_ishifts[4 * j + 1])] ^ + AES_Td2[st.B(AES_ishifts[4 * j + 2])] ^ + AES_Td3[st.B(AES_ishifts[4 * j + 3])]); } } @@ -2270,8 +2271,8 @@ void glue(helper_aesdeclast, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) Reg st = *d; Reg rk = *s; - for (i = 0; i < 16; i++) { - d->B(i) = rk.B(i) ^ (AES_isbox[st.B(AES_ishifts[i])]); + for (i = 0; i < 8 << SHIFT; i++) { + d->B(i) = rk.B(i) ^ (AES_isbox[st.B(AES_ishifts[i & 15] + (i & ~15))]); } } @@ -2281,11 +2282,12 @@ void glue(helper_aesenc, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) Reg st = *d; Reg rk = *s; - for (i = 0 ; i < 4 ; i++) { - d->L(i) = rk.L(i) ^ bswap32(AES_Te0[st.B(AES_shifts[4*i+0])] ^ - AES_Te1[st.B(AES_shifts[4*i+1])] ^ - AES_Te2[st.B(AES_shifts[4*i+2])] ^ - AES_Te3[st.B(AES_shifts[4*i+3])]); + for (i = 0 ; i < 2 << SHIFT ; i++) { + int j = i & 3; + d->L(i) = rk.L(i) ^ bswap32(AES_Te0[st.B(AES_shifts[4 * j + 0])] ^ + AES_Te1[st.B(AES_shifts[4 * j + 1])] ^ + AES_Te2[st.B(AES_shifts[4 * j + 2])] ^ + AES_Te3[st.B(AES_shifts[4 * j + 3])]); } } @@ -2295,22 +2297,22 @@ void glue(helper_aesenclast, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) Reg st = *d; Reg rk = *s; - for (i = 0; i < 16; i++) { - d->B(i) = rk.B(i) ^ (AES_sbox[st.B(AES_shifts[i])]); + for (i = 0; i < 8 << SHIFT; i++) { + d->B(i) = rk.B(i) ^ (AES_sbox[st.B(AES_shifts[i & 15] + (i & ~15))]); } - } +#if SHIFT == 1 void glue(helper_aesimc, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) { int i; Reg tmp = *s; for (i = 0 ; i < 4 ; i++) { - d->L(i) = bswap32(AES_imc[tmp.B(4*i+0)][0] ^ - AES_imc[tmp.B(4*i+1)][1] ^ - AES_imc[tmp.B(4*i+2)][2] ^ - AES_imc[tmp.B(4*i+3)][3]); + d->L(i) = bswap32(AES_imc[tmp.B(4 * i + 0)][0] ^ + AES_imc[tmp.B(4 * i + 1)][1] ^ + AES_imc[tmp.B(4 * i + 2)][2] ^ + AES_imc[tmp.B(4 * i + 3)][3]); } } @@ -2328,6 +2330,7 @@ void glue(helper_aeskeygenassist, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, d->L(3) = (d->L(2) << 24 | d->L(2) >> 8) ^ ctrl; } #endif +#endif #undef SSE_HELPER_S From 10dab9f2635b9bab23a2b29974b526e62bb61268 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:20:02 +0200 Subject: [PATCH 0305/1020] vdpa: Skip the maps not in the iova tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Next patch will skip the registering of dma maps that the vdpa device rejects in the iova tree. We need to consider that here or we cause a SIGSEGV accessing result. Reported-by: Lei Yang Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-vdpa.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 3ff9ce3501..983d3697b0 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -289,6 +289,10 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, }; result = vhost_iova_tree_find_iova(v->iova_tree, &mem_region); + if (!result) { + /* The memory listener map wasn't mapped */ + return; + } iova = result->iova; vhost_iova_tree_remove(v->iova_tree, result); } From 7dab70bec397e3522211e7bcc36d879bad8154c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:20:03 +0200 Subject: [PATCH 0306/1020] vdpa: do not save failed dma maps in SVQ iova tree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a map fails for whatever reason, it must not be saved in the tree. Otherwise, qemu will try to unmap it in cleanup, leaving to more errors. Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ") Reported-by: Lei Yang Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-vdpa.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 983d3697b0..7e28d2f674 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -176,6 +176,7 @@ static void vhost_vdpa_listener_commit(MemoryListener *listener) static void vhost_vdpa_listener_region_add(MemoryListener *listener, MemoryRegionSection *section) { + DMAMap mem_region = {}; struct vhost_vdpa *v = container_of(listener, struct vhost_vdpa, listener); hwaddr iova; Int128 llend, llsize; @@ -212,13 +213,13 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, llsize = int128_sub(llend, int128_make64(iova)); if (v->shadow_vqs_enabled) { - DMAMap mem_region = { - .translated_addr = (hwaddr)(uintptr_t)vaddr, - .size = int128_get64(llsize) - 1, - .perm = IOMMU_ACCESS_FLAG(true, section->readonly), - }; + int r; - int r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region); + mem_region.translated_addr = (hwaddr)(uintptr_t)vaddr, + mem_region.size = int128_get64(llsize) - 1, + mem_region.perm = IOMMU_ACCESS_FLAG(true, section->readonly), + + r = vhost_iova_tree_map_alloc(v->iova_tree, &mem_region); if (unlikely(r != IOVA_OK)) { error_report("Can't allocate a mapping (%d)", r); goto fail; @@ -232,11 +233,16 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, vaddr, section->readonly); if (ret) { error_report("vhost vdpa map fail!"); - goto fail; + goto fail_map; } return; +fail_map: + if (v->shadow_vqs_enabled) { + vhost_iova_tree_remove(v->iova_tree, &mem_region); + } + fail: /* * On the initfn path, store the first error in the container so we From 69292a8e40f4dae8af5f04724e06392cdf03c09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:20:04 +0200 Subject: [PATCH 0307/1020] util: accept iova_tree_remove_parameter by value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's convenient to call iova_tree_remove from a map returned from iova_tree_find or iova_tree_find_iova. With the current code this is not possible, since we will free it, and then we will try to search for it again. Fix it making accepting the map by value, forcing a copy of the argument. Not applying a fixes tag, since there is no use like that at the moment. Signed-off-by: Eugenio PĂ©rez Signed-off-by: Jason Wang --- hw/i386/intel_iommu.c | 6 +++--- hw/virtio/vhost-iova-tree.c | 2 +- hw/virtio/vhost-iova-tree.h | 2 +- hw/virtio/vhost-vdpa.c | 6 +++--- include/qemu/iova-tree.h | 2 +- net/vhost-vdpa.c | 4 ++-- util/iova-tree.c | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 2162394e08..05d53a1aa9 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -1187,7 +1187,7 @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info) return ret; } /* Drop any existing mapping */ - iova_tree_remove(as->iova_tree, &target); + iova_tree_remove(as->iova_tree, target); /* Recover the correct type */ event->type = IOMMU_NOTIFIER_MAP; entry->perm = cache_perm; @@ -1200,7 +1200,7 @@ static int vtd_page_walk_one(IOMMUTLBEvent *event, vtd_page_walk_info *info) trace_vtd_page_walk_one_skip_unmap(entry->iova, entry->addr_mask); return 0; } - iova_tree_remove(as->iova_tree, &target); + iova_tree_remove(as->iova_tree, target); } trace_vtd_page_walk_one(info->domain_id, entry->iova, @@ -3563,7 +3563,7 @@ static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n) map.iova = n->start; map.size = size; - iova_tree_remove(as->iova_tree, &map); + iova_tree_remove(as->iova_tree, map); } static void vtd_address_space_unmap_all(IntelIOMMUState *s) diff --git a/hw/virtio/vhost-iova-tree.c b/hw/virtio/vhost-iova-tree.c index 67bf6d57ab..3d03395a77 100644 --- a/hw/virtio/vhost-iova-tree.c +++ b/hw/virtio/vhost-iova-tree.c @@ -104,7 +104,7 @@ int vhost_iova_tree_map_alloc(VhostIOVATree *tree, DMAMap *map) * @iova_tree: The vhost iova tree * @map: The map to remove */ -void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map) +void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map) { iova_tree_remove(iova_tree->iova_taddr_map, map); } diff --git a/hw/virtio/vhost-iova-tree.h b/hw/virtio/vhost-iova-tree.h index 6a4f24e0f9..4adfd79ff0 100644 --- a/hw/virtio/vhost-iova-tree.h +++ b/hw/virtio/vhost-iova-tree.h @@ -22,6 +22,6 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(VhostIOVATree, vhost_iova_tree_delete); const DMAMap *vhost_iova_tree_find_iova(const VhostIOVATree *iova_tree, const DMAMap *map); int vhost_iova_tree_map_alloc(VhostIOVATree *iova_tree, DMAMap *map); -void vhost_iova_tree_remove(VhostIOVATree *iova_tree, const DMAMap *map); +void vhost_iova_tree_remove(VhostIOVATree *iova_tree, DMAMap map); #endif diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 7e28d2f674..87e0ad393f 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -240,7 +240,7 @@ static void vhost_vdpa_listener_region_add(MemoryListener *listener, fail_map: if (v->shadow_vqs_enabled) { - vhost_iova_tree_remove(v->iova_tree, &mem_region); + vhost_iova_tree_remove(v->iova_tree, mem_region); } fail: @@ -300,7 +300,7 @@ static void vhost_vdpa_listener_region_del(MemoryListener *listener, return; } iova = result->iova; - vhost_iova_tree_remove(v->iova_tree, result); + vhost_iova_tree_remove(v->iova_tree, *result); } vhost_vdpa_iotlb_batch_begin_once(v); ret = vhost_vdpa_dma_unmap(v, iova, int128_get64(llsize)); @@ -944,7 +944,7 @@ static bool vhost_vdpa_svq_map_ring(struct vhost_vdpa *v, DMAMap *needle, needle->perm == IOMMU_RO); if (unlikely(r != 0)) { error_setg_errno(errp, -r, "Cannot map region to device"); - vhost_iova_tree_remove(v->iova_tree, needle); + vhost_iova_tree_remove(v->iova_tree, *needle); } return r == 0; diff --git a/include/qemu/iova-tree.h b/include/qemu/iova-tree.h index 16bbfdf5f8..8528e5c98f 100644 --- a/include/qemu/iova-tree.h +++ b/include/qemu/iova-tree.h @@ -73,7 +73,7 @@ int iova_tree_insert(IOVATree *tree, const DMAMap *map); * all the mappings that are included in the provided range will be * removed from the tree. Here map->translated_addr is meaningless. */ -void iova_tree_remove(IOVATree *tree, const DMAMap *map); +void iova_tree_remove(IOVATree *tree, DMAMap map); /** * iova_tree_find: diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 303447a68e..a49e7e649d 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -244,7 +244,7 @@ static void vhost_vdpa_cvq_unmap_buf(struct vhost_vdpa *v, void *addr) error_report("Device cannot unmap: %s(%d)", g_strerror(r), r); } - vhost_iova_tree_remove(tree, map); + vhost_iova_tree_remove(tree, *map); } static size_t vhost_vdpa_net_cvq_cmd_len(void) @@ -297,7 +297,7 @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, return true; dma_map_err: - vhost_iova_tree_remove(v->iova_tree, &map); + vhost_iova_tree_remove(v->iova_tree, map); return false; } diff --git a/util/iova-tree.c b/util/iova-tree.c index fee530a579..536789797e 100644 --- a/util/iova-tree.c +++ b/util/iova-tree.c @@ -164,11 +164,11 @@ void iova_tree_foreach(IOVATree *tree, iova_tree_iterator iterator) g_tree_foreach(tree->tree, iova_tree_traverse, iterator); } -void iova_tree_remove(IOVATree *tree, const DMAMap *map) +void iova_tree_remove(IOVATree *tree, DMAMap map) { const DMAMap *overlap; - while ((overlap = iova_tree_find(tree, map))) { + while ((overlap = iova_tree_find(tree, &map))) { g_tree_remove(tree->tree, overlap); } } From b37c12be962f95fd1e93b470a5ff05f6e2035d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:20:05 +0200 Subject: [PATCH 0308/1020] vdpa: Remove SVQ vring from iova_tree at shutdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although the device will be reset before usage, the right thing to do is to clean it. Reported-by: Lei Yang Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ") Signed-off-by: Eugenio PĂ©rez Signed-off-by: Jason Wang --- hw/virtio/vhost-vdpa.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 87e0ad393f..e16e0e222e 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -898,6 +898,12 @@ static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, size = ROUND_UP(result->size, qemu_real_host_page_size()); r = vhost_vdpa_dma_unmap(v, result->iova, size); + if (unlikely(r < 0)) { + error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r); + return false; + } + + vhost_iova_tree_remove(v->iova_tree, *result); return r == 0; } From 5b590f51b923776a14d3bcafcb393279c1b72022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:20:06 +0200 Subject: [PATCH 0309/1020] vdpa: Make SVQ vring unmapping return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing actually reads the return value, but an error in cleaning some entries could cause device stop to abort, making a restart impossible. Better ignore explicitely the return value. Reported-by: Lei Yang Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ") Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-vdpa.c | 32 ++++++++++---------------------- 1 file changed, 10 insertions(+), 22 deletions(-) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index e16e0e222e..e208dd000e 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -884,7 +884,7 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, /** * Unmap a SVQ area in the device */ -static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, +static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, const DMAMap *needle) { const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle); @@ -893,38 +893,33 @@ static bool vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, if (unlikely(!result)) { error_report("Unable to find SVQ address to unmap"); - return false; + return; } size = ROUND_UP(result->size, qemu_real_host_page_size()); r = vhost_vdpa_dma_unmap(v, result->iova, size); if (unlikely(r < 0)) { error_report("Unable to unmap SVQ vring: %s (%d)", g_strerror(-r), -r); - return false; + return; } vhost_iova_tree_remove(v->iova_tree, *result); - return r == 0; } -static bool vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev, +static void vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev, const VhostShadowVirtqueue *svq) { DMAMap needle = {}; struct vhost_vdpa *v = dev->opaque; struct vhost_vring_addr svq_addr; - bool ok; vhost_svq_get_vring_addr(svq, &svq_addr); needle.translated_addr = svq_addr.desc_user_addr; - ok = vhost_vdpa_svq_unmap_ring(v, &needle); - if (unlikely(!ok)) { - return false; - } + vhost_vdpa_svq_unmap_ring(v, &needle); needle.translated_addr = svq_addr.used_user_addr; - return vhost_vdpa_svq_unmap_ring(v, &needle); + vhost_vdpa_svq_unmap_ring(v, &needle); } /** @@ -1095,26 +1090,22 @@ err: return false; } -static bool vhost_vdpa_svqs_stop(struct vhost_dev *dev) +static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) { struct vhost_vdpa *v = dev->opaque; if (!v->shadow_vqs) { - return true; + return; } for (unsigned i = 0; i < v->shadow_vqs->len; ++i) { VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); - bool ok = vhost_vdpa_svq_unmap_rings(dev, svq); - if (unlikely(!ok)) { - return false; - } + vhost_vdpa_svq_unmap_rings(dev, svq); } if (v->migration_blocker) { migrate_del_blocker(v->migration_blocker); } - return true; } static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) @@ -1131,10 +1122,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) } vhost_vdpa_set_vring_ready(dev); } else { - ok = vhost_vdpa_svqs_stop(dev); - if (unlikely(!ok)) { - return -1; - } + vhost_vdpa_svqs_stop(dev); vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs); } From 8b64e486423b09db4463799727bf1fad62fe496a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:20:07 +0200 Subject: [PATCH 0310/1020] vhost: Always store new kick fd on vhost_svq_set_svq_kick_fd MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can unbind twice a file descriptor if we call twice vhost_svq_set_svq_kick_fd because of this. Since it comes from vhost and not from SVQ, that file descriptor could be a different thing that guest's vhost notifier. Likewise, it can happens the same if a guest start and stop the device multiple times. Reported-by: Lei Yang Fixes: dff4426fa6 ("vhost: Add Shadow VirtQueue kick forwarding capabilities") Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-shadow-virtqueue.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index e4956728dd..82a784d250 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -602,13 +602,13 @@ void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd) event_notifier_set_handler(svq_kick, NULL); } + event_notifier_init_fd(svq_kick, svq_kick_fd); /* * event_notifier_set_handler already checks for guest's notifications if * they arrive at the new file descriptor in the switch, so there is no * need to explicitly check for them. */ if (poll_start) { - event_notifier_init_fd(svq_kick, svq_kick_fd); event_notifier_set(svq_kick); event_notifier_set_handler(svq_kick, vhost_handle_guest_kick_notifier); } @@ -655,7 +655,7 @@ void vhost_svq_start(VhostShadowVirtqueue *svq, VirtIODevice *vdev, */ void vhost_svq_stop(VhostShadowVirtqueue *svq) { - event_notifier_set_handler(&svq->svq_kick, NULL); + vhost_svq_set_svq_kick_fd(svq, VHOST_FILE_UNBIND); g_autofree VirtQueueElement *next_avail_elem = NULL; if (!svq->vq) { From 8b6d6119ad7fd983d192f60c4960fb6a9197d995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:20:08 +0200 Subject: [PATCH 0311/1020] vdpa: Use ring hwaddr at vhost_vdpa_svq_unmap_ring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce code duplication. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-vdpa.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index e208dd000e..23ae5ef48b 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -884,10 +884,12 @@ static int vhost_vdpa_svq_set_fds(struct vhost_dev *dev, /** * Unmap a SVQ area in the device */ -static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, - const DMAMap *needle) +static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, hwaddr addr) { - const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, needle); + const DMAMap needle = { + .translated_addr = addr, + }; + const DMAMap *result = vhost_iova_tree_find_iova(v->iova_tree, &needle); hwaddr size; int r; @@ -909,17 +911,14 @@ static void vhost_vdpa_svq_unmap_ring(struct vhost_vdpa *v, static void vhost_vdpa_svq_unmap_rings(struct vhost_dev *dev, const VhostShadowVirtqueue *svq) { - DMAMap needle = {}; struct vhost_vdpa *v = dev->opaque; struct vhost_vring_addr svq_addr; vhost_svq_get_vring_addr(svq, &svq_addr); - needle.translated_addr = svq_addr.desc_user_addr; - vhost_vdpa_svq_unmap_ring(v, &needle); + vhost_vdpa_svq_unmap_ring(v, svq_addr.desc_user_addr); - needle.translated_addr = svq_addr.used_user_addr; - vhost_vdpa_svq_unmap_ring(v, &needle); + vhost_vdpa_svq_unmap_ring(v, svq_addr.used_user_addr); } /** @@ -997,7 +996,7 @@ static bool vhost_vdpa_svq_map_rings(struct vhost_dev *dev, ok = vhost_vdpa_svq_map_ring(v, &device_region, errp); if (unlikely(!ok)) { error_prepend(errp, "Cannot create vq device region: "); - vhost_vdpa_svq_unmap_ring(v, &driver_region); + vhost_vdpa_svq_unmap_ring(v, driver_region.translated_addr); } addr->used_user_addr = device_region.iova; From 9c2ab2f1ec333be8614cc12272d4b91960704dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:26 +0200 Subject: [PATCH 0312/1020] vhost: stop transfer elem ownership in vhost_handle_guest_kick MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was easier to allow vhost_svq_add to handle the memory. Now that we will allow qemu to add elements to a SVQ without the guest's knowledge, it's better to handle it in the caller. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-shadow-virtqueue.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index 82a784d250..a1261d4a0f 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -233,9 +233,6 @@ static void vhost_svq_kick(VhostShadowVirtqueue *svq) /** * Add an element to a SVQ. * - * The caller must check that there is enough slots for the new element. It - * takes ownership of the element: In case of failure not ENOSPC, it is free. - * * Return -EINVAL if element is invalid, -ENOSPC if dev queue is full */ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, @@ -252,7 +249,6 @@ int vhost_svq_add(VhostShadowVirtqueue *svq, const struct iovec *out_sg, ok = vhost_svq_add_split(svq, out_sg, out_num, in_sg, in_num, &qemu_head); if (unlikely(!ok)) { - g_free(elem); return -EINVAL; } @@ -293,7 +289,7 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) virtio_queue_set_notification(svq->vq, false); while (true) { - VirtQueueElement *elem; + g_autofree VirtQueueElement *elem; int r; if (svq->next_guest_avail_elem) { @@ -324,12 +320,14 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) * queue the current guest descriptor and ignore kicks * until some elements are used. */ - svq->next_guest_avail_elem = elem; + svq->next_guest_avail_elem = g_steal_pointer(&elem); } /* VQ is full or broken, just return and ignore kicks */ return; } + /* elem belongs to SVQ or external caller now */ + elem = NULL; } virtio_queue_set_notification(svq->vq, true); From 86f5f2546f03a3dfde421c715187b262e29b2848 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:27 +0200 Subject: [PATCH 0313/1020] vhost: use SVQ element ndescs instead of opaque data for desc validation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we're going to allow SVQ to add elements without the guest's knowledge and without its own VirtQueueElement, it's easier to check if an element is a valid head checking a different thing than the VirtQueueElement. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-shadow-virtqueue.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index a1261d4a0f..b35aeef4bd 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -414,7 +414,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, return NULL; } - if (unlikely(!svq->desc_state[used_elem.id].elem)) { + if (unlikely(!svq->desc_state[used_elem.id].ndescs)) { qemu_log_mask(LOG_GUEST_ERROR, "Device %s says index %u is used, but it was not available", svq->vdev->name, used_elem.id); @@ -422,6 +422,7 @@ static VirtQueueElement *vhost_svq_get_buf(VhostShadowVirtqueue *svq, } num = svq->desc_state[used_elem.id].ndescs; + svq->desc_state[used_elem.id].ndescs = 0; last_used_chain = vhost_svq_last_desc_of_chain(svq, num, used_elem.id); svq->desc_next[last_used_chain] = svq->free_head; svq->free_head = used_elem.id; From 9e193cec5db949e4001070442a2f7de7042ef09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:28 +0200 Subject: [PATCH 0314/1020] vhost: Delete useless read memory barrier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As discussed in previous series [1], this memory barrier is useless with the atomic read of used idx at vhost_svq_more_used. Deleting it. [1] https://lists.nongnu.org/archive/html/qemu-devel/2022-07/msg02616.html Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-shadow-virtqueue.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index b35aeef4bd..8df5296f24 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -509,9 +509,6 @@ size_t vhost_svq_poll(VhostShadowVirtqueue *svq) if (unlikely(g_get_monotonic_time() - start_us > 10e6)) { return 0; } - - /* Make sure we read new used_idx */ - smp_rmb(); } while (true); } From d368c0b052ad95d3bf4fcc5a5d25715a35c91d4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:29 +0200 Subject: [PATCH 0315/1020] vhost: Do not depend on !NULL VirtQueueElement on vhost_svq_flush MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since QEMU will be able to inject new elements on CVQ to restore the state, we need not to depend on a VirtQueueElement to know if a new element has been used by the device or not. Instead of check that, check if there are new elements only using used idx on vhost_svq_flush. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-shadow-virtqueue.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index 8df5296f24..e8e5bbc368 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -499,17 +499,20 @@ static void vhost_svq_flush(VhostShadowVirtqueue *svq, size_t vhost_svq_poll(VhostShadowVirtqueue *svq) { int64_t start_us = g_get_monotonic_time(); + uint32_t len; + do { - uint32_t len; - VirtQueueElement *elem = vhost_svq_get_buf(svq, &len); - if (elem) { - return len; + if (vhost_svq_more_used(svq)) { + break; } if (unlikely(g_get_monotonic_time() - start_us > 10e6)) { return 0; } } while (true); + + vhost_svq_get_buf(svq, &len); + return len; } /** From eb92b75380fc0f2368e22be45d1e2d1e2cd2f79c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:30 +0200 Subject: [PATCH 0316/1020] vhost_net: Add NetClientInfo start callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is used by the backend to perform actions before the device is started. In particular, vdpa net use it to map CVQ buffers to the device, so it can send control commands using them. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/net/vhost_net.c | 7 +++++++ include/net/net.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index ccac5b7a64..2e0baeba26 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -244,6 +244,13 @@ static int vhost_net_start_one(struct vhost_net *net, struct vhost_vring_file file = { }; int r; + if (net->nc->info->start) { + r = net->nc->info->start(net->nc); + if (r < 0) { + return r; + } + } + r = vhost_dev_enable_notifiers(&net->dev, dev); if (r < 0) { goto fail_notifiers; diff --git a/include/net/net.h b/include/net/net.h index 523136c7ac..ad9e80083a 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -44,6 +44,7 @@ typedef struct NICConf { typedef void (NetPoll)(NetClientState *, bool enable); typedef bool (NetCanReceive)(NetClientState *); +typedef int (NetStart)(NetClientState *); typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t); typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); typedef void (NetCleanup) (NetClientState *); @@ -71,6 +72,7 @@ typedef struct NetClientInfo { NetReceive *receive_raw; NetReceiveIOV *receive_iov; NetCanReceive *can_receive; + NetStart *start; NetCleanup *cleanup; LinkStatusChanged *link_status_changed; QueryRxFilter *query_rx_filter; From c5e5269d8a955a0f924218911c2f4a0b34e87a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:31 +0200 Subject: [PATCH 0317/1020] vhost_net: Add NetClientInfo stop callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Used by the backend to perform actions after the device is stopped. In particular, vdpa net use it to unmap CVQ buffers to the device, cleaning the actions performed in prepare(). Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/net/vhost_net.c | 3 +++ include/net/net.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 2e0baeba26..9d4b334453 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -320,6 +320,9 @@ static void vhost_net_stop_one(struct vhost_net *net, net->nc->info->poll(net->nc, true); } vhost_dev_stop(&net->dev, dev); + if (net->nc->info->stop) { + net->nc->info->stop(net->nc); + } vhost_dev_disable_notifiers(&net->dev, dev); } diff --git a/include/net/net.h b/include/net/net.h index ad9e80083a..476ad45b9a 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -45,6 +45,7 @@ typedef struct NICConf { typedef void (NetPoll)(NetClientState *, bool enable); typedef bool (NetCanReceive)(NetClientState *); typedef int (NetStart)(NetClientState *); +typedef void (NetStop)(NetClientState *); typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t); typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); typedef void (NetCleanup) (NetClientState *); @@ -73,6 +74,7 @@ typedef struct NetClientInfo { NetReceiveIOV *receive_iov; NetCanReceive *can_receive; NetStart *start; + NetStop *stop; NetCleanup *cleanup; LinkStatusChanged *link_status_changed; QueryRxFilter *query_rx_filter; From f8972b56eeace10a410990f032406250abe18d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:32 +0200 Subject: [PATCH 0318/1020] vdpa: add net_vhost_vdpa_cvq_info NetClientInfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Next patches will add a new info callback to restore NIC status through CVQ. Since only the CVQ vhost device is needed, create it with a new NetClientInfo. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index a49e7e649d..1a597c2e92 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -334,6 +334,16 @@ static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, return true; } +static NetClientInfo net_vhost_vdpa_cvq_info = { + .type = NET_CLIENT_DRIVER_VHOST_VDPA, + .size = sizeof(VhostVDPAState), + .receive = vhost_vdpa_receive, + .cleanup = vhost_vdpa_cleanup, + .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, + .has_ufo = vhost_vdpa_has_ufo, + .check_peer_type = vhost_vdpa_check_peer_type, +}; + /** * Do not forward commands not supported by SVQ. Otherwise, the device could * accept it and qemu would not know how to update the device model. @@ -475,7 +485,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, nc = qemu_new_net_client(&net_vhost_vdpa_info, peer, device, name); } else { - nc = qemu_new_net_control_client(&net_vhost_vdpa_info, peer, + nc = qemu_new_net_control_client(&net_vhost_vdpa_cvq_info, peer, device, name); } snprintf(nc->info_str, sizeof(nc->info_str), TYPE_VHOST_VDPA); From 7a7f87e94c4e75ca177564491595dd17b7e41a62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:33 +0200 Subject: [PATCH 0319/1020] vdpa: Move command buffers map to start of net device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As this series will reuse them to restore the device state at the end of a migration (or a device start), let's allocate only once at the device start so we don't duplicate their map and unmap. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 123 ++++++++++++++++++++++------------------------- 1 file changed, 58 insertions(+), 65 deletions(-) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 1a597c2e92..452d10ed93 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -263,29 +263,20 @@ static size_t vhost_vdpa_net_cvq_cmd_page_len(void) return ROUND_UP(vhost_vdpa_net_cvq_cmd_len(), qemu_real_host_page_size()); } -/** Copy and map a guest buffer. */ -static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, - const struct iovec *out_data, - size_t out_num, size_t data_len, void *buf, - size_t *written, bool write) +/** Map CVQ buffer. */ +static int vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, void *buf, size_t size, + bool write) { DMAMap map = {}; int r; - if (unlikely(!data_len)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid legnth of %s buffer\n", - __func__, write ? "in" : "out"); - return false; - } - - *written = iov_to_buf(out_data, out_num, 0, buf, data_len); map.translated_addr = (hwaddr)(uintptr_t)buf; - map.size = vhost_vdpa_net_cvq_cmd_page_len() - 1; + map.size = size - 1; map.perm = write ? IOMMU_RW : IOMMU_RO, r = vhost_iova_tree_map_alloc(v->iova_tree, &map); if (unlikely(r != IOVA_OK)) { error_report("Cannot map injected element"); - return false; + return r; } r = vhost_vdpa_dma_map(v, map.iova, vhost_vdpa_net_cvq_cmd_page_len(), buf, @@ -294,50 +285,58 @@ static bool vhost_vdpa_cvq_map_buf(struct vhost_vdpa *v, goto dma_map_err; } - return true; + return 0; dma_map_err: vhost_iova_tree_remove(v->iova_tree, map); - return false; + return r; } -/** - * Copy the guest element into a dedicated buffer suitable to be sent to NIC - * - * @iov: [0] is the out buffer, [1] is the in one - */ -static bool vhost_vdpa_net_cvq_map_elem(VhostVDPAState *s, - VirtQueueElement *elem, - struct iovec *iov) +static int vhost_vdpa_net_cvq_start(NetClientState *nc) { - size_t in_copied; - bool ok; + VhostVDPAState *s; + int r; - iov[0].iov_base = s->cvq_cmd_out_buffer; - ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, elem->out_sg, elem->out_num, - vhost_vdpa_net_cvq_cmd_len(), iov[0].iov_base, - &iov[0].iov_len, false); - if (unlikely(!ok)) { - return false; + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + + s = DO_UPCAST(VhostVDPAState, nc, nc); + if (!s->vhost_vdpa.shadow_vqs_enabled) { + return 0; } - iov[1].iov_base = s->cvq_cmd_in_buffer; - ok = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, NULL, 0, - sizeof(virtio_net_ctrl_ack), iov[1].iov_base, - &in_copied, true); - if (unlikely(!ok)) { + r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer, + vhost_vdpa_net_cvq_cmd_page_len(), false); + if (unlikely(r < 0)) { + return r; + } + + r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer, + vhost_vdpa_net_cvq_cmd_page_len(), true); + if (unlikely(r < 0)) { vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); - return false; } - iov[1].iov_len = sizeof(virtio_net_ctrl_ack); - return true; + return r; +} + +static void vhost_vdpa_net_cvq_stop(NetClientState *nc) +{ + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); + + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + + if (s->vhost_vdpa.shadow_vqs_enabled) { + vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); + vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer); + } } static NetClientInfo net_vhost_vdpa_cvq_info = { .type = NET_CLIENT_DRIVER_VHOST_VDPA, .size = sizeof(VhostVDPAState), .receive = vhost_vdpa_receive, + .start = vhost_vdpa_net_cvq_start, + .stop = vhost_vdpa_net_cvq_stop, .cleanup = vhost_vdpa_cleanup, .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, .has_ufo = vhost_vdpa_has_ufo, @@ -348,19 +347,17 @@ static NetClientInfo net_vhost_vdpa_cvq_info = { * Do not forward commands not supported by SVQ. Otherwise, the device could * accept it and qemu would not know how to update the device model. */ -static bool vhost_vdpa_net_cvq_validate_cmd(const struct iovec *out, - size_t out_num) +static bool vhost_vdpa_net_cvq_validate_cmd(const void *out_buf, size_t len) { struct virtio_net_ctrl_hdr ctrl; - size_t n; - n = iov_to_buf(out, out_num, 0, &ctrl, sizeof(ctrl)); - if (unlikely(n < sizeof(ctrl))) { + if (unlikely(len < sizeof(ctrl))) { qemu_log_mask(LOG_GUEST_ERROR, - "%s: invalid legnth of out buffer %zu\n", __func__, n); + "%s: invalid legnth of out buffer %zu\n", __func__, len); return false; } + memcpy(&ctrl, out_buf, sizeof(ctrl)); switch (ctrl.class) { case VIRTIO_NET_CTRL_MAC: switch (ctrl.cmd) { @@ -392,10 +389,14 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, VhostVDPAState *s = opaque; size_t in_len, dev_written; virtio_net_ctrl_ack status = VIRTIO_NET_ERR; - /* out and in buffers sent to the device */ - struct iovec dev_buffers[2] = { - { .iov_base = s->cvq_cmd_out_buffer }, - { .iov_base = s->cvq_cmd_in_buffer }, + /* Out buffer sent to both the vdpa device and the device model */ + struct iovec out = { + .iov_base = s->cvq_cmd_out_buffer, + }; + /* In buffer sent to the device */ + const struct iovec dev_in = { + .iov_base = s->cvq_cmd_in_buffer, + .iov_len = sizeof(virtio_net_ctrl_ack), }; /* in buffer used for device model */ const struct iovec in = { @@ -405,17 +406,15 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, int r = -EINVAL; bool ok; - ok = vhost_vdpa_net_cvq_map_elem(s, elem, dev_buffers); + out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0, + s->cvq_cmd_out_buffer, + vhost_vdpa_net_cvq_cmd_len()); + ok = vhost_vdpa_net_cvq_validate_cmd(s->cvq_cmd_out_buffer, out.iov_len); if (unlikely(!ok)) { goto out; } - ok = vhost_vdpa_net_cvq_validate_cmd(&dev_buffers[0], 1); - if (unlikely(!ok)) { - goto out; - } - - r = vhost_svq_add(svq, &dev_buffers[0], 1, &dev_buffers[1], 1, elem); + r = vhost_svq_add(svq, &out, 1, &dev_in, 1, elem); if (unlikely(r != 0)) { if (unlikely(r == -ENOSPC)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n", @@ -435,13 +434,13 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, goto out; } - memcpy(&status, dev_buffers[1].iov_base, sizeof(status)); + memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status)); if (status != VIRTIO_NET_OK) { goto out; } status = VIRTIO_NET_ERR; - virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, dev_buffers, 1); + virtio_net_handle_ctrl_iov(svq->vdev, &in, 1, &out, 1); if (status != VIRTIO_NET_OK) { error_report("Bad CVQ processing in model"); } @@ -454,12 +453,6 @@ out: } vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status))); g_free(elem); - if (dev_buffers[0].iov_base) { - vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[0].iov_base); - } - if (dev_buffers[1].iov_base) { - vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, dev_buffers[1].iov_base); - } return r; } From be4278b65fc1be8fce87e1e7c01bc52602d304eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:34 +0200 Subject: [PATCH 0320/1020] vdpa: extract vhost_vdpa_net_cvq_add from vhost_vdpa_net_handle_ctrl_avail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So we can reuse it to inject state messages. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang -- v7: * Remove double free error v6: * Do not assume in buffer sent to the device is sizeof(virtio_net_ctrl_ack) v5: * Do not use an artificial !NULL VirtQueueElement * Use only out size instead of iovec dev_buffers for these functions. Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 59 +++++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 452d10ed93..3575bf64ee 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -331,6 +331,38 @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc) } } +static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, + size_t in_len) +{ + /* Buffers for the device */ + const struct iovec out = { + .iov_base = s->cvq_cmd_out_buffer, + .iov_len = out_len, + }; + const struct iovec in = { + .iov_base = s->cvq_cmd_in_buffer, + .iov_len = sizeof(virtio_net_ctrl_ack), + }; + VhostShadowVirtqueue *svq = g_ptr_array_index(s->vhost_vdpa.shadow_vqs, 0); + int r; + + r = vhost_svq_add(svq, &out, 1, &in, 1, NULL); + if (unlikely(r != 0)) { + if (unlikely(r == -ENOSPC)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n", + __func__); + } + return r; + } + + /* + * We can poll here since we've had BQL from the time we sent the + * descriptor. Also, we need to take the answer before SVQ pulls by itself, + * when BQL is released + */ + return vhost_svq_poll(svq); +} + static NetClientInfo net_vhost_vdpa_cvq_info = { .type = NET_CLIENT_DRIVER_VHOST_VDPA, .size = sizeof(VhostVDPAState), @@ -387,23 +419,18 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, void *opaque) { VhostVDPAState *s = opaque; - size_t in_len, dev_written; + size_t in_len; virtio_net_ctrl_ack status = VIRTIO_NET_ERR; /* Out buffer sent to both the vdpa device and the device model */ struct iovec out = { .iov_base = s->cvq_cmd_out_buffer, }; - /* In buffer sent to the device */ - const struct iovec dev_in = { - .iov_base = s->cvq_cmd_in_buffer, - .iov_len = sizeof(virtio_net_ctrl_ack), - }; /* in buffer used for device model */ const struct iovec in = { .iov_base = &status, .iov_len = sizeof(status), }; - int r = -EINVAL; + ssize_t dev_written = -EINVAL; bool ok; out.iov_len = iov_to_buf(elem->out_sg, elem->out_num, 0, @@ -414,21 +441,11 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, goto out; } - r = vhost_svq_add(svq, &out, 1, &dev_in, 1, elem); - if (unlikely(r != 0)) { - if (unlikely(r == -ENOSPC)) { - qemu_log_mask(LOG_GUEST_ERROR, "%s: No space on device queue\n", - __func__); - } + dev_written = vhost_vdpa_net_cvq_add(s, out.iov_len, sizeof(status)); + if (unlikely(dev_written < 0)) { goto out; } - /* - * We can poll here since we've had BQL from the time we sent the - * descriptor. Also, we need to take the answer before SVQ pulls by itself, - * when BQL is released - */ - dev_written = vhost_svq_poll(svq); if (unlikely(dev_written < sizeof(status))) { error_report("Insufficient written data (%zu)", dev_written); goto out; @@ -436,7 +453,7 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status)); if (status != VIRTIO_NET_OK) { - goto out; + return VIRTIO_NET_ERR; } status = VIRTIO_NET_ERR; @@ -453,7 +470,7 @@ out: } vhost_svq_push_elem(svq, elem, MIN(in_len, sizeof(status))); g_free(elem); - return r; + return dev_written < 0 ? dev_written : 0; } static const VhostShadowVirtqueueOps vhost_vdpa_net_svq_ops = { From 539573c317dc0b8d50a128db60550f2f2898d2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:35 +0200 Subject: [PATCH 0321/1020] vhost_net: add NetClientState->load() callback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It allows per-net client operations right after device's successful start. In particular, to load the device status. Vhost-vdpa net will use it to add the CVQ buffers to restore the device status. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/net/vhost_net.c | 7 +++++++ include/net/net.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 9d4b334453..d28f8b974b 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -281,6 +281,13 @@ static int vhost_net_start_one(struct vhost_net *net, } } } + + if (net->nc->info->load) { + r = net->nc->info->load(net->nc); + if (r < 0) { + goto fail; + } + } return 0; fail: file.fd = -1; diff --git a/include/net/net.h b/include/net/net.h index 476ad45b9a..81d0b21def 100644 --- a/include/net/net.h +++ b/include/net/net.h @@ -45,6 +45,7 @@ typedef struct NICConf { typedef void (NetPoll)(NetClientState *, bool enable); typedef bool (NetCanReceive)(NetClientState *); typedef int (NetStart)(NetClientState *); +typedef int (NetLoad)(NetClientState *); typedef void (NetStop)(NetClientState *); typedef ssize_t (NetReceive)(NetClientState *, const uint8_t *, size_t); typedef ssize_t (NetReceiveIOV)(NetClientState *, const struct iovec *, int); @@ -74,6 +75,7 @@ typedef struct NetClientInfo { NetReceiveIOV *receive_iov; NetCanReceive *can_receive; NetStart *start; + NetLoad *load; NetStop *stop; NetCleanup *cleanup; LinkStatusChanged *link_status_changed; From dd036d8d278e6882803bccaa8c51b8527ea33f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:36 +0200 Subject: [PATCH 0322/1020] vdpa: Add virtio-net mac address via CVQ at start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is needed so the destination vdpa device see the same state a the guest set in the source. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 3575bf64ee..640434d1ea 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -363,11 +363,51 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, return vhost_svq_poll(svq); } +static int vhost_vdpa_net_load(NetClientState *nc) +{ + VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); + const struct vhost_vdpa *v = &s->vhost_vdpa; + const VirtIONet *n; + uint64_t features; + + assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); + + if (!v->shadow_vqs_enabled) { + return 0; + } + + n = VIRTIO_NET(v->dev->vdev); + features = n->parent_obj.guest_features; + if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) { + const struct virtio_net_ctrl_hdr ctrl = { + .class = VIRTIO_NET_CTRL_MAC, + .cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET, + }; + char *cursor = s->cvq_cmd_out_buffer; + ssize_t dev_written; + + memcpy(cursor, &ctrl, sizeof(ctrl)); + cursor += sizeof(ctrl); + memcpy(cursor, n->mac, sizeof(n->mac)); + + dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + sizeof(n->mac), + sizeof(virtio_net_ctrl_ack)); + if (unlikely(dev_written < 0)) { + return dev_written; + } + + return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != VIRTIO_NET_OK; + } + + return 0; +} + static NetClientInfo net_vhost_vdpa_cvq_info = { .type = NET_CLIENT_DRIVER_VHOST_VDPA, .size = sizeof(VhostVDPAState), .receive = vhost_vdpa_receive, .start = vhost_vdpa_net_cvq_start, + .load = vhost_vdpa_net_load, .stop = vhost_vdpa_net_cvq_stop, .cleanup = vhost_vdpa_cleanup, .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, From 0e3fdcffead7c651ce06ab50cffb89e806f04e2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 23 Aug 2022 20:30:37 +0200 Subject: [PATCH 0323/1020] vdpa: Delete CVQ migration blocker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can restore the device state in the destination via CVQ now. Remove the migration blocker. Signed-off-by: Eugenio PĂ©rez Acked-by: Jason Wang Signed-off-by: Jason Wang --- hw/virtio/vhost-vdpa.c | 15 --------------- include/hw/virtio/vhost-vdpa.h | 1 - net/vhost-vdpa.c | 2 -- 3 files changed, 18 deletions(-) diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c index 23ae5ef48b..7468e44b87 100644 --- a/hw/virtio/vhost-vdpa.c +++ b/hw/virtio/vhost-vdpa.c @@ -1033,13 +1033,6 @@ static bool vhost_vdpa_svqs_start(struct vhost_dev *dev) return true; } - if (v->migration_blocker) { - int r = migrate_add_blocker(v->migration_blocker, &err); - if (unlikely(r < 0)) { - return false; - } - } - for (i = 0; i < v->shadow_vqs->len; ++i) { VirtQueue *vq = virtio_get_queue(dev->vdev, dev->vq_index + i); VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); @@ -1082,10 +1075,6 @@ err: vhost_svq_stop(svq); } - if (v->migration_blocker) { - migrate_del_blocker(v->migration_blocker); - } - return false; } @@ -1101,10 +1090,6 @@ static void vhost_vdpa_svqs_stop(struct vhost_dev *dev) VhostShadowVirtqueue *svq = g_ptr_array_index(v->shadow_vqs, i); vhost_vdpa_svq_unmap_rings(dev, svq); } - - if (v->migration_blocker) { - migrate_del_blocker(v->migration_blocker); - } } static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started) diff --git a/include/hw/virtio/vhost-vdpa.h b/include/hw/virtio/vhost-vdpa.h index d10a89303e..1111d85643 100644 --- a/include/hw/virtio/vhost-vdpa.h +++ b/include/hw/virtio/vhost-vdpa.h @@ -35,7 +35,6 @@ typedef struct vhost_vdpa { bool shadow_vqs_enabled; /* IOVA mapping used by the Shadow Virtqueue */ VhostIOVATree *iova_tree; - Error *migration_blocker; GPtrArray *shadow_vqs; const VhostShadowVirtqueueOps *shadow_vq_ops; void *shadow_vq_ops_opaque; diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 640434d1ea..6ce68fcd3f 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -555,8 +555,6 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops; s->vhost_vdpa.shadow_vq_ops_opaque = s; - error_setg(&s->vhost_vdpa.migration_blocker, - "Migration disabled: vhost-vdpa uses CVQ."); } ret = vhost_vdpa_add(nc, (void *)&s->vhost_vdpa, queue_pair_index, nvqs); if (ret) { From 3772cf0d1b37d32e61dc314e9cc18ff745327ddd Mon Sep 17 00:00:00 2001 From: Zhang Chen Date: Mon, 22 Aug 2022 16:14:36 +0800 Subject: [PATCH 0324/1020] net/colo.c: Fix the pointer issue reported by Coverity. When enabled the virtio-net-pci, guest network packet will load the vnet_hdr. In COLO status, the primary VM's network packet maybe redirect to another VM, it needs filter-redirect enable the vnet_hdr flag at the same time, COLO-proxy will correctly parse the original network packet. If have any misconfiguration here, the vnet_hdr_len is wrong for parse the packet, the data+offset will point to wrong place. Signed-off-by: Zhang Chen Signed-off-by: Jason Wang --- net/colo.c | 25 ++++++++++++++++--------- net/colo.h | 1 + net/trace-events | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/net/colo.c b/net/colo.c index 6b0ff562ad..fb2c36a026 100644 --- a/net/colo.c +++ b/net/colo.c @@ -44,21 +44,28 @@ int parse_packet_early(Packet *pkt) { int network_length; static const uint8_t vlan[] = {0x81, 0x00}; - uint8_t *data = pkt->data + pkt->vnet_hdr_len; + uint8_t *data = pkt->data; uint16_t l3_proto; ssize_t l2hdr_len; - if (data == NULL) { - trace_colo_proxy_main_vnet_info("This packet is not parsed correctly, " - "pkt->vnet_hdr_len", pkt->vnet_hdr_len); - return 1; - } - l2hdr_len = eth_get_l2_hdr_length(data); + assert(data); - if (pkt->size < ETH_HLEN + pkt->vnet_hdr_len) { - trace_colo_proxy_main("pkt->size < ETH_HLEN"); + /* Check the received vnet_hdr_len then add the offset */ + if ((pkt->vnet_hdr_len > sizeof(struct virtio_net_hdr_v1_hash)) || + (pkt->size < sizeof(struct eth_header) + sizeof(struct vlan_header) + + pkt->vnet_hdr_len)) { + /* + * The received remote packet maybe misconfiguration here, + * Please enable/disable filter module's the vnet_hdr flag at + * the same time. + */ + trace_colo_proxy_main_vnet_info("This received packet load wrong ", + pkt->vnet_hdr_len, pkt->size); return 1; } + data += pkt->vnet_hdr_len; + + l2hdr_len = eth_get_l2_hdr_length(data); /* * TODO: support vlan. diff --git a/net/colo.h b/net/colo.h index 8b3e8d5a83..22fc3031f7 100644 --- a/net/colo.h +++ b/net/colo.h @@ -18,6 +18,7 @@ #include "qemu/jhash.h" #include "qemu/timer.h" #include "net/eth.h" +#include "standard-headers/linux/virtio_net.h" #define HASHTABLE_MAX_SIZE 16384 diff --git a/net/trace-events b/net/trace-events index 6af927b4b9..823a071bdc 100644 --- a/net/trace-events +++ b/net/trace-events @@ -9,7 +9,7 @@ vhost_user_event(const char *chr, int event) "chr: %s got event: %d" # colo.c colo_proxy_main(const char *chr) ": %s" -colo_proxy_main_vnet_info(const char *sta, int size) ": %s = %d" +colo_proxy_main_vnet_info(const char *sta, uint32_t vnet_hdr, int size) ": %s pkt->vnet_hdr_len = %u, pkt->size = %d" # colo-compare.c colo_compare_main(const char *chr) ": %s" From 36a894aeb64a2e02871016da1c37d4a4ca109182 Mon Sep 17 00:00:00 2001 From: Zheyu Ma Date: Sun, 21 Aug 2022 20:43:43 +0800 Subject: [PATCH 0325/1020] net: tulip: Restrict DMA engine to memories The DMA engine is started by I/O access and then itself accesses the I/O registers, triggering a reentrancy bug. The following log can reveal it: ==5637==ERROR: AddressSanitizer: stack-overflow #0 0x5595435f6078 in tulip_xmit_list_update qemu/hw/net/tulip.c:673 #1 0x5595435f204a in tulip_write qemu/hw/net/tulip.c:805:13 #2 0x559544637f86 in memory_region_write_accessor qemu/softmmu/memory.c:492:5 #3 0x5595446379fa in access_with_adjusted_size qemu/softmmu/memory.c:554:18 #4 0x5595446372fa in memory_region_dispatch_write qemu/softmmu/memory.c #5 0x55954468b74c in flatview_write_continue qemu/softmmu/physmem.c:2825:23 #6 0x559544683662 in flatview_write qemu/softmmu/physmem.c:2867:12 #7 0x5595446833f3 in address_space_write qemu/softmmu/physmem.c:2963:18 #8 0x5595435fb082 in dma_memory_rw_relaxed qemu/include/sysemu/dma.h:87:12 #9 0x5595435fb082 in dma_memory_rw qemu/include/sysemu/dma.h:130:12 #10 0x5595435fb082 in dma_memory_write qemu/include/sysemu/dma.h:171:12 #11 0x5595435fb082 in stl_le_dma qemu/include/sysemu/dma.h:272:1 #12 0x5595435fb082 in stl_le_pci_dma qemu/include/hw/pci/pci.h:910:1 #13 0x5595435fb082 in tulip_desc_write qemu/hw/net/tulip.c:101:9 #14 0x5595435f7e3d in tulip_xmit_list_update qemu/hw/net/tulip.c:706:9 #15 0x5595435f204a in tulip_write qemu/hw/net/tulip.c:805:13 Fix this bug by restricting the DMA engine to memories regions. Signed-off-by: Zheyu Ma Signed-off-by: Jason Wang --- hw/net/tulip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/net/tulip.c b/hw/net/tulip.c index 097e905bec..b9e42c322a 100644 --- a/hw/net/tulip.c +++ b/hw/net/tulip.c @@ -70,7 +70,7 @@ static const VMStateDescription vmstate_pci_tulip = { static void tulip_desc_read(TULIPState *s, hwaddr p, struct tulip_descriptor *desc) { - const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + const MemTxAttrs attrs = { .memory = true }; if (s->csr[0] & CSR0_DBO) { ldl_be_pci_dma(&s->dev, p, &desc->status, attrs); @@ -88,7 +88,7 @@ static void tulip_desc_read(TULIPState *s, hwaddr p, static void tulip_desc_write(TULIPState *s, hwaddr p, struct tulip_descriptor *desc) { - const MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED; + const MemTxAttrs attrs = { .memory = true }; if (s->csr[0] & CSR0_DBO) { stl_be_pci_dma(&s->dev, p, desc->status, attrs); From d409373b9d0482bbce312539d02a648cbb1c790a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 2 Aug 2022 15:51:58 +0800 Subject: [PATCH 0326/1020] util/qemu-sockets: Enable unix socket support on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for the unix socket has existed both in BSD and Linux for the longest time, but not on Windows. Since Windows 10 build 17063 [1], the native support for the unix socket has come to Windows. Starting this build, two Win32 processes can use the AF_UNIX address family over Winsock API to communicate with each other. [1] https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/ Signed-off-by: Xuzhou Cheng Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220802075200.907360-3-bmeng.cn@gmail.com> --- include/sysemu/os-win32.h | 17 +++++++++++++++++ meson.build | 3 +++ util/qemu-sockets.c | 25 ------------------------- 3 files changed, 20 insertions(+), 25 deletions(-) diff --git a/include/sysemu/os-win32.h b/include/sysemu/os-win32.h index edc3b38a57..5b38c7bd04 100644 --- a/include/sysemu/os-win32.h +++ b/include/sysemu/os-win32.h @@ -30,6 +30,23 @@ #include #include +#ifdef HAVE_AFUNIX_H +#include +#else +/* + * Fallback definitions of things we need in afunix.h, if not available from + * the used Windows SDK or MinGW headers. + */ +#define UNIX_PATH_MAX 108 + +typedef struct sockaddr_un { + ADDRESS_FAMILY sun_family; + char sun_path[UNIX_PATH_MAX]; +} SOCKADDR_UN, *PSOCKADDR_UN; + +#define SIO_AF_UNIX_GETPEERPID _WSAIOR(IOC_VENDOR, 256) +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/meson.build b/meson.build index 20fddbd707..169b18a279 100644 --- a/meson.build +++ b/meson.build @@ -1890,6 +1890,9 @@ config_host_data.set('HAVE_PTY_H', cc.has_header('pty.h')) config_host_data.set('HAVE_SYS_DISK_H', cc.has_header('sys/disk.h')) config_host_data.set('HAVE_SYS_IOCCOM_H', cc.has_header('sys/ioccom.h')) config_host_data.set('HAVE_SYS_KCOV_H', cc.has_header('sys/kcov.h')) +if targetos == 'windows' + config_host_data.set('HAVE_AFUNIX_H', cc.has_header('afunix.h')) +endif # has_function config_host_data.set('CONFIG_ACCEPT4', cc.has_function('accept4')) diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c index 0e2298278f..83f4bd6fd2 100644 --- a/util/qemu-sockets.c +++ b/util/qemu-sockets.c @@ -880,8 +880,6 @@ static int vsock_parse(VsockSocketAddress *addr, const char *str, } #endif /* CONFIG_AF_VSOCK */ -#ifndef _WIN32 - static bool saddr_is_abstract(UnixSocketAddress *saddr) { #ifdef CONFIG_LINUX @@ -1054,25 +1052,6 @@ static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) return -1; } -#else - -static int unix_listen_saddr(UnixSocketAddress *saddr, - int num, - Error **errp) -{ - error_setg(errp, "unix sockets are not available on windows"); - errno = ENOTSUP; - return -1; -} - -static int unix_connect_saddr(UnixSocketAddress *saddr, Error **errp) -{ - error_setg(errp, "unix sockets are not available on windows"); - errno = ENOTSUP; - return -1; -} -#endif - /* compatibility wrapper */ int unix_listen(const char *str, Error **errp) { @@ -1335,7 +1314,6 @@ socket_sockaddr_to_address_inet(struct sockaddr_storage *sa, } -#ifndef WIN32 static SocketAddress * socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, socklen_t salen, @@ -1362,7 +1340,6 @@ socket_sockaddr_to_address_unix(struct sockaddr_storage *sa, addr->u.q_unix.path = g_strndup(su->sun_path, salen); return addr; } -#endif /* WIN32 */ #ifdef CONFIG_AF_VSOCK static SocketAddress * @@ -1394,10 +1371,8 @@ socket_sockaddr_to_address(struct sockaddr_storage *sa, case AF_INET6: return socket_sockaddr_to_address_inet(sa, salen, errp); -#ifndef WIN32 case AF_UNIX: return socket_sockaddr_to_address_unix(sa, salen, errp); -#endif /* WIN32 */ #ifdef CONFIG_AF_VSOCK case AF_VSOCK: From 120fa5e0e6ebacd811e4d830cff8a405806d305c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 2 Aug 2022 15:51:59 +0800 Subject: [PATCH 0327/1020] chardev/char-socket: Update AF_UNIX for Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that AF_UNIX has come to Windows, update the existing logic in qemu_chr_compute_filename() and qmp_chardev_open_socket() for Windows. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220802075200.907360-4-bmeng.cn@gmail.com> --- chardev/char-socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chardev/char-socket.c b/chardev/char-socket.c index dc4e218eeb..879564aa8a 100644 --- a/chardev/char-socket.c +++ b/chardev/char-socket.c @@ -557,12 +557,10 @@ static char *qemu_chr_compute_filename(SocketChardev *s) const char *left = "", *right = ""; switch (ss->ss_family) { -#ifndef _WIN32 case AF_UNIX: return g_strdup_printf("unix:%s%s", ((struct sockaddr_un *)(ss))->sun_path, s->is_listen ? ",server=on" : ""); -#endif case AF_INET6: left = "["; right = "]"; @@ -1372,10 +1370,12 @@ static void qmp_chardev_open_socket(Chardev *chr, } qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_RECONNECTABLE); +#ifndef _WIN32 /* TODO SOCKET_ADDRESS_FD where fd has AF_UNIX */ if (addr->type == SOCKET_ADDRESS_TYPE_UNIX) { qemu_chr_set_feature(chr, QEMU_CHAR_FEATURE_FD_PASS); } +#endif /* * In the chardev-change special-case, we shouldn't register a new yank From 0370f239ad14aeacc496775e241b9ef041df4374 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 2 Aug 2022 15:52:00 +0800 Subject: [PATCH 0328/1020] tests/unit: Update test-io-channel-socket.c for Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change to dynamically include the test cases by checking AF_UNIX availability using a new helper socket_check_afunix_support(). With such changes testing on a Windows host can be covered as well. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220802075200.907360-5-bmeng.cn@gmail.com> --- tests/unit/socket-helpers.c | 16 +++++++++++++ tests/unit/socket-helpers.h | 9 +++++++ tests/unit/test-io-channel-socket.c | 37 ++++++++++++++++++----------- 3 files changed, 48 insertions(+), 14 deletions(-) diff --git a/tests/unit/socket-helpers.c b/tests/unit/socket-helpers.c index 5af4de513b..eecadf3a3c 100644 --- a/tests/unit/socket-helpers.c +++ b/tests/unit/socket-helpers.c @@ -154,3 +154,19 @@ int socket_check_protocol_support(bool *has_ipv4, bool *has_ipv6) return 0; } + +void socket_check_afunix_support(bool *has_afunix) +{ + int fd; + + fd = socket(PF_UNIX, SOCK_STREAM, 0); + closesocket(fd); + +#ifdef _WIN32 + *has_afunix = (fd != (int)INVALID_SOCKET); +#else + *has_afunix = (fd >= 0); +#endif + + return; +} diff --git a/tests/unit/socket-helpers.h b/tests/unit/socket-helpers.h index 512a004811..ed8477ceb3 100644 --- a/tests/unit/socket-helpers.h +++ b/tests/unit/socket-helpers.h @@ -32,4 +32,13 @@ */ int socket_check_protocol_support(bool *has_ipv4, bool *has_ipv6); +/* + * @has_afunix: set to true on return if unix socket support is available + * + * Check whether unix domain socket support is available for use. + * On success, @has_afunix will be set to indicate whether AF_UNIX protocol + * is available. + */ +void socket_check_afunix_support(bool *has_afunix); + #endif diff --git a/tests/unit/test-io-channel-socket.c b/tests/unit/test-io-channel-socket.c index 6713886d02..b36a5d972a 100644 --- a/tests/unit/test-io-channel-socket.c +++ b/tests/unit/test-io-channel-socket.c @@ -179,10 +179,12 @@ static void test_io_channel(bool async, test_io_channel_setup_async(listen_addr, connect_addr, &srv, &src, &dst); +#ifndef _WIN32 g_assert(!passFD || qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); g_assert(!passFD || qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); +#endif g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); @@ -206,10 +208,12 @@ static void test_io_channel(bool async, test_io_channel_setup_async(listen_addr, connect_addr, &srv, &src, &dst); +#ifndef _WIN32 g_assert(!passFD || qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); g_assert(!passFD || qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); +#endif g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); @@ -236,10 +240,12 @@ static void test_io_channel(bool async, test_io_channel_setup_sync(listen_addr, connect_addr, &srv, &src, &dst); +#ifndef _WIN32 g_assert(!passFD || qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); g_assert(!passFD || qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); +#endif g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); @@ -263,10 +269,12 @@ static void test_io_channel(bool async, test_io_channel_setup_sync(listen_addr, connect_addr, &srv, &src, &dst); +#ifndef _WIN32 g_assert(!passFD || qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_FD_PASS)); g_assert(!passFD || qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_FD_PASS)); +#endif g_assert(qio_channel_has_feature(src, QIO_CHANNEL_FEATURE_SHUTDOWN)); g_assert(qio_channel_has_feature(dst, QIO_CHANNEL_FEATURE_SHUTDOWN)); @@ -367,7 +375,6 @@ static void test_io_channel_ipv6_async(void) } -#ifndef _WIN32 static void test_io_channel_unix(bool async) { SocketAddress *listen_addr = g_new0(SocketAddress, 1); @@ -398,6 +405,7 @@ static void test_io_channel_unix_async(void) return test_io_channel_unix(true); } +#ifndef _WIN32 static void test_io_channel_unix_fd_pass(void) { SocketAddress *listen_addr = g_new0(SocketAddress, 1); @@ -491,6 +499,7 @@ static void test_io_channel_unix_fd_pass(void) } g_free(fdrecv); } +#endif /* _WIN32 */ static void test_io_channel_unix_listen_cleanup(void) { @@ -522,9 +531,6 @@ static void test_io_channel_unix_listen_cleanup(void) unlink(TEST_SOCKET); } -#endif /* _WIN32 */ - - static void test_io_channel_ipv4_fd(void) { QIOChannel *ioc; @@ -555,7 +561,7 @@ static void test_io_channel_ipv4_fd(void) int main(int argc, char **argv) { - bool has_ipv4, has_ipv6; + bool has_ipv4, has_ipv6, has_afunix; module_call_init(MODULE_INIT_QOM); qemu_init_main_loop(&error_abort); @@ -588,16 +594,19 @@ int main(int argc, char **argv) test_io_channel_ipv6_async); } + socket_check_afunix_support(&has_afunix); + if (has_afunix) { + g_test_add_func("/io/channel/socket/unix-sync", + test_io_channel_unix_sync); + g_test_add_func("/io/channel/socket/unix-async", + test_io_channel_unix_async); #ifndef _WIN32 - g_test_add_func("/io/channel/socket/unix-sync", - test_io_channel_unix_sync); - g_test_add_func("/io/channel/socket/unix-async", - test_io_channel_unix_async); - g_test_add_func("/io/channel/socket/unix-fd-pass", - test_io_channel_unix_fd_pass); - g_test_add_func("/io/channel/socket/unix-listen-cleanup", - test_io_channel_unix_listen_cleanup); -#endif /* _WIN32 */ + g_test_add_func("/io/channel/socket/unix-fd-pass", + test_io_channel_unix_fd_pass); +#endif + g_test_add_func("/io/channel/socket/unix-listen-cleanup", + test_io_channel_unix_listen_cleanup); + } end: return g_test_run(); From 0f957c53c84d655f2e99677d407cf2bbe1832de4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 22 Aug 2022 17:10:21 +0400 Subject: [PATCH 0329/1020] audio: exit(1) if audio backend failed to be found or initialized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you specify a known backend but it isn't compiled in, or failed to initialize, you get a simple warning and the "none" backend as a fallback, and QEMU runs happily: $ qemu-system-x86_64 -audiodev id=audio,driver=dsound audio: Unknown audio driver `dsound' audio: warning: Using timer based audio emulation ... Instead, QEMU should fail to start: $ qemu-system-x86_64 -audiodev id=audio,driver=dsound audio: Unknown audio driver `dsound' $ Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1983493 Signed-off-by: Marc-AndrĂ© Lureau Reviewed-by: Volker RĂ¼melin Message-Id: <20220822131021.975656-1-marcandre.lureau@redhat.com> --- audio/audio.c | 14 +++++++++++--- audio/audio.h | 2 +- softmmu/vl.c | 4 +++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index a02f3ce5c6..76b8735b44 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -1743,7 +1743,6 @@ static AudioState *audio_init(Audiodev *dev, const char *name) atexit(audio_cleanup); atexit_registered = true; } - QTAILQ_INSERT_TAIL(&audio_states, s, list); s->ts = timer_new_ns(QEMU_CLOCK_VIRTUAL, audio_timer, s); @@ -1769,6 +1768,10 @@ static AudioState *audio_init(Audiodev *dev, const char *name) } else { dolog ("Unknown audio driver `%s'\n", drvname); } + if (!done) { + free_audio_state(s); + return NULL; + } } else { for (i = 0; audio_prio_list[i]; i++) { AudiodevListEntry *e = audiodev_find(&head, audio_prio_list[i]); @@ -1806,6 +1809,7 @@ static AudioState *audio_init(Audiodev *dev, const char *name) "(Audio can continue looping even after stopping the VM)\n"); } + QTAILQ_INSERT_TAIL(&audio_states, s, list); QLIST_INIT (&s->card_head); vmstate_register (NULL, 0, &vmstate_audio, s); return s; @@ -2119,13 +2123,17 @@ void audio_define(Audiodev *dev) QSIMPLEQ_INSERT_TAIL(&audiodevs, e, next); } -void audio_init_audiodevs(void) +bool audio_init_audiodevs(void) { AudiodevListEntry *e; QSIMPLEQ_FOREACH(e, &audiodevs, next) { - audio_init(e->dev, NULL); + if (!audio_init(e->dev, NULL)) { + return false; + } } + + return true; } audsettings audiodev_to_audsettings(AudiodevPerDirectionOptions *pdo) diff --git a/audio/audio.h b/audio/audio.h index b5e17cd218..27e67079a0 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -170,7 +170,7 @@ void audio_sample_from_uint64(void *samples, int pos, void audio_define(Audiodev *audio); void audio_parse_option(const char *opt); -void audio_init_audiodevs(void); +bool audio_init_audiodevs(void); void audio_legacy_help(void); AudioState *audio_state_by_name(const char *name); diff --git a/softmmu/vl.c b/softmmu/vl.c index 706bd7cff7..dea4005e47 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1885,7 +1885,9 @@ static void qemu_create_early_backends(void) * setting machine properties, so they can be referred to. */ configure_blockdev(&bdo_queue, machine_class, snapshot); - audio_init_audiodevs(); + if (!audio_init_audiodevs()) { + exit(1); + } } From 7025114b1cd7683cb7fbef0810577c67aa3cbbd8 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sat, 28 May 2022 01:42:34 +0900 Subject: [PATCH 0330/1020] hw/openrisc: Split re-usable boot time apis out to boot.c These will be shared with the virt platform. Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- hw/openrisc/boot.c | 116 +++++++++++++++++++++++++++++++++++++ hw/openrisc/meson.build | 1 + hw/openrisc/openrisc_sim.c | 106 ++------------------------------- include/hw/openrisc/boot.h | 34 +++++++++++ 4 files changed, 157 insertions(+), 100 deletions(-) create mode 100644 hw/openrisc/boot.c create mode 100644 include/hw/openrisc/boot.h diff --git a/hw/openrisc/boot.c b/hw/openrisc/boot.c new file mode 100644 index 0000000000..128ccbcba2 --- /dev/null +++ b/hw/openrisc/boot.c @@ -0,0 +1,116 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QEMU OpenRISC boot helpers. + * + * (c) 2022 Stafford Horne + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "exec/cpu-defs.h" +#include "elf.h" +#include "hw/loader.h" +#include "hw/openrisc/boot.h" +#include "sysemu/device_tree.h" +#include "sysemu/qtest.h" + +#include + +#define KERNEL_LOAD_ADDR 0x100 + +hwaddr openrisc_load_kernel(ram_addr_t ram_size, + const char *kernel_filename, + uint32_t *bootstrap_pc) +{ + long kernel_size; + uint64_t elf_entry; + uint64_t high_addr; + hwaddr entry; + + if (kernel_filename && !qtest_enabled()) { + kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, + &elf_entry, NULL, &high_addr, NULL, 1, + EM_OPENRISC, 1, 0); + entry = elf_entry; + if (kernel_size < 0) { + kernel_size = load_uimage(kernel_filename, + &entry, NULL, NULL, NULL, NULL); + high_addr = entry + kernel_size; + } + if (kernel_size < 0) { + kernel_size = load_image_targphys(kernel_filename, + KERNEL_LOAD_ADDR, + ram_size - KERNEL_LOAD_ADDR); + high_addr = KERNEL_LOAD_ADDR + kernel_size; + } + + if (entry <= 0) { + entry = KERNEL_LOAD_ADDR; + } + + if (kernel_size < 0) { + error_report("couldn't load the kernel '%s'", kernel_filename); + exit(1); + } + *bootstrap_pc = entry; + + return high_addr; + } + return 0; +} + +hwaddr openrisc_load_initrd(void *fdt, const char *filename, + hwaddr load_start, uint64_t mem_size) +{ + int size; + hwaddr start; + + /* We put the initrd right after the kernel; page aligned. */ + start = TARGET_PAGE_ALIGN(load_start); + + size = load_ramdisk(filename, start, mem_size - start); + if (size < 0) { + size = load_image_targphys(filename, start, mem_size - start); + if (size < 0) { + error_report("could not load ramdisk '%s'", filename); + exit(1); + } + } + + if (fdt) { + qemu_fdt_setprop_cell(fdt, "/chosen", + "linux,initrd-start", start); + qemu_fdt_setprop_cell(fdt, "/chosen", + "linux,initrd-end", start + size); + } + + return start + size; +} + +uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start, + uint64_t mem_size) +{ + uint32_t fdt_addr; + int ret; + int fdtsize = fdt_totalsize(fdt); + + if (fdtsize <= 0) { + error_report("invalid device-tree"); + exit(1); + } + + /* We put fdt right after the kernel and/or initrd. */ + fdt_addr = TARGET_PAGE_ALIGN(load_start); + + ret = fdt_pack(fdt); + /* Should only fail if we've built a corrupted tree */ + g_assert(ret == 0); + /* copy in the device tree */ + qemu_fdt_dumpdtb(fdt, fdtsize); + + rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr, + &address_space_memory); + + return fdt_addr; +} diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build index ec48172c9d..ab563820c5 100644 --- a/hw/openrisc/meson.build +++ b/hw/openrisc/meson.build @@ -1,5 +1,6 @@ openrisc_ss = ss.source_set() openrisc_ss.add(files('cputimer.c')) +openrisc_ss.add(files('boot.c')) openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), fdt]) hw_arch += {'openrisc': openrisc_ss} diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c index 35adce17ac..35da123aef 100644 --- a/hw/openrisc/openrisc_sim.c +++ b/hw/openrisc/openrisc_sim.c @@ -24,10 +24,9 @@ #include "cpu.h" #include "hw/irq.h" #include "hw/boards.h" -#include "elf.h" #include "hw/char/serial.h" #include "net/net.h" -#include "hw/loader.h" +#include "hw/openrisc/boot.h" #include "hw/qdev-properties.h" #include "exec/address-spaces.h" #include "sysemu/device_tree.h" @@ -283,101 +282,6 @@ static void openrisc_sim_serial_init(Or1ksimState *state, hwaddr base, g_free(nodename); } -static hwaddr openrisc_load_kernel(ram_addr_t ram_size, - const char *kernel_filename) -{ - long kernel_size; - uint64_t elf_entry; - uint64_t high_addr; - hwaddr entry; - - if (kernel_filename && !qtest_enabled()) { - kernel_size = load_elf(kernel_filename, NULL, NULL, NULL, - &elf_entry, NULL, &high_addr, NULL, 1, - EM_OPENRISC, 1, 0); - entry = elf_entry; - if (kernel_size < 0) { - kernel_size = load_uimage(kernel_filename, - &entry, NULL, NULL, NULL, NULL); - high_addr = entry + kernel_size; - } - if (kernel_size < 0) { - kernel_size = load_image_targphys(kernel_filename, - KERNEL_LOAD_ADDR, - ram_size - KERNEL_LOAD_ADDR); - high_addr = KERNEL_LOAD_ADDR + kernel_size; - } - - if (entry <= 0) { - entry = KERNEL_LOAD_ADDR; - } - - if (kernel_size < 0) { - error_report("couldn't load the kernel '%s'", kernel_filename); - exit(1); - } - boot_info.bootstrap_pc = entry; - - return high_addr; - } - return 0; -} - -static hwaddr openrisc_load_initrd(Or1ksimState *state, const char *filename, - hwaddr load_start, uint64_t mem_size) -{ - void *fdt = state->fdt; - int size; - hwaddr start; - - /* We put the initrd right after the kernel; page aligned. */ - start = TARGET_PAGE_ALIGN(load_start); - - size = load_ramdisk(filename, start, mem_size - start); - if (size < 0) { - size = load_image_targphys(filename, start, mem_size - start); - if (size < 0) { - error_report("could not load ramdisk '%s'", filename); - exit(1); - } - } - - qemu_fdt_setprop_cell(fdt, "/chosen", - "linux,initrd-start", start); - qemu_fdt_setprop_cell(fdt, "/chosen", - "linux,initrd-end", start + size); - - return start + size; -} - -static uint32_t openrisc_load_fdt(Or1ksimState *state, hwaddr load_start, - uint64_t mem_size) -{ - void *fdt = state->fdt; - uint32_t fdt_addr; - int ret; - int fdtsize = fdt_totalsize(fdt); - - if (fdtsize <= 0) { - error_report("invalid device-tree"); - exit(1); - } - - /* We put fdt right after the kernel and/or initrd. */ - fdt_addr = TARGET_PAGE_ALIGN(load_start); - - ret = fdt_pack(fdt); - /* Should only fail if we've built a corrupted tree */ - g_assert(ret == 0); - /* copy in the device tree */ - qemu_fdt_dumpdtb(fdt, fdtsize); - - rom_add_blob_fixed_as("fdt", fdt, fdtsize, fdt_addr, - &address_space_memory); - - return fdt_addr; -} - static void openrisc_sim_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; @@ -428,13 +332,15 @@ static void openrisc_sim_init(MachineState *machine) or1ksim_memmap[OR1KSIM_UART].size, smp_cpus, cpus, OR1KSIM_UART_IRQ, n); - load_addr = openrisc_load_kernel(ram_size, kernel_filename); + load_addr = openrisc_load_kernel(ram_size, kernel_filename, + &boot_info.bootstrap_pc); if (load_addr > 0) { if (machine->initrd_filename) { - load_addr = openrisc_load_initrd(state, machine->initrd_filename, + load_addr = openrisc_load_initrd(state->fdt, + machine->initrd_filename, load_addr, machine->ram_size); } - boot_info.fdt_addr = openrisc_load_fdt(state, load_addr, + boot_info.fdt_addr = openrisc_load_fdt(state->fdt, load_addr, machine->ram_size); } } diff --git a/include/hw/openrisc/boot.h b/include/hw/openrisc/boot.h new file mode 100644 index 0000000000..25a313d63a --- /dev/null +++ b/include/hw/openrisc/boot.h @@ -0,0 +1,34 @@ +/* + * QEMU OpenRISC boot helpers. + * + * Copyright (c) 2022 Stafford Horne + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef OPENRISC_BOOT_H +#define OPENRISC_BOOT_H + +#include "exec/cpu-defs.h" + +hwaddr openrisc_load_kernel(ram_addr_t ram_size, + const char *kernel_filename, + uint32_t *bootstrap_pc); + +hwaddr openrisc_load_initrd(void *fdt, const char *filename, + hwaddr load_start, uint64_t mem_size); + +uint32_t openrisc_load_fdt(void *fdt, hwaddr load_start, + uint64_t mem_size); + +#endif /* OPENRISC_BOOT_H */ From 0fd8a106efb6bc2e55b3e9629b106d13a7214570 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 12 Jun 2022 18:59:34 +0900 Subject: [PATCH 0331/1020] target/openrisc: Fix memory reading in debugger In commit f0655423ca ("target/openrisc: Reorg tlb lookup") data and instruction TLB reads were combined. This, broke debugger reads where we first tried to map using the data tlb then fall back to the instruction tlb. This patch replicates this logic by first requesting a PAGE_READ protection mapping then falling back to PAGE_EXEC. Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/mmu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/openrisc/mmu.c b/target/openrisc/mmu.c index d7e1320998..0b8afdbacf 100644 --- a/target/openrisc/mmu.c +++ b/target/openrisc/mmu.c @@ -148,7 +148,13 @@ hwaddr openrisc_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) case SR_DME | SR_IME: /* The mmu is definitely enabled. */ excp = get_phys_mmu(cpu, &phys_addr, &prot, addr, - PAGE_EXEC | PAGE_READ | PAGE_WRITE, + PAGE_READ, + (sr & SR_SM) != 0); + if (!excp) { + return phys_addr; + } + excp = get_phys_mmu(cpu, &phys_addr, &prot, addr, + PAGE_EXEC, (sr & SR_SM) != 0); return excp ? -1 : phys_addr; From 65f5144e1726c36c97df7e70484250941aafaa27 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 12 Jun 2022 20:53:44 +0900 Subject: [PATCH 0332/1020] goldfish_rtc: Add big-endian property Add a new property "big-endian" to allow configuring the RTC as either little or big endian, the default is little endian. Currently overriding the default to big endian is only used by the m68k virt platform. New platforms should prefer to use little endian and not set this. Cc: Laurent Vivier Reviewed-by: Anup Patel Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- hw/m68k/virt.c | 1 + hw/rtc/goldfish_rtc.c | 37 ++++++++++++++++++++++++++--------- include/hw/rtc/goldfish_rtc.h | 2 ++ 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c index 3122c8ef2c..2f3ffc0de6 100644 --- a/hw/m68k/virt.c +++ b/hw/m68k/virt.c @@ -173,6 +173,7 @@ static void virt_init(MachineState *machine) io_base = VIRT_GF_RTC_MMIO_BASE; for (i = 0; i < VIRT_GF_RTC_NB; i++) { dev = qdev_new(TYPE_GOLDFISH_RTC); + qdev_prop_set_bit(dev, "big-endian", true); sysbus = SYS_BUS_DEVICE(dev); sysbus_realize_and_unref(sysbus, &error_fatal); sysbus_mmio_map(sysbus, 0, io_base); diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c index 35e493be31..19a56402a0 100644 --- a/hw/rtc/goldfish_rtc.c +++ b/hw/rtc/goldfish_rtc.c @@ -216,14 +216,25 @@ static int goldfish_rtc_post_load(void *opaque, int version_id) return 0; } -static const MemoryRegionOps goldfish_rtc_ops = { - .read = goldfish_rtc_read, - .write = goldfish_rtc_write, - .endianness = DEVICE_NATIVE_ENDIAN, - .valid = { - .min_access_size = 4, - .max_access_size = 4 - } +static const MemoryRegionOps goldfish_rtc_ops[2] = { + [false] = { + .read = goldfish_rtc_read, + .write = goldfish_rtc_write, + .endianness = DEVICE_LITTLE_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } + }, + [true] = { + .read = goldfish_rtc_read, + .write = goldfish_rtc_write, + .endianness = DEVICE_BIG_ENDIAN, + .valid = { + .min_access_size = 4, + .max_access_size = 4 + } + }, }; static const VMStateDescription goldfish_rtc_vmstate = { @@ -265,7 +276,8 @@ static void goldfish_rtc_realize(DeviceState *d, Error **errp) SysBusDevice *dev = SYS_BUS_DEVICE(d); GoldfishRTCState *s = GOLDFISH_RTC(d); - memory_region_init_io(&s->iomem, OBJECT(s), &goldfish_rtc_ops, s, + memory_region_init_io(&s->iomem, OBJECT(s), + &goldfish_rtc_ops[s->big_endian], s, "goldfish_rtc", 0x24); sysbus_init_mmio(dev, &s->iomem); @@ -274,10 +286,17 @@ static void goldfish_rtc_realize(DeviceState *d, Error **errp) s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s); } +static Property goldfish_rtc_properties[] = { + DEFINE_PROP_BOOL("big-endian", GoldfishRTCState, big_endian, + false), + DEFINE_PROP_END_OF_LIST(), +}; + static void goldfish_rtc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + device_class_set_props(dc, goldfish_rtc_properties); dc->realize = goldfish_rtc_realize; dc->reset = goldfish_rtc_reset; dc->vmsd = &goldfish_rtc_vmstate; diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h index 79ca7daf5d..162be33863 100644 --- a/include/hw/rtc/goldfish_rtc.h +++ b/include/hw/rtc/goldfish_rtc.h @@ -42,6 +42,8 @@ struct GoldfishRTCState { uint32_t irq_pending; uint32_t irq_enabled; uint32_t time_high; + + bool big_endian; }; #endif From b5fcfe927b7a9cbbc0864e7fc4f34bc94631ee0e Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Fri, 20 May 2022 22:38:13 +0900 Subject: [PATCH 0333/1020] hw/openrisc: Add the OpenRISC virtual machine This patch adds the OpenRISC virtual machine 'virt' for OpenRISC. This platform allows for a convenient CI platform for toolchain, software ports and the OpenRISC linux kernel port. Much of this has been sourced from the m68k and riscv virt platforms. The platform provides: - OpenRISC SMP with up to 4 cpus - A virtio bus with up to 8 devices - Standard ns16550a serial - Goldfish RTC - SiFive TEST device for poweroff and reboot - Generated Device Tree to automatically configure the guest kernel Signed-off-by: Stafford Horne --- configs/devices/or1k-softmmu/default.mak | 1 + hw/openrisc/Kconfig | 9 + hw/openrisc/meson.build | 1 + hw/openrisc/virt.c | 417 +++++++++++++++++++++++ 4 files changed, 428 insertions(+) create mode 100644 hw/openrisc/virt.c diff --git a/configs/devices/or1k-softmmu/default.mak b/configs/devices/or1k-softmmu/default.mak index 168101c39a..89c39e3123 100644 --- a/configs/devices/or1k-softmmu/default.mak +++ b/configs/devices/or1k-softmmu/default.mak @@ -3,3 +3,4 @@ # Boards: # CONFIG_OR1K_SIM=y +CONFIG_OR1K_VIRT=y diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig index 8f284f3ba0..202134668e 100644 --- a/hw/openrisc/Kconfig +++ b/hw/openrisc/Kconfig @@ -4,3 +4,12 @@ config OR1K_SIM select OPENCORES_ETH select OMPIC select SPLIT_IRQ + +config OR1K_VIRT + bool + imply VIRTIO_VGA + imply TEST_DEVICES + select GOLDFISH_RTC + select SERIAL + select SIFIVE_TEST + select VIRTIO_MMIO diff --git a/hw/openrisc/meson.build b/hw/openrisc/meson.build index ab563820c5..2dbc6365bb 100644 --- a/hw/openrisc/meson.build +++ b/hw/openrisc/meson.build @@ -2,5 +2,6 @@ openrisc_ss = ss.source_set() openrisc_ss.add(files('cputimer.c')) openrisc_ss.add(files('boot.c')) openrisc_ss.add(when: 'CONFIG_OR1K_SIM', if_true: [files('openrisc_sim.c'), fdt]) +openrisc_ss.add(when: 'CONFIG_OR1K_VIRT', if_true: [files('virt.c'), fdt]) hw_arch += {'openrisc': openrisc_ss} diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c new file mode 100644 index 0000000000..54f2732a6b --- /dev/null +++ b/hw/openrisc/virt.c @@ -0,0 +1,417 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * OpenRISC QEMU virtual machine. + * + * (c) 2022 Stafford Horne + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "qapi/error.h" +#include "cpu.h" +#include "exec/address-spaces.h" +#include "hw/irq.h" +#include "hw/boards.h" +#include "hw/char/serial.h" +#include "hw/core/split-irq.h" +#include "hw/openrisc/boot.h" +#include "hw/misc/sifive_test.h" +#include "hw/qdev-properties.h" +#include "hw/rtc/goldfish_rtc.h" +#include "hw/sysbus.h" +#include "hw/virtio/virtio-mmio.h" +#include "sysemu/device_tree.h" +#include "sysemu/sysemu.h" +#include "sysemu/qtest.h" +#include "sysemu/reset.h" + +#include + +#define VIRT_CPUS_MAX 4 +#define VIRT_CLK_MHZ 20000000 + +#define TYPE_VIRT_MACHINE MACHINE_TYPE_NAME("virt") +#define VIRT_MACHINE(obj) \ + OBJECT_CHECK(OR1KVirtState, (obj), TYPE_VIRT_MACHINE) + +typedef struct OR1KVirtState { + /*< private >*/ + MachineState parent_obj; + + /*< public >*/ + void *fdt; + int fdt_size; + +} OR1KVirtState; + +enum { + VIRT_DRAM, + VIRT_TEST, + VIRT_RTC, + VIRT_VIRTIO, + VIRT_UART, + VIRT_OMPIC, +}; + +enum { + VIRT_OMPIC_IRQ = 1, + VIRT_UART_IRQ = 2, + VIRT_RTC_IRQ = 3, + VIRT_VIRTIO_IRQ = 4, /* to 12 */ + VIRTIO_COUNT = 8, +}; + +static const struct MemmapEntry { + hwaddr base; + hwaddr size; +} virt_memmap[] = { + [VIRT_DRAM] = { 0x00000000, 0 }, + [VIRT_UART] = { 0x90000000, 0x100 }, + [VIRT_TEST] = { 0x96000000, 0x8 }, + [VIRT_RTC] = { 0x96005000, 0x1000 }, + [VIRT_VIRTIO] = { 0x97000000, 0x1000 }, + [VIRT_OMPIC] = { 0x98000000, VIRT_CPUS_MAX * 8 }, +}; + +static struct openrisc_boot_info { + uint32_t bootstrap_pc; + uint32_t fdt_addr; +} boot_info; + +static void main_cpu_reset(void *opaque) +{ + OpenRISCCPU *cpu = opaque; + CPUState *cs = CPU(cpu); + + cpu_reset(CPU(cpu)); + + cpu_set_pc(cs, boot_info.bootstrap_pc); + cpu_set_gpr(&cpu->env, 3, boot_info.fdt_addr); +} + +static qemu_irq get_cpu_irq(OpenRISCCPU *cpus[], int cpunum, int irq_pin) +{ + return qdev_get_gpio_in_named(DEVICE(cpus[cpunum]), "IRQ", irq_pin); +} + +static qemu_irq get_per_cpu_irq(OpenRISCCPU *cpus[], int num_cpus, int irq_pin) +{ + int i; + + if (num_cpus > 1) { + DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ); + qdev_prop_set_uint32(splitter, "num-lines", num_cpus); + qdev_realize_and_unref(splitter, NULL, &error_fatal); + for (i = 0; i < num_cpus; i++) { + qdev_connect_gpio_out(splitter, i, get_cpu_irq(cpus, i, irq_pin)); + } + return qdev_get_gpio_in(splitter, 0); + } else { + return get_cpu_irq(cpus, 0, irq_pin); + } +} + +static void openrisc_create_fdt(OR1KVirtState *state, + const struct MemmapEntry *memmap, + int num_cpus, uint64_t mem_size, + const char *cmdline) +{ + void *fdt; + int cpu; + char *nodename; + int pic_ph; + + fdt = state->fdt = create_device_tree(&state->fdt_size); + if (!fdt) { + error_report("create_device_tree() failed"); + exit(1); + } + + qemu_fdt_setprop_string(fdt, "/", "compatible", "opencores,or1ksim"); + qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x1); + qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x1); + + qemu_fdt_add_subnode(fdt, "/soc"); + qemu_fdt_setprop(fdt, "/soc", "ranges", NULL, 0); + qemu_fdt_setprop_string(fdt, "/soc", "compatible", "simple-bus"); + qemu_fdt_setprop_cell(fdt, "/soc", "#address-cells", 0x1); + qemu_fdt_setprop_cell(fdt, "/soc", "#size-cells", 0x1); + + nodename = g_strdup_printf("/memory@%" HWADDR_PRIx, + memmap[VIRT_DRAM].base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cells(fdt, nodename, "reg", + memmap[VIRT_DRAM].base, mem_size); + qemu_fdt_setprop_string(fdt, nodename, "device_type", "memory"); + g_free(nodename); + + qemu_fdt_add_subnode(fdt, "/cpus"); + qemu_fdt_setprop_cell(fdt, "/cpus", "#size-cells", 0x0); + qemu_fdt_setprop_cell(fdt, "/cpus", "#address-cells", 0x1); + + for (cpu = 0; cpu < num_cpus; cpu++) { + nodename = g_strdup_printf("/cpus/cpu@%d", cpu); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "opencores,or1200-rtlsvn481"); + qemu_fdt_setprop_cell(fdt, nodename, "reg", cpu); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", + VIRT_CLK_MHZ); + g_free(nodename); + } + + nodename = (char *)"/pic"; + qemu_fdt_add_subnode(fdt, nodename); + pic_ph = qemu_fdt_alloc_phandle(fdt); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "opencores,or1k-pic-level"); + qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1); + qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", pic_ph); + + qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", pic_ph); + + qemu_fdt_add_subnode(fdt, "/chosen"); + if (cmdline) { + qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); + } + + /* Create aliases node for use by devices. */ + qemu_fdt_add_subnode(fdt, "/aliases"); +} + +static void openrisc_virt_ompic_init(OR1KVirtState *state, hwaddr base, + hwaddr size, int num_cpus, + OpenRISCCPU *cpus[], int irq_pin) +{ + void *fdt = state->fdt; + DeviceState *dev; + SysBusDevice *s; + char *nodename; + int i; + + dev = qdev_new("or1k-ompic"); + qdev_prop_set_uint32(dev, "num-cpus", num_cpus); + + s = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(s, &error_fatal); + for (i = 0; i < num_cpus; i++) { + sysbus_connect_irq(s, i, get_cpu_irq(cpus, i, irq_pin)); + } + sysbus_mmio_map(s, 0, base); + + /* Add device tree node for ompic. */ + nodename = g_strdup_printf("/ompic@%" HWADDR_PRIx, base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "openrisc,ompic"); + qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size); + qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 0); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin); + g_free(nodename); +} + +static void openrisc_virt_serial_init(OR1KVirtState *state, hwaddr base, + hwaddr size, int num_cpus, + OpenRISCCPU *cpus[], int irq_pin) +{ + void *fdt = state->fdt; + char *nodename; + qemu_irq serial_irq = get_per_cpu_irq(cpus, num_cpus, irq_pin); + + serial_mm_init(get_system_memory(), base, 0, serial_irq, 115200, + serial_hd(0), DEVICE_NATIVE_ENDIAN); + + /* Add device tree node for serial. */ + nodename = g_strdup_printf("/serial@%" HWADDR_PRIx, base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "ns16550a"); + qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin); + qemu_fdt_setprop_cell(fdt, nodename, "clock-frequency", VIRT_CLK_MHZ); + qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0); + + /* The /chosen node is created during fdt creation. */ + qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", nodename); + qemu_fdt_setprop_string(fdt, "/aliases", "uart0", nodename); + g_free(nodename); +} + +static void openrisc_virt_test_init(OR1KVirtState *state, hwaddr base, + hwaddr size) +{ + void *fdt = state->fdt; + int test_ph; + char *nodename; + + /* SiFive Test MMIO device */ + sifive_test_create(base); + + /* SiFive Test MMIO Reset device FDT */ + nodename = g_strdup_printf("/soc/test@%" HWADDR_PRIx, base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon"); + test_ph = qemu_fdt_alloc_phandle(fdt); + qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", test_ph); + qemu_fdt_setprop(fdt, nodename, "big-endian", NULL, 0); + g_free(nodename); + + nodename = g_strdup_printf("/soc/reboot"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon-reboot"); + qemu_fdt_setprop_cell(fdt, nodename, "regmap", test_ph); + qemu_fdt_setprop_cell(fdt, nodename, "offset", 0x0); + qemu_fdt_setprop_cell(fdt, nodename, "value", FINISHER_RESET); + g_free(nodename); + + nodename = g_strdup_printf("/soc/poweroff"); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "syscon-poweroff"); + qemu_fdt_setprop_cell(fdt, nodename, "regmap", test_ph); + qemu_fdt_setprop_cell(fdt, nodename, "offset", 0x0); + qemu_fdt_setprop_cell(fdt, nodename, "value", FINISHER_PASS); + g_free(nodename); + +} +static void openrisc_virt_rtc_init(OR1KVirtState *state, hwaddr base, + hwaddr size, int num_cpus, + OpenRISCCPU *cpus[], int irq_pin) +{ + void *fdt = state->fdt; + char *nodename; + qemu_irq rtc_irq = get_per_cpu_irq(cpus, num_cpus, irq_pin); + + /* Goldfish RTC */ + sysbus_create_simple(TYPE_GOLDFISH_RTC, base, rtc_irq); + + /* Goldfish RTC FDT */ + nodename = g_strdup_printf("/soc/rtc@%" HWADDR_PRIx, base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "google,goldfish-rtc"); + qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin); + g_free(nodename); + +} +static void openrisc_virt_virtio_init(OR1KVirtState *state, hwaddr base, + hwaddr size, int num_cpus, + OpenRISCCPU *cpus[], int irq_pin) +{ + void *fdt = state->fdt; + char *nodename; + DeviceState *dev; + SysBusDevice *sysbus; + qemu_irq virtio_irq = get_per_cpu_irq(cpus, num_cpus, irq_pin); + + /* VirtIO MMIO devices */ + dev = qdev_new(TYPE_VIRTIO_MMIO); + qdev_prop_set_bit(dev, "force-legacy", false); + sysbus = SYS_BUS_DEVICE(dev); + sysbus_realize_and_unref(sysbus, &error_fatal); + sysbus_connect_irq(sysbus, 0, virtio_irq); + sysbus_mmio_map(sysbus, 0, base); + + /* VirtIO MMIO devices FDT */ + nodename = g_strdup_printf("/soc/virtio_mmio@%" HWADDR_PRIx, base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_string(fdt, nodename, "compatible", "virtio,mmio"); + qemu_fdt_setprop_cells(fdt, nodename, "reg", base, size); + qemu_fdt_setprop_cell(fdt, nodename, "interrupts", irq_pin); + g_free(nodename); +} + +static void openrisc_virt_init(MachineState *machine) +{ + ram_addr_t ram_size = machine->ram_size; + const char *kernel_filename = machine->kernel_filename; + OpenRISCCPU *cpus[VIRT_CPUS_MAX] = {}; + OR1KVirtState *state = VIRT_MACHINE(machine); + MemoryRegion *ram; + hwaddr load_addr; + int n; + unsigned int smp_cpus = machine->smp.cpus; + + assert(smp_cpus >= 1 && smp_cpus <= VIRT_CPUS_MAX); + for (n = 0; n < smp_cpus; n++) { + cpus[n] = OPENRISC_CPU(cpu_create(machine->cpu_type)); + if (cpus[n] == NULL) { + fprintf(stderr, "Unable to find CPU definition!\n"); + exit(1); + } + + cpu_openrisc_clock_init(cpus[n]); + + qemu_register_reset(main_cpu_reset, cpus[n]); + } + + ram = g_malloc(sizeof(*ram)); + memory_region_init_ram(ram, NULL, "openrisc.ram", ram_size, &error_fatal); + memory_region_add_subregion(get_system_memory(), 0, ram); + + openrisc_create_fdt(state, virt_memmap, smp_cpus, machine->ram_size, + machine->kernel_cmdline); + + if (smp_cpus > 1) { + openrisc_virt_ompic_init(state, virt_memmap[VIRT_OMPIC].base, + virt_memmap[VIRT_OMPIC].size, + smp_cpus, cpus, VIRT_OMPIC_IRQ); + } + + openrisc_virt_serial_init(state, virt_memmap[VIRT_UART].base, + virt_memmap[VIRT_UART].size, + smp_cpus, cpus, VIRT_UART_IRQ); + + openrisc_virt_test_init(state, virt_memmap[VIRT_TEST].base, + virt_memmap[VIRT_TEST].size); + + openrisc_virt_rtc_init(state, virt_memmap[VIRT_RTC].base, + virt_memmap[VIRT_RTC].size, smp_cpus, cpus, + VIRT_RTC_IRQ); + + for (n = 0; n < VIRTIO_COUNT; n++) { + openrisc_virt_virtio_init(state, virt_memmap[VIRT_VIRTIO].base + + n * virt_memmap[VIRT_VIRTIO].size, + virt_memmap[VIRT_VIRTIO].size, + smp_cpus, cpus, VIRT_VIRTIO_IRQ + n); + } + + load_addr = openrisc_load_kernel(ram_size, kernel_filename, + &boot_info.bootstrap_pc); + if (load_addr > 0) { + if (machine->initrd_filename) { + load_addr = openrisc_load_initrd(state->fdt, + machine->initrd_filename, + load_addr, machine->ram_size); + } + boot_info.fdt_addr = openrisc_load_fdt(state->fdt, load_addr, + machine->ram_size); + } +} + +static void openrisc_virt_machine_init(ObjectClass *oc, void *data) +{ + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "or1k virtual machine"; + mc->init = openrisc_virt_init; + mc->max_cpus = VIRT_CPUS_MAX; + mc->is_default = false; + mc->default_cpu_type = OPENRISC_CPU_TYPE_NAME("or1200"); +} + +static const TypeInfo or1ksim_machine_typeinfo = { + .name = TYPE_VIRT_MACHINE, + .parent = TYPE_MACHINE, + .class_init = openrisc_virt_machine_init, + .instance_size = sizeof(OR1KVirtState), +}; + +static void or1ksim_machine_init_register_types(void) +{ + type_register_static(&or1ksim_machine_typeinfo); +} + +type_init(or1ksim_machine_init_register_types) From 40fef82c4e7ea723b52eb3d2a0c4a46189f1ad44 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Sun, 12 Jun 2022 21:22:53 +0900 Subject: [PATCH 0334/1020] hw/openrisc: Add PCI bus support to virt This is mostly borrowed from xtensa and riscv as examples. The create_pcie_irq_map swizzle function is almost and exact copy but here we use a single cell interrupt, possibly we can make this generic. Signed-off-by: Stafford Horne --- hw/openrisc/Kconfig | 3 + hw/openrisc/virt.c | 160 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 157 insertions(+), 6 deletions(-) diff --git a/hw/openrisc/Kconfig b/hw/openrisc/Kconfig index 202134668e..97af258b55 100644 --- a/hw/openrisc/Kconfig +++ b/hw/openrisc/Kconfig @@ -7,8 +7,11 @@ config OR1K_SIM config OR1K_VIRT bool + imply PCI_DEVICES imply VIRTIO_VGA imply TEST_DEVICES + select PCI + select PCI_EXPRESS_GENERIC_BRIDGE select GOLDFISH_RTC select SERIAL select SIFIVE_TEST diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c index 54f2732a6b..9a78234a28 100644 --- a/hw/openrisc/virt.c +++ b/hw/openrisc/virt.c @@ -17,6 +17,8 @@ #include "hw/core/split-irq.h" #include "hw/openrisc/boot.h" #include "hw/misc/sifive_test.h" +#include "hw/pci/pci.h" +#include "hw/pci-host/gpex.h" #include "hw/qdev-properties.h" #include "hw/rtc/goldfish_rtc.h" #include "hw/sysbus.h" @@ -47,6 +49,9 @@ typedef struct OR1KVirtState { enum { VIRT_DRAM, + VIRT_ECAM, + VIRT_MMIO, + VIRT_PIO, VIRT_TEST, VIRT_RTC, VIRT_VIRTIO, @@ -60,6 +65,7 @@ enum { VIRT_RTC_IRQ = 3, VIRT_VIRTIO_IRQ = 4, /* to 12 */ VIRTIO_COUNT = 8, + VIRT_PCI_IRQ_BASE = 13, /* to 17 */ }; static const struct MemmapEntry { @@ -72,6 +78,9 @@ static const struct MemmapEntry { [VIRT_RTC] = { 0x96005000, 0x1000 }, [VIRT_VIRTIO] = { 0x97000000, 0x1000 }, [VIRT_OMPIC] = { 0x98000000, VIRT_CPUS_MAX * 8 }, + [VIRT_ECAM] = { 0x9e000000, 0x1000000 }, + [VIRT_PIO] = { 0x9f000000, 0x1000000 }, + [VIRT_MMIO] = { 0xa0000000, 0x10000000 }, }; static struct openrisc_boot_info { @@ -115,12 +124,12 @@ static qemu_irq get_per_cpu_irq(OpenRISCCPU *cpus[], int num_cpus, int irq_pin) static void openrisc_create_fdt(OR1KVirtState *state, const struct MemmapEntry *memmap, int num_cpus, uint64_t mem_size, - const char *cmdline) + const char *cmdline, + int32_t *pic_phandle) { void *fdt; int cpu; char *nodename; - int pic_ph; fdt = state->fdt = create_device_tree(&state->fdt_size); if (!fdt) { @@ -163,14 +172,14 @@ static void openrisc_create_fdt(OR1KVirtState *state, nodename = (char *)"/pic"; qemu_fdt_add_subnode(fdt, nodename); - pic_ph = qemu_fdt_alloc_phandle(fdt); + *pic_phandle = qemu_fdt_alloc_phandle(fdt); qemu_fdt_setprop_string(fdt, nodename, "compatible", "opencores,or1k-pic-level"); qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1); qemu_fdt_setprop(fdt, nodename, "interrupt-controller", NULL, 0); - qemu_fdt_setprop_cell(fdt, nodename, "phandle", pic_ph); + qemu_fdt_setprop_cell(fdt, nodename, "phandle", *pic_phandle); - qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", pic_ph); + qemu_fdt_setprop_cell(fdt, "/", "interrupt-parent", *pic_phandle); qemu_fdt_add_subnode(fdt, "/chosen"); if (cmdline) { @@ -275,6 +284,7 @@ static void openrisc_virt_test_init(OR1KVirtState *state, hwaddr base, g_free(nodename); } + static void openrisc_virt_rtc_init(OR1KVirtState *state, hwaddr base, hwaddr size, int num_cpus, OpenRISCCPU *cpus[], int irq_pin) @@ -296,6 +306,134 @@ static void openrisc_virt_rtc_init(OR1KVirtState *state, hwaddr base, g_free(nodename); } + +static void create_pcie_irq_map(void *fdt, char *nodename, int irq_base, + uint32_t irqchip_phandle) +{ + int pin, dev; + uint32_t irq_map_stride = 0; + uint32_t full_irq_map[GPEX_NUM_IRQS * GPEX_NUM_IRQS * 6] = {}; + uint32_t *irq_map = full_irq_map; + + /* + * This code creates a standard swizzle of interrupts such that + * each device's first interrupt is based on it's PCI_SLOT number. + * (See pci_swizzle_map_irq_fn()) + * + * We only need one entry per interrupt in the table (not one per + * possible slot) seeing the interrupt-map-mask will allow the table + * to wrap to any number of devices. + */ + for (dev = 0; dev < GPEX_NUM_IRQS; dev++) { + int devfn = dev << 3; + + for (pin = 0; pin < GPEX_NUM_IRQS; pin++) { + int irq_nr = irq_base + ((pin + PCI_SLOT(devfn)) % GPEX_NUM_IRQS); + int i = 0; + + /* Fill PCI address cells */ + irq_map[i++] = cpu_to_be32(devfn << 8); + irq_map[i++] = 0; + irq_map[i++] = 0; + + /* Fill PCI Interrupt cells */ + irq_map[i++] = cpu_to_be32(pin + 1); + + /* Fill interrupt controller phandle and cells */ + irq_map[i++] = cpu_to_be32(irqchip_phandle); + irq_map[i++] = cpu_to_be32(irq_nr); + + if (!irq_map_stride) { + irq_map_stride = i; + } + irq_map += irq_map_stride; + } + } + + qemu_fdt_setprop(fdt, nodename, "interrupt-map", full_irq_map, + GPEX_NUM_IRQS * GPEX_NUM_IRQS * + irq_map_stride * sizeof(uint32_t)); + + qemu_fdt_setprop_cells(fdt, nodename, "interrupt-map-mask", + 0x1800, 0, 0, 0x7); +} + +static void openrisc_virt_pcie_init(OR1KVirtState *state, + hwaddr ecam_base, hwaddr ecam_size, + hwaddr pio_base, hwaddr pio_size, + hwaddr mmio_base, hwaddr mmio_size, + int num_cpus, OpenRISCCPU *cpus[], + int irq_base, int32_t pic_phandle) +{ + void *fdt = state->fdt; + char *nodename; + MemoryRegion *alias; + MemoryRegion *reg; + DeviceState *dev; + qemu_irq pcie_irq; + int i; + + dev = qdev_new(TYPE_GPEX_HOST); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + /* Map ECAM space. */ + alias = g_new0(MemoryRegion, 1); + reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); + memory_region_init_alias(alias, OBJECT(dev), "pcie-ecam", + reg, 0, ecam_size); + memory_region_add_subregion(get_system_memory(), ecam_base, alias); + + /* + * Map the MMIO window into system address space so as to expose + * the section of PCI MMIO space which starts at the same base address + * (ie 1:1 mapping for that part of PCI MMIO space visible through + * the window). + */ + alias = g_new0(MemoryRegion, 1); + reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); + memory_region_init_alias(alias, OBJECT(dev), "pcie-mmio", + reg, mmio_base, mmio_size); + memory_region_add_subregion(get_system_memory(), mmio_base, alias); + + /* Map IO port space. */ + alias = g_new0(MemoryRegion, 1); + reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 2); + memory_region_init_alias(alias, OBJECT(dev), "pcie-pio", + reg, 0, pio_size); + memory_region_add_subregion(get_system_memory(), pio_base, alias); + + /* Connect IRQ lines. */ + for (i = 0; i < GPEX_NUM_IRQS; i++) { + pcie_irq = get_per_cpu_irq(cpus, num_cpus, irq_base + i); + + sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, pcie_irq); + gpex_set_irq_num(GPEX_HOST(dev), i, irq_base + i); + } + + nodename = g_strdup_printf("/soc/pci@%" HWADDR_PRIx, ecam_base); + qemu_fdt_add_subnode(fdt, nodename); + qemu_fdt_setprop_cell(fdt, nodename, "#interrupt-cells", 1); + qemu_fdt_setprop_cell(fdt, nodename, "#address-cells", 3); + qemu_fdt_setprop_cell(fdt, nodename, "#size-cells", 2); + qemu_fdt_setprop_string(fdt, nodename, "compatible", + "pci-host-ecam-generic"); + qemu_fdt_setprop_string(fdt, nodename, "device_type", "pci"); + qemu_fdt_setprop_cell(fdt, nodename, "linux,pci-domain", 0); + qemu_fdt_setprop_cells(fdt, nodename, "bus-range", 0, + ecam_size / PCIE_MMCFG_SIZE_MIN - 1); + qemu_fdt_setprop(fdt, nodename, "dma-coherent", NULL, 0); + qemu_fdt_setprop_cells(fdt, nodename, "reg", ecam_base, ecam_size); + /* pci-address(3) cpu-address(1) pci-size(2) */ + qemu_fdt_setprop_cells(fdt, nodename, "ranges", + FDT_PCI_RANGE_IOPORT, 0, 0, + pio_base, 0, pio_size, + FDT_PCI_RANGE_MMIO, 0, mmio_base, + mmio_base, 0, mmio_size); + + create_pcie_irq_map(fdt, nodename, irq_base, pic_phandle); + g_free(nodename); +} + static void openrisc_virt_virtio_init(OR1KVirtState *state, hwaddr base, hwaddr size, int num_cpus, OpenRISCCPU *cpus[], int irq_pin) @@ -333,6 +471,7 @@ static void openrisc_virt_init(MachineState *machine) hwaddr load_addr; int n; unsigned int smp_cpus = machine->smp.cpus; + int32_t pic_phandle; assert(smp_cpus >= 1 && smp_cpus <= VIRT_CPUS_MAX); for (n = 0; n < smp_cpus; n++) { @@ -352,7 +491,7 @@ static void openrisc_virt_init(MachineState *machine) memory_region_add_subregion(get_system_memory(), 0, ram); openrisc_create_fdt(state, virt_memmap, smp_cpus, machine->ram_size, - machine->kernel_cmdline); + machine->kernel_cmdline, &pic_phandle); if (smp_cpus > 1) { openrisc_virt_ompic_init(state, virt_memmap[VIRT_OMPIC].base, @@ -371,6 +510,15 @@ static void openrisc_virt_init(MachineState *machine) virt_memmap[VIRT_RTC].size, smp_cpus, cpus, VIRT_RTC_IRQ); + openrisc_virt_pcie_init(state, virt_memmap[VIRT_ECAM].base, + virt_memmap[VIRT_ECAM].size, + virt_memmap[VIRT_PIO].base, + virt_memmap[VIRT_PIO].size, + virt_memmap[VIRT_MMIO].base, + virt_memmap[VIRT_MMIO].size, + smp_cpus, cpus, + VIRT_PCI_IRQ_BASE, pic_phandle); + for (n = 0; n < VIRTIO_COUNT; n++) { openrisc_virt_virtio_init(state, virt_memmap[VIRT_VIRTIO].base + n * virt_memmap[VIRT_VIRTIO].size, From 557e37071d4d4e6de577f5a4dfb012a6a733f319 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Wed, 15 Jun 2022 08:40:16 +0900 Subject: [PATCH 0335/1020] hw/openrisc: Initialize timer time at startup The last_clk time was initialized at zero, this means when we calculate the first delta we will calculate 0 vs current time which could cause unnecessary hops. This patch moves timer initialization to the cpu reset. There are two resets registered here: 1. Per cpu timer mask (ttmr) reset. 2. Global cpu timer (last_clk and ttcr) reset, attached to the first cpu only. Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- hw/openrisc/cputimer.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/hw/openrisc/cputimer.c b/hw/openrisc/cputimer.c index 93268815d8..10163b391b 100644 --- a/hw/openrisc/cputimer.c +++ b/hw/openrisc/cputimer.c @@ -22,6 +22,7 @@ #include "cpu.h" #include "migration/vmstate.h" #include "qemu/timer.h" +#include "sysemu/reset.h" #define TIMER_PERIOD 50 /* 50 ns period for 20 MHz timer */ @@ -122,6 +123,24 @@ static void openrisc_timer_cb(void *opaque) qemu_cpu_kick(CPU(cpu)); } +/* Reset the per CPU counter state. */ +static void openrisc_count_reset(void *opaque) +{ + OpenRISCCPU *cpu = opaque; + + if (cpu->env.is_counting) { + cpu_openrisc_count_stop(cpu); + } + cpu->env.ttmr = 0x00000000; +} + +/* Reset the global timer state. */ +static void openrisc_timer_reset(void *opaque) +{ + or1k_timer->ttcr = 0x00000000; + or1k_timer->last_clk = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); +} + static const VMStateDescription vmstate_or1k_timer = { .name = "or1k_timer", .version_id = 1, @@ -136,10 +155,11 @@ static const VMStateDescription vmstate_or1k_timer = { void cpu_openrisc_clock_init(OpenRISCCPU *cpu) { cpu->env.timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &openrisc_timer_cb, cpu); - cpu->env.ttmr = 0x00000000; + qemu_register_reset(openrisc_count_reset, cpu); if (or1k_timer == NULL) { or1k_timer = g_new0(OR1KTimerState, 1); + qemu_register_reset(openrisc_timer_reset, cpu); vmstate_register(NULL, 0, &vmstate_or1k_timer, or1k_timer); } } From bbe6855ef80f61c6b00da22aa0cd550d79d8e381 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Wed, 15 Jun 2022 08:42:25 +0900 Subject: [PATCH 0336/1020] target/openrisc: Add interrupted CPU to log When we are tracing it's helpful to know which CPU's are getting interrupted, add that detail to the log line. Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/interrupt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/openrisc/interrupt.c b/target/openrisc/interrupt.c index e5724f5371..c31c6f12c4 100644 --- a/target/openrisc/interrupt.c +++ b/target/openrisc/interrupt.c @@ -83,7 +83,9 @@ void openrisc_cpu_do_interrupt(CPUState *cs) [EXCP_TRAP] = "TRAP", }; - qemu_log_mask(CPU_LOG_INT, "INT: %s\n", int_name[exception]); + qemu_log_mask(CPU_LOG_INT, "CPU: %d INT: %s\n", + cs->cpu_index, + int_name[exception]); hwaddr vect_pc = exception << 8; if (env->cpucfgr & CPUCFGR_EVBARP) { From 6a0fc96ad2b16a264ead6b696bdb91a963450dbb Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Wed, 15 Jun 2022 08:43:56 +0900 Subject: [PATCH 0337/1020] target/openrisc: Enable MTTCG This patch enables multithread TCG for OpenRISC. Since the or1k shared syncrhonized timer can be updated from each vCPU via helpers we use a mutex to synchronize updates. Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- configs/targets/or1k-softmmu.mak | 1 + target/openrisc/cpu.h | 2 ++ target/openrisc/sys_helper.c | 7 ++++++- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/configs/targets/or1k-softmmu.mak b/configs/targets/or1k-softmmu.mak index 263e970870..432f855a30 100644 --- a/configs/targets/or1k-softmmu.mak +++ b/configs/targets/or1k-softmmu.mak @@ -1,3 +1,4 @@ TARGET_ARCH=openrisc +TARGET_SUPPORTS_MTTCG=y TARGET_BIG_ENDIAN=y TARGET_NEED_FDT=y diff --git a/target/openrisc/cpu.h b/target/openrisc/cpu.h index b9584f10d4..1d5efa5ca2 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -25,6 +25,8 @@ #include "hw/core/cpu.h" #include "qom/object.h" +#define TCG_GUEST_DEFAULT_MO (0) + #define TYPE_OPENRISC_CPU "or1k-cpu" OBJECT_DECLARE_CPU_TYPE(OpenRISCCPU, OpenRISCCPUClass, OPENRISC_CPU) diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 48674231e7..da88ad9e77 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -145,6 +145,7 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) break; case TO_SPR(10, 0): /* TTMR */ { + qemu_mutex_lock_iothread(); if ((env->ttmr & TTMR_M) ^ (rb & TTMR_M)) { switch (rb & TTMR_M) { case TIMER_NONE: @@ -168,14 +169,16 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) env->ttmr = rb & ~TTMR_IP; cs->interrupt_request &= ~CPU_INTERRUPT_TIMER; } - cpu_openrisc_timer_update(cpu); + qemu_mutex_unlock_iothread(); } break; case TO_SPR(10, 1): /* TTCR */ + qemu_mutex_lock_iothread(); cpu_openrisc_count_set(cpu, rb); cpu_openrisc_timer_update(cpu); + qemu_mutex_unlock_iothread(); break; #endif @@ -303,7 +306,9 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, return env->ttmr; case TO_SPR(10, 1): /* TTCR */ + qemu_mutex_lock_iothread(); cpu_openrisc_count_update(cpu); + qemu_mutex_unlock_iothread(); return cpu_openrisc_count_get(cpu); #endif From 66564c31e4e012c65c84d403c2dc14c0a754047f Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Fri, 24 Jun 2022 05:44:56 +0900 Subject: [PATCH 0338/1020] target/openrisc: Interrupt handling fixes When running SMP systems we sometimes were seeing lockups where IPI interrupts were being raised by never handled. This looks to be caused by 2 issues in the openrisc interrupt handling logic. 1. After clearing an interrupt the openrisc_cpu_set_irq handler will always clear PICSR. This is not correct as masked interrupts should still be visible in PICSR. 2. After setting PICMR (mask register) and exposed interrupts should cause an interrupt to be raised. This was not being done so add it. This patch fixes both issues. Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- target/openrisc/cpu.c | 1 - target/openrisc/sys_helper.c | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index 41d1b2a24a..cb9f35f408 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -98,7 +98,6 @@ static void openrisc_cpu_set_irq(void *opaque, int irq, int level) cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - cpu->env.picsr = 0; } } #endif diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index da88ad9e77..09b3c97d7c 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -139,6 +139,13 @@ void HELPER(mtspr)(CPUOpenRISCState *env, target_ulong spr, target_ulong rb) break; case TO_SPR(9, 0): /* PICMR */ env->picmr = rb; + qemu_mutex_lock_iothread(); + if (env->picsr & env->picmr) { + cpu_interrupt(cs, CPU_INTERRUPT_HARD); + } else { + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + } + qemu_mutex_unlock_iothread(); break; case TO_SPR(9, 2): /* PICSR */ env->picsr &= ~rb; From c6fe3e6b4cd8d7b98ea37bf37fb3686ecd1304fe Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 22 Jun 2022 13:45:13 +0200 Subject: [PATCH 0339/1020] hw/openrisc: virt: pass random seed to fdt If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to initialize early. Set this using the usual guest random number generation function. This is confirmed to successfully initialize the RNG on Linux 5.19-rc2. Signed-off-by: Jason A. Donenfeld Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- hw/openrisc/virt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/openrisc/virt.c b/hw/openrisc/virt.c index 9a78234a28..f8a68a6a6b 100644 --- a/hw/openrisc/virt.c +++ b/hw/openrisc/virt.c @@ -8,6 +8,7 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" +#include "qemu/guest-random.h" #include "qapi/error.h" #include "cpu.h" #include "exec/address-spaces.h" @@ -130,6 +131,7 @@ static void openrisc_create_fdt(OR1KVirtState *state, void *fdt; int cpu; char *nodename; + uint8_t rng_seed[32]; fdt = state->fdt = create_device_tree(&state->fdt_size); if (!fdt) { @@ -186,6 +188,10 @@ static void openrisc_create_fdt(OR1KVirtState *state, qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", cmdline); } + /* Pass seed to RNG. */ + qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); + qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed)); + /* Create aliases node for use by devices. */ qemu_fdt_add_subnode(fdt, "/aliases"); } From b14df228d7c4fe6e86e7f8a4998e9ccf4967b678 Mon Sep 17 00:00:00 2001 From: Stafford Horne Date: Fri, 1 Jul 2022 08:29:17 +0900 Subject: [PATCH 0340/1020] docs/system: openrisc: Add OpenRISC documentation Reviewed-by: Richard Henderson Signed-off-by: Stafford Horne --- docs/system/openrisc/cpu-features.rst | 15 ++++++ docs/system/openrisc/emulation.rst | 17 +++++++ docs/system/openrisc/or1k-sim.rst | 43 ++++++++++++++++ docs/system/openrisc/virt.rst | 50 +++++++++++++++++++ docs/system/target-openrisc.rst | 71 +++++++++++++++++++++++++++ docs/system/targets.rst | 1 + 6 files changed, 197 insertions(+) create mode 100644 docs/system/openrisc/cpu-features.rst create mode 100644 docs/system/openrisc/emulation.rst create mode 100644 docs/system/openrisc/or1k-sim.rst create mode 100644 docs/system/openrisc/virt.rst create mode 100644 docs/system/target-openrisc.rst diff --git a/docs/system/openrisc/cpu-features.rst b/docs/system/openrisc/cpu-features.rst new file mode 100644 index 0000000000..aeb65e22ff --- /dev/null +++ b/docs/system/openrisc/cpu-features.rst @@ -0,0 +1,15 @@ +CPU Features +============ + +The QEMU emulation of the OpenRISC architecture provides following built in +features. + +- Shadow GPRs +- MMU TLB with 128 entries, 1 way +- Power Management (PM) +- Programmable Interrupt Controller (PIC) +- Tick Timer + +These features are on by default and the presence can be confirmed by checking +the contents of the Unit Presence Register (``UPR``) and CPU Configuration +Register (``CPUCFGR``). diff --git a/docs/system/openrisc/emulation.rst b/docs/system/openrisc/emulation.rst new file mode 100644 index 0000000000..0af898ab20 --- /dev/null +++ b/docs/system/openrisc/emulation.rst @@ -0,0 +1,17 @@ +OpenRISC 1000 CPU architecture support +====================================== + +QEMU's TCG emulation includes support for the OpenRISC or1200 implementation of +the OpenRISC 1000 cpu architecture. + +The or1200 cpu also has support for the following instruction subsets: + +- ORBIS32 (OpenRISC Basic Instruction Set) +- ORFPX32 (OpenRISC Floating-Point eXtension) + +In addition to the instruction subsets the QEMU TCG emulation also has support +for most Class II (optional) instructions. + +For information on all OpenRISC instructions please refer to the latest +architecture manual available on the OpenRISC website in the +`OpenRISC Architecture `_ section. diff --git a/docs/system/openrisc/or1k-sim.rst b/docs/system/openrisc/or1k-sim.rst new file mode 100644 index 0000000000..ef10439737 --- /dev/null +++ b/docs/system/openrisc/or1k-sim.rst @@ -0,0 +1,43 @@ +Or1ksim board +============= + +The QEMU Or1ksim machine emulates the standard OpenRISC board simulator which is +also the standard SoC configuration. + +Supported devices +----------------- + + * 16550A UART + * ETHOC Ethernet controller + * SMP (OpenRISC multicore using ompic) + +Boot options +------------ + +The Or1ksim machine can be started using the ``-kernel`` and ``-initrd`` options +to load a Linux kernel and optional disk image. + +.. code-block:: bash + + $ qemu-system-or1k -cpu or1220 -M or1k-sim -nographic \ + -kernel vmlinux \ + -initrd initramfs.cpio.gz \ + -m 128 + +Linux guest kernel configuration +"""""""""""""""""""""""""""""""" + +The 'or1ksim_defconfig' for Linux openrisc kernels includes the right +drivers for the or1ksim machine. If you would like to run an SMP system +choose the 'simple_smp_defconfig' config. + +Hardware configuration information +"""""""""""""""""""""""""""""""""" + +The ``or1k-sim`` board automatically generates a device tree blob ("dtb") +which it passes to the guest. This provides information about the +addresses, interrupt lines and other configuration of the various devices +in the system. + +The location of the DTB will be passed in register ``r3`` to the guest operating +system. diff --git a/docs/system/openrisc/virt.rst b/docs/system/openrisc/virt.rst new file mode 100644 index 0000000000..2fe61ac942 --- /dev/null +++ b/docs/system/openrisc/virt.rst @@ -0,0 +1,50 @@ +'virt' generic virtual platform +=============================== + +The ``virt`` board is a platform which does not correspond to any +real hardware; it is designed for use in virtual machines. +It is the recommended board type if you simply want to run +a guest such as Linux and do not care about reproducing the +idiosyncrasies and limitations of a particular bit of real-world +hardware. + +Supported devices +----------------- + + * PCI/PCIe devices + * 8 virtio-mmio transport devices + * 16550A UART + * Goldfish RTC + * SiFive Test device for poweroff and reboot + * SMP (OpenRISC multicore using ompic) + +Boot options +------------ + +The virt machine can be started using the ``-kernel`` and ``-initrd`` options +to load a Linux kernel and optional disk image. For example: + +.. code-block:: bash + + $ qemu-system-or1k -cpu or1220 -M or1k-sim -nographic \ + -device virtio-net-device,netdev=user -netdev user,id=user,net=10.9.0.1/24,host=10.9.0.100 \ + -device virtio-blk-device,drive=d0 -drive file=virt.qcow2,id=d0,if=none,format=qcow2 \ + -kernel vmlinux \ + -initrd initramfs.cpio.gz \ + -m 128 + +Linux guest kernel configuration +"""""""""""""""""""""""""""""""" + +The 'virt_defconfig' for Linux openrisc kernels includes the right drivers for +the ``virt`` machine. + +Hardware configuration information +"""""""""""""""""""""""""""""""""" + +The ``virt`` board automatically generates a device tree blob ("dtb") which it +passes to the guest. This provides information about the addresses, interrupt +lines and other configuration of the various devices in the system. + +The location of the DTB will be passed in register ``r3`` to the guest operating +system. diff --git a/docs/system/target-openrisc.rst b/docs/system/target-openrisc.rst new file mode 100644 index 0000000000..22cb2217a6 --- /dev/null +++ b/docs/system/target-openrisc.rst @@ -0,0 +1,71 @@ +.. _OpenRISC-System-emulator: + +OpenRISC System emulator +~~~~~~~~~~~~~~~~~~~~~~~~ + +QEMU can emulate 32-bit OpenRISC CPUs using the ``qemu-system-or1k`` executable. + +OpenRISC CPUs are generally built into "system-on-chip" (SoC) designs that run +on FPGAs. These SoCs are based on the same core architecture as the or1ksim +(the original OpenRISC instruction level simulator) which QEMU supports. For +this reason QEMU does not need to support many different boards to support the +OpenRISC hardware ecosystem. + +The OpenRISC CPU supported by QEMU is the ``or1200``, it supports an MMU and can +run linux. + +Choosing a board model +====================== + +For QEMU's OpenRISC system emulation, you must specify which board model you +want to use with the ``-M`` or ``--machine`` option; the default machine is +``or1k-sim``. + +If you intend to boot Linux, it is possible to have a single kernel image that +will boot on any of the QEMU machines. To do this one would compile all required +drivers into the kernel. This is possible because QEMU will create a device tree +structure that describes the QEMU machine and pass a pointer to the structure to +the kernel. The kernel can then use this to configure itself for the machine. + +However, typically users will have specific firmware images for a specific machine. + +If you already have a system image or a kernel that works on hardware and you +want to boot with QEMU, check whether QEMU lists that machine in its ``-machine +help`` output. If it is listed, then you can probably use that board model. If +it is not listed, then unfortunately your image will almost certainly not boot +on QEMU. (You might be able to extract the filesystem and use that with a +different kernel which boots on a system that QEMU does emulate.) + +If you don't care about reproducing the idiosyncrasies of a particular +bit of hardware, such as small amount of RAM, no PCI or other hard disk, etc., +and just want to run Linux, the best option is to use the ``virt`` board. This +is a platform which doesn't correspond to any real hardware and is designed for +use in virtual machines. You'll need to compile Linux with a suitable +configuration for running on the ``virt`` board. ``virt`` supports PCI, virtio +and large amounts of RAM. + +Board-specific documentation +============================ + +.. + This table of contents should be kept sorted alphabetically + by the title text of each file, which isn't the same ordering + as an alphabetical sort by filename. + +.. toctree:: + :maxdepth: 1 + + openrisc/or1k-sim + openrisc/virt + +Emulated CPU architecture support +================================= + +.. toctree:: + openrisc/emulation + +OpenRISC CPU features +===================== + +.. toctree:: + openrisc/cpu-features diff --git a/docs/system/targets.rst b/docs/system/targets.rst index 9dcd95dd84..224fadae71 100644 --- a/docs/system/targets.rst +++ b/docs/system/targets.rst @@ -21,6 +21,7 @@ Contents: target-m68k target-mips target-ppc + target-openrisc target-riscv target-rx target-s390x From 3e01455edd5fce06c14e2926b6ef408d9a94c9fb Mon Sep 17 00:00:00 2001 From: Samuel Thibault Date: Tue, 6 Sep 2022 00:09:50 +0200 Subject: [PATCH 0341/1020] usb-braille: Better explain that one also has to create a chardev backend Users have reported not to understand the documentation. This completes it to give an explicit example how one is supposed to set up a virtual braille USB device. Signed-off-by: Samuel Thibault --- docs/system/devices/usb.rst | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/system/devices/usb.rst b/docs/system/devices/usb.rst index f39a88f080..37cb9b33ae 100644 --- a/docs/system/devices/usb.rst +++ b/docs/system/devices/usb.rst @@ -178,8 +178,20 @@ option or the ``device_add`` monitor command. Available devices are: host character device id. ``usb-braille,chardev=id`` - Braille device. This will use BrlAPI to display the braille output on - a real or fake device referenced by id. + Braille device. This emulates a Baum Braille device USB port. id has to + specify a character device defined with ``-chardev …,id=id``. One will + normally use BrlAPI to display the braille output on a BRLTTY-supported + device with + + .. parsed-literal:: + + |qemu_system| [...] -chardev braille,id=brl -device usb-braille,chardev=brl + + or alternatively, use the following equivalent shortcut: + + .. parsed-literal:: + + |qemu_system| [...] -usbdevice braille ``usb-net[,netdev=id]`` Network adapter that supports CDC ethernet and RNDIS protocols. id From fbd3c4cff641cae082edb765017cbb699efa6712 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 17:22:04 -0700 Subject: [PATCH 0342/1020] linux-user/arm: Mark the commpage executable We're about to start validating PAGE_EXEC, which means that we've got to mark the commpage executable. We had been placing the commpage outside of reserved_va, which was incorrect and lead to an abort. Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- linux-user/arm/target_cpu.h | 4 ++-- linux-user/elfload.c | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h index 709d19bc9e..89ba274cfc 100644 --- a/linux-user/arm/target_cpu.h +++ b/linux-user/arm/target_cpu.h @@ -34,9 +34,9 @@ static inline unsigned long arm_max_reserved_va(CPUState *cs) } else { /* * We need to be able to map the commpage. - * See validate_guest_space in linux-user/elfload.c. + * See init_guest_commpage in linux-user/elfload.c. */ - return 0xffff0000ul; + return 0xfffffffful; } } #define MAX_RESERVED_VA arm_max_reserved_va diff --git a/linux-user/elfload.c b/linux-user/elfload.c index ce902dbd56..3e3dc02499 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -398,7 +398,8 @@ enum { static bool init_guest_commpage(void) { - void *want = g2h_untagged(HI_COMMPAGE & -qemu_host_page_size); + abi_ptr commpage = HI_COMMPAGE & -qemu_host_page_size; + void *want = g2h_untagged(commpage); void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); @@ -417,6 +418,9 @@ static bool init_guest_commpage(void) perror("Protecting guest commpage"); exit(EXIT_FAILURE); } + + page_set_flags(commpage, commpage + qemu_host_page_size, + PAGE_READ | PAGE_EXEC | PAGE_VALID); return true; } From eee816c0b972bd085e62fcd7d2de7a34dbbd155b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 18:44:48 -0700 Subject: [PATCH 0343/1020] linux-user/hppa: Allocate page zero as a commpage We're about to start validating PAGE_EXEC, which means that we've got to mark page zero executable. We had been special casing this entirely within translate. Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- linux-user/elfload.c | 34 +++++++++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 3e3dc02499..29d910c4cc 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1646,6 +1646,34 @@ static inline void init_thread(struct target_pt_regs *regs, regs->gr[31] = infop->entry; } +#define LO_COMMPAGE 0 + +static bool init_guest_commpage(void) +{ + void *want = g2h_untagged(LO_COMMPAGE); + void *addr = mmap(want, qemu_host_page_size, PROT_NONE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + + if (addr == MAP_FAILED) { + perror("Allocating guest commpage"); + exit(EXIT_FAILURE); + } + if (addr != want) { + return false; + } + + /* + * On Linux, page zero is normally marked execute only + gateway. + * Normal read or write is supposed to fail (thus PROT_NONE above), + * but specific offsets have kernel code mapped to raise permissions + * and implement syscalls. Here, simply mark the page executable. + * Special case the entry points during translation (see do_page_zero). + */ + page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE, + PAGE_EXEC | PAGE_VALID); + return true; +} + #endif /* TARGET_HPPA */ #ifdef TARGET_XTENSA @@ -2326,12 +2354,12 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, } #if defined(HI_COMMPAGE) -#define LO_COMMPAGE 0 +#define LO_COMMPAGE -1 #elif defined(LO_COMMPAGE) #define HI_COMMPAGE 0 #else #define HI_COMMPAGE 0 -#define LO_COMMPAGE 0 +#define LO_COMMPAGE -1 #define init_guest_commpage() true #endif @@ -2555,7 +2583,7 @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr, } else { offset = -(HI_COMMPAGE & -align); } - } else if (LO_COMMPAGE != 0) { + } else if (LO_COMMPAGE != -1) { loaddr = MIN(loaddr, LO_COMMPAGE & -align); } From d461b73ec007ccbe861db91bbcd792c92e46fcad Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 11 Aug 2022 11:18:29 -0700 Subject: [PATCH 0344/1020] linux-user/x86_64: Allocate vsyscall page as a commpage We're about to start validating PAGE_EXEC, which means that we've got to mark the vsyscall page executable. We had been special casing this entirely within translate. Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- linux-user/elfload.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 29d910c4cc..82fecf9e5a 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -195,6 +195,27 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en (*regs)[26] = tswapreg(env->segs[R_GS].selector & 0xffff); } +#if ULONG_MAX > UINT32_MAX +#define INIT_GUEST_COMMPAGE +static bool init_guest_commpage(void) +{ + /* + * The vsyscall page is at a high negative address aka kernel space, + * which means that we cannot actually allocate it with target_mmap. + * We still should be able to use page_set_flags, unless the user + * has specified -R reserved_va, which would trigger an assert(). + */ + if (reserved_va != 0 && + TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE >= reserved_va) { + error_report("Cannot allocate vsyscall page"); + exit(EXIT_FAILURE); + } + page_set_flags(TARGET_VSYSCALL_PAGE, + TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE, + PAGE_EXEC | PAGE_VALID); + return true; +} +#endif #else #define ELF_START_MMAP 0x80000000 @@ -2360,8 +2381,10 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, #else #define HI_COMMPAGE 0 #define LO_COMMPAGE -1 +#ifndef INIT_GUEST_COMMPAGE #define init_guest_commpage() true #endif +#endif static void pgb_fail_in_use(const char *image_name) { From 872f3d046f2381e3f416519e82df96bd60818311 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 23:00:52 -0700 Subject: [PATCH 0345/1020] linux-user: Honor PT_GNU_STACK Map the stack executable if required by default or on demand. Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- include/elf.h | 1 + linux-user/elfload.c | 19 ++++++++++++++++++- linux-user/qemu.h | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/elf.h b/include/elf.h index 3a4bcb646a..3d6b9062c0 100644 --- a/include/elf.h +++ b/include/elf.h @@ -31,6 +31,7 @@ typedef int64_t Elf64_Sxword; #define PT_LOPROC 0x70000000 #define PT_HIPROC 0x7fffffff +#define PT_GNU_STACK (PT_LOOS + 0x474e551) #define PT_GNU_PROPERTY (PT_LOOS + 0x474e553) #define PT_MIPS_REGINFO 0x70000000 diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 82fecf9e5a..ba5c4c02e5 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -232,6 +232,7 @@ static bool init_guest_commpage(void) #define ELF_ARCH EM_386 #define ELF_PLATFORM get_elf_platform() +#define EXSTACK_DEFAULT true static const char *get_elf_platform(void) { @@ -308,6 +309,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en #define ELF_ARCH EM_ARM #define ELF_CLASS ELFCLASS32 +#define EXSTACK_DEFAULT true static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) @@ -776,6 +778,7 @@ static inline void init_thread(struct target_pt_regs *regs, #else #define ELF_CLASS ELFCLASS32 +#define EXSTACK_DEFAULT true #endif @@ -973,6 +976,7 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en #define ELF_CLASS ELFCLASS64 #define ELF_ARCH EM_LOONGARCH +#define EXSTACK_DEFAULT true #define elf_check_arch(x) ((x) == EM_LOONGARCH) @@ -1068,6 +1072,7 @@ static uint32_t get_elf_hwcap(void) #define ELF_CLASS ELFCLASS32 #endif #define ELF_ARCH EM_MIPS +#define EXSTACK_DEFAULT true #ifdef TARGET_ABI_MIPSN32 #define elf_check_abi(x) ((x) & EF_MIPS_ABI2) @@ -1806,6 +1811,10 @@ static inline void init_thread(struct target_pt_regs *regs, #define bswaptls(ptr) bswap32s(ptr) #endif +#ifndef EXSTACK_DEFAULT +#define EXSTACK_DEFAULT false +#endif + #include "elf.h" /* We must delay the following stanzas until after "elf.h". */ @@ -2081,6 +2090,7 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm, struct image_info *info) { abi_ulong size, error, guard; + int prot; size = guest_stack_size; if (size < STACK_LOWER_LIMIT) { @@ -2091,7 +2101,11 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm, guard = qemu_real_host_page_size(); } - error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE, + prot = PROT_READ | PROT_WRITE; + if (info->exec_stack) { + prot |= PROT_EXEC; + } + error = target_mmap(0, size + guard, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if (error == -1) { perror("mmap stack"); @@ -2921,6 +2935,7 @@ static void load_elf_image(const char *image_name, int image_fd, */ loaddr = -1, hiaddr = 0; info->alignment = 0; + info->exec_stack = EXSTACK_DEFAULT; for (i = 0; i < ehdr->e_phnum; ++i) { struct elf_phdr *eppnt = phdr + i; if (eppnt->p_type == PT_LOAD) { @@ -2963,6 +2978,8 @@ static void load_elf_image(const char *image_name, int image_fd, if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) { goto exit_errmsg; } + } else if (eppnt->p_type == PT_GNU_STACK) { + info->exec_stack = eppnt->p_flags & PF_X; } } diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 7d90de1b15..e2e93fbd1d 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -48,6 +48,7 @@ struct image_info { uint32_t elf_flags; int personality; abi_ulong alignment; + bool exec_stack; /* Generic semihosting knows about these pointers. */ abi_ulong arg_strings; /* strings for argv */ From aa98e2d885ca9de66ddd56d88b19b0e162cc90d7 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 17 Aug 2022 17:05:03 +0200 Subject: [PATCH 0346/1020] linux-user: Clear translations on mprotect() Currently it's possible to execute pages that do not have PAGE_EXEC if there is an existing translation block. Fix by invalidating TBs that touch the affected pages. Signed-off-by: Ilya Leoshkevich Message-Id: <20220817150506.592862-2-iii@linux.ibm.com> Signed-off-by: Richard Henderson --- linux-user/mmap.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 048c4135af..6a828e8418 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -177,9 +177,11 @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot) goto error; } } + page_set_flags(start, start + len, page_flags); - mmap_unlock(); - return 0; + tb_invalidate_phys_range(start, start + len); + ret = 0; + error: mmap_unlock(); return ret; From d64655c2c35d967e9c496937885c511240204e76 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 11 Aug 2022 10:58:36 -0700 Subject: [PATCH 0347/1020] tests/tcg/i386: Move smc_code2 to an executable section We're about to start validating PAGE_EXEC, which means that we've got to put this code into a section that is both writable and executable. Note that this test did not run on hardware beforehand either. Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- tests/tcg/i386/test-i386.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c index ac8d5a3c1f..e6b308a2c0 100644 --- a/tests/tcg/i386/test-i386.c +++ b/tests/tcg/i386/test-i386.c @@ -1998,7 +1998,7 @@ uint8_t code[] = { 0xc3, /* ret */ }; -asm(".section \".data\"\n" +asm(".section \".data_x\",\"awx\"\n" "smc_code2:\n" "movl 4(%esp), %eax\n" "movl %eax, smc_patch_addr2 + 1\n" From f3b2b81b6fdaacfa8a769ad5834e6f6f129e2119 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Thu, 11 Aug 2022 11:55:31 +0200 Subject: [PATCH 0348/1020] accel/tcg: Introduce is_same_page() Introduce a function that checks whether a given address is on the same page as where disassembly started. Having it improves readability of the following patches. Reviewed-by: Alistair Francis Signed-off-by: Ilya Leoshkevich Message-Id: <20220811095534.241224-3-iii@linux.ibm.com> Reviewed-by: Richard Henderson [rth: Make the DisasContextBase parameter const.] Signed-off-by: Richard Henderson --- include/exec/translator.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/include/exec/translator.h b/include/exec/translator.h index 7db6845535..0d0bf3a31e 100644 --- a/include/exec/translator.h +++ b/include/exec/translator.h @@ -187,4 +187,14 @@ FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD) #undef GEN_TRANSLATOR_LD +/* + * Return whether addr is on the same page as where disassembly started. + * Translators can use this to enforce the rule that only single-insn + * translation blocks are allowed to cross page boundaries. + */ +static inline bool is_same_page(const DisasContextBase *db, target_ulong addr) +{ + return ((addr ^ db->pc_first) & TARGET_PAGE_MASK) == 0; +} + #endif /* EXEC__TRANSLATOR_H */ From cdf7130851318004e6512dbfdb73156fe59c7a59 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 13:52:50 -0700 Subject: [PATCH 0349/1020] accel/tcg: Properly implement get_page_addr_code for user-only The current implementation is a no-op, simply returning addr. This is incorrect, because we ought to be checking the page permissions for execution. Make get_page_addr_code inline for both implementations. Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Acked-by: Alistair Francis Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 5 --- accel/tcg/user-exec.c | 14 +++++++ include/exec/exec-all.h | 85 ++++++++++++++--------------------------- 3 files changed, 42 insertions(+), 62 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index a46f3a654d..43bd65c973 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1544,11 +1544,6 @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, return qemu_ram_addr_from_host_nofail(p); } -tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr) -{ - return get_page_addr_code_hostp(env, addr, NULL); -} - static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size, CPUIOTLBEntry *iotlbentry, uintptr_t retaddr) { diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 20ada5472b..2bc4394b80 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -199,6 +199,20 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size, return size ? g2h(env_cpu(env), addr) : NULL; } +tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, + void **hostp) +{ + int flags; + + flags = probe_access_internal(env, addr, 1, MMU_INST_FETCH, false, 0); + g_assert(flags == 0); + + if (hostp) { + *hostp = g2h_untagged(addr); + } + return addr; +} + /* The softmmu versions of these helpers are in cputlb.c. */ /* diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 311e5fb422..0475ec6007 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -598,43 +598,44 @@ struct MemoryRegionSection *iotlb_to_section(CPUState *cpu, hwaddr index, MemTxAttrs attrs); #endif -#if defined(CONFIG_USER_ONLY) -void mmap_lock(void); -void mmap_unlock(void); -bool have_mmap_lock(void); - /** - * get_page_addr_code() - user-mode version + * get_page_addr_code_hostp() * @env: CPUArchState * @addr: guest virtual address of guest code * - * Returns @addr. + * See get_page_addr_code() (full-system version) for documentation on the + * return value. + * + * Sets *@hostp (when @hostp is non-NULL) as follows. + * If the return value is -1, sets *@hostp to NULL. Otherwise, sets *@hostp + * to the host address where @addr's content is kept. + * + * Note: this function can trigger an exception. + */ +tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, + void **hostp); + +/** + * get_page_addr_code() + * @env: CPUArchState + * @addr: guest virtual address of guest code + * + * If we cannot translate and execute from the entire RAM page, or if + * the region is not backed by RAM, returns -1. Otherwise, returns the + * ram_addr_t corresponding to the guest code at @addr. + * + * Note: this function can trigger an exception. */ static inline tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr) { - return addr; + return get_page_addr_code_hostp(env, addr, NULL); } -/** - * get_page_addr_code_hostp() - user-mode version - * @env: CPUArchState - * @addr: guest virtual address of guest code - * - * Returns @addr. - * - * If @hostp is non-NULL, sets *@hostp to the host address where @addr's content - * is kept. - */ -static inline tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, - target_ulong addr, - void **hostp) -{ - if (hostp) { - *hostp = g2h_untagged(addr); - } - return addr; -} +#if defined(CONFIG_USER_ONLY) +void mmap_lock(void); +void mmap_unlock(void); +bool have_mmap_lock(void); /** * adjust_signal_pc: @@ -691,36 +692,6 @@ G_NORETURN void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr, static inline void mmap_lock(void) {} static inline void mmap_unlock(void) {} -/** - * get_page_addr_code() - full-system version - * @env: CPUArchState - * @addr: guest virtual address of guest code - * - * If we cannot translate and execute from the entire RAM page, or if - * the region is not backed by RAM, returns -1. Otherwise, returns the - * ram_addr_t corresponding to the guest code at @addr. - * - * Note: this function can trigger an exception. - */ -tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr); - -/** - * get_page_addr_code_hostp() - full-system version - * @env: CPUArchState - * @addr: guest virtual address of guest code - * - * See get_page_addr_code() (full-system version) for documentation on the - * return value. - * - * Sets *@hostp (when @hostp is non-NULL) as follows. - * If the return value is -1, sets *@hostp to NULL. Otherwise, sets *@hostp - * to the host address where @addr's content is kept. - * - * Note: this function can trigger an exception. - */ -tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, - void **hostp); - void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length); void tlb_set_dirty(CPUState *cpu, target_ulong vaddr); From 297368c74d077b24f0bb5c4f1ce541cc23d36815 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 17:14:26 -0700 Subject: [PATCH 0350/1020] accel/tcg: Unlock mmap_lock after longjmp The mmap_lock is held around tb_gen_code. While the comment is correct that the lock is dropped when tb_gen_code runs out of memory, the lock is *not* dropped when an exception is raised reading code for translation. Acked-by: Alistair Francis Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- accel/tcg/cpu-exec.c | 12 ++++++------ accel/tcg/user-exec.c | 3 --- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index a565a3f8ec..d18081ca6f 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -462,13 +462,11 @@ void cpu_exec_step_atomic(CPUState *cpu) cpu_tb_exec(cpu, tb, &tb_exit); cpu_exec_exit(cpu); } else { - /* - * The mmap_lock is dropped by tb_gen_code if it runs out of - * memory. - */ #ifndef CONFIG_SOFTMMU clear_helper_retaddr(); - tcg_debug_assert(!have_mmap_lock()); + if (have_mmap_lock()) { + mmap_unlock(); + } #endif if (qemu_mutex_iothread_locked()) { qemu_mutex_unlock_iothread(); @@ -936,7 +934,9 @@ int cpu_exec(CPUState *cpu) #ifndef CONFIG_SOFTMMU clear_helper_retaddr(); - tcg_debug_assert(!have_mmap_lock()); + if (have_mmap_lock()) { + mmap_unlock(); + } #endif if (qemu_mutex_iothread_locked()) { qemu_mutex_unlock_iothread(); diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 2bc4394b80..521aa8b61e 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -80,10 +80,7 @@ MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write) * (and if the translator doesn't handle page boundaries correctly * there's little we can do about that here). Therefore, do not * trigger the unwinder. - * - * Like tb_gen_code, release the memory lock before cpu_loop_exit. */ - mmap_unlock(); *pc = 0; return MMU_INST_FETCH; } From 0c90ba16e3b51381dc82b0f54532c6609261aea0 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 16 Aug 2022 13:53:18 -0500 Subject: [PATCH 0351/1020] accel/tcg: Make tb_htable_lookup static The function is not used outside of cpu-exec.c. Move it and its subroutines up in the file, before the first use. Reviewed-by: Alistair Francis Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- accel/tcg/cpu-exec.c | 122 ++++++++++++++++++++-------------------- include/exec/exec-all.h | 3 - 2 files changed, 61 insertions(+), 64 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index d18081ca6f..7887af6f45 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -170,6 +170,67 @@ uint32_t curr_cflags(CPUState *cpu) return cflags; } +struct tb_desc { + target_ulong pc; + target_ulong cs_base; + CPUArchState *env; + tb_page_addr_t phys_page1; + uint32_t flags; + uint32_t cflags; + uint32_t trace_vcpu_dstate; +}; + +static bool tb_lookup_cmp(const void *p, const void *d) +{ + const TranslationBlock *tb = p; + const struct tb_desc *desc = d; + + if (tb->pc == desc->pc && + tb->page_addr[0] == desc->phys_page1 && + tb->cs_base == desc->cs_base && + tb->flags == desc->flags && + tb->trace_vcpu_dstate == desc->trace_vcpu_dstate && + tb_cflags(tb) == desc->cflags) { + /* check next page if needed */ + if (tb->page_addr[1] == -1) { + return true; + } else { + tb_page_addr_t phys_page2; + target_ulong virt_page2; + + virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + phys_page2 = get_page_addr_code(desc->env, virt_page2); + if (tb->page_addr[1] == phys_page2) { + return true; + } + } + } + return false; +} + +static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, + target_ulong cs_base, uint32_t flags, + uint32_t cflags) +{ + tb_page_addr_t phys_pc; + struct tb_desc desc; + uint32_t h; + + desc.env = cpu->env_ptr; + desc.cs_base = cs_base; + desc.flags = flags; + desc.cflags = cflags; + desc.trace_vcpu_dstate = *cpu->trace_dstate; + desc.pc = pc; + phys_pc = get_page_addr_code(desc.env, pc); + if (phys_pc == -1) { + return NULL; + } + desc.phys_page1 = phys_pc & TARGET_PAGE_MASK; + h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate); + return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); +} + /* Might cause an exception, so have a longjmp destination ready */ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, target_ulong cs_base, @@ -485,67 +546,6 @@ void cpu_exec_step_atomic(CPUState *cpu) end_exclusive(); } -struct tb_desc { - target_ulong pc; - target_ulong cs_base; - CPUArchState *env; - tb_page_addr_t phys_page1; - uint32_t flags; - uint32_t cflags; - uint32_t trace_vcpu_dstate; -}; - -static bool tb_lookup_cmp(const void *p, const void *d) -{ - const TranslationBlock *tb = p; - const struct tb_desc *desc = d; - - if (tb->pc == desc->pc && - tb->page_addr[0] == desc->phys_page1 && - tb->cs_base == desc->cs_base && - tb->flags == desc->flags && - tb->trace_vcpu_dstate == desc->trace_vcpu_dstate && - tb_cflags(tb) == desc->cflags) { - /* check next page if needed */ - if (tb->page_addr[1] == -1) { - return true; - } else { - tb_page_addr_t phys_page2; - target_ulong virt_page2; - - virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; - phys_page2 = get_page_addr_code(desc->env, virt_page2); - if (tb->page_addr[1] == phys_page2) { - return true; - } - } - } - return false; -} - -TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, - target_ulong cs_base, uint32_t flags, - uint32_t cflags) -{ - tb_page_addr_t phys_pc; - struct tb_desc desc; - uint32_t h; - - desc.env = cpu->env_ptr; - desc.cs_base = cs_base; - desc.flags = flags; - desc.cflags = cflags; - desc.trace_vcpu_dstate = *cpu->trace_dstate; - desc.pc = pc; - phys_pc = get_page_addr_code(desc.env, pc); - if (phys_pc == -1) { - return NULL; - } - desc.phys_page1 = phys_pc & TARGET_PAGE_MASK; - h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate); - return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); -} - void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr) { if (TCG_TARGET_HAS_direct_jump) { diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 0475ec6007..9f35e3b7a9 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -552,9 +552,6 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs); #endif void tb_flush(CPUState *cpu); void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr); -TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, - target_ulong cs_base, uint32_t flags, - uint32_t cflags); void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr); /* GETPC is the true target of the return instruction that we'll execute. */ From 97e03465f7dac073434373428388eb6e0998ecea Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 12:04:15 -0700 Subject: [PATCH 0352/1020] accel/tcg: Move qemu_ram_addr_from_host_nofail to physmem.c The base qemu_ram_addr_from_host function is already in softmmu/physmem.c; move the nofail version to be adjacent. Reviewed-by: Alistair Francis Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 12 ------------ include/exec/cpu-common.h | 1 + softmmu/physmem.c | 12 ++++++++++++ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 43bd65c973..80a3eb4f1c 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1283,18 +1283,6 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr, prot, mmu_idx, size); } -static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) -{ - ram_addr_t ram_addr; - - ram_addr = qemu_ram_addr_from_host(ptr); - if (ram_addr == RAM_ADDR_INVALID) { - error_report("Bad ram pointer %p", ptr); - abort(); - } - return ram_addr; -} - /* * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 2281be4e10..d909429427 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -72,6 +72,7 @@ typedef uintptr_t ram_addr_t; void qemu_ram_remap(ram_addr_t addr, ram_addr_t length); /* This should not be used by devices. */ ram_addr_t qemu_ram_addr_from_host(void *ptr); +ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr); RAMBlock *qemu_ram_block_by_name(const char *name); RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset, ram_addr_t *offset); diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 50231bab30..56e03e07b5 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -2443,6 +2443,18 @@ ram_addr_t qemu_ram_addr_from_host(void *ptr) return block->offset + offset; } +ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr) +{ + ram_addr_t ram_addr; + + ram_addr = qemu_ram_addr_from_host(ptr); + if (ram_addr == RAM_ADDR_INVALID) { + error_report("Bad ram pointer %p", ptr); + abort(); + } + return ram_addr; +} + static MemTxResult flatview_read(FlatView *fv, hwaddr addr, MemTxAttrs attrs, void *buf, hwaddr len); static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs, From 7e0d9973ea665bf459b2dbd173d0e51bc6ca5216 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 14:13:30 -0700 Subject: [PATCH 0353/1020] accel/tcg: Use probe_access_internal for softmmu get_page_addr_code_hostp Simplify the implementation of get_page_addr_code_hostp by reusing the existing probe_access infrastructure. Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 76 ++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 50 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 80a3eb4f1c..8fad2d9b83 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1482,56 +1482,6 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index, victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \ (ADDR) & TARGET_PAGE_MASK) -/* - * Return a ram_addr_t for the virtual address for execution. - * - * Return -1 if we can't translate and execute from an entire page - * of RAM. This will force us to execute by loading and translating - * one insn at a time, without caching. - * - * NOTE: This function will trigger an exception if the page is - * not executable. - */ -tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, - void **hostp) -{ - uintptr_t mmu_idx = cpu_mmu_index(env, true); - uintptr_t index = tlb_index(env, mmu_idx, addr); - CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); - void *p; - - if (unlikely(!tlb_hit(entry->addr_code, addr))) { - if (!VICTIM_TLB_HIT(addr_code, addr)) { - tlb_fill(env_cpu(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0); - index = tlb_index(env, mmu_idx, addr); - entry = tlb_entry(env, mmu_idx, addr); - - if (unlikely(entry->addr_code & TLB_INVALID_MASK)) { - /* - * The MMU protection covers a smaller range than a target - * page, so we must redo the MMU check for every insn. - */ - return -1; - } - } - assert(tlb_hit(entry->addr_code, addr)); - } - - if (unlikely(entry->addr_code & TLB_MMIO)) { - /* The region is not backed by RAM. */ - if (hostp) { - *hostp = NULL; - } - return -1; - } - - p = (void *)((uintptr_t)addr + entry->addend); - if (hostp) { - *hostp = p; - } - return qemu_ram_addr_from_host_nofail(p); -} - static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size, CPUIOTLBEntry *iotlbentry, uintptr_t retaddr) { @@ -1687,6 +1637,32 @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, return flags ? NULL : host; } +/* + * Return a ram_addr_t for the virtual address for execution. + * + * Return -1 if we can't translate and execute from an entire page + * of RAM. This will force us to execute by loading and translating + * one insn at a time, without caching. + * + * NOTE: This function will trigger an exception if the page is + * not executable. + */ +tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, + void **hostp) +{ + void *p; + + (void)probe_access_internal(env, addr, 1, MMU_INST_FETCH, + cpu_mmu_index(env, true), false, &p, 0); + if (p == NULL) { + return -1; + } + if (hostp) { + *hostp = p; + } + return qemu_ram_addr_from_host_nofail(p); +} + #ifdef CONFIG_PLUGIN /* * Perform a TLB lookup and populate the qemu_plugin_hwaddr structure. From 9867b30287ec98728e52ed49d03c666e86c90a04 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 18:50:46 -0700 Subject: [PATCH 0354/1020] accel/tcg: Document the faulting lookup in tb_lookup_cmp It was non-obvious to me why we can raise an exception in the middle of a comparison function, but it works. While nearby, use TARGET_PAGE_ALIGN instead of open-coding. Acked-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- accel/tcg/cpu-exec.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 7887af6f45..5f43b9769a 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -198,7 +198,16 @@ static bool tb_lookup_cmp(const void *p, const void *d) tb_page_addr_t phys_page2; target_ulong virt_page2; - virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE; + /* + * We know that the first page matched, and an otherwise valid TB + * encountered an incomplete instruction at the end of that page, + * therefore we know that generating a new TB from the current PC + * must also require reading from the next page -- even if the + * second pages do not match, and therefore the resulting insn + * is different for the new TB. Therefore any exception raised + * here by the faulting lookup is not premature. + */ + virt_page2 = TARGET_PAGE_ALIGN(desc->pc); phys_page2 = get_page_addr_code(desc->env, virt_page2); if (tb->page_addr[1] == phys_page2) { return true; From dac8d19bdb3ccaafbcbd2df34135464964232a8f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 21:05:31 -0700 Subject: [PATCH 0355/1020] accel/tcg: Remove translator_ldsw The only user can easily use translator_lduw and adjust the type to signed during the return. Reviewed-by: Alistair Francis Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- include/exec/translator.h | 1 - target/i386/tcg/translate.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/include/exec/translator.h b/include/exec/translator.h index 0d0bf3a31e..45b9268ca4 100644 --- a/include/exec/translator.h +++ b/include/exec/translator.h @@ -178,7 +178,6 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest); #define FOR_EACH_TRANSLATOR_LD(F) \ F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \ - F(translator_ldsw, int16_t, cpu_ldsw_code, bswap16) \ F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \ F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \ F(translator_ldq, uint64_t, cpu_ldq_code, bswap64) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index fc081e6ad6..983439d926 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2033,7 +2033,7 @@ static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s) static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s) { - return translator_ldsw(env, &s->base, advance_pc(env, s, 2)); + return translator_lduw(env, &s->base, advance_pc(env, s, 2)); } static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s) From 306c872103b4d0986c9f671eb7538b0b70bf69b5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 11 Aug 2022 13:48:03 -0700 Subject: [PATCH 0356/1020] accel/tcg: Add pc and host_pc params to gen_intermediate_code Pass these along to translator_loop -- pc may be used instead of tb->pc, and host_pc is currently unused. Adjust all targets at one time. Acked-by: Alistair Francis Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 6 ++++-- accel/tcg/translator.c | 9 +++++---- include/exec/exec-all.h | 1 - include/exec/translator.h | 24 ++++++++++++++++++++---- target/alpha/translate.c | 5 +++-- target/arm/translate.c | 5 +++-- target/avr/translate.c | 5 +++-- target/cris/translate.c | 5 +++-- target/hexagon/translate.c | 6 ++++-- target/hppa/translate.c | 5 +++-- target/i386/tcg/translate.c | 5 +++-- target/loongarch/translate.c | 6 ++++-- target/m68k/translate.c | 5 +++-- target/microblaze/translate.c | 5 +++-- target/mips/tcg/translate.c | 5 +++-- target/nios2/translate.c | 5 +++-- target/openrisc/translate.c | 6 ++++-- target/ppc/translate.c | 5 +++-- target/riscv/translate.c | 5 +++-- target/rx/translate.c | 5 +++-- target/s390x/tcg/translate.c | 5 +++-- target/sh4/translate.c | 5 +++-- target/sparc/translate.c | 5 +++-- target/tricore/translate.c | 6 ++++-- target/xtensa/translate.c | 6 ++++-- 25 files changed, 97 insertions(+), 53 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index b83161a081..587886aa4e 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -46,6 +46,7 @@ #include "exec/cputlb.h" #include "exec/translate-all.h" +#include "exec/translator.h" #include "qemu/bitmap.h" #include "qemu/qemu-print.h" #include "qemu/timer.h" @@ -1392,11 +1393,12 @@ TranslationBlock *tb_gen_code(CPUState *cpu, TCGProfile *prof = &tcg_ctx->prof; int64_t ti; #endif + void *host_pc; assert_memory_lock(); qemu_thread_jit_write(); - phys_pc = get_page_addr_code(env, pc); + phys_pc = get_page_addr_code_hostp(env, pc, &host_pc); if (phys_pc == -1) { /* Generate a one-shot TB with 1 insn in it */ @@ -1444,7 +1446,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tcg_func_start(tcg_ctx); tcg_ctx->cpu = env_cpu(env); - gen_intermediate_code(cpu, tb, max_insns); + gen_intermediate_code(cpu, tb, max_insns, pc, host_pc); assert(tb->size != 0); tcg_ctx->cpu = NULL; max_insns = tb->icount; diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index fe7af9b943..3eef30d93a 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -51,16 +51,17 @@ static inline void translator_page_protect(DisasContextBase *dcbase, #endif } -void translator_loop(const TranslatorOps *ops, DisasContextBase *db, - CPUState *cpu, TranslationBlock *tb, int max_insns) +void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc, + const TranslatorOps *ops, DisasContextBase *db) { uint32_t cflags = tb_cflags(tb); bool plugin_enabled; /* Initialize DisasContext */ db->tb = tb; - db->pc_first = tb->pc; - db->pc_next = db->pc_first; + db->pc_first = pc; + db->pc_next = pc; db->is_jmp = DISAS_NEXT; db->num_insns = 0; db->max_insns = max_insns; diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 9f35e3b7a9..bcad607c4e 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -39,7 +39,6 @@ typedef ram_addr_t tb_page_addr_t; #define TB_PAGE_ADDR_FMT RAM_ADDR_FMT #endif -void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns); void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb, target_ulong *data); diff --git a/include/exec/translator.h b/include/exec/translator.h index 45b9268ca4..69db0f5c21 100644 --- a/include/exec/translator.h +++ b/include/exec/translator.h @@ -26,6 +26,19 @@ #include "exec/translate-all.h" #include "tcg/tcg.h" +/** + * gen_intermediate_code + * @cpu: cpu context + * @tb: translation block + * @max_insns: max number of instructions to translate + * @pc: guest virtual program counter address + * @host_pc: host physical program counter address + * + * This function must be provided by the target, which should create + * the target-specific DisasContext, and then invoke translator_loop. + */ +void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc); /** * DisasJumpType: @@ -123,11 +136,13 @@ typedef struct TranslatorOps { /** * translator_loop: - * @ops: Target-specific operations. - * @db: Disassembly context. * @cpu: Target vCPU. * @tb: Translation block. * @max_insns: Maximum number of insns to translate. + * @pc: guest virtual program counter address + * @host_pc: host physical program counter address + * @ops: Target-specific operations. + * @db: Disassembly context. * * Generic translator loop. * @@ -141,8 +156,9 @@ typedef struct TranslatorOps { * - When single-stepping is enabled (system-wide or on the current vCPU). * - When too many instructions have been translated. */ -void translator_loop(const TranslatorOps *ops, DisasContextBase *db, - CPUState *cpu, TranslationBlock *tb, int max_insns); +void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc, + const TranslatorOps *ops, DisasContextBase *db); void translator_loop_temp_check(DisasContextBase *db); diff --git a/target/alpha/translate.c b/target/alpha/translate.c index 9af1627079..6766350f56 100644 --- a/target/alpha/translate.c +++ b/target/alpha/translate.c @@ -3043,10 +3043,11 @@ static const TranslatorOps alpha_tr_ops = { .disas_log = alpha_tr_disas_log, }; -void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc; - translator_loop(&alpha_tr_ops, &dc.base, cpu, tb, max_insns); + translator_loop(cpu, tb, max_insns, pc, host_pc, &alpha_tr_ops, &dc.base); } void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb, diff --git a/target/arm/translate.c b/target/arm/translate.c index ad617b9948..9474e4b44b 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9892,7 +9892,8 @@ static const TranslatorOps thumb_translator_ops = { }; /* generate intermediate code for basic block 'tb'. */ -void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc = { }; const TranslatorOps *ops = &arm_translator_ops; @@ -9907,7 +9908,7 @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) } #endif - translator_loop(ops, &dc.base, cpu, tb, max_insns); + translator_loop(cpu, tb, max_insns, pc, host_pc, ops, &dc.base); } void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, diff --git a/target/avr/translate.c b/target/avr/translate.c index 026753c963..e65b6008c0 100644 --- a/target/avr/translate.c +++ b/target/avr/translate.c @@ -3049,10 +3049,11 @@ static const TranslatorOps avr_tr_ops = { .disas_log = avr_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc = { }; - translator_loop(&avr_tr_ops, &dc.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &avr_tr_ops, &dc.base); } void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb, diff --git a/target/cris/translate.c b/target/cris/translate.c index ac101344a3..73385b0b3c 100644 --- a/target/cris/translate.c +++ b/target/cris/translate.c @@ -3286,10 +3286,11 @@ static const TranslatorOps cris_tr_ops = { .disas_log = cris_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc; - translator_loop(&cris_tr_ops, &dc.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &cris_tr_ops, &dc.base); } void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags) diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index d4fc92f7e9..0e8a0772f7 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -850,11 +850,13 @@ static const TranslatorOps hexagon_tr_ops = { .disas_log = hexagon_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&hexagon_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, + &hexagon_tr_ops, &ctx.base); } #define NAME_LEN 64 diff --git a/target/hppa/translate.c b/target/hppa/translate.c index b8dbfee5e9..8b861957e0 100644 --- a/target/hppa/translate.c +++ b/target/hppa/translate.c @@ -4340,10 +4340,11 @@ static const TranslatorOps hppa_tr_ops = { .disas_log = hppa_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&hppa_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &hppa_tr_ops, &ctx.base); } void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb, diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 983439d926..ba2ab2b45d 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -8821,11 +8821,12 @@ static const TranslatorOps i386_tr_ops = { }; /* generate intermediate code for basic block 'tb'. */ -void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc; - translator_loop(&i386_tr_ops, &dc.base, cpu, tb, max_insns); + translator_loop(cpu, tb, max_insns, pc, host_pc, &i386_tr_ops, &dc.base); } void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb, diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c index 51ba291430..95b37ea180 100644 --- a/target/loongarch/translate.c +++ b/target/loongarch/translate.c @@ -241,11 +241,13 @@ static const TranslatorOps loongarch_tr_ops = { .disas_log = loongarch_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&loongarch_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, + &loongarch_tr_ops, &ctx.base); } void loongarch_translate_init(void) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 8f3c298ad0..5098f7e570 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -6361,10 +6361,11 @@ static const TranslatorOps m68k_tr_ops = { .disas_log = m68k_tr_disas_log, }; -void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc; - translator_loop(&m68k_tr_ops, &dc.base, cpu, tb, max_insns); + translator_loop(cpu, tb, max_insns, pc, host_pc, &m68k_tr_ops, &dc.base); } static double floatx80_to_double(CPUM68KState *env, uint16_t high, uint64_t low) diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c index bf01384d33..c5546f93aa 100644 --- a/target/microblaze/translate.c +++ b/target/microblaze/translate.c @@ -1849,10 +1849,11 @@ static const TranslatorOps mb_tr_ops = { .disas_log = mb_tr_disas_log, }; -void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc; - translator_loop(&mb_tr_ops, &dc.base, cpu, tb, max_insns); + translator_loop(cpu, tb, max_insns, pc, host_pc, &mb_tr_ops, &dc.base); } void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags) diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index de1511baaf..0d936e2648 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -16155,11 +16155,12 @@ static const TranslatorOps mips_tr_ops = { .disas_log = mips_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &mips_tr_ops, &ctx.base); } void mips_tcg_init(void) diff --git a/target/nios2/translate.c b/target/nios2/translate.c index 3a037a68cc..c588e8e885 100644 --- a/target/nios2/translate.c +++ b/target/nios2/translate.c @@ -1038,10 +1038,11 @@ static const TranslatorOps nios2_tr_ops = { .disas_log = nios2_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc; - translator_loop(&nios2_tr_ops, &dc.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &nios2_tr_ops, &dc.base); } void nios2_cpu_dump_state(CPUState *cs, FILE *f, int flags) diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 7b8ad43d5f..8154f9d744 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -1705,11 +1705,13 @@ static const TranslatorOps openrisc_tr_ops = { .disas_log = openrisc_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, + &openrisc_tr_ops, &ctx.base); } void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 388337f81b..000b1e518d 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -7719,11 +7719,12 @@ static const TranslatorOps ppc_tr_ops = { .disas_log = ppc_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&ppc_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &ppc_tr_ops, &ctx.base); } void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb, diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 63b04e8a94..38666ddc91 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1196,11 +1196,12 @@ static const TranslatorOps riscv_tr_ops = { .disas_log = riscv_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&riscv_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &riscv_tr_ops, &ctx.base); } void riscv_translate_init(void) diff --git a/target/rx/translate.c b/target/rx/translate.c index 62aee66937..ea5653bc95 100644 --- a/target/rx/translate.c +++ b/target/rx/translate.c @@ -2363,11 +2363,12 @@ static const TranslatorOps rx_tr_ops = { .disas_log = rx_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc; - translator_loop(&rx_tr_ops, &dc.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &rx_tr_ops, &dc.base); } void restore_state_to_opc(CPURXState *env, TranslationBlock *tb, diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index e2ee005671..d4c0b9b3a2 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -6676,11 +6676,12 @@ static const TranslatorOps s390x_tr_ops = { .disas_log = s390x_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc; - translator_loop(&s390x_tr_ops, &dc.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &s390x_tr_ops, &dc.base); } void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb, diff --git a/target/sh4/translate.c b/target/sh4/translate.c index f1b190e7cf..01056571c3 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -2368,11 +2368,12 @@ static const TranslatorOps sh4_tr_ops = { .disas_log = sh4_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&sh4_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &sh4_tr_ops, &ctx.base); } void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb, diff --git a/target/sparc/translate.c b/target/sparc/translate.c index 2e28222d31..2cbbe2396a 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -5917,11 +5917,12 @@ static const TranslatorOps sparc_tr_ops = { .disas_log = sparc_tr_disas_log, }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc = {}; - translator_loop(&sparc_tr_ops, &dc.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base); } void sparc_tcg_init(void) diff --git a/target/tricore/translate.c b/target/tricore/translate.c index d170500fa5..a0558ead71 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -8878,10 +8878,12 @@ static const TranslatorOps tricore_tr_ops = { }; -void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext ctx; - translator_loop(&tricore_tr_ops, &ctx.base, cs, tb, max_insns); + translator_loop(cs, tb, max_insns, pc, host_pc, + &tricore_tr_ops, &ctx.base); } void diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 70e11eeb45..8b864ef925 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -1279,10 +1279,12 @@ static const TranslatorOps xtensa_translator_ops = { .disas_log = xtensa_tr_disas_log, }; -void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns) +void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns, + target_ulong pc, void *host_pc) { DisasContext dc = {}; - translator_loop(&xtensa_translator_ops, &dc.base, cpu, tb, max_insns); + translator_loop(cpu, tb, max_insns, pc, host_pc, + &xtensa_translator_ops, &dc.base); } void xtensa_cpu_dump_state(CPUState *cs, FILE *f, int flags) From 50627f1b7b1b1db60166a670fbc17623c7d7243e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 21:39:29 -0700 Subject: [PATCH 0357/1020] accel/tcg: Add fast path for translator_ld* Cache the translation from guest to host address, so we may use direct loads when we hit on the primary translation page. Look up the second translation page only once, during translation. This obviates another lookup of the second page within tb_gen_code after translation. Fixes a bug in that plugin_insn_append should be passed the bytes in the original memory order, not bswapped by pieces. Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 23 +++---- accel/tcg/translator.c | 126 +++++++++++++++++++++++++++++--------- include/exec/translator.h | 63 +++++++++++-------- 3 files changed, 141 insertions(+), 71 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 587886aa4e..f5e8592d4a 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1385,8 +1385,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, { CPUArchState *env = cpu->env_ptr; TranslationBlock *tb, *existing_tb; - tb_page_addr_t phys_pc, phys_page2; - target_ulong virt_page2; + tb_page_addr_t phys_pc; tcg_insn_unit *gen_code_buf; int gen_code_size, search_size, max_insns; #ifdef CONFIG_PROFILER @@ -1429,6 +1428,8 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tb->flags = flags; tb->cflags = cflags; tb->trace_vcpu_dstate = *cpu->trace_dstate; + tb->page_addr[0] = phys_pc; + tb->page_addr[1] = -1; tcg_ctx->tb_cflags = cflags; tb_overflow: @@ -1622,13 +1623,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu, } /* - * If the TB is not associated with a physical RAM page then - * it must be a temporary one-insn TB, and we have nothing to do - * except fill in the page_addr[] fields. Return early before - * attempting to link to other TBs or add to the lookup table. + * If the TB is not associated with a physical RAM page then it must be + * a temporary one-insn TB, and we have nothing left to do. Return early + * before attempting to link to other TBs or add to the lookup table. */ - if (phys_pc == -1) { - tb->page_addr[0] = tb->page_addr[1] = -1; + if (tb->page_addr[0] == -1) { return tb; } @@ -1639,17 +1638,11 @@ TranslationBlock *tb_gen_code(CPUState *cpu, */ tcg_tb_insert(tb); - /* check next page if needed */ - virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK; - phys_page2 = -1; - if ((pc & TARGET_PAGE_MASK) != virt_page2) { - phys_page2 = get_page_addr_code(env, virt_page2); - } /* * No explicit memory barrier is required -- tb_link_page() makes the * TB visible in a consistent state. */ - existing_tb = tb_link_page(tb, phys_pc, phys_page2); + existing_tb = tb_link_page(tb, tb->page_addr[0], tb->page_addr[1]); /* if the TB already exists, discard what we just translated */ if (unlikely(existing_tb != tb)) { uintptr_t orig_aligned = (uintptr_t)gen_code_buf; diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index 3eef30d93a..ca8a5f2d83 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -42,15 +42,6 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest) return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0; } -static inline void translator_page_protect(DisasContextBase *dcbase, - target_ulong pc) -{ -#ifdef CONFIG_USER_ONLY - dcbase->page_protect_end = pc | ~TARGET_PAGE_MASK; - page_protect(pc); -#endif -} - void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns, target_ulong pc, void *host_pc, const TranslatorOps *ops, DisasContextBase *db) @@ -66,7 +57,12 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns, db->num_insns = 0; db->max_insns = max_insns; db->singlestep_enabled = cflags & CF_SINGLE_STEP; - translator_page_protect(db, db->pc_next); + db->host_addr[0] = host_pc; + db->host_addr[1] = NULL; + +#ifdef CONFIG_USER_ONLY + page_protect(pc); +#endif ops->init_disas_context(db, cpu); tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ @@ -151,31 +147,103 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns, #endif } -static inline void translator_maybe_page_protect(DisasContextBase *dcbase, - target_ulong pc, size_t len) +static void *translator_access(CPUArchState *env, DisasContextBase *db, + target_ulong pc, size_t len) { -#ifdef CONFIG_USER_ONLY - target_ulong end = pc + len - 1; + void *host; + target_ulong base, end; + TranslationBlock *tb; - if (end > dcbase->page_protect_end) { - translator_page_protect(dcbase, end); + tb = db->tb; + + /* Use slow path if first page is MMIO. */ + if (unlikely(tb->page_addr[0] == -1)) { + return NULL; } + + end = pc + len - 1; + if (likely(is_same_page(db, end))) { + host = db->host_addr[0]; + base = db->pc_first; + } else { + host = db->host_addr[1]; + base = TARGET_PAGE_ALIGN(db->pc_first); + if (host == NULL) { + tb->page_addr[1] = + get_page_addr_code_hostp(env, base, &db->host_addr[1]); +#ifdef CONFIG_USER_ONLY + page_protect(end); #endif + /* We cannot handle MMIO as second page. */ + assert(tb->page_addr[1] != -1); + host = db->host_addr[1]; + } + + /* Use slow path when crossing pages. */ + if (is_same_page(db, pc)) { + return NULL; + } + } + + tcg_debug_assert(pc >= base); + return host + (pc - base); } -#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \ - type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \ - abi_ptr pc, bool do_swap) \ - { \ - translator_maybe_page_protect(dcbase, pc, sizeof(type)); \ - type ret = load_fn(env, pc); \ - if (do_swap) { \ - ret = swap_fn(ret); \ - } \ - plugin_insn_append(pc, &ret, sizeof(ret)); \ - return ret; \ +uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc) +{ + uint8_t ret; + void *p = translator_access(env, db, pc, sizeof(ret)); + + if (p) { + plugin_insn_append(pc, p, sizeof(ret)); + return ldub_p(p); } + ret = cpu_ldub_code(env, pc); + plugin_insn_append(pc, &ret, sizeof(ret)); + return ret; +} -FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD) +uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc) +{ + uint16_t ret, plug; + void *p = translator_access(env, db, pc, sizeof(ret)); -#undef GEN_TRANSLATOR_LD + if (p) { + plugin_insn_append(pc, p, sizeof(ret)); + return lduw_p(p); + } + ret = cpu_lduw_code(env, pc); + plug = tswap16(ret); + plugin_insn_append(pc, &plug, sizeof(ret)); + return ret; +} + +uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc) +{ + uint32_t ret, plug; + void *p = translator_access(env, db, pc, sizeof(ret)); + + if (p) { + plugin_insn_append(pc, p, sizeof(ret)); + return ldl_p(p); + } + ret = cpu_ldl_code(env, pc); + plug = tswap32(ret); + plugin_insn_append(pc, &plug, sizeof(ret)); + return ret; +} + +uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc) +{ + uint64_t ret, plug; + void *p = translator_access(env, db, pc, sizeof(ret)); + + if (p) { + plugin_insn_append(pc, p, sizeof(ret)); + return ldq_p(p); + } + ret = cpu_ldq_code(env, pc); + plug = tswap64(ret); + plugin_insn_append(pc, &plug, sizeof(ret)); + return ret; +} diff --git a/include/exec/translator.h b/include/exec/translator.h index 69db0f5c21..3b77f5f4aa 100644 --- a/include/exec/translator.h +++ b/include/exec/translator.h @@ -81,24 +81,14 @@ typedef enum DisasJumpType { * Architecture-agnostic disassembly context. */ typedef struct DisasContextBase { - const TranslationBlock *tb; + TranslationBlock *tb; target_ulong pc_first; target_ulong pc_next; DisasJumpType is_jmp; int num_insns; int max_insns; bool singlestep_enabled; -#ifdef CONFIG_USER_ONLY - /* - * Guest address of the last byte of the last protected page. - * - * Pages containing the translated instructions are made non-writable in - * order to achieve consistency in case another thread is modifying the - * code while translate_insn() fetches the instruction bytes piecemeal. - * Such writer threads are blocked on mmap_lock() in page_unprotect(). - */ - target_ulong page_protect_end; -#endif + void *host_addr[2]; } DisasContextBase; /** @@ -183,24 +173,43 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest); * the relevant information at translation time. */ -#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \ - type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \ - abi_ptr pc, bool do_swap); \ - static inline type fullname(CPUArchState *env, \ - DisasContextBase *dcbase, abi_ptr pc) \ - { \ - return fullname ## _swap(env, dcbase, pc, false); \ +uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc); +uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc); +uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc); +uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc); + +static inline uint16_t +translator_lduw_swap(CPUArchState *env, DisasContextBase *db, + abi_ptr pc, bool do_swap) +{ + uint16_t ret = translator_lduw(env, db, pc); + if (do_swap) { + ret = bswap16(ret); } + return ret; +} -#define FOR_EACH_TRANSLATOR_LD(F) \ - F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \ - F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \ - F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \ - F(translator_ldq, uint64_t, cpu_ldq_code, bswap64) +static inline uint32_t +translator_ldl_swap(CPUArchState *env, DisasContextBase *db, + abi_ptr pc, bool do_swap) +{ + uint32_t ret = translator_ldl(env, db, pc); + if (do_swap) { + ret = bswap32(ret); + } + return ret; +} -FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD) - -#undef GEN_TRANSLATOR_LD +static inline uint64_t +translator_ldq_swap(CPUArchState *env, DisasContextBase *db, + abi_ptr pc, bool do_swap) +{ + uint64_t ret = translator_ldq(env, db, pc); + if (do_swap) { + ret = bswap64(ret); + } + return ret; +} /* * Return whether addr is on the same page as where disassembly started. From ab12c95d3f1999648d70bca54ebcc0588a07dd3e Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 17 Aug 2022 17:05:04 +0200 Subject: [PATCH 0358/1020] target/s390x: Make translator stop before the end of a page Right now translator stops right *after* the end of a page, which breaks reporting of fault locations when the last instruction of a multi-insn translation block crosses a page boundary. Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Message-Id: <20220817150506.592862-3-iii@linux.ibm.com> Signed-off-by: Richard Henderson --- target/s390x/tcg/translate.c | 15 +++- tests/tcg/multiarch/noexec.c.inc | 139 +++++++++++++++++++++++++++++++ tests/tcg/s390x/Makefile.target | 1 + tests/tcg/s390x/noexec.c | 106 +++++++++++++++++++++++ 4 files changed, 257 insertions(+), 4 deletions(-) create mode 100644 tests/tcg/multiarch/noexec.c.inc create mode 100644 tests/tcg/s390x/noexec.c diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index d4c0b9b3a2..1d2dddab1c 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -6609,6 +6609,14 @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs) dc->insn_start = tcg_last_op(); } +static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s, + uint64_t pc) +{ + uint64_t insn = ld_code2(env, s, pc); + + return pc + get_ilen((insn >> 8) & 0xff); +} + static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) { CPUS390XState *env = cs->env_ptr; @@ -6616,10 +6624,9 @@ static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) dc->base.is_jmp = translate_one(env, dc); if (dc->base.is_jmp == DISAS_NEXT) { - uint64_t page_start; - - page_start = dc->base.pc_first & TARGET_PAGE_MASK; - if (dc->base.pc_next - page_start >= TARGET_PAGE_SIZE || dc->ex_value) { + if (!is_same_page(dcbase, dc->base.pc_next) || + !is_same_page(dcbase, get_next_pc(env, dc, dc->base.pc_next)) || + dc->ex_value) { dc->base.is_jmp = DISAS_TOO_MANY; } } diff --git a/tests/tcg/multiarch/noexec.c.inc b/tests/tcg/multiarch/noexec.c.inc new file mode 100644 index 0000000000..2ef539b721 --- /dev/null +++ b/tests/tcg/multiarch/noexec.c.inc @@ -0,0 +1,139 @@ +/* + * Common code for arch-specific MMU_INST_FETCH fault testing. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Forward declarations. */ + +static void *arch_mcontext_pc(const mcontext_t *ctx); +static int arch_mcontext_arg(const mcontext_t *ctx); +static void arch_flush(void *p, int len); + +/* Testing infrastructure. */ + +struct noexec_test { + const char *name; + const char *test_code; + int test_len; + int page_ofs; + int entry_ofs; + int expected_si_ofs; + int expected_pc_ofs; + int expected_arg; +}; + +static void *page_base; +static int page_size; +static const struct noexec_test *current_noexec_test; + +static void handle_err(const char *syscall) +{ + printf("[ FAILED ] %s: %s\n", syscall, strerror(errno)); + exit(EXIT_FAILURE); +} + +static void handle_segv(int sig, siginfo_t *info, void *ucontext) +{ + const struct noexec_test *test = current_noexec_test; + const mcontext_t *mc = &((ucontext_t *)ucontext)->uc_mcontext; + void *expected_si; + void *expected_pc; + void *pc; + int arg; + + if (test == NULL) { + printf("[ FAILED ] unexpected SEGV\n"); + exit(EXIT_FAILURE); + } + current_noexec_test = NULL; + + expected_si = page_base + test->expected_si_ofs; + if (info->si_addr != expected_si) { + printf("[ FAILED ] wrong si_addr (%p != %p)\n", + info->si_addr, expected_si); + exit(EXIT_FAILURE); + } + + pc = arch_mcontext_pc(mc); + expected_pc = page_base + test->expected_pc_ofs; + if (pc != expected_pc) { + printf("[ FAILED ] wrong pc (%p != %p)\n", pc, expected_pc); + exit(EXIT_FAILURE); + } + + arg = arch_mcontext_arg(mc); + if (arg != test->expected_arg) { + printf("[ FAILED ] wrong arg (%d != %d)\n", arg, test->expected_arg); + exit(EXIT_FAILURE); + } + + if (mprotect(page_base, page_size, + PROT_READ | PROT_WRITE | PROT_EXEC) < 0) { + handle_err("mprotect"); + } +} + +static void test_noexec_1(const struct noexec_test *test) +{ + void *start = page_base + test->page_ofs; + void (*fn)(int arg) = page_base + test->entry_ofs; + + memcpy(start, test->test_code, test->test_len); + arch_flush(start, test->test_len); + + /* Trigger TB creation in order to test invalidation. */ + fn(0); + + if (mprotect(page_base, page_size, PROT_NONE) < 0) { + handle_err("mprotect"); + } + + /* Trigger SEGV and check that handle_segv() ran. */ + current_noexec_test = test; + fn(0); + assert(current_noexec_test == NULL); +} + +static int test_noexec(struct noexec_test *tests, size_t n_tests) +{ + struct sigaction act; + size_t i; + + memset(&act, 0, sizeof(act)); + act.sa_sigaction = handle_segv; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGSEGV, &act, NULL) < 0) { + handle_err("sigaction"); + } + + page_size = getpagesize(); + page_base = mmap(NULL, 2 * page_size, + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (page_base == MAP_FAILED) { + handle_err("mmap"); + } + page_base += page_size; + + for (i = 0; i < n_tests; i++) { + struct noexec_test *test = &tests[i]; + + printf("[ RUN ] %s\n", test->name); + test_noexec_1(test); + printf("[ OK ]\n"); + } + + printf("[ PASSED ]\n"); + return EXIT_SUCCESS; +} diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 1a7a4a2f59..5e13a41c3f 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -16,6 +16,7 @@ TESTS+=shift TESTS+=trap TESTS+=signals-s390x TESTS+=branch-relative-long +TESTS+=noexec Z14_TESTS=vfminmax vfminmax: LDFLAGS+=-lm diff --git a/tests/tcg/s390x/noexec.c b/tests/tcg/s390x/noexec.c new file mode 100644 index 0000000000..15d007d07f --- /dev/null +++ b/tests/tcg/s390x/noexec.c @@ -0,0 +1,106 @@ +#include "../multiarch/noexec.c.inc" + +static void *arch_mcontext_pc(const mcontext_t *ctx) +{ + return (void *)ctx->psw.addr; +} + +static int arch_mcontext_arg(const mcontext_t *ctx) +{ + return ctx->gregs[2]; +} + +static void arch_flush(void *p, int len) +{ +} + +extern char noexec_1[]; +extern char noexec_2[]; +extern char noexec_end[]; + +asm("noexec_1:\n" + " lgfi %r2,1\n" /* %r2 is 0 on entry, set 1. */ + "noexec_2:\n" + " lgfi %r2,2\n" /* %r2 is 0/1; set 2. */ + " br %r14\n" /* return */ + "noexec_end:"); + +extern char exrl_1[]; +extern char exrl_2[]; +extern char exrl_end[]; + +asm("exrl_1:\n" + " exrl %r0, exrl_2\n" + " br %r14\n" + "exrl_2:\n" + " lgfi %r2,2\n" + "exrl_end:"); + +int main(void) +{ + struct noexec_test noexec_tests[] = { + { + .name = "fallthrough", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2, + .entry_ofs = noexec_1 - noexec_2, + .expected_si_ofs = 0, + .expected_pc_ofs = 0, + .expected_arg = 1, + }, + { + .name = "jump", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2, + .entry_ofs = 0, + .expected_si_ofs = 0, + .expected_pc_ofs = 0, + .expected_arg = 0, + }, + { + .name = "exrl", + .test_code = exrl_1, + .test_len = exrl_end - exrl_1, + .page_ofs = exrl_1 - exrl_2, + .entry_ofs = exrl_1 - exrl_2, + .expected_si_ofs = 0, + .expected_pc_ofs = exrl_1 - exrl_2, + .expected_arg = 0, + }, + { + .name = "fallthrough [cross]", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2 - 2, + .entry_ofs = noexec_1 - noexec_2 - 2, + .expected_si_ofs = 0, + .expected_pc_ofs = -2, + .expected_arg = 1, + }, + { + .name = "jump [cross]", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2 - 2, + .entry_ofs = -2, + .expected_si_ofs = 0, + .expected_pc_ofs = -2, + .expected_arg = 0, + }, + { + .name = "exrl [cross]", + .test_code = exrl_1, + .test_len = exrl_end - exrl_1, + .page_ofs = exrl_1 - exrl_2 - 2, + .entry_ofs = exrl_1 - exrl_2 - 2, + .expected_si_ofs = 0, + .expected_pc_ofs = exrl_1 - exrl_2 - 2, + .expected_arg = 0, + }, + }; + + return test_noexec(noexec_tests, + sizeof(noexec_tests) / sizeof(noexec_tests[0])); +} From 950936681f322a5ba2813f83eb44dd972be2d5a3 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 17 Aug 2022 17:05:05 +0200 Subject: [PATCH 0359/1020] target/i386: Make translator stop before the end of a page Right now translator stops right *after* the end of a page, which breaks reporting of fault locations when the last instruction of a multi-insn translation block crosses a page boundary. An implementation, like the one arm and s390x have, would require an i386 length disassembler, which is burdensome to maintain. Another alternative would be to single-step at the end of a guest page, but this may come with a performance impact. Fix by snapshotting disassembly state and restoring it after we figure out we crossed a page boundary. This includes rolling back cc_op updates and emitted ops. Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1143 Message-Id: <20220817150506.592862-4-iii@linux.ibm.com> [rth: Simplify end-of-insn cross-page checks.] Signed-off-by: Richard Henderson --- target/i386/tcg/translate.c | 64 ++++++++++++++++----------- tests/tcg/x86_64/Makefile.target | 3 +- tests/tcg/x86_64/noexec.c | 75 ++++++++++++++++++++++++++++++++ 3 files changed, 116 insertions(+), 26 deletions(-) create mode 100644 tests/tcg/x86_64/noexec.c diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index ba2ab2b45d..d6420df31d 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -130,6 +130,7 @@ typedef struct DisasContext { TCGv_i64 tmp1_i64; sigjmp_buf jmpbuf; + TCGOp *prev_insn_end; } DisasContext; /* The environment in which user-only runs is constrained. */ @@ -2008,6 +2009,12 @@ static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes) { uint64_t pc = s->pc; + /* This is a subsequent insn that crosses a page boundary. */ + if (s->base.num_insns > 1 && + !is_same_page(&s->base, s->pc + num_bytes - 1)) { + siglongjmp(s->jmpbuf, 2); + } + s->pc += num_bytes; if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) { /* If the instruction's 16th byte is on a different page than the 1st, a @@ -4669,6 +4676,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) int modrm, reg, rm, mod, op, opreg, val; target_ulong next_eip, tval; target_ulong pc_start = s->base.pc_next; + bool orig_cc_op_dirty = s->cc_op_dirty; + CCOp orig_cc_op = s->cc_op; s->pc_start = s->pc = pc_start; s->override = -1; @@ -4681,9 +4690,22 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) s->rip_offset = 0; /* for relative ip address */ s->vex_l = 0; s->vex_v = 0; - if (sigsetjmp(s->jmpbuf, 0) != 0) { + switch (sigsetjmp(s->jmpbuf, 0)) { + case 0: + break; + case 1: gen_exception_gpf(s); return s->pc; + case 2: + /* Restore state that may affect the next instruction. */ + s->cc_op_dirty = orig_cc_op_dirty; + s->cc_op = orig_cc_op; + s->base.num_insns--; + tcg_remove_ops_after(s->prev_insn_end); + s->base.is_jmp = DISAS_TOO_MANY; + return pc_start; + default: + g_assert_not_reached(); } prefixes = 0; @@ -8745,6 +8767,7 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu) { DisasContext *dc = container_of(dcbase, DisasContext, base); + dc->prev_insn_end = tcg_last_op(); tcg_gen_insn_start(dc->base.pc_next, dc->cc_op); } @@ -8765,31 +8788,22 @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) #endif pc_next = disas_insn(dc, cpu); - - if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) { - /* if single step mode, we generate only one instruction and - generate an exception */ - /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear - the flag and abort the translation to give the irqs a - chance to happen */ - dc->base.is_jmp = DISAS_TOO_MANY; - } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT) - && ((pc_next & TARGET_PAGE_MASK) - != ((pc_next + TARGET_MAX_INSN_SIZE - 1) - & TARGET_PAGE_MASK) - || (pc_next & ~TARGET_PAGE_MASK) == 0)) { - /* Do not cross the boundary of the pages in icount mode, - it can cause an exception. Do it only when boundary is - crossed by the first instruction in the block. - If current instruction already crossed the bound - it's ok, - because an exception hasn't stopped this code. - */ - dc->base.is_jmp = DISAS_TOO_MANY; - } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) { - dc->base.is_jmp = DISAS_TOO_MANY; - } - dc->base.pc_next = pc_next; + + if (dc->base.is_jmp == DISAS_NEXT) { + if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) { + /* + * If single step mode, we generate only one instruction and + * generate an exception. + * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear + * the flag and abort the translation to give the irqs a + * chance to happen. + */ + dc->base.is_jmp = DISAS_TOO_MANY; + } else if (!is_same_page(&dc->base, pc_next)) { + dc->base.is_jmp = DISAS_TOO_MANY; + } + } } static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu) diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target index 6177fd845a..861a0966f4 100644 --- a/tests/tcg/x86_64/Makefile.target +++ b/tests/tcg/x86_64/Makefile.target @@ -10,6 +10,7 @@ include $(SRC_PATH)/tests/tcg/i386/Makefile.target ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET)) X86_64_TESTS += vsyscall +X86_64_TESTS += noexec TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64 else TESTS=$(MULTIARCH_TESTS) @@ -23,5 +24,5 @@ test-x86_64: LDFLAGS+=-lm -lc test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) -vsyscall: $(SRC_PATH)/tests/tcg/x86_64/vsyscall.c +%: $(SRC_PATH)/tests/tcg/x86_64/%.c $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS) diff --git a/tests/tcg/x86_64/noexec.c b/tests/tcg/x86_64/noexec.c new file mode 100644 index 0000000000..9b124901be --- /dev/null +++ b/tests/tcg/x86_64/noexec.c @@ -0,0 +1,75 @@ +#include "../multiarch/noexec.c.inc" + +static void *arch_mcontext_pc(const mcontext_t *ctx) +{ + return (void *)ctx->gregs[REG_RIP]; +} + +int arch_mcontext_arg(const mcontext_t *ctx) +{ + return ctx->gregs[REG_RDI]; +} + +static void arch_flush(void *p, int len) +{ +} + +extern char noexec_1[]; +extern char noexec_2[]; +extern char noexec_end[]; + +asm("noexec_1:\n" + " movq $1,%rdi\n" /* %rdi is 0 on entry, set 1. */ + "noexec_2:\n" + " movq $2,%rdi\n" /* %rdi is 0/1; set 2. */ + " ret\n" + "noexec_end:"); + +int main(void) +{ + struct noexec_test noexec_tests[] = { + { + .name = "fallthrough", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2, + .entry_ofs = noexec_1 - noexec_2, + .expected_si_ofs = 0, + .expected_pc_ofs = 0, + .expected_arg = 1, + }, + { + .name = "jump", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2, + .entry_ofs = 0, + .expected_si_ofs = 0, + .expected_pc_ofs = 0, + .expected_arg = 0, + }, + { + .name = "fallthrough [cross]", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2 - 2, + .entry_ofs = noexec_1 - noexec_2 - 2, + .expected_si_ofs = 0, + .expected_pc_ofs = -2, + .expected_arg = 1, + }, + { + .name = "jump [cross]", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2 - 2, + .entry_ofs = -2, + .expected_si_ofs = 0, + .expected_pc_ofs = -2, + .expected_arg = 0, + }, + }; + + return test_noexec(noexec_tests, + sizeof(noexec_tests) / sizeof(noexec_tests[0])); +} From ef6e987b64343e0dc9e8526c80ee8d27d0654549 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 18 Aug 2022 12:07:28 -0700 Subject: [PATCH 0360/1020] target/riscv: Add MAX_INSN_LEN and insn_len These will be useful in properly ending the TB. Reviewed-by: Alistair Francis Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- target/riscv/translate.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 38666ddc91..a719aa6e63 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1022,6 +1022,14 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) /* Include decoders for factored-out extensions */ #include "decode-XVentanaCondOps.c.inc" +/* The specification allows for longer insns, but not supported by qemu. */ +#define MAX_INSN_LEN 4 + +static inline int insn_len(uint16_t first_word) +{ + return (first_word & 3) == 3 ? 4 : 2; +} + static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode) { /* @@ -1037,7 +1045,7 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode) }; /* Check for compressed insn */ - if (extract16(opcode, 0, 2) != 3) { + if (insn_len(opcode) == 2) { if (!has_ext(ctx, RVC)) { gen_exception_illegal(ctx); } else { From 00c07344fa245b22e895b363320ba4cd0ec1088a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 18 Aug 2022 18:00:30 -0700 Subject: [PATCH 0361/1020] target/riscv: Make translator stop before the end of a page Right now the translator stops right *after* the end of a page, which breaks reporting of fault locations when the last instruction of a multi-insn translation block crosses a page boundary. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1155 Reviewed-by: Alistair Francis Acked-by: Ilya Leoshkevich Tested-by: Ilya Leoshkevich Signed-off-by: Richard Henderson --- target/riscv/translate.c | 17 +++++-- tests/tcg/riscv64/Makefile.target | 1 + tests/tcg/riscv64/noexec.c | 79 +++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 tests/tcg/riscv64/noexec.c diff --git a/target/riscv/translate.c b/target/riscv/translate.c index a719aa6e63..f8af6daa70 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1154,12 +1154,21 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu) } ctx->nftemp = 0; + /* Only the first insn within a TB is allowed to cross a page boundary. */ if (ctx->base.is_jmp == DISAS_NEXT) { - target_ulong page_start; - - page_start = ctx->base.pc_first & TARGET_PAGE_MASK; - if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) { + if (!is_same_page(&ctx->base, ctx->base.pc_next)) { ctx->base.is_jmp = DISAS_TOO_MANY; + } else { + unsigned page_ofs = ctx->base.pc_next & ~TARGET_PAGE_MASK; + + if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) { + uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next); + int len = insn_len(next_insn); + + if (!is_same_page(&ctx->base, ctx->base.pc_next + len)) { + ctx->base.is_jmp = DISAS_TOO_MANY; + } + } } } } diff --git a/tests/tcg/riscv64/Makefile.target b/tests/tcg/riscv64/Makefile.target index d41bf6d60d..b5b89dfb0e 100644 --- a/tests/tcg/riscv64/Makefile.target +++ b/tests/tcg/riscv64/Makefile.target @@ -3,3 +3,4 @@ VPATH += $(SRC_PATH)/tests/tcg/riscv64 TESTS += test-div +TESTS += noexec diff --git a/tests/tcg/riscv64/noexec.c b/tests/tcg/riscv64/noexec.c new file mode 100644 index 0000000000..86f64b28db --- /dev/null +++ b/tests/tcg/riscv64/noexec.c @@ -0,0 +1,79 @@ +#include "../multiarch/noexec.c.inc" + +static void *arch_mcontext_pc(const mcontext_t *ctx) +{ + return (void *)ctx->__gregs[REG_PC]; +} + +static int arch_mcontext_arg(const mcontext_t *ctx) +{ + return ctx->__gregs[REG_A0]; +} + +static void arch_flush(void *p, int len) +{ + __builtin___clear_cache(p, p + len); +} + +extern char noexec_1[]; +extern char noexec_2[]; +extern char noexec_end[]; + +asm(".option push\n" + ".option norvc\n" + "noexec_1:\n" + " li a0,1\n" /* a0 is 0 on entry, set 1. */ + "noexec_2:\n" + " li a0,2\n" /* a0 is 0/1; set 2. */ + " ret\n" + "noexec_end:\n" + ".option pop"); + +int main(void) +{ + struct noexec_test noexec_tests[] = { + { + .name = "fallthrough", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2, + .entry_ofs = noexec_1 - noexec_2, + .expected_si_ofs = 0, + .expected_pc_ofs = 0, + .expected_arg = 1, + }, + { + .name = "jump", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2, + .entry_ofs = 0, + .expected_si_ofs = 0, + .expected_pc_ofs = 0, + .expected_arg = 0, + }, + { + .name = "fallthrough [cross]", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2 - 2, + .entry_ofs = noexec_1 - noexec_2 - 2, + .expected_si_ofs = 0, + .expected_pc_ofs = -2, + .expected_arg = 1, + }, + { + .name = "jump [cross]", + .test_code = noexec_1, + .test_len = noexec_end - noexec_1, + .page_ofs = noexec_1 - noexec_2 - 2, + .entry_ofs = -2, + .expected_si_ofs = 0, + .expected_pc_ofs = -2, + .expected_arg = 0, + }, + }; + + return test_noexec(noexec_tests, + sizeof(noexec_tests) / sizeof(noexec_tests[0])); +} From 8e2aa21b0a0d434be2f53a9435fec4f63ec192c4 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Thu, 30 Jun 2022 11:41:49 +0530 Subject: [PATCH 0362/1020] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt() We should write transformed instruction encoding of the trapped instruction in [m|h]tinst CSR at time of taking trap as defined by the RISC-V privileged specification v1.12. Reviewed-by: Alistair Francis Signed-off-by: Anup Patel Acked-by: dramforever Message-Id: <20220630061150.905174-2-apatel@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 5 + target/riscv/cpu_helper.c | 252 +++++++++++++++++++++++++++++++++++++- target/riscv/instmap.h | 45 +++++++ 3 files changed, 296 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 5c7acc055a..ffb1a18873 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -285,6 +285,11 @@ struct CPUArchState { /* Signals whether the current exception occurred with two-stage address translation active. */ bool two_stage_lookup; + /* + * Signals whether the current exception occurred while doing two-stage + * address translation for the VS-stage page table walk. + */ + bool two_stage_indirect_lookup; target_ulong scounteren; target_ulong mcounteren; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 59b3680b1b..87daf7220f 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -22,6 +22,7 @@ #include "qemu/main-loop.h" #include "cpu.h" #include "exec/exec-all.h" +#include "instmap.h" #include "tcg/tcg-op.h" #include "trace.h" #include "semihosting/common-semi.h" @@ -1053,7 +1054,8 @@ restart: static void raise_mmu_exception(CPURISCVState *env, target_ulong address, MMUAccessType access_type, bool pmp_violation, - bool first_stage, bool two_stage) + bool first_stage, bool two_stage, + bool two_stage_indirect) { CPUState *cs = env_cpu(env); int page_fault_exceptions, vm; @@ -1103,6 +1105,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, } env->badaddr = address; env->two_stage_lookup = two_stage; + env->two_stage_indirect_lookup = two_stage_indirect; } hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr) @@ -1148,6 +1151,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, env->badaddr = addr; env->two_stage_lookup = riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(mmu_idx); + env->two_stage_indirect_lookup = false; cpu_loop_exit_restore(cs, retaddr); } @@ -1173,6 +1177,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, env->badaddr = addr; env->two_stage_lookup = riscv_cpu_virt_enabled(env) || riscv_cpu_two_stage_lookup(mmu_idx); + env->two_stage_indirect_lookup = false; cpu_loop_exit_restore(cs, retaddr); } @@ -1188,6 +1193,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool pmp_violation = false; bool first_stage_error = true; bool two_stage_lookup = false; + bool two_stage_indirect_error = false; int ret = TRANSLATE_FAIL; int mode = mmu_idx; /* default TLB page size */ @@ -1225,6 +1231,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, */ if (ret == TRANSLATE_G_STAGE_FAIL) { first_stage_error = false; + two_stage_indirect_error = true; access_type = MMU_DATA_LOAD; } @@ -1308,12 +1315,218 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, raise_mmu_exception(env, address, access_type, pmp_violation, first_stage_error, riscv_cpu_virt_enabled(env) || - riscv_cpu_two_stage_lookup(mmu_idx)); + riscv_cpu_two_stage_lookup(mmu_idx), + two_stage_indirect_error); cpu_loop_exit_restore(cs, retaddr); } return true; } + +static target_ulong riscv_transformed_insn(CPURISCVState *env, + target_ulong insn, + target_ulong taddr) +{ + target_ulong xinsn = 0; + target_ulong access_rs1 = 0, access_imm = 0, access_size = 0; + + /* + * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to + * be uncompressed. The Quadrant 1 of RVC instruction space need + * not be transformed because these instructions won't generate + * any load/store trap. + */ + + if ((insn & 0x3) != 0x3) { + /* Transform 16bit instruction into 32bit instruction */ + switch (GET_C_OP(insn)) { + case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */ + switch (GET_C_FUNC(insn)) { + case OPC_RISC_C_FUNC_FLD_LQ: + if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */ + xinsn = OPC_RISC_FLD; + xinsn = SET_RD(xinsn, GET_C_RS2S(insn)); + access_rs1 = GET_C_RS1S(insn); + access_imm = GET_C_LD_IMM(insn); + access_size = 8; + } + break; + case OPC_RISC_C_FUNC_LW: /* C.LW */ + xinsn = OPC_RISC_LW; + xinsn = SET_RD(xinsn, GET_C_RS2S(insn)); + access_rs1 = GET_C_RS1S(insn); + access_imm = GET_C_LW_IMM(insn); + access_size = 4; + break; + case OPC_RISC_C_FUNC_FLW_LD: + if (riscv_cpu_xlen(env) == 32) { /* C.FLW (RV32) */ + xinsn = OPC_RISC_FLW; + xinsn = SET_RD(xinsn, GET_C_RS2S(insn)); + access_rs1 = GET_C_RS1S(insn); + access_imm = GET_C_LW_IMM(insn); + access_size = 4; + } else { /* C.LD (RV64/RV128) */ + xinsn = OPC_RISC_LD; + xinsn = SET_RD(xinsn, GET_C_RS2S(insn)); + access_rs1 = GET_C_RS1S(insn); + access_imm = GET_C_LD_IMM(insn); + access_size = 8; + } + break; + case OPC_RISC_C_FUNC_FSD_SQ: + if (riscv_cpu_xlen(env) != 128) { /* C.FSD (RV32/64) */ + xinsn = OPC_RISC_FSD; + xinsn = SET_RS2(xinsn, GET_C_RS2S(insn)); + access_rs1 = GET_C_RS1S(insn); + access_imm = GET_C_SD_IMM(insn); + access_size = 8; + } + break; + case OPC_RISC_C_FUNC_SW: /* C.SW */ + xinsn = OPC_RISC_SW; + xinsn = SET_RS2(xinsn, GET_C_RS2S(insn)); + access_rs1 = GET_C_RS1S(insn); + access_imm = GET_C_SW_IMM(insn); + access_size = 4; + break; + case OPC_RISC_C_FUNC_FSW_SD: + if (riscv_cpu_xlen(env) == 32) { /* C.FSW (RV32) */ + xinsn = OPC_RISC_FSW; + xinsn = SET_RS2(xinsn, GET_C_RS2S(insn)); + access_rs1 = GET_C_RS1S(insn); + access_imm = GET_C_SW_IMM(insn); + access_size = 4; + } else { /* C.SD (RV64/RV128) */ + xinsn = OPC_RISC_SD; + xinsn = SET_RS2(xinsn, GET_C_RS2S(insn)); + access_rs1 = GET_C_RS1S(insn); + access_imm = GET_C_SD_IMM(insn); + access_size = 8; + } + break; + default: + break; + } + break; + case OPC_RISC_C_OP_QUAD2: /* Quadrant 2 */ + switch (GET_C_FUNC(insn)) { + case OPC_RISC_C_FUNC_FLDSP_LQSP: + if (riscv_cpu_xlen(env) != 128) { /* C.FLDSP (RV32/64) */ + xinsn = OPC_RISC_FLD; + xinsn = SET_RD(xinsn, GET_C_RD(insn)); + access_rs1 = 2; + access_imm = GET_C_LDSP_IMM(insn); + access_size = 8; + } + break; + case OPC_RISC_C_FUNC_LWSP: /* C.LWSP */ + xinsn = OPC_RISC_LW; + xinsn = SET_RD(xinsn, GET_C_RD(insn)); + access_rs1 = 2; + access_imm = GET_C_LWSP_IMM(insn); + access_size = 4; + break; + case OPC_RISC_C_FUNC_FLWSP_LDSP: + if (riscv_cpu_xlen(env) == 32) { /* C.FLWSP (RV32) */ + xinsn = OPC_RISC_FLW; + xinsn = SET_RD(xinsn, GET_C_RD(insn)); + access_rs1 = 2; + access_imm = GET_C_LWSP_IMM(insn); + access_size = 4; + } else { /* C.LDSP (RV64/RV128) */ + xinsn = OPC_RISC_LD; + xinsn = SET_RD(xinsn, GET_C_RD(insn)); + access_rs1 = 2; + access_imm = GET_C_LDSP_IMM(insn); + access_size = 8; + } + break; + case OPC_RISC_C_FUNC_FSDSP_SQSP: + if (riscv_cpu_xlen(env) != 128) { /* C.FSDSP (RV32/64) */ + xinsn = OPC_RISC_FSD; + xinsn = SET_RS2(xinsn, GET_C_RS2(insn)); + access_rs1 = 2; + access_imm = GET_C_SDSP_IMM(insn); + access_size = 8; + } + break; + case OPC_RISC_C_FUNC_SWSP: /* C.SWSP */ + xinsn = OPC_RISC_SW; + xinsn = SET_RS2(xinsn, GET_C_RS2(insn)); + access_rs1 = 2; + access_imm = GET_C_SWSP_IMM(insn); + access_size = 4; + break; + case 7: + if (riscv_cpu_xlen(env) == 32) { /* C.FSWSP (RV32) */ + xinsn = OPC_RISC_FSW; + xinsn = SET_RS2(xinsn, GET_C_RS2(insn)); + access_rs1 = 2; + access_imm = GET_C_SWSP_IMM(insn); + access_size = 4; + } else { /* C.SDSP (RV64/RV128) */ + xinsn = OPC_RISC_SD; + xinsn = SET_RS2(xinsn, GET_C_RS2(insn)); + access_rs1 = 2; + access_imm = GET_C_SDSP_IMM(insn); + access_size = 8; + } + break; + default: + break; + } + break; + default: + break; + } + + /* + * Clear Bit1 of transformed instruction to indicate that + * original insruction was a 16bit instruction + */ + xinsn &= ~((target_ulong)0x2); + } else { + /* Transform 32bit (or wider) instructions */ + switch (MASK_OP_MAJOR(insn)) { + case OPC_RISC_ATOMIC: + xinsn = insn; + access_rs1 = GET_RS1(insn); + access_size = 1 << GET_FUNCT3(insn); + break; + case OPC_RISC_LOAD: + case OPC_RISC_FP_LOAD: + xinsn = SET_I_IMM(insn, 0); + access_rs1 = GET_RS1(insn); + access_imm = GET_IMM(insn); + access_size = 1 << GET_FUNCT3(insn); + break; + case OPC_RISC_STORE: + case OPC_RISC_FP_STORE: + xinsn = SET_S_IMM(insn, 0); + access_rs1 = GET_RS1(insn); + access_imm = GET_STORE_IMM(insn); + access_size = 1 << GET_FUNCT3(insn); + break; + case OPC_RISC_SYSTEM: + if (MASK_OP_SYSTEM(insn) == OPC_RISC_HLVHSV) { + xinsn = insn; + access_rs1 = GET_RS1(insn); + access_size = 1 << ((GET_FUNCT7(insn) >> 1) & 0x3); + access_size = 1 << access_size; + } + break; + default: + break; + } + } + + if (access_size) { + xinsn = SET_RS1(xinsn, (taddr - (env->gpr[access_rs1] + access_imm)) & + (access_size - 1)); + } + + return xinsn; +} #endif /* !CONFIG_USER_ONLY */ /* @@ -1338,6 +1551,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) target_ulong cause = cs->exception_index & RISCV_EXCP_INT_MASK; uint64_t deleg = async ? env->mideleg : env->medeleg; target_ulong tval = 0; + target_ulong tinst = 0; target_ulong htval = 0; target_ulong mtval2 = 0; @@ -1353,20 +1567,43 @@ void riscv_cpu_do_interrupt(CPUState *cs) if (!async) { /* set tval to badaddr for traps with address information */ switch (cause) { - case RISCV_EXCP_INST_GUEST_PAGE_FAULT: case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT: case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT: - case RISCV_EXCP_INST_ADDR_MIS: - case RISCV_EXCP_INST_ACCESS_FAULT: case RISCV_EXCP_LOAD_ADDR_MIS: case RISCV_EXCP_STORE_AMO_ADDR_MIS: case RISCV_EXCP_LOAD_ACCESS_FAULT: case RISCV_EXCP_STORE_AMO_ACCESS_FAULT: - case RISCV_EXCP_INST_PAGE_FAULT: case RISCV_EXCP_LOAD_PAGE_FAULT: case RISCV_EXCP_STORE_PAGE_FAULT: write_gva = env->two_stage_lookup; tval = env->badaddr; + if (env->two_stage_indirect_lookup) { + /* + * special pseudoinstruction for G-stage fault taken while + * doing VS-stage page table walk. + */ + tinst = (riscv_cpu_xlen(env) == 32) ? 0x00002000 : 0x00003000; + } else { + /* + * The "Addr. Offset" field in transformed instruction is + * non-zero only for misaligned access. + */ + tinst = riscv_transformed_insn(env, env->bins, tval); + } + break; + case RISCV_EXCP_INST_GUEST_PAGE_FAULT: + case RISCV_EXCP_INST_ADDR_MIS: + case RISCV_EXCP_INST_ACCESS_FAULT: + case RISCV_EXCP_INST_PAGE_FAULT: + write_gva = env->two_stage_lookup; + tval = env->badaddr; + if (env->two_stage_indirect_lookup) { + /* + * special pseudoinstruction for G-stage fault taken while + * doing VS-stage page table walk. + */ + tinst = (riscv_cpu_xlen(env) == 32) ? 0x00002000 : 0x00003000; + } break; case RISCV_EXCP_ILLEGAL_INST: case RISCV_EXCP_VIRT_INSTRUCTION_FAULT: @@ -1446,6 +1683,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->sepc = env->pc; env->stval = tval; env->htval = htval; + env->htinst = tinst; env->pc = (env->stvec >> 2 << 2) + ((async && (env->stvec & 3) == 1) ? cause * 4 : 0); riscv_cpu_set_mode(env, PRV_S); @@ -1476,6 +1714,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->mepc = env->pc; env->mtval = tval; env->mtval2 = mtval2; + env->mtinst = tinst; env->pc = (env->mtvec >> 2 << 2) + ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0); riscv_cpu_set_mode(env, PRV_M); @@ -1488,6 +1727,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) */ env->two_stage_lookup = false; + env->two_stage_indirect_lookup = false; #endif cs->exception_index = RISCV_EXCP_NONE; /* mark handled to qemu */ } diff --git a/target/riscv/instmap.h b/target/riscv/instmap.h index 40b6d2b64d..f877530576 100644 --- a/target/riscv/instmap.h +++ b/target/riscv/instmap.h @@ -184,6 +184,8 @@ enum { OPC_RISC_CSRRWI = OPC_RISC_SYSTEM | (0x5 << 12), OPC_RISC_CSRRSI = OPC_RISC_SYSTEM | (0x6 << 12), OPC_RISC_CSRRCI = OPC_RISC_SYSTEM | (0x7 << 12), + + OPC_RISC_HLVHSV = OPC_RISC_SYSTEM | (0x4 << 12), }; #define MASK_OP_FP_LOAD(op) (MASK_OP_MAJOR(op) | (op & (0x7 << 12))) @@ -310,12 +312,20 @@ enum { | (extract32(inst, 12, 8) << 12) \ | (sextract64(inst, 31, 1) << 20)) +#define GET_FUNCT3(inst) extract32(inst, 12, 3) +#define GET_FUNCT7(inst) extract32(inst, 25, 7) #define GET_RM(inst) extract32(inst, 12, 3) #define GET_RS3(inst) extract32(inst, 27, 5) #define GET_RS1(inst) extract32(inst, 15, 5) #define GET_RS2(inst) extract32(inst, 20, 5) #define GET_RD(inst) extract32(inst, 7, 5) #define GET_IMM(inst) sextract64(inst, 20, 12) +#define SET_RS1(inst, val) deposit32(inst, 15, 5, val) +#define SET_RS2(inst, val) deposit32(inst, 20, 5, val) +#define SET_RD(inst, val) deposit32(inst, 7, 5, val) +#define SET_I_IMM(inst, val) deposit32(inst, 20, 12, val) +#define SET_S_IMM(inst, val) \ + deposit32(deposit32(inst, 7, 5, val), 25, 7, (val) >> 5) /* RVC decoding macros */ #define GET_C_IMM(inst) (extract32(inst, 2, 5) \ @@ -346,6 +356,8 @@ enum { | (extract32(inst, 5, 1) << 6)) #define GET_C_LD_IMM(inst) ((extract16(inst, 10, 3) << 3) \ | (extract16(inst, 5, 2) << 6)) +#define GET_C_SW_IMM(inst) GET_C_LW_IMM(inst) +#define GET_C_SD_IMM(inst) GET_C_LD_IMM(inst) #define GET_C_J_IMM(inst) ((extract32(inst, 3, 3) << 1) \ | (extract32(inst, 11, 1) << 4) \ | (extract32(inst, 2, 1) << 5) \ @@ -366,4 +378,37 @@ enum { #define GET_C_RS1S(inst) (8 + extract16(inst, 7, 3)) #define GET_C_RS2S(inst) (8 + extract16(inst, 2, 3)) +#define GET_C_FUNC(inst) extract32(inst, 13, 3) +#define GET_C_OP(inst) extract32(inst, 0, 2) + +enum { + /* RVC Quadrants */ + OPC_RISC_C_OP_QUAD0 = 0x0, + OPC_RISC_C_OP_QUAD1 = 0x1, + OPC_RISC_C_OP_QUAD2 = 0x2 +}; + +enum { + /* RVC Quadrant 0 */ + OPC_RISC_C_FUNC_ADDI4SPN = 0x0, + OPC_RISC_C_FUNC_FLD_LQ = 0x1, + OPC_RISC_C_FUNC_LW = 0x2, + OPC_RISC_C_FUNC_FLW_LD = 0x3, + OPC_RISC_C_FUNC_FSD_SQ = 0x5, + OPC_RISC_C_FUNC_SW = 0x6, + OPC_RISC_C_FUNC_FSW_SD = 0x7 +}; + +enum { + /* RVC Quadrant 2 */ + OPC_RISC_C_FUNC_SLLI_SLLI64 = 0x0, + OPC_RISC_C_FUNC_FLDSP_LQSP = 0x1, + OPC_RISC_C_FUNC_LWSP = 0x2, + OPC_RISC_C_FUNC_FLWSP_LDSP = 0x3, + OPC_RISC_C_FUNC_JR_MV_EBREAK_JALR_ADD = 0x4, + OPC_RISC_C_FUNC_FSDSP_SQSP = 0x5, + OPC_RISC_C_FUNC_SWSP = 0x6, + OPC_RISC_C_FUNC_FSWSP_SDSP = 0x7 +}; + #endif From 9a1f054d5bd9acaa82b66e09309482cba9eced63 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Thu, 30 Jun 2022 11:41:50 +0530 Subject: [PATCH 0363/1020] target/riscv: Force disable extensions if priv spec version does not match We should disable extensions in riscv_cpu_realize() if minimum required priv spec version is not satisfied. This also ensures that machines with priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter extensions. Fixes: a775398be2e9 ("target/riscv: Add isa extenstion strings to the device tree") Reviewed-by: Alistair Francis Signed-off-by: Anup Patel Signed-off-by: Rahul Pathak Message-Id: <20220630061150.905174-3-apatel@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 150 ++++++++++++++++++++++++++++----------------- 1 file changed, 94 insertions(+), 56 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ac6f82ebd0..cab74faaca 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -43,9 +43,82 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH"; struct isa_ext_data { const char *name; - bool enabled; + bool multi_letter; + int min_version; + int ext_enable_offset; }; +#define ISA_EXT_DATA_ENTRY(_name, _m_letter, _min_ver, _prop) \ +{#_name, _m_letter, _min_ver, offsetof(struct RISCVCPUConfig, _prop)} + +/** + * Here are the ordering rules of extension naming defined by RISC-V + * specification : + * 1. All extensions should be separated from other multi-letter extensions + * by an underscore. + * 2. The first letter following the 'Z' conventionally indicates the most + * closely related alphabetical extension category, IMAFDQLCBKJTPVH. + * If multiple 'Z' extensions are named, they should be ordered first + * by category, then alphabetically within a category. + * 3. Standard supervisor-level extensions (starts with 'S') should be + * listed after standard unprivileged extensions. If multiple + * supervisor-level extensions are listed, they should be ordered + * alphabetically. + * 4. Non-standard extensions (starts with 'X') must be listed after all + * standard extensions. They must be separated from other multi-letter + * extensions by an underscore. + */ +static const struct isa_ext_data isa_edata_arr[] = { + ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h), + ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v), + ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr), + ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei), + ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh), + ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin), + ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx), + ISA_EXT_DATA_ENTRY(zdinx, true, PRIV_VERSION_1_12_0, ext_zdinx), + ISA_EXT_DATA_ENTRY(zba, true, PRIV_VERSION_1_12_0, ext_zba), + ISA_EXT_DATA_ENTRY(zbb, true, PRIV_VERSION_1_12_0, ext_zbb), + ISA_EXT_DATA_ENTRY(zbc, true, PRIV_VERSION_1_12_0, ext_zbc), + ISA_EXT_DATA_ENTRY(zbkb, true, PRIV_VERSION_1_12_0, ext_zbkb), + ISA_EXT_DATA_ENTRY(zbkc, true, PRIV_VERSION_1_12_0, ext_zbkc), + ISA_EXT_DATA_ENTRY(zbkx, true, PRIV_VERSION_1_12_0, ext_zbkx), + ISA_EXT_DATA_ENTRY(zbs, true, PRIV_VERSION_1_12_0, ext_zbs), + ISA_EXT_DATA_ENTRY(zk, true, PRIV_VERSION_1_12_0, ext_zk), + ISA_EXT_DATA_ENTRY(zkn, true, PRIV_VERSION_1_12_0, ext_zkn), + ISA_EXT_DATA_ENTRY(zknd, true, PRIV_VERSION_1_12_0, ext_zknd), + ISA_EXT_DATA_ENTRY(zkne, true, PRIV_VERSION_1_12_0, ext_zkne), + ISA_EXT_DATA_ENTRY(zknh, true, PRIV_VERSION_1_12_0, ext_zknh), + ISA_EXT_DATA_ENTRY(zkr, true, PRIV_VERSION_1_12_0, ext_zkr), + ISA_EXT_DATA_ENTRY(zks, true, PRIV_VERSION_1_12_0, ext_zks), + ISA_EXT_DATA_ENTRY(zksed, true, PRIV_VERSION_1_12_0, ext_zksed), + ISA_EXT_DATA_ENTRY(zksh, true, PRIV_VERSION_1_12_0, ext_zksh), + ISA_EXT_DATA_ENTRY(zkt, true, PRIV_VERSION_1_12_0, ext_zkt), + ISA_EXT_DATA_ENTRY(zve32f, true, PRIV_VERSION_1_12_0, ext_zve32f), + ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f), + ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx), + ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin), + ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval), + ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot), + ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt), +}; + +static bool isa_ext_is_enabled(RISCVCPU *cpu, + const struct isa_ext_data *edata) +{ + bool *ext_enabled = (void *)&cpu->cfg + edata->ext_enable_offset; + + return *ext_enabled; +} + +static void isa_ext_update_enabled(RISCVCPU *cpu, + const struct isa_ext_data *edata, bool en) +{ + bool *ext_enabled = (void *)&cpu->cfg + edata->ext_enable_offset; + + *ext_enabled = en; +} + 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", @@ -530,7 +603,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) CPURISCVState *env = &cpu->env; RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); CPUClass *cc = CPU_CLASS(mcc); - int priv_version = -1; + int i, priv_version = -1; Error *local_err = NULL; cpu_exec_realizefn(cs, &local_err); @@ -558,6 +631,23 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_priv_version(env, priv_version); } + /* 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, &isa_edata_arr[i]) && + (env->priv_ver < isa_edata_arr[i].min_version)) { + isa_ext_update_enabled(cpu, &isa_edata_arr[i], false); +#ifndef CONFIG_USER_ONLY + warn_report("disabling %s extension for hart 0x%lx because " + "privilege spec version does not match", + isa_edata_arr[i].name, (unsigned long)env->mhartid); +#else + warn_report("disabling %s extension because " + "privilege spec version does not match", + isa_edata_arr[i].name); +#endif + } + } + if (cpu->cfg.mmu) { riscv_set_feature(env, RISCV_FEATURE_MMU); } @@ -1044,67 +1134,15 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) device_class_set_props(dc, riscv_cpu_properties); } -#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop} - static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int max_str_len) { char *old = *isa_str; char *new = *isa_str; int i; - /** - * Here are the ordering rules of extension naming defined by RISC-V - * specification : - * 1. All extensions should be separated from other multi-letter extensions - * by an underscore. - * 2. The first letter following the 'Z' conventionally indicates the most - * closely related alphabetical extension category, IMAFDQLCBKJTPVH. - * If multiple 'Z' extensions are named, they should be ordered first - * by category, then alphabetically within a category. - * 3. Standard supervisor-level extensions (starts with 'S') should be - * listed after standard unprivileged extensions. If multiple - * supervisor-level extensions are listed, they should be ordered - * alphabetically. - * 4. Non-standard extensions (starts with 'X') must be listed after all - * standard extensions. They must be separated from other multi-letter - * extensions by an underscore. - */ - struct isa_ext_data isa_edata_arr[] = { - ISA_EDATA_ENTRY(zicsr, ext_icsr), - ISA_EDATA_ENTRY(zifencei, ext_ifencei), - ISA_EDATA_ENTRY(zmmul, ext_zmmul), - ISA_EDATA_ENTRY(zfh, ext_zfh), - ISA_EDATA_ENTRY(zfhmin, ext_zfhmin), - ISA_EDATA_ENTRY(zfinx, ext_zfinx), - ISA_EDATA_ENTRY(zdinx, ext_zdinx), - ISA_EDATA_ENTRY(zba, ext_zba), - ISA_EDATA_ENTRY(zbb, ext_zbb), - ISA_EDATA_ENTRY(zbc, ext_zbc), - ISA_EDATA_ENTRY(zbkb, ext_zbkb), - ISA_EDATA_ENTRY(zbkc, ext_zbkc), - ISA_EDATA_ENTRY(zbkx, ext_zbkx), - ISA_EDATA_ENTRY(zbs, ext_zbs), - ISA_EDATA_ENTRY(zk, ext_zk), - ISA_EDATA_ENTRY(zkn, ext_zkn), - ISA_EDATA_ENTRY(zknd, ext_zknd), - ISA_EDATA_ENTRY(zkne, ext_zkne), - ISA_EDATA_ENTRY(zknh, ext_zknh), - ISA_EDATA_ENTRY(zkr, ext_zkr), - ISA_EDATA_ENTRY(zks, ext_zks), - ISA_EDATA_ENTRY(zksed, ext_zksed), - ISA_EDATA_ENTRY(zksh, ext_zksh), - ISA_EDATA_ENTRY(zkt, ext_zkt), - ISA_EDATA_ENTRY(zve32f, ext_zve32f), - ISA_EDATA_ENTRY(zve64f, ext_zve64f), - ISA_EDATA_ENTRY(zhinx, ext_zhinx), - ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin), - ISA_EDATA_ENTRY(svinval, ext_svinval), - ISA_EDATA_ENTRY(svnapot, ext_svnapot), - ISA_EDATA_ENTRY(svpbmt, ext_svpbmt), - }; - for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) { - if (isa_edata_arr[i].enabled) { + if (isa_edata_arr[i].multi_letter && + isa_ext_is_enabled(cpu, &isa_edata_arr[i])) { new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL); g_free(old); old = new; From 3363277525958e173b4526f9dca225e125b1a5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20P=C3=A9trot?= Date: Sun, 10 Jul 2022 13:04:51 +0200 Subject: [PATCH 0364/1020] target/riscv: fix shifts shamt value for rv128c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For rv128c shifts, a shamt of 0 is a shamt of 64, while for rv32c/rv64c it stays 0 and is a hint instruction that does not change processor state. For rv128c right shifts, the 6-bit shamt is in addition sign extended to 7 bits. Signed-off-by: FrĂ©dĂ©ric PĂ©trot Reviewed-by: Weiwei Li Reviewed-by: Richard Henderson Message-Id: <20220710110451.245567-1-frederic.petrot@univ-grenoble-alpes.fr> Signed-off-by: Alistair Francis --- disas/riscv.c | 27 +++++++++++++++++++++------ target/riscv/insn16.decode | 7 ++++--- target/riscv/translate.c | 20 ++++++++++++++++++-- 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/disas/riscv.c b/disas/riscv.c index 7af6afc8fa..489c2ae5e8 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -2402,10 +2402,25 @@ static int32_t operand_sbimm12(rv_inst inst) ((inst << 56) >> 63) << 11; } -static uint32_t operand_cimmsh6(rv_inst inst) +static uint32_t operand_cimmshl6(rv_inst inst, rv_isa isa) { - return ((inst << 51) >> 63) << 5 | + int imm = ((inst << 51) >> 63) << 5 | (inst << 57) >> 59; + if (isa == rv128) { + imm = imm ? imm : 64; + } + return imm; +} + +static uint32_t operand_cimmshr6(rv_inst inst, rv_isa isa) +{ + int imm = ((inst << 51) >> 63) << 5 | + (inst << 57) >> 59; + if (isa == rv128) { + imm = imm | (imm & 32) << 1; + imm = imm ? imm : 64; + } + return imm; } static int32_t operand_cimmi(rv_inst inst) @@ -2529,7 +2544,7 @@ static uint32_t operand_rnum(rv_inst inst) /* decode operands */ -static void decode_inst_operands(rv_decode *dec) +static void decode_inst_operands(rv_decode *dec, rv_isa isa) { rv_inst inst = dec->inst; dec->codec = opcode_data[dec->op].codec; @@ -2652,7 +2667,7 @@ static void decode_inst_operands(rv_decode *dec) case rv_codec_cb_sh6: dec->rd = dec->rs1 = operand_crs1rdq(inst) + 8; dec->rs2 = rv_ireg_zero; - dec->imm = operand_cimmsh6(inst); + dec->imm = operand_cimmshr6(inst, isa); break; case rv_codec_ci: dec->rd = dec->rs1 = operand_crs1rd(inst); @@ -2667,7 +2682,7 @@ static void decode_inst_operands(rv_decode *dec) case rv_codec_ci_sh6: dec->rd = dec->rs1 = operand_crs1rd(inst); dec->rs2 = rv_ireg_zero; - dec->imm = operand_cimmsh6(inst); + dec->imm = operand_cimmshl6(inst, isa); break; case rv_codec_ci_16sp: dec->rd = rv_ireg_sp; @@ -3193,7 +3208,7 @@ disasm_inst(char *buf, size_t buflen, rv_isa isa, uint64_t pc, rv_inst inst) dec.pc = pc; dec.inst = inst; decode_inst_opcode(&dec, isa); - decode_inst_operands(&dec); + decode_inst_operands(&dec, isa); decode_inst_decompress(&dec, isa); decode_inst_lift_pseudo(&dec); format_inst(buf, buflen, 16, &dec); diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode index 02c8f61b48..ccfe59f294 100644 --- a/target/riscv/insn16.decode +++ b/target/riscv/insn16.decode @@ -31,7 +31,8 @@ %imm_cb 12:s1 5:2 2:1 10:2 3:2 !function=ex_shift_1 %imm_cj 12:s1 8:1 9:2 6:1 7:1 2:1 11:1 3:3 !function=ex_shift_1 -%shimm_6bit 12:1 2:5 !function=ex_rvc_shifti +%shlimm_6bit 12:1 2:5 !function=ex_rvc_shiftli +%shrimm_6bit 12:1 2:5 !function=ex_rvc_shiftri %uimm_6bit_lq 2:4 12:1 6:1 !function=ex_shift_4 %uimm_6bit_ld 2:3 12:1 5:2 !function=ex_shift_3 %uimm_6bit_lw 2:2 12:1 4:3 !function=ex_shift_2 @@ -82,9 +83,9 @@ @c_addi16sp ... . ..... ..... .. &i imm=%imm_addi16sp rs1=2 rd=2 @c_shift ... . .. ... ..... .. \ - &shift rd=%rs1_3 rs1=%rs1_3 shamt=%shimm_6bit + &shift rd=%rs1_3 rs1=%rs1_3 shamt=%shrimm_6bit @c_shift2 ... . .. ... ..... .. \ - &shift rd=%rd rs1=%rd shamt=%shimm_6bit + &shift rd=%rd rs1=%rd shamt=%shlimm_6bit @c_andi ... . .. ... ..... .. &i imm=%imm_ci rs1=%rs1_3 rd=%rs1_3 diff --git a/target/riscv/translate.c b/target/riscv/translate.c index f8af6daa70..6eeb728462 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -705,10 +705,26 @@ static int ex_rvc_register(DisasContext *ctx, int reg) return 8 + reg; } -static int ex_rvc_shifti(DisasContext *ctx, int imm) +static int ex_rvc_shiftli(DisasContext *ctx, int imm) { /* For RV128 a shamt of 0 means a shift by 64. */ - return imm ? imm : 64; + if (get_ol(ctx) == MXL_RV128) { + imm = imm ? imm : 64; + } + return imm; +} + +static int ex_rvc_shiftri(DisasContext *ctx, int imm) +{ + /* + * For RV128 a shamt of 0 means a shift by 64, furthermore, for right + * shifts, the shamt is sign-extended. + */ + if (get_ol(ctx) == MXL_RV128) { + imm = imm | (imm & 32) << 1; + imm = imm ? imm : 64; + } + return imm; } /* Include the auto-generated decoder for 32 bit insn */ From 6d00ffad4e9549086e80a47566ed5f3b4b8bb2dd Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Sun, 10 Jul 2022 18:15:46 +0800 Subject: [PATCH 0365/1020] target/riscv: move zmmul out of the experimental properties - Zmmul is ratified and is now version 1.0 Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Alistair Francis Message-Id: <20220710101546.3907-1-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index cab74faaca..a3e4e2477f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1009,12 +1009,13 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("zhinx", RISCVCPU, cfg.ext_zhinx, false), DEFINE_PROP_BOOL("zhinxmin", RISCVCPU, cfg.ext_zhinxmin, false), + DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false), + /* Vendor-specific custom extensions */ DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false), /* These are experimental so mark with 'x-' */ DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false), - DEFINE_PROP_BOOL("x-zmmul", RISCVCPU, cfg.ext_zmmul, false), /* ePMP 0.9.3 */ DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false), DEFINE_PROP_BOOL("x-aia", RISCVCPU, cfg.aia, false), From e4b4f0b71ccbeb0157489c0904ba4957761528ff Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 13 Jun 2022 13:58:10 +0200 Subject: [PATCH 0366/1020] hw/riscv: virt: pass random seed to fdt If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to initialize early. Set this using the usual guest random number generation function. This is confirmed to successfully initialize the RNG on Linux 5.19-rc2. Cc: Alistair Francis Signed-off-by: Jason A. Donenfeld Reviewed-by: Bin Meng Message-Id: <20220613115810.178210-1-Jason@zx2c4.com> Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index bc424dd2f5..f2ce5663a4 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -21,6 +21,7 @@ #include "qemu/osdep.h" #include "qemu/units.h" #include "qemu/error-report.h" +#include "qemu/guest-random.h" #include "qapi/error.h" #include "hw/boards.h" #include "hw/loader.h" @@ -998,6 +999,7 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, MachineState *mc = MACHINE(s); uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1; uint32_t irq_pcie_phandle = 1, irq_virtio_phandle = 1; + uint8_t rng_seed[32]; if (mc->dtb) { mc->fdt = load_device_tree(mc->dtb, &s->fdt_size); @@ -1046,6 +1048,10 @@ update_bootargs: if (cmdline && *cmdline) { qemu_fdt_setprop_string(mc->fdt, "/chosen", "bootargs", cmdline); } + + /* Pass seed to RNG */ + qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); + qemu_fdt_setprop(mc->fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed)); } static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, From 0b572c8131998e7bcd048dbbbe78f95e6101d68d Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Mon, 18 Jul 2022 21:09:50 +0800 Subject: [PATCH 0367/1020] target/riscv: Add check for supported privilege mode combinations There are 3 suggested privilege mode combinations listed in section 1.2 of the riscv-privileged spec(draft-20220717): 1) M, 2) M, U 3) M, S, U Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-Id: <20220718130955.11899-2-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index a3e4e2477f..b919ad9056 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -721,6 +721,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) return; } + if (cpu->cfg.ext_s && !cpu->cfg.ext_u) { + error_setg(errp, + "Setting S extension without U extension is illegal"); + return; + } + if (cpu->cfg.ext_f && !cpu->cfg.ext_icsr) { error_setg(errp, "F extension requires Zicsr"); return; From 756b0374dc37af2213e3b652fb3f50a4cc9acb24 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Mon, 18 Jul 2022 21:09:51 +0800 Subject: [PATCH 0368/1020] target/riscv: H extension depends on I extension Add check for "H depends on an I base integer ISA with 32 x registers" which is stated at the beginning of chapter 8 of the riscv-privileged spec(draft-20220717) Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-Id: <20220718130955.11899-3-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index b919ad9056..fb37ffac64 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -727,6 +727,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) return; } + if (cpu->cfg.ext_h && !cpu->cfg.ext_i) { + error_setg(errp, + "H depends on an I base integer ISA with 32 x registers"); + return; + } + if (cpu->cfg.ext_f && !cpu->cfg.ext_icsr) { error_setg(errp, "F extension requires Zicsr"); return; From 108c4f26ce441fe0fa0ee20c776e2b71706068be Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Mon, 18 Jul 2022 21:09:52 +0800 Subject: [PATCH 0369/1020] target/riscv: Fix checkpatch warning may triggered in csr_ops table Fix the lines with over 80 characters Fix the lines which are obviously misalgined with other lines in the same group Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-Id: <20220718130955.11899-4-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 435 ++++++++++++++++++++++++--------------------- 1 file changed, 231 insertions(+), 204 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 235f2a011e..7d4b6ceced 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3461,20 +3461,20 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_FRM] = { "frm", fs, read_frm, write_frm }, [CSR_FCSR] = { "fcsr", fs, read_fcsr, write_fcsr }, /* Vector CSRs */ - [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VL] = { "vl", vs, read_vl, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VTYPE] = { "vtype", vs, read_vtype, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VLENB] = { "vlenb", vs, read_vlenb, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTART] = { "vstart", vs, read_vstart, write_vstart, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VXSAT] = { "vxsat", vs, read_vxsat, write_vxsat, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VXRM] = { "vxrm", vs, read_vxrm, write_vxrm, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VCSR] = { "vcsr", vs, read_vcsr, write_vcsr, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VL] = { "vl", vs, read_vl, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VTYPE] = { "vtype", vs, read_vtype, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VLENB] = { "vlenb", vs, read_vlenb, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* User Timers and Counters */ [CSR_CYCLE] = { "cycle", ctr, read_hpmcounter }, [CSR_INSTRET] = { "instret", ctr, read_hpmcounter }, @@ -3493,10 +3493,14 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { #if !defined(CONFIG_USER_ONLY) /* Machine Timers and Counters */ - [CSR_MCYCLE] = { "mcycle", any, read_hpmcounter, write_mhpmcounter}, - [CSR_MINSTRET] = { "minstret", any, read_hpmcounter, write_mhpmcounter}, - [CSR_MCYCLEH] = { "mcycleh", any32, read_hpmcounterh, write_mhpmcounterh}, - [CSR_MINSTRETH] = { "minstreth", any32, read_hpmcounterh, write_mhpmcounterh}, + [CSR_MCYCLE] = { "mcycle", any, read_hpmcounter, + write_mhpmcounter }, + [CSR_MINSTRET] = { "minstret", any, read_hpmcounter, + write_mhpmcounter }, + [CSR_MCYCLEH] = { "mcycleh", any32, read_hpmcounterh, + write_mhpmcounterh }, + [CSR_MINSTRETH] = { "minstreth", any32, read_hpmcounterh, + write_mhpmcounterh }, /* Machine Information Registers */ [CSR_MVENDORID] = { "mvendorid", any, read_mvendorid }, @@ -3505,23 +3509,25 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MHARTID] = { "mhartid", any, read_mhartid }, [CSR_MCONFIGPTR] = { "mconfigptr", any, read_zero, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Machine Trap Setup */ - [CSR_MSTATUS] = { "mstatus", any, read_mstatus, write_mstatus, NULL, - read_mstatus_i128 }, - [CSR_MISA] = { "misa", any, read_misa, write_misa, NULL, - read_misa_i128 }, - [CSR_MIDELEG] = { "mideleg", any, NULL, NULL, rmw_mideleg }, - [CSR_MEDELEG] = { "medeleg", any, read_medeleg, write_medeleg }, - [CSR_MIE] = { "mie", any, NULL, NULL, rmw_mie }, - [CSR_MTVEC] = { "mtvec", any, read_mtvec, write_mtvec }, - [CSR_MCOUNTEREN] = { "mcounteren", any, read_mcounteren, write_mcounteren }, + [CSR_MSTATUS] = { "mstatus", any, read_mstatus, write_mstatus, + NULL, read_mstatus_i128 }, + [CSR_MISA] = { "misa", any, read_misa, write_misa, + NULL, read_misa_i128 }, + [CSR_MIDELEG] = { "mideleg", any, NULL, NULL, rmw_mideleg }, + [CSR_MEDELEG] = { "medeleg", any, read_medeleg, write_medeleg }, + [CSR_MIE] = { "mie", any, NULL, NULL, rmw_mie }, + [CSR_MTVEC] = { "mtvec", any, read_mtvec, write_mtvec }, + [CSR_MCOUNTEREN] = { "mcounteren", any, read_mcounteren, + write_mcounteren }, - [CSR_MSTATUSH] = { "mstatush", any32, read_mstatush, write_mstatush }, + [CSR_MSTATUSH] = { "mstatush", any32, read_mstatush, + write_mstatush }, /* Machine Trap Handling */ - [CSR_MSCRATCH] = { "mscratch", any, read_mscratch, write_mscratch, NULL, - read_mscratch_i128, write_mscratch_i128 }, + [CSR_MSCRATCH] = { "mscratch", any, read_mscratch, write_mscratch, + NULL, read_mscratch_i128, write_mscratch_i128 }, [CSR_MEPC] = { "mepc", any, read_mepc, write_mepc }, [CSR_MCAUSE] = { "mcause", any, read_mcause, write_mcause }, [CSR_MTVAL] = { "mtval", any, read_mtval, write_mtval }, @@ -3532,12 +3538,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MIREG] = { "mireg", aia_any, NULL, NULL, rmw_xireg }, /* Machine-Level Interrupts (AIA) */ - [CSR_MTOPEI] = { "mtopei", aia_any, NULL, NULL, rmw_xtopei }, - [CSR_MTOPI] = { "mtopi", aia_any, read_mtopi }, + [CSR_MTOPEI] = { "mtopei", aia_any, NULL, NULL, rmw_xtopei }, + [CSR_MTOPI] = { "mtopi", aia_any, read_mtopi }, /* Virtual Interrupts for Supervisor Level (AIA) */ - [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore }, - [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore }, + [CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore }, + [CSR_MVIP] = { "mvip", aia_any, read_zero, write_ignore }, /* Machine-Level High-Half CSRs (AIA) */ [CSR_MIDELEGH] = { "midelegh", aia_any32, NULL, NULL, rmw_midelegh }, @@ -3548,33 +3554,34 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { /* Execution environment configuration */ [CSR_MENVCFG] = { "menvcfg", any, read_menvcfg, write_menvcfg, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MENVCFGH] = { "menvcfgh", any32, read_menvcfgh, write_menvcfgh, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_SENVCFG] = { "senvcfg", smode, read_senvcfg, write_senvcfg, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_HENVCFG] = { "henvcfg", hmode, read_henvcfg, write_henvcfg, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_HENVCFGH] = { "henvcfgh", hmode32, read_henvcfgh, write_henvcfgh, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Supervisor Trap Setup */ - [CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, NULL, - read_sstatus_i128 }, - [CSR_SIE] = { "sie", smode, NULL, NULL, rmw_sie }, - [CSR_STVEC] = { "stvec", smode, read_stvec, write_stvec }, - [CSR_SCOUNTEREN] = { "scounteren", smode, read_scounteren, write_scounteren }, + [CSR_SSTATUS] = { "sstatus", smode, read_sstatus, write_sstatus, + NULL, read_sstatus_i128 }, + [CSR_SIE] = { "sie", smode, NULL, NULL, rmw_sie }, + [CSR_STVEC] = { "stvec", smode, read_stvec, write_stvec }, + [CSR_SCOUNTEREN] = { "scounteren", smode, read_scounteren, + write_scounteren }, /* Supervisor Trap Handling */ - [CSR_SSCRATCH] = { "sscratch", smode, read_sscratch, write_sscratch, NULL, - read_sscratch_i128, write_sscratch_i128 }, + [CSR_SSCRATCH] = { "sscratch", smode, read_sscratch, write_sscratch, + NULL, read_sscratch_i128, write_sscratch_i128 }, [CSR_SEPC] = { "sepc", smode, read_sepc, write_sepc }, [CSR_SCAUSE] = { "scause", smode, read_scause, write_scause }, - [CSR_STVAL] = { "stval", smode, read_stval, write_stval }, + [CSR_STVAL] = { "stval", smode, read_stval, write_stval }, [CSR_SIP] = { "sip", smode, NULL, NULL, rmw_sip }, /* Supervisor Protection and Translation */ - [CSR_SATP] = { "satp", smode, read_satp, write_satp }, + [CSR_SATP] = { "satp", smode, read_satp, write_satp }, /* Supervisor-Level Window to Indirectly Accessed Registers (AIA) */ [CSR_SISELECT] = { "siselect", aia_smode, NULL, NULL, rmw_xiselect }, @@ -3588,87 +3595,100 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh }, [CSR_SIPH] = { "siph", aia_smode32, NULL, NULL, rmw_siph }, - [CSR_HSTATUS] = { "hstatus", hmode, read_hstatus, write_hstatus, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HEDELEG] = { "hedeleg", hmode, read_hedeleg, write_hedeleg, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HSTATUS] = { "hstatus", hmode, read_hstatus, write_hstatus, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HEDELEG] = { "hedeleg", hmode, read_hedeleg, write_hedeleg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_HIDELEG] = { "hideleg", hmode, NULL, NULL, rmw_hideleg, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HVIP] = { "hvip", hmode, NULL, NULL, rmw_hvip, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HIP] = { "hip", hmode, NULL, NULL, rmw_hip, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HIE] = { "hie", hmode, NULL, NULL, rmw_hie, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HCOUNTEREN] = { "hcounteren", hmode, read_hcounteren, write_hcounteren, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HGEIE] = { "hgeie", hmode, read_hgeie, write_hgeie, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HTVAL] = { "htval", hmode, read_htval, write_htval, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HTINST] = { "htinst", hmode, read_htinst, write_htinst, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HVIP] = { "hvip", hmode, NULL, NULL, rmw_hvip, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HIP] = { "hip", hmode, NULL, NULL, rmw_hip, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HIE] = { "hie", hmode, NULL, NULL, rmw_hie, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HCOUNTEREN] = { "hcounteren", hmode, read_hcounteren, + write_hcounteren, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HGEIE] = { "hgeie", hmode, read_hgeie, write_hgeie, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HTVAL] = { "htval", hmode, read_htval, write_htval, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HTINST] = { "htinst", hmode, read_htinst, write_htinst, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_HGEIP] = { "hgeip", hmode, read_hgeip, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, write_htimedelta, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_HTIMEDELTAH] = { "htimedeltah", hmode32, read_htimedeltah, write_htimedeltah, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HGATP] = { "hgatp", hmode, read_hgatp, write_hgatp, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HTIMEDELTA] = { "htimedelta", hmode, read_htimedelta, + write_htimedelta, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_HTIMEDELTAH] = { "htimedeltah", hmode32, read_htimedeltah, + write_htimedeltah, + .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSSTATUS] = { "vsstatus", hmode, read_vsstatus, write_vsstatus, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSIP] = { "vsip", hmode, NULL, NULL, rmw_vsip, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSIE] = { "vsie", hmode, NULL, NULL, rmw_vsie , - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSTVEC] = { "vstvec", hmode, read_vstvec, write_vstvec, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSSCRATCH] = { "vsscratch", hmode, read_vsscratch, write_vsscratch, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSEPC] = { "vsepc", hmode, read_vsepc, write_vsepc, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSCAUSE] = { "vscause", hmode, read_vscause, write_vscause, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSTVAL] = { "vstval", hmode, read_vstval, write_vstval, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_VSATP] = { "vsatp", hmode, read_vsatp, write_vsatp, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSSTATUS] = { "vsstatus", hmode, read_vsstatus, + write_vsstatus, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSIP] = { "vsip", hmode, NULL, NULL, rmw_vsip, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSIE] = { "vsie", hmode, NULL, NULL, rmw_vsie , + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTVEC] = { "vstvec", hmode, read_vstvec, write_vstvec, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSSCRATCH] = { "vsscratch", hmode, read_vsscratch, + write_vsscratch, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSEPC] = { "vsepc", hmode, read_vsepc, write_vsepc, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSCAUSE] = { "vscause", hmode, read_vscause, write_vscause, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTVAL] = { "vstval", hmode, read_vstval, write_vstval, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSATP] = { "vsatp", hmode, read_vsatp, write_vsatp, + .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MTVAL2] = { "mtval2", hmode, read_mtval2, write_mtval2, - .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst, - .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MTVAL2] = { "mtval2", hmode, read_mtval2, write_mtval2, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MTINST] = { "mtinst", hmode, read_mtinst, write_mtinst, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */ [CSR_HVIEN] = { "hvien", aia_hmode, read_zero, write_ignore }, - [CSR_HVICTL] = { "hvictl", aia_hmode, read_hvictl, write_hvictl }, - [CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, write_hviprio1 }, - [CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, write_hviprio2 }, + [CSR_HVICTL] = { "hvictl", aia_hmode, read_hvictl, + write_hvictl }, + [CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, + write_hviprio1 }, + [CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, + write_hviprio2 }, /* * VS-Level Window to Indirectly Accessed Registers (H-extension with AIA) */ - [CSR_VSISELECT] = { "vsiselect", aia_hmode, NULL, NULL, rmw_xiselect }, - [CSR_VSIREG] = { "vsireg", aia_hmode, NULL, NULL, rmw_xireg }, + [CSR_VSISELECT] = { "vsiselect", aia_hmode, NULL, NULL, + rmw_xiselect }, + [CSR_VSIREG] = { "vsireg", aia_hmode, NULL, NULL, rmw_xireg }, /* VS-Level Interrupts (H-extension with AIA) */ [CSR_VSTOPEI] = { "vstopei", aia_hmode, NULL, NULL, rmw_xtopei }, [CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi }, /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */ - [CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh }, - [CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, write_ignore }, + [CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, + rmw_hidelegh }, + [CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, + write_ignore }, [CSR_HVIPH] = { "hviph", aia_hmode32, NULL, NULL, rmw_hviph }, - [CSR_HVIPRIO1H] = { "hviprio1h", aia_hmode32, read_hviprio1h, write_hviprio1h }, - [CSR_HVIPRIO2H] = { "hviprio2h", aia_hmode32, read_hviprio2h, write_hviprio2h }, + [CSR_HVIPRIO1H] = { "hviprio1h", aia_hmode32, read_hviprio1h, + write_hviprio1h }, + [CSR_HVIPRIO2H] = { "hviprio2h", aia_hmode32, read_hviprio2h, + write_hviprio2h }, [CSR_VSIEH] = { "vsieh", aia_hmode32, NULL, NULL, rmw_vsieh }, [CSR_VSIPH] = { "vsiph", aia_hmode32, NULL, NULL, rmw_vsiph }, /* Physical Memory Protection */ [CSR_MSECCFG] = { "mseccfg", epmp, read_mseccfg, write_mseccfg, - .min_priv_ver = PRIV_VERSION_1_11_0 }, + .min_priv_ver = PRIV_VERSION_1_11_0 }, [CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg }, [CSR_PMPCFG1] = { "pmpcfg1", pmp, read_pmpcfg, write_pmpcfg }, [CSR_PMPCFG2] = { "pmpcfg2", pmp, read_pmpcfg, write_pmpcfg }, @@ -3697,17 +3717,23 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_TDATA3] = { "tdata3", debug, read_tdata, write_tdata }, /* User Pointer Masking */ - [CSR_UMTE] = { "umte", pointer_masking, read_umte, write_umte }, - [CSR_UPMMASK] = { "upmmask", pointer_masking, read_upmmask, write_upmmask }, - [CSR_UPMBASE] = { "upmbase", pointer_masking, read_upmbase, write_upmbase }, + [CSR_UMTE] = { "umte", pointer_masking, read_umte, write_umte }, + [CSR_UPMMASK] = { "upmmask", pointer_masking, read_upmmask, + write_upmmask }, + [CSR_UPMBASE] = { "upmbase", pointer_masking, read_upmbase, + write_upmbase }, /* Machine Pointer Masking */ - [CSR_MMTE] = { "mmte", pointer_masking, read_mmte, write_mmte }, - [CSR_MPMMASK] = { "mpmmask", pointer_masking, read_mpmmask, write_mpmmask }, - [CSR_MPMBASE] = { "mpmbase", pointer_masking, read_mpmbase, write_mpmbase }, + [CSR_MMTE] = { "mmte", pointer_masking, read_mmte, write_mmte }, + [CSR_MPMMASK] = { "mpmmask", pointer_masking, read_mpmmask, + write_mpmmask }, + [CSR_MPMBASE] = { "mpmbase", pointer_masking, read_mpmbase, + write_mpmbase }, /* Supervisor Pointer Masking */ - [CSR_SMTE] = { "smte", pointer_masking, read_smte, write_smte }, - [CSR_SPMMASK] = { "spmmask", pointer_masking, read_spmmask, write_spmmask }, - [CSR_SPMBASE] = { "spmbase", pointer_masking, read_spmbase, write_spmbase }, + [CSR_SMTE] = { "smte", pointer_masking, read_smte, write_smte }, + [CSR_SPMMASK] = { "spmmask", pointer_masking, read_spmmask, + write_spmmask }, + [CSR_SPMBASE] = { "spmbase", pointer_masking, read_spmbase, + write_spmbase }, /* Performance Counters */ [CSR_HPMCOUNTER3] = { "hpmcounter3", ctr, read_hpmcounter }, @@ -3741,125 +3767,126 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_HPMCOUNTER31] = { "hpmcounter31", ctr, read_hpmcounter }, [CSR_MHPMCOUNTER3] = { "mhpmcounter3", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER4] = { "mhpmcounter4", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER5] = { "mhpmcounter5", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER6] = { "mhpmcounter6", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER7] = { "mhpmcounter7", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER8] = { "mhpmcounter8", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER9] = { "mhpmcounter9", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER10] = { "mhpmcounter10", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER11] = { "mhpmcounter11", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER12] = { "mhpmcounter12", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER13] = { "mhpmcounter13", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER14] = { "mhpmcounter14", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER15] = { "mhpmcounter15", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER16] = { "mhpmcounter16", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER17] = { "mhpmcounter17", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER18] = { "mhpmcounter18", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER19] = { "mhpmcounter19", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER20] = { "mhpmcounter20", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER21] = { "mhpmcounter21", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER22] = { "mhpmcounter22", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER23] = { "mhpmcounter23", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER24] = { "mhpmcounter24", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER25] = { "mhpmcounter25", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER26] = { "mhpmcounter26", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER27] = { "mhpmcounter27", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER28] = { "mhpmcounter28", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER29] = { "mhpmcounter29", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER30] = { "mhpmcounter30", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MHPMCOUNTER31] = { "mhpmcounter31", mctr, read_hpmcounter, - write_mhpmcounter }, + write_mhpmcounter }, [CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_mcountinhibit, - write_mcountinhibit, .min_priv_ver = PRIV_VERSION_1_11_0 }, + write_mcountinhibit, + .min_priv_ver = PRIV_VERSION_1_11_0 }, [CSR_MHPMEVENT3] = { "mhpmevent3", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT4] = { "mhpmevent4", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT5] = { "mhpmevent5", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT6] = { "mhpmevent6", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT7] = { "mhpmevent7", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT8] = { "mhpmevent8", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT9] = { "mhpmevent9", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT10] = { "mhpmevent10", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT11] = { "mhpmevent11", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT12] = { "mhpmevent12", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT13] = { "mhpmevent13", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT14] = { "mhpmevent14", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT15] = { "mhpmevent15", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT16] = { "mhpmevent16", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT17] = { "mhpmevent17", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT18] = { "mhpmevent18", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT19] = { "mhpmevent19", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT20] = { "mhpmevent20", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT21] = { "mhpmevent21", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT22] = { "mhpmevent22", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT23] = { "mhpmevent23", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT24] = { "mhpmevent24", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT25] = { "mhpmevent25", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT26] = { "mhpmevent26", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT27] = { "mhpmevent27", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT28] = { "mhpmevent28", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT29] = { "mhpmevent29", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT30] = { "mhpmevent30", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_MHPMEVENT31] = { "mhpmevent31", any, read_mhpmevent, - write_mhpmevent }, + write_mhpmevent }, [CSR_HPMCOUNTER3H] = { "hpmcounter3h", ctr32, read_hpmcounterh }, [CSR_HPMCOUNTER4H] = { "hpmcounter4h", ctr32, read_hpmcounterh }, @@ -3892,62 +3919,62 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_HPMCOUNTER31H] = { "hpmcounter31h", ctr32, read_hpmcounterh }, [CSR_MHPMCOUNTER3H] = { "mhpmcounter3h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER4H] = { "mhpmcounter4h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER5H] = { "mhpmcounter5h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER6H] = { "mhpmcounter6h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER7H] = { "mhpmcounter7h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER8H] = { "mhpmcounter8h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER9H] = { "mhpmcounter9h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER10H] = { "mhpmcounter10h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER11H] = { "mhpmcounter11h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER12H] = { "mhpmcounter12h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER13H] = { "mhpmcounter13h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER14H] = { "mhpmcounter14h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER15H] = { "mhpmcounter15h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER16H] = { "mhpmcounter16h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER17H] = { "mhpmcounter17h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER18H] = { "mhpmcounter18h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER19H] = { "mhpmcounter19h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER20H] = { "mhpmcounter20h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER21H] = { "mhpmcounter21h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER22H] = { "mhpmcounter22h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER23H] = { "mhpmcounter23h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER24H] = { "mhpmcounter24h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER25H] = { "mhpmcounter25h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER26H] = { "mhpmcounter26h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER27H] = { "mhpmcounter27h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER28H] = { "mhpmcounter28h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER29H] = { "mhpmcounter29h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER30H] = { "mhpmcounter30h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, [CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", mctr32, read_hpmcounterh, - write_mhpmcounterh }, + write_mhpmcounterh }, #endif /* !CONFIG_USER_ONLY */ }; From c126f83cd64883f7cb4be90a7fbf29e2be3bb9c7 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Mon, 18 Jul 2022 21:09:53 +0800 Subject: [PATCH 0370/1020] target/riscv: Add check for csrs existed with U extension Add umode/umode32 predicate for mcounteren, menvcfg/menvcfgh Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-Id: <20220718130955.11899-5-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 7d4b6ceced..5c69dc838c 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -339,6 +339,24 @@ static RISCVException hmode32(CPURISCVState *env, int csrno) } +static RISCVException umode(CPURISCVState *env, int csrno) +{ + if (riscv_has_ext(env, RVU)) { + return RISCV_EXCP_NONE; + } + + return RISCV_EXCP_ILLEGAL_INST; +} + +static RISCVException umode32(CPURISCVState *env, int csrno) +{ + if (riscv_cpu_mxl(env) != MXL_RV32) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return umode(env, csrno); +} + /* Checks if PointerMasking registers could be accessed */ static RISCVException pointer_masking(CPURISCVState *env, int csrno) { @@ -3519,7 +3537,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MEDELEG] = { "medeleg", any, read_medeleg, write_medeleg }, [CSR_MIE] = { "mie", any, NULL, NULL, rmw_mie }, [CSR_MTVEC] = { "mtvec", any, read_mtvec, write_mtvec }, - [CSR_MCOUNTEREN] = { "mcounteren", any, read_mcounteren, + [CSR_MCOUNTEREN] = { "mcounteren", umode, read_mcounteren, write_mcounteren }, [CSR_MSTATUSH] = { "mstatush", any32, read_mstatush, @@ -3553,9 +3571,9 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MIPH] = { "miph", aia_any32, NULL, NULL, rmw_miph }, /* Execution environment configuration */ - [CSR_MENVCFG] = { "menvcfg", any, read_menvcfg, write_menvcfg, + [CSR_MENVCFG] = { "menvcfg", umode, read_menvcfg, write_menvcfg, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MENVCFGH] = { "menvcfgh", any32, read_menvcfgh, write_menvcfgh, + [CSR_MENVCFGH] = { "menvcfgh", umode32, read_menvcfgh, write_menvcfgh, .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_SENVCFG] = { "senvcfg", smode, read_senvcfg, write_senvcfg, .min_priv_ver = PRIV_VERSION_1_12_0 }, From 62a09b9b4118ca42e79d9bd179daf7230462705b Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Mon, 18 Jul 2022 21:09:54 +0800 Subject: [PATCH 0371/1020] target/riscv: Fix checks in hmode/hmode32 Add check for the implicit dependence between H and S Csrs only existed in RV32 will not trigger virtual instruction fault when not in RV32 based on section 8.6.1 of riscv-privileged spec (draft-20220717) Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Andrew Jones Reviewed-by: Alistair Francis Message-Id: <20220718130955.11899-6-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 5 +++++ target/riscv/csr.c | 9 ++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index fb37ffac64..117d308ae5 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -733,6 +733,11 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) return; } + if (cpu->cfg.ext_h && !cpu->cfg.ext_s) { + error_setg(errp, "H extension implicitly requires S-mode"); + return; + } + if (cpu->cfg.ext_f && !cpu->cfg.ext_icsr) { error_setg(errp, "F extension requires Zicsr"); return; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 5c69dc838c..cf15aa67b7 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -311,8 +311,7 @@ static int aia_smode32(CPURISCVState *env, int csrno) static RISCVException hmode(CPURISCVState *env, int csrno) { - if (riscv_has_ext(env, RVS) && - riscv_has_ext(env, RVH)) { + if (riscv_has_ext(env, RVH)) { /* Hypervisor extension is supported */ if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || env->priv == PRV_M) { @@ -328,11 +327,7 @@ static RISCVException hmode(CPURISCVState *env, int csrno) static RISCVException hmode32(CPURISCVState *env, int csrno) { if (riscv_cpu_mxl(env) != MXL_RV32) { - if (!riscv_cpu_virt_enabled(env)) { - return RISCV_EXCP_ILLEGAL_INST; - } else { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } + return RISCV_EXCP_ILLEGAL_INST; } return hmode(env, csrno); From 5de124538b618c864508868eae505e77149649b7 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Mon, 18 Jul 2022 21:09:55 +0800 Subject: [PATCH 0372/1020] target/riscv: Simplify the check in hmode to reuse the check in riscv_csrrw_check Just add 1 to the effective privledge level when in HS mode, then reuse the check of 'effective_priv < csr_priv' in riscv_csrrw_check to replace the privilege level related check in hmode. Then, hmode will only check whether H extension is supported. When accessing Hypervior CSRs: 1) If accessing from M privilege level, the check of 'effective_priv< csr_priv' passes, returns hmode(...) which will return RISCV_EXCP_ILLEGAL_INST when H extension is not supported and return RISCV_EXCP_NONE otherwise. 2) If accessing from HS privilege level, effective_priv will add 1, the check passes and also returns hmode(...) too. 3) If accessing from VS/VU privilege level, the check fails, and returns RISCV_EXCP_VIRT_INSTRUCTION_FAULT 4) If accessing from U privilege level, the check fails, and returns RISCV_EXCP_ILLEGAL_INST Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-Id: <20220718130955.11899-7-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index cf15aa67b7..0fb042b2fd 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -312,13 +312,7 @@ static int aia_smode32(CPURISCVState *env, int csrno) static RISCVException hmode(CPURISCVState *env, int csrno) { if (riscv_has_ext(env, RVH)) { - /* Hypervisor extension is supported */ - if ((env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) || - env->priv == PRV_M) { - return RISCV_EXCP_NONE; - } else { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } + return RISCV_EXCP_NONE; } return RISCV_EXCP_ILLEGAL_INST; @@ -3279,13 +3273,11 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, #if !defined(CONFIG_USER_ONLY) int csr_priv, effective_priv = env->priv; - if (riscv_has_ext(env, RVH) && env->priv == PRV_S) { + if (riscv_has_ext(env, RVH) && env->priv == PRV_S && + !riscv_cpu_virt_enabled(env)) { /* - * We are in either HS or VS mode. - * Add 1 to the effective privledge level to allow us to access the - * Hypervisor CSRs. The `hmode` predicate will determine if access - * should be allowed(HS) or if a virtual instruction exception should be - * raised(VS). + * We are in HS mode. Add 1 to the effective privledge level to + * allow us to access the Hypervisor CSRs. */ effective_priv++; } From 780bb81bb3624b304d3226803b61e881777d183d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Wed, 13 Jul 2022 17:00:31 +0800 Subject: [PATCH 0373/1020] roms/opensbi: Upgrade from v1.0 to v1.1 Upgrade OpenSBI from v1.0 to v1.1 and the pre-built bios images. The v1.1 release includes the following commits: 5b99603 lib: utils/ipi: Fix size check in aclint_mswi_cold_init() 6dde435 lib: utils/sys: Extend HTIF library to allow custom base address 8257262 platform: sifive_fu740: do not use a global in da9063_reset/shutdown fb688d9 platform: sifive_fu740: fix reset when watchdog is running 5d025eb lib: fix pointer of type 'void *' used in arithmetic 632f593 lib: sbi: Map only the counters enabled in hardware 3b7c204 lib: sbi: Disable interrupt during config matching a26dc60 lib: sbi: Disable interrupt and inhibit counting in M-mode during init 5d53b55 Makefile: fix build with binutils 2.38 6ad8917 lib: fix compilation when strings.h is included ce4c018 lib: utils/serial: Round UART8250 baud rate divisor to nearest integer 01250d0 include: sbi: Add AIA related CSR defines 8f96070 lib: sbi: Detect AIA CSRs at boot-time 65b4c7c lib: sbi: Use AIA CSRs for local interrupts when available 222132f lib: sbi: Add sbi_trap_set_external_irqfn() API 5f56314 lib: utils/irqchip: Allow multiple FDT irqchip drivers 1050940 include: sbi: Introduce nascent_init() platform callback 55e79f8 lib: sbi: Enable mie.MEIE bit for IPIs based on external interrupts. 9f73669 lib: utils/irqchip: Add IMSIC library 811da5c lib: utils/irqchip: Add FDT based driver for IMSIC 7127aaa lib: utils: Disable appropriate IMSIC DT nodes in fdt_fixups() 9979265 lib: utils/irqchip: Add APLIC initialization library 3461219 lib: utils/irqchip: Add FDT based driver for APLIC 8e2ef4f lib: utils: Disable appropriate APLIC DT nodes in fdt_fixups() 3a69cc1 lib: sbi: fix typo in is_region_subset f2ccf2f lib: sbi: verbose sbi_domain_root_add_memregion f3f4604 lib: sbi: Add a simple external interrupt handling framework 4998a71 lib: utils: serial: Initial commit of xlnx-uartlite 2dfbd3c lib: pmp_set/pmp_get moved errors from runtime to compile time b6b7220 firmware: Fix code for accessing hart_count and stack_size d552fc8 lib: Add error messages via conditional compilation for the future 555bdb1 include: Use static asserts for SBI_PLATFORM_xxx_OFFSET defines 1b42d3a include: Use static asserts for SBI_SCRATCH_xxx_OFFSET defines 7924a0b include: Use static asserts for FW_DYNAMIC_INFO_xxx_OFFSET defines 722f80d include: Add defines for [m|h|s]envcfg CSRs 31fecad lib: sbi: Detect menvcfg CSR at boot time 47d6765 lib: sbi: Enable Zicbo[m|z] extensions in the menvcfg CSR 794986f lib: sbi: Enable Svpbmt extension in the menvcfg CSR 499601a lib: sbi: Add Smstateen extension defines d44568a lib: sbi: Detect Smstateen CSRs at boot-time 3383d6a lib: irqchip/imsic: configure mstateen 5c5cbb5 lib: utils/serial: support 'reg-offset' property c1e47d0 include: correct the definition of MSTATUS_VS 9cd95e1 lib: sbi/hart: preserve csr validation value 4035ae9 docs: pmu: Improve the PMU DT bindings d62f6da lib: sbi: Implement Sstc extension 474a9d4 lib: sbi: Fix mstatus_init() for RV32 when Sscofpmf is not available e576b3e include: sbi: Define SBI_PMU_HW_EVENT_MAX to 256 b0c9df5 lib: sbi: Fix mhpmeventh access for rv32 in absence of sscofpmf 1a754bb lib: sbi: Detect and print privileged spec version 5a6be99 lib: sbi: Remove 's' and 'u' from misa_string() output 5b8b377 lib: sbi: Update the name of ISA string printed at boot time d4b563c lib: sbi: Remove MCOUNTEREN and SCOUNTEREN hart features dbc3d8f lib: sbi: Remove MCOUNTINHIBT hart feature 97a17c2 lib: sbi: Remove MENVCFG hart feature a6ab94f lib: sbi: Fix AIA feature detection cad6c91 lib: sbi: Convert hart features into hart extensions be4903a lib: sbi: Detect hart features only once for each hart 994ace3 lib: sbi: Add sbi_hart_update_extension() function 023f0ad lib: sbi_platform: Add callback to populate HART extensions f726f2d Makefile: Allow generated C source to be anywhere in build directory 7fb474b Makefile: Add support for generating C array at compile time 73cf511 lib: utils/reset: Generate FDT reset driver list at compile-time 1e62705 lib: utils/serial: Generate FDT serial driver list at compile-time bfeb305 lib: utils/timer: Generate FDT timer driver list at compile-time 3a69d12 lib: utils/irqchip: Generate FDT irqchip driver list at compile-time 4ee0c57 lib: utils/ipi: Generate FDT ipi driver list at compile-time 998ed43 lib: utils/i2c: Generate FDT i2c adapter driver list at compile-time 4eacd82 lib: utils/gpio: Generate FDT gpio driver list at compile-time a3a3c60 platform: generic: Generate platform override module list at compile-time 9a7a677 platform: generic: Move Sifive platform overrides into own directory 851c14d lib: utils/irqchip: fix typo when checking for CPU node 90a9dd2 lib: utils/fdt: introduce fdt_node_is_enabled() 616da52 lib: utils: check if CPU node is enabled 575bb4e platform: generic: check if CPU node is enabled 1bc67db lib: utils/fdt: rename fdt_parse_max_hart_id f067bb8 lib: sbi: fix system_opcode_insn fab0379 lib: utils/fdt: Require match data to be const 295e5f3 lib: sbi_timer: Drop unnecessary get_platform_ticks wrapper ff65bfe lib: sbi_illegal_insn: Constify illegal_insn_table cb8271c lib: sbi_illegal_insn: Add emulation for fence.tso adc3388 lib: sbi_trap: Redirect exception based on hedeleg ce1d618 platform: generic: add overrides for vendor extensions b20ed9f lib: sbi_hsm: Call a device hook during hart resume 79e42eb lib: sbi_hsm: Assume a consistent resume address 2ea7799 lib: irqchip/plic: Constify plic_data pointers 8c362e7 lib: irqchip/plic: Factor out a context init function 415ecf2 lib: irqchip/plic: Add context save/restore helpers 2b79b69 lib: irqchip/plic: Add priority save/restore helpers 69be3df lib: utils/irqchip: Add FDT wrappers for PLIC save/restore functions 5e56758 lib: utils/irqchip: Add wrapper for T-HEAD PLIC delegation 9dc5ec5 platform: Add HSM implementation for Allwinner D1 551c70c include: sbi: Add mtinst/htinst psuedoinstructions 187127f lib: sbi: Fixup tinst for exceptions in sbi_misaligned_*() a07402a lib: sbi: Fix tval and tinst for sbi_get_insn() c653001 lib: utils: Remove CSRs that set/clear an IMSIC interrupt file bits 7738345 lib: utils/timer: Add a separate compatible for the D1 CLINT d76a196 lib: irqchip/plic: fix typo in plic_warm_irqchip_init 6f1fe98 lib: utils/timer: Remove Allwinner D1 CLINT compatibles c6fdbcf include: sbi: Change spec version to 1.0 3f66465 lib: pmu: allow to use the highest available counter 4489876 include: Bump-up version to 1.1 Signed-off-by: Bin Meng Reviewed-by: Alistair Francis Message-Id: <20220713090613.204046-1-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- .../opensbi-riscv32-generic-fw_dynamic.bin | Bin 108504 -> 117704 bytes .../opensbi-riscv64-generic-fw_dynamic.bin | Bin 105296 -> 115344 bytes roms/opensbi | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin index dba8e8655fbf39c128b19675cdd205805f85e7e1..81bab1adc97bbe9b376f3bfe4da98cdfcf3ade7a 100644 GIT binary patch delta 61109 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%0A=YYPa$97&KyvjYlURJ^rl+N^hZATK1>-F9 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 b>Xn9T_r+LQLdFc&{`Aitd&)Er`1gMRit`iQ diff --git a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin index f223e56991f56f96521453eaaf89a1f4a9bf2c31..5eb0a743260b47e07e674db3728d6ba4125847c0 100644 GIT binary patch delta 55872 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 Date: Sun, 17 Jul 2022 13:15:43 +0300 Subject: [PATCH 0374/1020] target/riscv: Fix typo and restore Pointer Masking functionality for RISC-V Fixes: 4302bef9e178 ("target/riscv: Calculate address according to XLEN") Signed-off-by: Alexey Baturo Reviewed-by: Alistair Francis Message-Id: <20220717101543.478533-2-space.monkey.delivers@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/translate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 6eeb728462..76da8db8a7 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -544,7 +544,7 @@ static TCGv get_address(DisasContext *ctx, int rs1, int imm) tcg_gen_addi_tl(addr, src1, imm); if (ctx->pm_mask_enabled) { - tcg_gen_and_tl(addr, addr, pm_mask); + tcg_gen_andc_tl(addr, addr, pm_mask); } else if (get_xl(ctx) == MXL_RV32) { tcg_gen_ext32u_tl(addr, addr); } From 079520033facc70beee5eedee8d7a27a2a9261b4 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 19 Jul 2022 16:26:35 +0800 Subject: [PATCH 0375/1020] docs: List kvm as a supported accelerator on RISC-V Since commit fbf43c7dbf18 ("target/riscv: enable riscv kvm accel"), KVM accelerator is supported on RISC-V. Let's document it. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Reviewed-by: Alistair Francis Message-Id: <20220719082635.3741878-1-bin.meng@windriver.com> Signed-off-by: Alistair Francis --- docs/about/build-platforms.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/about/build-platforms.rst b/docs/about/build-platforms.rst index 26028756d0..a2fee53248 100644 --- a/docs/about/build-platforms.rst +++ b/docs/about/build-platforms.rst @@ -46,7 +46,7 @@ Those hosts are officially supported, with various accelerators: * - PPC - kvm, tcg * - RISC-V - - tcg + - kvm, tcg * - s390x - kvm, tcg * - SPARC From 355d5584de1129eec1c4043fdee1335010cfabb6 Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:51:02 +0000 Subject: [PATCH 0376/1020] target/riscv: rvv: Add mask agnostic for vv instructions According to v-spec, mask agnostic behavior can be either kept as undisturbed or set elements' bits to all 1s. To distinguish the difference of mask policies, QEMU should be able to simulate the mask agnostic behavior as "set mask elements' bits to all 1s". There are multiple possibility for agnostic elements according to v-spec. The main intent of this patch-set tries to add option that can distinguish between mask policies. Setting agnostic elements to all 1s allows QEMU to express this. This is the first commit regarding the optional mask agnostic behavior. Follow-up commits will add this optional behavior for all rvv instructions. Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Reviewed-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-1@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 2 ++ target/riscv/cpu_helper.c | 2 ++ target/riscv/insn_trans/trans_rvv.c.inc | 3 +++ target/riscv/internals.h | 5 +++-- target/riscv/translate.c | 2 ++ target/riscv/vector_helper.c | 8 ++++++++ 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index ffb1a18873..561d7fa92c 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -439,6 +439,7 @@ struct RISCVCPUConfig { bool ext_zve64f; bool ext_zmmul; bool rvv_ta_all_1s; + bool rvv_ma_all_1s; uint32_t mvendorid; uint64_t marchid; @@ -596,6 +597,7 @@ FIELD(TB_FLAGS, XL, 20, 2) FIELD(TB_FLAGS, PM_MASK_ENABLED, 22, 1) FIELD(TB_FLAGS, PM_BASE_ENABLED, 23, 1) FIELD(TB_FLAGS, VTA, 24, 1) +FIELD(TB_FLAGS, VMA, 25, 1) #ifdef TARGET_RISCV32 #define riscv_cpu_mxl(env) ((void)(env), MXL_RV32) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 87daf7220f..650574accf 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -68,6 +68,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax); flags = FIELD_DP32(flags, TB_FLAGS, VTA, FIELD_EX64(env->vtype, VTYPE, VTA)); + flags = FIELD_DP32(flags, TB_FLAGS, VMA, + FIELD_EX64(env->vtype, VTYPE, VMA)); } else { flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1); } diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 6c091824b6..5ec113f6fd 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -1247,6 +1247,7 @@ do_opivv_gvec(DisasContext *s, arg_rmrr *a, GVecGen3Fn *gvec_fn, data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), cpu_env, s->cfg_ptr->vlen / 8, @@ -1545,6 +1546,7 @@ static bool do_opivv_widen(DisasContext *s, arg_rmrr *a, data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), @@ -1627,6 +1629,7 @@ static bool do_opiwv_widen(DisasContext *s, arg_rmrr *a, data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs1), vreg_ofs(s, a->rs2), diff --git a/target/riscv/internals.h b/target/riscv/internals.h index 193ce57a6d..5620fbffb6 100644 --- a/target/riscv/internals.h +++ b/target/riscv/internals.h @@ -26,8 +26,9 @@ FIELD(VDATA, VM, 0, 1) FIELD(VDATA, LMUL, 1, 3) FIELD(VDATA, VTA, 4, 1) FIELD(VDATA, VTA_ALL_1S, 5, 1) -FIELD(VDATA, NF, 6, 4) -FIELD(VDATA, WD, 6, 1) +FIELD(VDATA, VMA, 6, 1) +FIELD(VDATA, NF, 7, 4) +FIELD(VDATA, WD, 7, 1) /* float point classify helpers */ target_ulong fclass_h(uint64_t frs1); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 76da8db8a7..8925a44c6e 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -95,6 +95,7 @@ typedef struct DisasContext { int8_t lmul; uint8_t sew; uint8_t vta; + uint8_t vma; bool cfg_vta_all_1s; target_ulong vstart; bool vl_eq_vlmax; @@ -1121,6 +1122,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) ctx->sew = FIELD_EX32(tb_flags, TB_FLAGS, SEW); ctx->lmul = sextract32(FIELD_EX32(tb_flags, TB_FLAGS, LMUL), 0, 3); ctx->vta = FIELD_EX32(tb_flags, TB_FLAGS, VTA) && cpu->cfg.rvv_ta_all_1s; + ctx->vma = FIELD_EX32(tb_flags, TB_FLAGS, VMA) && cpu->cfg.rvv_ma_all_1s; ctx->cfg_vta_all_1s = cpu->cfg.rvv_ta_all_1s; ctx->vstart = env->vstart; ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX); diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index a96fc49c71..de895050e0 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -127,6 +127,11 @@ static inline uint32_t vext_vta(uint32_t desc) return FIELD_EX32(simd_data(desc), VDATA, VTA); } +static inline uint32_t vext_vma(uint32_t desc) +{ + return FIELD_EX32(simd_data(desc), VDATA, VMA); +} + static inline uint32_t vext_vta_all_1s(uint32_t desc) { return FIELD_EX32(simd_data(desc), VDATA, VTA_ALL_1S); @@ -812,10 +817,13 @@ static void do_vext_vv(void *vd, void *v0, void *vs1, void *vs2, uint32_t vl = env->vl; uint32_t total_elems = vext_get_total_elems(env, desc, esz); uint32_t vta = vext_vta(desc); + uint32_t vma = vext_vma(desc); uint32_t i; for (i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { + /* set masked-off elements to 1s */ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); continue; } fn(vd, vs1, vs2, i); From 265ecd4c62a008f3be351a75e1847cee9c71e380 Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:51:02 +0000 Subject: [PATCH 0377/1020] target/riscv: rvv: Add mask agnostic for vector load / store instructions Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Acked-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-2@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 5 ++++ target/riscv/vector_helper.c | 35 +++++++++++++++++-------- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 5ec113f6fd..0627eda0c0 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -712,6 +712,7 @@ static bool ld_us_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew) data = FIELD_DP32(data, VDATA, LMUL, emul); data = FIELD_DP32(data, VDATA, NF, a->nf); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); return ldst_us_trans(a->rd, a->rs1, data, fn, s, false); } @@ -777,6 +778,7 @@ static bool ld_us_mask_op(DisasContext *s, arg_vlm_v *a, uint8_t eew) data = FIELD_DP32(data, VDATA, NF, 1); /* Mask destination register are always tail-agnostic */ data = FIELD_DP32(data, VDATA, VTA, s->cfg_vta_all_1s); + data = FIELD_DP32(data, VDATA, VMA, s->vma); return ldst_us_trans(a->rd, a->rs1, data, fn, s, false); } @@ -866,6 +868,7 @@ static bool ld_stride_op(DisasContext *s, arg_rnfvm *a, uint8_t eew) data = FIELD_DP32(data, VDATA, LMUL, emul); data = FIELD_DP32(data, VDATA, NF, a->nf); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); return ldst_stride_trans(a->rd, a->rs1, a->rs2, data, fn, s, false); } @@ -996,6 +999,7 @@ static bool ld_index_op(DisasContext *s, arg_rnfvm *a, uint8_t eew) data = FIELD_DP32(data, VDATA, LMUL, emul); data = FIELD_DP32(data, VDATA, NF, a->nf); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); return ldst_index_trans(a->rd, a->rs1, a->rs2, data, fn, s, false); } @@ -1114,6 +1118,7 @@ static bool ldff_op(DisasContext *s, arg_r2nfvm *a, uint8_t eew) data = FIELD_DP32(data, VDATA, LMUL, emul); data = FIELD_DP32(data, VDATA, NF, a->nf); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); return ldff_trans(a->rd, a->rs1, data, fn, s); } diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index de895050e0..e3810d2bc3 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -283,14 +283,18 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base, uint32_t esz = 1 << log2_esz; uint32_t total_elems = vext_get_total_elems(env, desc, esz); uint32_t vta = vext_vta(desc); + uint32_t vma = vext_vma(desc); for (i = env->vstart; i < env->vl; i++, env->vstart++) { - if (!vm && !vext_elem_mask(v0, i)) { - continue; - } - k = 0; while (k < nf) { + if (!vm && !vext_elem_mask(v0, i)) { + /* set masked-off elements to 1s */ + vext_set_elems_1s(vd, vma, (i + k * max_elems) * esz, + (i + k * max_elems + 1) * esz); + k++; + continue; + } target_ulong addr = base + stride * i + (k << log2_esz); ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); k++; @@ -482,15 +486,19 @@ vext_ldst_index(void *vd, void *v0, target_ulong base, uint32_t esz = 1 << log2_esz; uint32_t total_elems = vext_get_total_elems(env, desc, esz); uint32_t vta = vext_vta(desc); + uint32_t vma = vext_vma(desc); /* load bytes from guest memory */ for (i = env->vstart; i < env->vl; i++, env->vstart++) { - if (!vm && !vext_elem_mask(v0, i)) { - continue; - } - k = 0; while (k < nf) { + if (!vm && !vext_elem_mask(v0, i)) { + /* set masked-off elements to 1s */ + vext_set_elems_1s(vd, vma, (i + k * max_elems) * esz, + (i + k * max_elems + 1) * esz); + k++; + continue; + } abi_ptr addr = get_index_addr(base, i, vs2) + (k << log2_esz); ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); k++; @@ -579,6 +587,7 @@ vext_ldff(void *vd, void *v0, target_ulong base, uint32_t esz = 1 << log2_esz; uint32_t total_elems = vext_get_total_elems(env, desc, esz); uint32_t vta = vext_vta(desc); + uint32_t vma = vext_vma(desc); target_ulong addr, offset, remain; /* probe every access*/ @@ -624,10 +633,14 @@ ProbeSuccess: } for (i = env->vstart; i < env->vl; i++) { k = 0; - if (!vm && !vext_elem_mask(v0, i)) { - continue; - } while (k < nf) { + if (!vm && !vext_elem_mask(v0, i)) { + /* set masked-off elements to 1s */ + vext_set_elems_1s(vd, vma, (i + k * max_elems) * esz, + (i + k * max_elems + 1) * esz); + k++; + continue; + } target_ulong addr = base + ((i * nf + k) << log2_esz); ldst_elem(env, adjust_addr(env, addr), i + k * max_elems, vd, ra); k++; From bce9a636beabbb2c538cdfca49592b04bfbf7e2c Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:50:58 +0000 Subject: [PATCH 0378/1020] target/riscv: rvv: Add mask agnostic for vx instructions Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Acked-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-3@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 2 ++ target/riscv/vector_helper.c | 3 +++ 2 files changed, 5 insertions(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 0627eda0c0..07d86551a9 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -1301,6 +1301,7 @@ static bool opivx_trans(uint32_t vd, uint32_t rs1, uint32_t vs2, uint32_t vm, data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); + data = FIELD_DP32(data, VDATA, VMA, s->vma); desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, data)); @@ -1468,6 +1469,7 @@ static bool opivi_trans(uint32_t vd, uint32_t imm, uint32_t vs2, uint32_t vm, data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); data = FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s); + data = FIELD_DP32(data, VDATA, VMA, s->vma); desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlen / 8, s->cfg_ptr->vlen / 8, data)); diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index e3810d2bc3..6be3c4e739 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -899,10 +899,13 @@ static void do_vext_vx(void *vd, void *v0, target_long s1, void *vs2, uint32_t vl = env->vl; uint32_t total_elems = vext_get_total_elems(env, desc, esz); uint32_t vta = vext_vta(desc); + uint32_t vma = vext_vma(desc); uint32_t i; for (i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { + /* set masked-off elements to 1s */ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); continue; } fn(vd, s1, vs2, i); From fd93045ebfa6ab07ce7017fb4095736c3f6f315a Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:50:58 +0000 Subject: [PATCH 0379/1020] target/riscv: rvv: Add mask agnostic for vector integer shift instructions Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Acked-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-4@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 1 + target/riscv/vector_helper.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 07d86551a9..83b85bb851 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -1901,6 +1901,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ vreg_ofs(s, a->rs2), cpu_env, \ diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 6be3c4e739..d1daa764b7 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -1298,10 +1298,13 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ uint32_t esz = sizeof(TS1); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ TS1 s1 = *((TS1 *)vs1 + HS1(i)); \ @@ -1339,10 +1342,14 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, \ uint32_t total_elems = \ vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, \ + (i + 1) * esz); \ continue; \ } \ TS2 s2 = *((TS2 *)vs2 + HS2(i)); \ From 6e11d7eaa02c5834e5172d25e8c794ac5731b56e Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:51:11 +0000 Subject: [PATCH 0380/1020] target/riscv: rvv: Add mask agnostic for vector integer comparison instructions Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Acked-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-5@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 1 + target/riscv/vector_helper.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 83b85bb851..e6aa5295a1 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -1718,6 +1718,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ data = \ FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ vreg_ofs(s, a->rs2), cpu_env, \ diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index d1daa764b7..07ce671879 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -1404,12 +1404,17 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t vl = env->vl; \ uint32_t total_elems = env_archcpu(env)->cfg.vlen; \ uint32_t vta_all_1s = vext_vta_all_1s(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + if (vma) { \ + vext_set_elem_mask(vd, i, 1); \ + } \ continue; \ } \ vext_set_elem_mask(vd, i, DO_OP(s2, s1)); \ @@ -1462,11 +1467,16 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t vl = env->vl; \ uint32_t total_elems = env_archcpu(env)->cfg.vlen; \ uint32_t vta_all_1s = vext_vta_all_1s(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + if (vma) { \ + vext_set_elem_mask(vd, i, 1); \ + } \ continue; \ } \ vext_set_elem_mask(vd, i, \ From 72e17a9f86098feb25d2c1f2af043dc5f9f211e3 Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:51:11 +0000 Subject: [PATCH 0381/1020] target/riscv: rvv: Add mask agnostic for vector fix-point arithmetic instructions Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Acked-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-6@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/vector_helper.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 07ce671879..597fa9c752 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -2129,10 +2129,12 @@ static inline void vext_vv_rm_1(void *vd, void *v0, void *vs1, void *vs2, CPURISCVState *env, uint32_t vl, uint32_t vm, int vxrm, - opivv2_rm_fn *fn) + opivv2_rm_fn *fn, uint32_t vma, uint32_t esz) { for (uint32_t i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { + /* set masked-off elements to 1s */ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); continue; } fn(vd, vs1, vs2, i, env, vxrm); @@ -2150,23 +2152,24 @@ vext_vv_rm_2(void *vd, void *v0, void *vs1, void *vs2, uint32_t vl = env->vl; uint32_t total_elems = vext_get_total_elems(env, desc, esz); uint32_t vta = vext_vta(desc); + uint32_t vma = vext_vma(desc); switch (env->vxrm) { case 0: /* rnu */ vext_vv_rm_1(vd, v0, vs1, vs2, - env, vl, vm, 0, fn); + env, vl, vm, 0, fn, vma, esz); break; case 1: /* rne */ vext_vv_rm_1(vd, v0, vs1, vs2, - env, vl, vm, 1, fn); + env, vl, vm, 1, fn, vma, esz); break; case 2: /* rdn */ vext_vv_rm_1(vd, v0, vs1, vs2, - env, vl, vm, 2, fn); + env, vl, vm, 2, fn, vma, esz); break; default: /* rod */ vext_vv_rm_1(vd, v0, vs1, vs2, - env, vl, vm, 3, fn); + env, vl, vm, 3, fn, vma, esz); break; } /* set tail elements to 1s */ @@ -2250,10 +2253,12 @@ static inline void vext_vx_rm_1(void *vd, void *v0, target_long s1, void *vs2, CPURISCVState *env, uint32_t vl, uint32_t vm, int vxrm, - opivx2_rm_fn *fn) + opivx2_rm_fn *fn, uint32_t vma, uint32_t esz) { for (uint32_t i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { + /* set masked-off elements to 1s */ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); continue; } fn(vd, s1, vs2, i, env, vxrm); @@ -2271,23 +2276,24 @@ vext_vx_rm_2(void *vd, void *v0, target_long s1, void *vs2, uint32_t vl = env->vl; uint32_t total_elems = vext_get_total_elems(env, desc, esz); uint32_t vta = vext_vta(desc); + uint32_t vma = vext_vma(desc); switch (env->vxrm) { case 0: /* rnu */ vext_vx_rm_1(vd, v0, s1, vs2, - env, vl, vm, 0, fn); + env, vl, vm, 0, fn, vma, esz); break; case 1: /* rne */ vext_vx_rm_1(vd, v0, s1, vs2, - env, vl, vm, 1, fn); + env, vl, vm, 1, fn, vma, esz); break; case 2: /* rdn */ vext_vx_rm_1(vd, v0, s1, vs2, - env, vl, vm, 2, fn); + env, vl, vm, 2, fn, vma, esz); break; default: /* rod */ vext_vx_rm_1(vd, v0, s1, vs2, - env, vl, vm, 3, fn); + env, vl, vm, 3, fn, vma, esz); break; } /* set tail elements to 1s */ From 5b448f44c92f7355ae2b02af0699d22674cc5f6e Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:51:12 +0000 Subject: [PATCH 0382/1020] target/riscv: rvv: Add mask agnostic for vector floating-point instructions Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Acked-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-7@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 12 ++++++++++++ target/riscv/vector_helper.c | 26 +++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index e6aa5295a1..8ce3d28603 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -2361,6 +2361,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ data = \ FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ vreg_ofs(s, a->rs2), cpu_env, \ @@ -2446,6 +2447,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ data = FIELD_DP32(data, VDATA, VTA_ALL_1S, \ s->cfg_vta_all_1s); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ return opfvf_trans(a->rd, a->rs1, a->rs2, data, \ fns[s->sew - 1], s); \ } \ @@ -2485,6 +2487,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ vreg_ofs(s, a->rs2), cpu_env, \ @@ -2525,6 +2528,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ return opfvf_trans(a->rd, a->rs1, a->rs2, data, \ fns[s->sew - 1], s); \ } \ @@ -2562,6 +2566,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_4_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs1), \ vreg_ofs(s, a->rs2), cpu_env, \ @@ -2602,6 +2607,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmrr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ return opfvf_trans(a->rd, a->rs1, a->rs2, data, \ fns[s->sew - 1], s); \ } \ @@ -2686,6 +2692,7 @@ static bool do_opfv(DisasContext *s, arg_rmr *a, data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs2), cpu_env, s->cfg_ptr->vlen / 8, @@ -2790,6 +2797,7 @@ static bool trans_vfmv_v_f(DisasContext *s, arg_vfmv_v_f *a) TCGv_i32 desc; uint32_t data = FIELD_DP32(0, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); static gen_helper_vmv_vx * const fns[3] = { gen_helper_vmv_v_x_h, gen_helper_vmv_v_x_w, @@ -2891,6 +2899,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs2), cpu_env, \ s->cfg_ptr->vlen / 8, \ @@ -2944,6 +2953,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs2), cpu_env, \ s->cfg_ptr->vlen / 8, \ @@ -3012,6 +3022,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs2), cpu_env, \ s->cfg_ptr->vlen / 8, \ @@ -3067,6 +3078,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, VM, a->vm); \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = FIELD_DP32(data, VDATA, VTA, s->vta); \ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), \ vreg_ofs(s, a->rs2), cpu_env, \ s->cfg_ptr->vlen / 8, \ diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 597fa9c752..315742c6b8 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -3051,10 +3051,14 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ uint32_t total_elems = \ vext_get_total_elems(env, desc, ESZ); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * ESZ, \ + (i + 1) * ESZ); \ continue; \ } \ do_##NAME(vd, vs1, vs2, i, env); \ @@ -3090,10 +3094,14 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, \ uint32_t total_elems = \ vext_get_total_elems(env, desc, ESZ); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * ESZ, \ + (i + 1) * ESZ); \ continue; \ } \ do_##NAME(vd, s1, vs2, i, env); \ @@ -3665,6 +3673,7 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, \ uint32_t total_elems = \ vext_get_total_elems(env, desc, ESZ); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ if (vl == 0) { \ @@ -3672,6 +3681,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, \ } \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * ESZ, \ + (i + 1) * ESZ); \ continue; \ } \ do_##NAME(vd, vs2, i, env); \ @@ -4182,12 +4194,17 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t vl = env->vl; \ uint32_t total_elems = env_archcpu(env)->cfg.vlen; \ uint32_t vta_all_1s = vext_vta_all_1s(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s1 = *((ETYPE *)vs1 + H(i)); \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + if (vma) { \ + vext_set_elem_mask(vd, i, 1); \ + } \ continue; \ } \ vext_set_elem_mask(vd, i, \ @@ -4215,11 +4232,16 @@ void HELPER(NAME)(void *vd, void *v0, uint64_t s1, void *vs2, \ uint32_t vl = env->vl; \ uint32_t total_elems = env_archcpu(env)->cfg.vlen; \ uint32_t vta_all_1s = vext_vta_all_1s(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ ETYPE s2 = *((ETYPE *)vs2 + H(i)); \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + if (vma) { \ + vext_set_elem_mask(vd, i, 1); \ + } \ continue; \ } \ vext_set_elem_mask(vd, i, \ @@ -4342,10 +4364,14 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, \ uint32_t total_elems = \ vext_get_total_elems(env, desc, ESZ); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * ESZ, \ + (i + 1) * ESZ); \ continue; \ } \ do_##NAME(vd, vs2, i); \ From 35f2d795f313c43af5851ca2243317c0b0834c6c Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:51:11 +0000 Subject: [PATCH 0383/1020] target/riscv: rvv: Add mask agnostic for vector mask instructions Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Acked-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-8@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 3 +++ target/riscv/vector_helper.c | 11 +++++++++++ 2 files changed, 14 insertions(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 8ce3d28603..c1bd29329e 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -3275,6 +3275,7 @@ static bool trans_##NAME(DisasContext *s, arg_rmr *a) \ data = FIELD_DP32(data, VDATA, LMUL, s->lmul); \ data = \ FIELD_DP32(data, VDATA, VTA_ALL_1S, s->cfg_vta_all_1s);\ + data = FIELD_DP32(data, VDATA, VMA, s->vma); \ tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), \ vreg_ofs(s, 0), vreg_ofs(s, a->rs2), \ cpu_env, s->cfg_ptr->vlen / 8, \ @@ -3313,6 +3314,7 @@ static bool trans_viota_m(DisasContext *s, arg_viota_m *a) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); static gen_helper_gvec_3_ptr * const fns[4] = { gen_helper_viota_m_b, gen_helper_viota_m_h, gen_helper_viota_m_w, gen_helper_viota_m_d, @@ -3343,6 +3345,7 @@ static bool trans_vid_v(DisasContext *s, arg_vid_v *a) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); static gen_helper_gvec_2_ptr * const fns[4] = { gen_helper_vid_v_b, gen_helper_vid_v_h, gen_helper_vid_v_w, gen_helper_vid_v_d, diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 315742c6b8..52518648bb 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -4879,11 +4879,16 @@ static void vmsetm(void *vd, void *v0, void *vs2, CPURISCVState *env, uint32_t vl = env->vl; uint32_t total_elems = env_archcpu(env)->cfg.vlen; uint32_t vta_all_1s = vext_vta_all_1s(desc); + uint32_t vma = vext_vma(desc); int i; bool first_mask_bit = false; for (i = env->vstart; i < vl; i++) { if (!vm && !vext_elem_mask(v0, i)) { + /* set masked-off elements to 1s */ + if (vma) { + vext_set_elem_mask(vd, i, 1); + } continue; } /* write a zero to all following active elements */ @@ -4944,11 +4949,14 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, CPURISCVState *env, \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t sum = 0; \ int i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ *((ETYPE *)vd + H(i)) = sum; \ @@ -4975,10 +4983,13 @@ void HELPER(NAME)(void *vd, void *v0, CPURISCVState *env, uint32_t desc) \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ int i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ *((ETYPE *)vd + H(i)) = i; \ From edabcd0e0aea2ac8d68931f31fcf8d3b99a28f20 Mon Sep 17 00:00:00 2001 From: "Yueh-Ting (eop) Chen" Date: Mon, 20 Jun 2022 06:51:12 +0000 Subject: [PATCH 0384/1020] target/riscv: rvv: Add mask agnostic for vector permutation instructions Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Acked-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-9@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvv.c.inc | 1 + target/riscv/vector_helper.c | 26 +++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index c1bd29329e..e58208f363 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -3891,6 +3891,7 @@ static bool int_ext_op(DisasContext *s, arg_rmr *a, uint8_t seq) data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, s->lmul); data = FIELD_DP32(data, VDATA, VTA, s->vta); + data = FIELD_DP32(data, VDATA, VMA, s->vma); tcg_gen_gvec_3_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, 0), vreg_ofs(s, a->rs2), cpu_env, diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 52518648bb..d224861c2c 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -5018,11 +5018,14 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ target_ulong offset = s1, i_min, i; \ \ i_min = MAX(env->vstart, offset); \ for (i = i_min; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - offset)); \ @@ -5047,13 +5050,17 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ target_ulong i_max, i; \ \ i_max = MAX(MIN(s1 < vlmax ? vlmax - s1 : 0, vl), env->vstart); \ for (i = env->vstart; i < i_max; ++i) { \ - if (vm || vext_elem_mask(v0, i)) { \ - *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i + s1)); \ + if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ + continue; \ } \ + *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i + s1)); \ } \ \ for (i = i_max; i < vl; ++i) { \ @@ -5083,10 +5090,13 @@ static void vslide1up_##BITWIDTH(void *vd, void *v0, target_ulong s1, \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ if (i == 0) { \ @@ -5128,10 +5138,13 @@ static void vslide1down_##BITWIDTH(void *vd, void *v0, target_ulong s1, \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ if (i == vl - 1) { \ @@ -5199,11 +5212,14 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t esz = sizeof(TS2); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint64_t index; \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ index = *((TS1 *)vs1 + HS1(i)); \ @@ -5239,11 +5255,14 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint64_t index = s1; \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ if (index >= vlmax) { \ @@ -5318,10 +5337,13 @@ void HELPER(NAME)(void *vd, void *v0, void *vs2, \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ uint32_t vta = vext_vta(desc); \ + uint32_t vma = vext_vma(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ if (!vm && !vext_elem_mask(v0, i)) { \ + /* set masked-off elements to 1s */ \ + vext_set_elems_1s(vd, vma, i * esz, (i + 1) * esz); \ continue; \ } \ *((ETYPE *)vd + HD(i)) = *((DTYPE *)vs2 + HS1(i)); \ From 1ad3f9bdc76c83b23d689a111d5a160c528ac8ba Mon Sep 17 00:00:00 2001 From: eopXD Date: Mon, 20 Jun 2022 06:51:11 +0000 Subject: [PATCH 0385/1020] target/riscv: rvv: Add option 'rvv_ma_all_1s' to enable optional mask agnostic behavior According to v-spec, mask agnostic behavior can be either kept as undisturbed or set elements' bits to all 1s. To distinguish the difference of mask policies, QEMU should be able to simulate the mask agnostic behavior as "set mask elements' bits to all 1s". There are multiple possibility for agnostic elements according to v-spec. The main intent of this patch-set tries to add option that can distinguish between mask policies. Setting agnostic elements to all 1s allows QEMU to express this. This commit adds option 'rvv_ma_all_1s' is added to enable the behavior, it is default as disabled. Signed-off-by: eop Chen Reviewed-by: Frank Chang Reviewed-by: Weiwei Li Reviewed-by: Alistair Francis Message-Id: <165570784143.17634.35095816584573691-10@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 117d308ae5..966e5f2dd7 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1061,6 +1061,7 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false), DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false), + DEFINE_PROP_BOOL("rvv_ma_all_1s", RISCVCPU, cfg.rvv_ma_all_1s, false), DEFINE_PROP_END_OF_LIST(), }; From 4696f0ab5c436ed53567ce6baec67c921d9b70ae Mon Sep 17 00:00:00 2001 From: Dao Lu Date: Sun, 24 Jul 2022 20:47:28 -0700 Subject: [PATCH 0386/1020] target/riscv: Add Zihintpause support Added support for RISC-V PAUSE instruction from Zihintpause extension, enabled by default. Tested-by: Heiko Stuebner Reviewed-by: Alistair Francis Signed-off-by: Dao Lu Message-Id: <20220725034728.2620750-2-daolu@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 2 ++ target/riscv/cpu.h | 1 + target/riscv/insn32.decode | 7 ++++++- target/riscv/insn_trans/trans_rvi.c.inc | 16 ++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 966e5f2dd7..d4635c7df4 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -73,6 +73,7 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v), ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr), ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei), + ISA_EXT_DATA_ENTRY(zihintpause, true, PRIV_VERSION_1_10_0, ext_zihintpause), ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh), ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin), ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx), @@ -987,6 +988,7 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), + DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, 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), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 561d7fa92c..4be4b82a83 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -426,6 +426,7 @@ struct RISCVCPUConfig { bool ext_zkt; bool ext_ifencei; bool ext_icsr; + bool ext_zihintpause; bool ext_svinval; bool ext_svnapot; bool ext_svpbmt; diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 4033565393..595fdcdad8 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -149,7 +149,12 @@ srl 0000000 ..... ..... 101 ..... 0110011 @r sra 0100000 ..... ..... 101 ..... 0110011 @r or 0000000 ..... ..... 110 ..... 0110011 @r and 0000000 ..... ..... 111 ..... 0110011 @r -fence ---- pred:4 succ:4 ----- 000 ----- 0001111 + +{ + pause 0000 0001 0000 00000 000 00000 0001111 + fence ---- pred:4 succ:4 ----- 000 ----- 0001111 +} + fence_i ---- ---- ---- ----- 001 ----- 0001111 csrrw ............ ..... 001 ..... 1110011 @csr csrrs ............ ..... 010 ..... 1110011 @csr diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index ca8e3d1ea1..c49dbec0eb 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -792,6 +792,22 @@ static bool trans_srad(DisasContext *ctx, arg_srad *a) return gen_shift(ctx, a, EXT_SIGN, tcg_gen_sar_tl, NULL); } +static bool trans_pause(DisasContext *ctx, arg_pause *a) +{ + if (!ctx->cfg_ptr->ext_zihintpause) { + return false; + } + + /* + * PAUSE is a no-op in QEMU, + * end the TB and return to main loop + */ + gen_set_pc_imm(ctx, ctx->pc_succ_insn); + tcg_gen_exit_tb(NULL, 0); + ctx->base.is_jmp = DISAS_NORETURN; + + return true; +} static bool trans_fence(DisasContext *ctx, arg_fence *a) { From 6934f15b225c9324eafa064d3520a698ed09f9df Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Thu, 28 Jul 2022 15:19:26 -0300 Subject: [PATCH 0387/1020] hw/riscv: remove 'fdt' param from riscv_setup_rom_reset_vec() The 'fdt' param is not being used in riscv_setup_rom_reset_vec(). Simplify the API by removing it. While we're at it, remove the redundant 'return' statement at the end of function. Cc: Palmer Dabbelt Cc: Alistair Francis Cc: Bin Meng Cc: Vijai Kumar K Signed-off-by: Daniel Henrique Barboza Reviewed-by: Bin Meng Reviewed-by: Alistair Francis Message-Id: <20220728181926.2123771-1-danielhb413@gmail.com> Signed-off-by: Alistair Francis --- hw/riscv/boot.c | 4 +--- hw/riscv/microchip_pfsoc.c | 2 +- hw/riscv/shakti_c.c | 3 +-- hw/riscv/spike.c | 2 +- hw/riscv/virt.c | 2 +- include/hw/riscv/boot.h | 2 +- 6 files changed, 6 insertions(+), 9 deletions(-) diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 06b4fc5ac3..1ae7596873 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -286,7 +286,7 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts hwaddr start_addr, hwaddr rom_base, hwaddr rom_size, uint64_t kernel_entry, - uint64_t fdt_load_addr, void *fdt) + uint64_t fdt_load_addr) { int i; uint32_t start_addr_hi32 = 0x00000000; @@ -326,8 +326,6 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts rom_base, &address_space_memory); riscv_rom_copy_firmware_info(machine, rom_base, rom_size, sizeof(reset_vec), kernel_entry); - - return; } void riscv_setup_direct_kernel(hwaddr kernel_addr, hwaddr fdt_addr) diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index 10a5d0e501..7313153606 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -583,7 +583,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine) riscv_setup_rom_reset_vec(machine, &s->soc.u_cpus, firmware_load_addr, memmap[MICROCHIP_PFSOC_ENVM_DATA].base, memmap[MICROCHIP_PFSOC_ENVM_DATA].size, - kernel_entry, fdt_load_addr, machine->fdt); + kernel_entry, fdt_load_addr); } } diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c index 90e2cf609f..e43cc9445c 100644 --- a/hw/riscv/shakti_c.c +++ b/hw/riscv/shakti_c.c @@ -66,8 +66,7 @@ static void shakti_c_machine_state_init(MachineState *mstate) riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus, shakti_c_memmap[SHAKTI_C_RAM].base, shakti_c_memmap[SHAKTI_C_ROM].base, - shakti_c_memmap[SHAKTI_C_ROM].size, 0, 0, - NULL); + shakti_c_memmap[SHAKTI_C_ROM].size, 0, 0); if (mstate->firmware) { riscv_load_firmware(mstate->firmware, shakti_c_memmap[SHAKTI_C_RAM].base, diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index e41b6aa9f0..5ba34543c8 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -308,7 +308,7 @@ static void spike_board_init(MachineState *machine) riscv_setup_rom_reset_vec(machine, &s->soc[0], memmap[SPIKE_DRAM].base, memmap[SPIKE_MROM].base, memmap[SPIKE_MROM].size, kernel_entry, - fdt_load_addr, s->fdt); + fdt_load_addr); /* initialize HTIF using symbols found in load_kernel */ htif_mm_init(system_memory, mask_rom, diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index f2ce5663a4..c1e8e0fcaf 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -1305,7 +1305,7 @@ static void virt_machine_done(Notifier *notifier, void *data) riscv_setup_rom_reset_vec(machine, &s->soc[0], start_addr, virt_memmap[VIRT_MROM].base, virt_memmap[VIRT_MROM].size, kernel_entry, - fdt_load_addr, machine->fdt); + fdt_load_addr); /* * Only direct boot kernel is currently supported for KVM VM, diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h index d2db29721a..a36f7618f5 100644 --- a/include/hw/riscv/boot.h +++ b/include/hw/riscv/boot.h @@ -51,7 +51,7 @@ void riscv_setup_rom_reset_vec(MachineState *machine, RISCVHartArrayState *harts hwaddr saddr, hwaddr rom_base, hwaddr rom_size, uint64_t kernel_entry, - uint64_t fdt_load_addr, void *fdt); + uint64_t fdt_load_addr); void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base, hwaddr rom_size, uint32_t reset_vec_size, From eacaf440195675bc528f4aac394da7a74a9d95eb Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Wed, 3 Aug 2022 20:36:52 +0800 Subject: [PATCH 0388/1020] target/riscv: Fix priority of csr related check in riscv_csrrw_check Normally, riscv_csrrw_check is called when executing Zicsr instructions. And we can only do access control for existed CSRs. So the priority of CSR related check, from highest to lowest, should be as follows: 1) check whether Zicsr is supported: raise RISCV_EXCP_ILLEGAL_INST if not 2) check whether csr is existed: raise RISCV_EXCP_ILLEGAL_INST if not 3) do access control: raise RISCV_EXCP_ILLEGAL_INST or RISCV_EXCP_VIRT_ INSTRUCTION_FAULT if not allowed The predicates contain parts of function of both 2) and 3), So they need to be placed in the middle of riscv_csrrw_check Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Alistair Francis Message-Id: <20220803123652.3700-1-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 0fb042b2fd..d81f466c80 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3270,6 +3270,30 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */ int read_only = get_field(csrno, 0xC00) == 3; int csr_min_priv = csr_ops[csrno].min_priv_ver; + + /* ensure the CSR extension is enabled. */ + if (!cpu->cfg.ext_icsr) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if (env->priv_ver < csr_min_priv) { + return RISCV_EXCP_ILLEGAL_INST; + } + + /* check predicate */ + if (!csr_ops[csrno].predicate) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if (write_mask && read_only) { + return RISCV_EXCP_ILLEGAL_INST; + } + + RISCVException ret = csr_ops[csrno].predicate(env, csrno); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + #if !defined(CONFIG_USER_ONLY) int csr_priv, effective_priv = env->priv; @@ -3290,25 +3314,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, return RISCV_EXCP_ILLEGAL_INST; } #endif - if (write_mask && read_only) { - return RISCV_EXCP_ILLEGAL_INST; - } - - /* ensure the CSR extension is enabled. */ - if (!cpu->cfg.ext_icsr) { - return RISCV_EXCP_ILLEGAL_INST; - } - - /* check predicate */ - if (!csr_ops[csrno].predicate) { - return RISCV_EXCP_ILLEGAL_INST; - } - - if (env->priv_ver < csr_min_priv) { - return RISCV_EXCP_ILLEGAL_INST; - } - - return csr_ops[csrno].predicate(env, csrno); + return RISCV_EXCP_NONE; } static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno, From bf8803c64d756128e4537e22fe86e3717a5274f1 Mon Sep 17 00:00:00 2001 From: Wilfred Mallawa Date: Fri, 12 Aug 2022 10:52:30 +1000 Subject: [PATCH 0389/1020] hw/riscv: opentitan: bump opentitan version The following patch updates opentitan to match the new configuration, as per, lowRISC/opentitan@217a0168ba118503c166a9587819e3811eeb0c0c Note: with this patch we now skip the usage of the opentitan `boot_rom`. The Opentitan boot rom contains hw verification for devies which we are currently not supporting in qemu. As of now, the `boot_rom` has no major significance, however, would be good to support in the future. Tested by running utests from the latest tock [1] (that supports this version of OT). [1] https://github.com/tock/tock/pull/3056 Signed-off-by: Wilfred Mallawa Reviewed-by: Alistair Francis Message-Id: <20220812005229.358850-1-wilfred.mallawa@opensource.wdc.com> Signed-off-by: Alistair Francis --- hw/riscv/opentitan.c | 12 ++++++++---- include/hw/riscv/opentitan.h | 11 ++++++----- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 4495a2c039..af13dbe3b1 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -29,9 +29,9 @@ #include "sysemu/sysemu.h" static const MemMapEntry ibex_memmap[] = { - [IBEX_DEV_ROM] = { 0x00008000, 16 * KiB }, - [IBEX_DEV_RAM] = { 0x10000000, 0x10000 }, - [IBEX_DEV_FLASH] = { 0x20000000, 0x80000 }, + [IBEX_DEV_ROM] = { 0x00008000, 0x8000 }, + [IBEX_DEV_RAM] = { 0x10000000, 0x20000 }, + [IBEX_DEV_FLASH] = { 0x20000000, 0x100000 }, [IBEX_DEV_UART] = { 0x40000000, 0x1000 }, [IBEX_DEV_GPIO] = { 0x40040000, 0x1000 }, [IBEX_DEV_SPI_DEVICE] = { 0x40050000, 0x1000 }, @@ -40,6 +40,7 @@ static const MemMapEntry ibex_memmap[] = { [IBEX_DEV_TIMER] = { 0x40100000, 0x1000 }, [IBEX_DEV_SENSOR_CTRL] = { 0x40110000, 0x1000 }, [IBEX_DEV_OTP_CTRL] = { 0x40130000, 0x4000 }, + [IBEX_DEV_LC_CTRL] = { 0x40140000, 0x1000 }, [IBEX_DEV_USBDEV] = { 0x40150000, 0x1000 }, [IBEX_DEV_SPI_HOST0] = { 0x40300000, 0x1000 }, [IBEX_DEV_SPI_HOST1] = { 0x40310000, 0x1000 }, @@ -141,7 +142,8 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) &error_abort); object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, &error_abort); - object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x8080, &error_abort); + object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x20000490, + &error_abort); sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); /* Boot ROM */ @@ -253,6 +255,8 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) memmap[IBEX_DEV_SENSOR_CTRL].base, memmap[IBEX_DEV_SENSOR_CTRL].size); create_unimplemented_device("riscv.lowrisc.ibex.otp_ctrl", memmap[IBEX_DEV_OTP_CTRL].base, memmap[IBEX_DEV_OTP_CTRL].size); + create_unimplemented_device("riscv.lowrisc.ibex.lc_ctrl", + memmap[IBEX_DEV_LC_CTRL].base, memmap[IBEX_DEV_LC_CTRL].size); create_unimplemented_device("riscv.lowrisc.ibex.pwrmgr", memmap[IBEX_DEV_PWRMGR].base, memmap[IBEX_DEV_PWRMGR].size); create_unimplemented_device("riscv.lowrisc.ibex.rstmgr", diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h index 68892cd8e5..26d960f288 100644 --- a/include/hw/riscv/opentitan.h +++ b/include/hw/riscv/opentitan.h @@ -74,6 +74,7 @@ enum { IBEX_DEV_TIMER, IBEX_DEV_SENSOR_CTRL, IBEX_DEV_OTP_CTRL, + IBEX_DEV_LC_CTRL, IBEX_DEV_PWRMGR, IBEX_DEV_RSTMGR, IBEX_DEV_CLKMGR, @@ -105,11 +106,11 @@ enum { IBEX_UART0_RX_BREAK_ERR_IRQ = 6, IBEX_UART0_RX_TIMEOUT_IRQ = 7, IBEX_UART0_RX_PARITY_ERR_IRQ = 8, - IBEX_TIMER_TIMEREXPIRED0_0 = 126, - IBEX_SPI_HOST0_ERR_IRQ = 150, - IBEX_SPI_HOST0_SPI_EVENT_IRQ = 151, - IBEX_SPI_HOST1_ERR_IRQ = 152, - IBEX_SPI_HOST1_SPI_EVENT_IRQ = 153, + IBEX_TIMER_TIMEREXPIRED0_0 = 127, + IBEX_SPI_HOST0_ERR_IRQ = 151, + IBEX_SPI_HOST0_SPI_EVENT_IRQ = 152, + IBEX_SPI_HOST1_ERR_IRQ = 153, + IBEX_SPI_HOST1_SPI_EVENT_IRQ = 154, }; #endif From 25da6e311336b431d8cf1eaa8fe8688b7ee710ed Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Sat, 13 Aug 2022 14:51:27 +0100 Subject: [PATCH 0390/1020] hw/riscv: microchip_pfsoc: fix kernel panics due to missing peripherals Booting using "Direct Kernel Boot" for PolarFire SoC & skipping u-boot entirely is probably not advisable, but it does at least show signs of life. Recent Linux kernel versions make use of peripherals that are missing definitions in QEMU and lead to kernel panics. These issues almost certain rear their head for other methods of booting, but I was unable to figure out a suitable HSS version that is recent enough to support these peripherals & works with QEMU. With these peripherals added, booting a kernel with the following hangs hangs waiting for the system controller's hwrng, but the kernel no longer panics. With the Linux driver for hwrng disabled, it boots to console. qemu-system-riscv64 -M microchip-icicle-kit \ -m 2G -smp 5 \ -kernel $(vmlinux_bin) \ -dtb $(dtb)\ -initrd $(initramfs) \ -display none -serial null \ -serial stdio More peripherals are added than strictly required to fix the panics in the hopes of avoiding a replication of this problem in the future. Some of the peripherals which are in the device tree for recent kernels are implemented in the FPGA fabric. The eMMC/SD mux, which exists as an unimplemented device is replaced by a wider entry. This updated entry covers both the mux & the remainder of the FPGA fabric connected to the MSS using Fabric Interrconnect (FIC) 3. Link: https://github.com/polarfire-soc/icicle-kit-reference-design#fabric-memory-map Link: https://ww1.microchip.com/downloads/aemDocuments/documents/FPGA/ProductDocuments/SupportingCollateral/V1_4_Register_Map.zip Signed-off-by: Conor Dooley Reviewed-by: Alistair Francis Message-Id: <20220813135127.2971754-1-mail@conchuod.ie> Signed-off-by: Alistair Francis --- hw/riscv/microchip_pfsoc.c | 67 +++++++++++++++++++++++++++--- include/hw/riscv/microchip_pfsoc.h | 14 ++++++- 2 files changed, 74 insertions(+), 7 deletions(-) diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index 7313153606..a821263d4f 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -100,8 +100,11 @@ static const MemMapEntry microchip_pfsoc_memmap[] = { [MICROCHIP_PFSOC_L2LIM] = { 0x8000000, 0x2000000 }, [MICROCHIP_PFSOC_PLIC] = { 0xc000000, 0x4000000 }, [MICROCHIP_PFSOC_MMUART0] = { 0x20000000, 0x1000 }, + [MICROCHIP_PFSOC_WDOG0] = { 0x20001000, 0x1000 }, [MICROCHIP_PFSOC_SYSREG] = { 0x20002000, 0x2000 }, + [MICROCHIP_PFSOC_AXISW] = { 0x20004000, 0x1000 }, [MICROCHIP_PFSOC_MPUCFG] = { 0x20005000, 0x1000 }, + [MICROCHIP_PFSOC_FMETER] = { 0x20006000, 0x1000 }, [MICROCHIP_PFSOC_DDR_SGMII_PHY] = { 0x20007000, 0x1000 }, [MICROCHIP_PFSOC_EMMC_SD] = { 0x20008000, 0x1000 }, [MICROCHIP_PFSOC_DDR_CFG] = { 0x20080000, 0x40000 }, @@ -109,19 +112,28 @@ static const MemMapEntry microchip_pfsoc_memmap[] = { [MICROCHIP_PFSOC_MMUART2] = { 0x20102000, 0x1000 }, [MICROCHIP_PFSOC_MMUART3] = { 0x20104000, 0x1000 }, [MICROCHIP_PFSOC_MMUART4] = { 0x20106000, 0x1000 }, + [MICROCHIP_PFSOC_WDOG1] = { 0x20101000, 0x1000 }, + [MICROCHIP_PFSOC_WDOG2] = { 0x20103000, 0x1000 }, + [MICROCHIP_PFSOC_WDOG3] = { 0x20105000, 0x1000 }, + [MICROCHIP_PFSOC_WDOG4] = { 0x20106000, 0x1000 }, [MICROCHIP_PFSOC_SPI0] = { 0x20108000, 0x1000 }, [MICROCHIP_PFSOC_SPI1] = { 0x20109000, 0x1000 }, + [MICROCHIP_PFSOC_I2C0] = { 0x2010a000, 0x1000 }, [MICROCHIP_PFSOC_I2C1] = { 0x2010b000, 0x1000 }, + [MICROCHIP_PFSOC_CAN0] = { 0x2010c000, 0x1000 }, + [MICROCHIP_PFSOC_CAN1] = { 0x2010d000, 0x1000 }, [MICROCHIP_PFSOC_GEM0] = { 0x20110000, 0x2000 }, [MICROCHIP_PFSOC_GEM1] = { 0x20112000, 0x2000 }, [MICROCHIP_PFSOC_GPIO0] = { 0x20120000, 0x1000 }, [MICROCHIP_PFSOC_GPIO1] = { 0x20121000, 0x1000 }, [MICROCHIP_PFSOC_GPIO2] = { 0x20122000, 0x1000 }, + [MICROCHIP_PFSOC_RTC] = { 0x20124000, 0x1000 }, [MICROCHIP_PFSOC_ENVM_CFG] = { 0x20200000, 0x1000 }, [MICROCHIP_PFSOC_ENVM_DATA] = { 0x20220000, 0x20000 }, + [MICROCHIP_PFSOC_USB] = { 0x20201000, 0x1000 }, [MICROCHIP_PFSOC_QSPI_XIP] = { 0x21000000, 0x1000000 }, [MICROCHIP_PFSOC_IOSCB] = { 0x30000000, 0x10000000 }, - [MICROCHIP_PFSOC_EMMC_SD_MUX] = { 0x4f000000, 0x4 }, + [MICROCHIP_PFSOC_FABRIC_FIC3] = { 0x40000000, 0x20000000 }, [MICROCHIP_PFSOC_DRAM_LO] = { 0x80000000, 0x40000000 }, [MICROCHIP_PFSOC_DRAM_LO_ALIAS] = { 0xc0000000, 0x40000000 }, [MICROCHIP_PFSOC_DRAM_HI] = { 0x1000000000, 0x0 }, @@ -292,11 +304,21 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->sysreg), 0, memmap[MICROCHIP_PFSOC_SYSREG].base); + /* AXISW */ + create_unimplemented_device("microchip.pfsoc.axisw", + memmap[MICROCHIP_PFSOC_AXISW].base, + memmap[MICROCHIP_PFSOC_AXISW].size); + /* MPUCFG */ create_unimplemented_device("microchip.pfsoc.mpucfg", memmap[MICROCHIP_PFSOC_MPUCFG].base, memmap[MICROCHIP_PFSOC_MPUCFG].size); + /* FMETER */ + create_unimplemented_device("microchip.pfsoc.fmeter", + memmap[MICROCHIP_PFSOC_FMETER].base, + memmap[MICROCHIP_PFSOC_FMETER].size); + /* DDR SGMII PHY */ sysbus_realize(SYS_BUS_DEVICE(&s->ddr_sgmii_phy), errp); sysbus_mmio_map(SYS_BUS_DEVICE(&s->ddr_sgmii_phy), 0, @@ -336,6 +358,23 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp) qdev_get_gpio_in(DEVICE(s->plic), MICROCHIP_PFSOC_MMUART4_IRQ), serial_hd(4)); + /* Watchdogs */ + create_unimplemented_device("microchip.pfsoc.watchdog0", + memmap[MICROCHIP_PFSOC_WDOG0].base, + memmap[MICROCHIP_PFSOC_WDOG0].size); + create_unimplemented_device("microchip.pfsoc.watchdog1", + memmap[MICROCHIP_PFSOC_WDOG1].base, + memmap[MICROCHIP_PFSOC_WDOG1].size); + create_unimplemented_device("microchip.pfsoc.watchdog2", + memmap[MICROCHIP_PFSOC_WDOG2].base, + memmap[MICROCHIP_PFSOC_WDOG2].size); + create_unimplemented_device("microchip.pfsoc.watchdog3", + memmap[MICROCHIP_PFSOC_WDOG3].base, + memmap[MICROCHIP_PFSOC_WDOG3].size); + create_unimplemented_device("microchip.pfsoc.watchdog4", + memmap[MICROCHIP_PFSOC_WDOG4].base, + memmap[MICROCHIP_PFSOC_WDOG4].size); + /* SPI */ create_unimplemented_device("microchip.pfsoc.spi0", memmap[MICROCHIP_PFSOC_SPI0].base, @@ -344,11 +383,27 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp) memmap[MICROCHIP_PFSOC_SPI1].base, memmap[MICROCHIP_PFSOC_SPI1].size); - /* I2C1 */ + /* I2C */ + create_unimplemented_device("microchip.pfsoc.i2c0", + memmap[MICROCHIP_PFSOC_I2C0].base, + memmap[MICROCHIP_PFSOC_I2C0].size); create_unimplemented_device("microchip.pfsoc.i2c1", memmap[MICROCHIP_PFSOC_I2C1].base, memmap[MICROCHIP_PFSOC_I2C1].size); + /* CAN */ + create_unimplemented_device("microchip.pfsoc.can0", + memmap[MICROCHIP_PFSOC_CAN0].base, + memmap[MICROCHIP_PFSOC_CAN0].size); + create_unimplemented_device("microchip.pfsoc.can1", + memmap[MICROCHIP_PFSOC_CAN1].base, + memmap[MICROCHIP_PFSOC_CAN1].size); + + /* USB */ + create_unimplemented_device("microchip.pfsoc.usb", + memmap[MICROCHIP_PFSOC_USB].base, + memmap[MICROCHIP_PFSOC_USB].size); + /* GEMs */ nd = &nd_table[0]; @@ -402,10 +457,10 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->ioscb), 0, memmap[MICROCHIP_PFSOC_IOSCB].base); - /* eMMC/SD mux */ - create_unimplemented_device("microchip.pfsoc.emmc_sd_mux", - memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].base, - memmap[MICROCHIP_PFSOC_EMMC_SD_MUX].size); + /* FPGA Fabric */ + create_unimplemented_device("microchip.pfsoc.fabricfic3", + memmap[MICROCHIP_PFSOC_FABRIC_FIC3].base, + memmap[MICROCHIP_PFSOC_FABRIC_FIC3].size); /* QSPI Flash */ memory_region_init_rom(qspi_xip_mem, OBJECT(dev), diff --git a/include/hw/riscv/microchip_pfsoc.h b/include/hw/riscv/microchip_pfsoc.h index a0673f5f59..a757b240e0 100644 --- a/include/hw/riscv/microchip_pfsoc.h +++ b/include/hw/riscv/microchip_pfsoc.h @@ -88,8 +88,11 @@ enum { MICROCHIP_PFSOC_L2LIM, MICROCHIP_PFSOC_PLIC, MICROCHIP_PFSOC_MMUART0, + MICROCHIP_PFSOC_WDOG0, MICROCHIP_PFSOC_SYSREG, + MICROCHIP_PFSOC_AXISW, MICROCHIP_PFSOC_MPUCFG, + MICROCHIP_PFSOC_FMETER, MICROCHIP_PFSOC_DDR_SGMII_PHY, MICROCHIP_PFSOC_EMMC_SD, MICROCHIP_PFSOC_DDR_CFG, @@ -97,19 +100,28 @@ enum { MICROCHIP_PFSOC_MMUART2, MICROCHIP_PFSOC_MMUART3, MICROCHIP_PFSOC_MMUART4, + MICROCHIP_PFSOC_WDOG1, + MICROCHIP_PFSOC_WDOG2, + MICROCHIP_PFSOC_WDOG3, + MICROCHIP_PFSOC_WDOG4, MICROCHIP_PFSOC_SPI0, MICROCHIP_PFSOC_SPI1, + MICROCHIP_PFSOC_I2C0, MICROCHIP_PFSOC_I2C1, + MICROCHIP_PFSOC_CAN0, + MICROCHIP_PFSOC_CAN1, MICROCHIP_PFSOC_GEM0, MICROCHIP_PFSOC_GEM1, MICROCHIP_PFSOC_GPIO0, MICROCHIP_PFSOC_GPIO1, MICROCHIP_PFSOC_GPIO2, + MICROCHIP_PFSOC_RTC, MICROCHIP_PFSOC_ENVM_CFG, MICROCHIP_PFSOC_ENVM_DATA, + MICROCHIP_PFSOC_USB, MICROCHIP_PFSOC_QSPI_XIP, MICROCHIP_PFSOC_IOSCB, - MICROCHIP_PFSOC_EMMC_SD_MUX, + MICROCHIP_PFSOC_FABRIC_FIC3, MICROCHIP_PFSOC_DRAM_LO, MICROCHIP_PFSOC_DRAM_LO_ALIAS, MICROCHIP_PFSOC_DRAM_HI, From 240b363618bdd981333e8ebbb1cb09e702315b0a Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Tue, 16 Aug 2022 16:23:21 -0700 Subject: [PATCH 0391/1020] target/riscv: Remove additional priv version check for mcountinhibit With .min_priv_version, additiona priv version check is uncessary for mcountinhibit read/write functions. Reviewed-by: Heiko Stuebner Tested-by: Heiko Stuebner Reviewed-by: Alistair Francis Signed-off-by: Atish Patra Message-Id: <20220816232321.558250-7-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index d81f466c80..4a7078f7d1 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1494,10 +1494,6 @@ static RISCVException write_mtvec(CPURISCVState *env, int csrno, static RISCVException read_mcountinhibit(CPURISCVState *env, int csrno, target_ulong *val) { - if (env->priv_ver < PRIV_VERSION_1_11_0) { - return RISCV_EXCP_ILLEGAL_INST; - } - *val = env->mcountinhibit; return RISCV_EXCP_NONE; } @@ -1508,10 +1504,6 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno, int cidx; PMUCTRState *counter; - if (env->priv_ver < PRIV_VERSION_1_11_0) { - return RISCV_EXCP_ILLEGAL_INST; - } - env->mcountinhibit = val; /* Check if any other counter is also monitoring cycles/instructions */ From 53c38f7ab1a5b55d63303d36a42c3e74b5fc9225 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 10 Aug 2022 19:46:09 +0100 Subject: [PATCH 0392/1020] hw/riscv: virt: fix uart node name "uart" is not a node name that complies with the dt-schema. Change the node name to "serial" to ix warnings seen during dt-validate on a dtbdump of the virt machine such as: /stuff/qemu/qemu.dtb: uart@10000000: $nodename:0: 'uart@10000000' does not match '^serial(@.*)?$' From schema: /stuff/linux/Documentation/devicetree/bindings/serial/8250.yaml Reported-by: Rob Herring Reviewed-by: Alistair Francis Signed-off-by: Conor Dooley Message-id: 20220810184612.157317-2-mail@conchuod.ie Link: https://lore.kernel.org/linux-riscv/20220803170552.GA2250266-robh@kernel.org/ Fixes: 04331d0b56 ("RISC-V VirtIO Machine") Signed-off-by: Conor Dooley Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index c1e8e0fcaf..9d36133b74 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -918,7 +918,7 @@ static void create_fdt_uart(RISCVVirtState *s, const MemMapEntry *memmap, char *name; MachineState *mc = MACHINE(s); - name = g_strdup_printf("/soc/uart@%lx", (long)memmap[VIRT_UART0].base); + name = g_strdup_printf("/soc/serial@%lx", (long)memmap[VIRT_UART0].base); qemu_fdt_add_subnode(mc->fdt, name); qemu_fdt_setprop_string(mc->fdt, name, "compatible", "ns16550a"); qemu_fdt_setprop_cells(mc->fdt, name, "reg", From 95e401d3785a9be9ac4edc7a5a7f9147d917e610 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 10 Aug 2022 19:46:10 +0100 Subject: [PATCH 0393/1020] hw/riscv: virt: fix the plic's address cells When optional AIA PLIC support was added the to the virt machine, the address cells property was removed leading the issues with dt-validate on a dump from the virt machine: /stuff/qemu/qemu.dtb: plic@c000000: '#address-cells' is a required property From schema: /stuff/linux/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml Add back the property to suppress the warning. Reported-by: Rob Herring Reviewed-by: Alistair Francis Signed-off-by: Conor Dooley Message-id: 20220810184612.157317-3-mail@conchuod.ie Link: https://lore.kernel.org/linux-riscv/20220803170552.GA2250266-robh@kernel.org/ Fixes: e6faee6585 ("hw/riscv: virt: Add optional AIA APLIC support to virt machine") Signed-off-by: Conor Dooley Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 2 ++ include/hw/riscv/virt.h | 1 + 2 files changed, 3 insertions(+) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 9d36133b74..f19758e1df 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -466,6 +466,8 @@ static void create_fdt_socket_plic(RISCVVirtState *s, qemu_fdt_add_subnode(mc->fdt, plic_name); qemu_fdt_setprop_cell(mc->fdt, plic_name, "#interrupt-cells", FDT_PLIC_INT_CELLS); + qemu_fdt_setprop_cell(mc->fdt, plic_name, + "#address-cells", FDT_PLIC_ADDR_CELLS); qemu_fdt_setprop_string_array(mc->fdt, plic_name, "compatible", (char **)&plic_compat, ARRAY_SIZE(plic_compat)); diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index 984e55c77f..be4ab8fe7f 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -111,6 +111,7 @@ enum { #define FDT_PCI_ADDR_CELLS 3 #define FDT_PCI_INT_CELLS 1 +#define FDT_PLIC_ADDR_CELLS 0 #define FDT_PLIC_INT_CELLS 1 #define FDT_APLIC_INT_CELLS 2 #define FDT_IMSIC_INT_CELLS 0 From ae29379998f101aedf32f9168135eb0545257b3c Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 10 Aug 2022 19:46:11 +0100 Subject: [PATCH 0394/1020] hw/riscv: virt: fix syscon subnode paths The reset and poweroff features of the syscon were originally added to top level, which is a valid path for a syscon subnode. Subsequently a reorganisation was carried out while implementing NUMA in which the subnodes were moved into the /soc node. As /soc is a "simple-bus", this path is invalid, and so dt-validate produces the following warnings: /stuff/qemu/qemu.dtb: soc: poweroff: {'value': [[21845]], 'offset': [[0]], 'regmap': [[4]], 'compatible': ['syscon-poweroff']} should not be valid under {'type': 'object'} From schema: /home/conor/.local/lib/python3.9/site-packages/dtschema/schemas/simple-bus.yaml /stuff/qemu/qemu.dtb: soc: reboot: {'value': [[30583]], 'offset': [[0]], 'regmap': [[4]], 'compatible': ['syscon-reboot']} should not be valid under {'type': 'object'} From schema: /home/conor/.local/lib/python3.9/site-packages/dtschema/schemas/simple-bus.yaml Move the syscon subnodes back to the top level and silence the warnings. Reported-by: Rob Herring Signed-off-by: Conor Dooley Reviewed-by: Alistair Francis Message-id: 20220810184612.157317-4-mail@conchuod.ie Link: https://lore.kernel.org/linux-riscv/20220803170552.GA2250266-robh@kernel.org/ Fixes: 18df0b4695 ("hw/riscv: virt: Allow creating multiple NUMA sockets") Signed-off-by: Conor Dooley Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index f19758e1df..686341a0e2 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -897,7 +897,7 @@ static void create_fdt_reset(RISCVVirtState *s, const MemMapEntry *memmap, test_phandle = qemu_fdt_get_phandle(mc->fdt, name); g_free(name); - name = g_strdup_printf("/soc/reboot"); + name = g_strdup_printf("/reboot"); qemu_fdt_add_subnode(mc->fdt, name); qemu_fdt_setprop_string(mc->fdt, name, "compatible", "syscon-reboot"); qemu_fdt_setprop_cell(mc->fdt, name, "regmap", test_phandle); @@ -905,7 +905,7 @@ static void create_fdt_reset(RISCVVirtState *s, const MemMapEntry *memmap, qemu_fdt_setprop_cell(mc->fdt, name, "value", FINISHER_RESET); g_free(name); - name = g_strdup_printf("/soc/poweroff"); + name = g_strdup_printf("/poweroff"); qemu_fdt_add_subnode(mc->fdt, name); qemu_fdt_setprop_string(mc->fdt, name, "compatible", "syscon-poweroff"); qemu_fdt_setprop_cell(mc->fdt, name, "regmap", test_phandle); From d1af78745cfc4e8efdda9b3484b32bbb4507276f Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 10 Aug 2022 19:46:12 +0100 Subject: [PATCH 0395/1020] hw/core: fix platform bus node name "platform" is not a valid name for a bus node in dt-schema, so warnings can be see in dt-validate on a dump of the riscv virt dtb: /stuff/qemu/qemu.dtb: platform@4000000: $nodename:0: 'platform@4000000' does not match '^([a-z][a-z0-9\\-]+-bus|bus|soc|axi|ahb|apb)(@[0-9a-f]+)?$' From schema: /home/conor/.local/lib/python3.9/site-packages/dtschema/schemas/simple-bus.yaml "platform-bus" is a valid name, so use that instead. CC: Rob Herring Fixes: 11d306b9df ("hw/arm/sysbus-fdt: helpers for platform bus nodes addition") Reviewed-by: Alistair Francis Signed-off-by: Conor Dooley Message-id: 20220810184612.157317-5-mail@conchuod.ie Signed-off-by: Alistair Francis --- hw/core/sysbus-fdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c index 19d22cbe73..edb0c49b19 100644 --- a/hw/core/sysbus-fdt.c +++ b/hw/core/sysbus-fdt.c @@ -539,7 +539,7 @@ void platform_bus_add_all_fdt_nodes(void *fdt, const char *intc, hwaddr addr, assert(fdt); - node = g_strdup_printf("/platform@%"PRIx64, addr); + node = g_strdup_printf("/platform-bus@%"PRIx64, addr); /* Create a /platform node that we can put all devices into */ qemu_fdt_add_subnode(fdt, node); From e0dea2f55f678a1aa1dab3a25c13f52d68b4ec2b Mon Sep 17 00:00:00 2001 From: Rahul Pathak Date: Tue, 16 Aug 2022 10:24:08 +0530 Subject: [PATCH 0396/1020] target/riscv: Add xicondops in ISA entry XVentanaCondOps is Ventana custom extension. Add its extension entry in the ISA Ext array Signed-off-by: Rahul Pathak Reviewed-by: Alistair Francis Message-id: 20220816045408.1231135-1-rpathak@ventanamicro.com Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d4635c7df4..e0d5941230 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -102,6 +102,7 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval), ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot), ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt), + ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps), }; static bool isa_ext_is_enabled(RISCVCPU *cpu, From dc9acc9ce4add37bc5b4437ae9117c318b4f09d4 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Sat, 20 Aug 2022 09:59:58 +0530 Subject: [PATCH 0397/1020] target/riscv: Use official extension names for AIA CSRs The arch review of AIA spec is completed and we now have official extension names for AIA: Smaia (M-mode AIA CSRs) and Ssaia (S-mode AIA CSRs). Refer, section 1.6 of the latest AIA v0.3.1 stable specification at https://github.com/riscv/riscv-aia/releases/download/0.3.1-draft.32/riscv-interrupts-032.pdf) Based on above, we update QEMU RISC-V to: 1) Have separate config options for Smaia and Ssaia extensions which replace RISCV_FEATURE_AIA in CPU features 2) Not generate AIA INTC compatible string in virt machine Signed-off-by: Anup Patel Reviewed-by: Andrew Jones Reviewed-by: Alistair Francis Message-id: 20220820042958.377018-1-apatel@ventanamicro.com Signed-off-by: Alistair Francis --- hw/intc/riscv_imsic.c | 4 +++- hw/riscv/virt.c | 13 ++----------- target/riscv/cpu.c | 9 ++++----- target/riscv/cpu.h | 4 ++-- target/riscv/cpu_helper.c | 3 ++- target/riscv/csr.c | 24 ++++++++++++++++++------ 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c index 8615e4cc1d..4d4d5b50ca 100644 --- a/hw/intc/riscv_imsic.c +++ b/hw/intc/riscv_imsic.c @@ -344,9 +344,11 @@ static void riscv_imsic_realize(DeviceState *dev, Error **errp) /* Force select AIA feature and setup CSR read-modify-write callback */ if (env) { - riscv_set_feature(env, RISCV_FEATURE_AIA); if (!imsic->mmode) { + rcpu->cfg.ext_ssaia = true; riscv_cpu_set_geilen(env, imsic->num_pages - 1); + } else { + rcpu->cfg.ext_smaia = true; } riscv_cpu_set_aia_ireg_rmw_fn(env, (imsic->mmode) ? PRV_M : PRV_S, riscv_imsic_rmw, imsic); diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 686341a0e2..ff8c0df5cd 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -260,17 +260,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket, qemu_fdt_add_subnode(mc->fdt, intc_name); qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle", intc_phandles[cpu]); - if (riscv_feature(&s->soc[socket].harts[cpu].env, - RISCV_FEATURE_AIA)) { - static const char * const compat[2] = { - "riscv,cpu-intc-aia", "riscv,cpu-intc" - }; - qemu_fdt_setprop_string_array(mc->fdt, intc_name, "compatible", - (char **)&compat, ARRAY_SIZE(compat)); - } else { - qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible", - "riscv,cpu-intc"); - } + qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible", + "riscv,cpu-intc"); qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0); qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index e0d5941230..26d44df446 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -99,6 +99,8 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f), ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx), ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin), + ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia), + ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia), ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval), ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot), ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt), @@ -666,10 +668,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) } } - if (cpu->cfg.aia) { - riscv_set_feature(env, RISCV_FEATURE_AIA); - } - if (cpu->cfg.debug) { riscv_set_feature(env, RISCV_FEATURE_DEBUG); } @@ -1038,7 +1036,8 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false), /* ePMP 0.9.3 */ DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false), - DEFINE_PROP_BOOL("x-aia", RISCVCPU, cfg.aia, false), + DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false), + DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 4be4b82a83..081cd05544 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -85,7 +85,6 @@ enum { RISCV_FEATURE_PMP, RISCV_FEATURE_EPMP, RISCV_FEATURE_MISA, - RISCV_FEATURE_AIA, RISCV_FEATURE_DEBUG }; @@ -439,6 +438,8 @@ struct RISCVCPUConfig { bool ext_zve32f; bool ext_zve64f; bool ext_zmmul; + bool ext_smaia; + bool ext_ssaia; bool rvv_ta_all_1s; bool rvv_ma_all_1s; @@ -459,7 +460,6 @@ struct RISCVCPUConfig { bool mmu; bool pmp; bool epmp; - bool aia; bool debug; uint64_t resetvec; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 650574accf..05c0c8d777 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -307,6 +307,7 @@ static int riscv_cpu_pending_to_irq(CPURISCVState *env, int extirq, unsigned int extirq_def_prio, uint64_t pending, uint8_t *iprio) { + RISCVCPU *cpu = env_archcpu(env); int irq, best_irq = RISCV_EXCP_NONE; unsigned int prio, best_prio = UINT_MAX; @@ -315,7 +316,7 @@ static int riscv_cpu_pending_to_irq(CPURISCVState *env, } irq = ctz64(pending); - if (!riscv_feature(env, RISCV_FEATURE_AIA)) { + if (!((extirq == IRQ_M_EXT) ? cpu->cfg.ext_smaia : cpu->cfg.ext_ssaia)) { return irq; } diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 4a7078f7d1..3ddf309055 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -257,7 +257,9 @@ static RISCVException any32(CPURISCVState *env, int csrno) static int aia_any(CPURISCVState *env, int csrno) { - if (!riscv_feature(env, RISCV_FEATURE_AIA)) { + RISCVCPU *cpu = env_archcpu(env); + + if (!cpu->cfg.ext_smaia) { return RISCV_EXCP_ILLEGAL_INST; } @@ -266,7 +268,9 @@ static int aia_any(CPURISCVState *env, int csrno) static int aia_any32(CPURISCVState *env, int csrno) { - if (!riscv_feature(env, RISCV_FEATURE_AIA)) { + RISCVCPU *cpu = env_archcpu(env); + + if (!cpu->cfg.ext_smaia) { return RISCV_EXCP_ILLEGAL_INST; } @@ -293,7 +297,9 @@ static int smode32(CPURISCVState *env, int csrno) static int aia_smode(CPURISCVState *env, int csrno) { - if (!riscv_feature(env, RISCV_FEATURE_AIA)) { + RISCVCPU *cpu = env_archcpu(env); + + if (!cpu->cfg.ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; } @@ -302,7 +308,9 @@ static int aia_smode(CPURISCVState *env, int csrno) static int aia_smode32(CPURISCVState *env, int csrno) { - if (!riscv_feature(env, RISCV_FEATURE_AIA)) { + RISCVCPU *cpu = env_archcpu(env); + + if (!cpu->cfg.ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; } @@ -358,7 +366,9 @@ static RISCVException pointer_masking(CPURISCVState *env, int csrno) static int aia_hmode(CPURISCVState *env, int csrno) { - if (!riscv_feature(env, RISCV_FEATURE_AIA)) { + RISCVCPU *cpu = env_archcpu(env); + + if (!cpu->cfg.ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; } @@ -367,7 +377,9 @@ static int aia_hmode(CPURISCVState *env, int csrno) static int aia_hmode32(CPURISCVState *env, int csrno) { - if (!riscv_feature(env, RISCV_FEATURE_AIA)) { + RISCVCPU *cpu = env_archcpu(env); + + if (!cpu->cfg.ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; } From 7cbcc538f4b3040db1e39a6547efa501a8a44907 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:13:55 -0700 Subject: [PATCH 0398/1020] hw/intc: Move mtimer/mtimecmp to aclint Historically, The mtime/mtimecmp has been part of the CPU because they are per hart entities. However, they actually belong to aclint which is a MMIO device. Move them to the ACLINT device. This also emulates the real hardware more closely. Reviewed-by: Anup Patel Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Signed-off-by: Atish Patra Message-Id: <20220824221357.41070-2-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- hw/intc/riscv_aclint.c | 48 ++++++++++++++++++++++++---------- hw/timer/ibex_timer.c | 18 +++++-------- include/hw/intc/riscv_aclint.h | 2 ++ include/hw/timer/ibex_timer.h | 2 ++ target/riscv/cpu.h | 2 -- target/riscv/machine.c | 5 ++-- 6 files changed, 47 insertions(+), 30 deletions(-) diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index e7942c4e5a..eee04643cb 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -32,6 +32,7 @@ #include "hw/intc/riscv_aclint.h" #include "qemu/timer.h" #include "hw/irq.h" +#include "migration/vmstate.h" typedef struct riscv_aclint_mtimer_callback { RISCVAclintMTimerState *s; @@ -65,19 +66,22 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer, uint64_t rtc_r = cpu_riscv_read_rtc(mtimer); - cpu->env.timecmp = value; - if (cpu->env.timecmp <= rtc_r) { + /* Compute the relative hartid w.r.t the socket */ + hartid = hartid - mtimer->hartid_base; + + mtimer->timecmp[hartid] = value; + if (mtimer->timecmp[hartid] <= rtc_r) { /* * If we're setting an MTIMECMP value in the "past", * immediately raise the timer interrupt */ - qemu_irq_raise(mtimer->timer_irqs[hartid - mtimer->hartid_base]); + qemu_irq_raise(mtimer->timer_irqs[hartid]); return; } /* otherwise, set up the future timer interrupt */ - qemu_irq_lower(mtimer->timer_irqs[hartid - mtimer->hartid_base]); - diff = cpu->env.timecmp - rtc_r; + qemu_irq_lower(mtimer->timer_irqs[hartid]); + diff = mtimer->timecmp[hartid] - rtc_r; /* back to ns (note args switched in muldiv64) */ uint64_t ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); @@ -102,7 +106,7 @@ static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer, next = MIN(next, INT64_MAX); } - timer_mod(cpu->env.timer, next); + timer_mod(mtimer->timers[hartid], next); } /* @@ -133,11 +137,11 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, hwaddr addr, "aclint-mtimer: invalid hartid: %zu", hartid); } else if ((addr & 0x7) == 0) { /* timecmp_lo for RV32/RV64 or timecmp for RV64 */ - uint64_t timecmp = env->timecmp; + uint64_t timecmp = mtimer->timecmp[hartid]; return (size == 4) ? (timecmp & 0xFFFFFFFF) : timecmp; } else if ((addr & 0x7) == 4) { /* timecmp_hi */ - uint64_t timecmp = env->timecmp; + uint64_t timecmp = mtimer->timecmp[hartid]; return (timecmp >> 32) & 0xFFFFFFFF; } else { qemu_log_mask(LOG_UNIMP, @@ -177,7 +181,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, } else if ((addr & 0x7) == 0) { if (size == 4) { /* timecmp_lo for RV32/RV64 */ - uint64_t timecmp_hi = env->timecmp >> 32; + uint64_t timecmp_hi = mtimer->timecmp[hartid] >> 32; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid, timecmp_hi << 32 | (value & 0xFFFFFFFF)); } else { @@ -188,7 +192,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, } else if ((addr & 0x7) == 4) { if (size == 4) { /* timecmp_hi for RV32/RV64 */ - uint64_t timecmp_lo = env->timecmp; + uint64_t timecmp_lo = mtimer->timecmp[hartid]; riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid, value << 32 | (timecmp_lo & 0xFFFFFFFF)); } else { @@ -234,7 +238,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr addr, } riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), mtimer->hartid_base + i, - env->timecmp); + mtimer->timecmp[i]); } return; } @@ -284,6 +288,8 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp) s->timer_irqs = g_new(qemu_irq, s->num_harts); qdev_init_gpio_out(dev, s->timer_irqs, s->num_harts); + s->timers = g_new0(QEMUTimer *, s->num_harts); + s->timecmp = g_new0(uint64_t, s->num_harts); /* Claim timer interrupt bits */ for (i = 0; i < s->num_harts; i++) { RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i)); @@ -310,6 +316,18 @@ static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type) riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8); } +static const VMStateDescription vmstate_riscv_mtimer = { + .name = "riscv_mtimer", + .version_id = 1, + .minimum_version_id = 1, + .fields = (VMStateField[]) { + VMSTATE_VARRAY_UINT32(timecmp, RISCVAclintMTimerState, + num_harts, 0, + vmstate_info_uint64, uint64_t), + VMSTATE_END_OF_LIST() + } +}; + static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -317,6 +335,7 @@ static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, riscv_aclint_mtimer_properties); ResettableClass *rc = RESETTABLE_CLASS(klass); rc->phases.enter = riscv_aclint_mtimer_reset_enter; + dc->vmsd = &vmstate_riscv_mtimer; } static const TypeInfo riscv_aclint_mtimer_info = { @@ -336,6 +355,7 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size, { int i; DeviceState *dev = qdev_new(TYPE_RISCV_ACLINT_MTIMER); + RISCVAclintMTimerState *s = RISCV_ACLINT_MTIMER(dev); assert(num_harts <= RISCV_ACLINT_MAX_HARTS); assert(!(addr & 0x7)); @@ -366,11 +386,11 @@ DeviceState *riscv_aclint_mtimer_create(hwaddr addr, hwaddr size, riscv_cpu_set_rdtime_fn(env, cpu_riscv_read_rtc, dev); } - cb->s = RISCV_ACLINT_MTIMER(dev); + cb->s = s; cb->num = i; - env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + s->timers[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_aclint_mtimer_cb, cb); - env->timecmp = 0; + s->timecmp[i] = 0; qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(DEVICE(rvcpu), IRQ_M_TIMER)); diff --git a/hw/timer/ibex_timer.c b/hw/timer/ibex_timer.c index 8c2ca364da..d8b8e4e1f6 100644 --- a/hw/timer/ibex_timer.c +++ b/hw/timer/ibex_timer.c @@ -60,8 +60,6 @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq) static void ibex_timer_update_irqs(IbexTimerState *s) { - CPUState *cs = qemu_get_cpu(0); - RISCVCPU *cpu = RISCV_CPU(cs); uint64_t value = s->timer_compare_lower0 | ((uint64_t)s->timer_compare_upper0 << 32); uint64_t next, diff; @@ -73,9 +71,9 @@ static void ibex_timer_update_irqs(IbexTimerState *s) } /* Update the CPUs mtimecmp */ - cpu->env.timecmp = value; + s->mtimecmp = value; - if (cpu->env.timecmp <= now) { + if (s->mtimecmp <= now) { /* * If the mtimecmp was in the past raise the interrupt now. */ @@ -91,7 +89,7 @@ static void ibex_timer_update_irqs(IbexTimerState *s) qemu_irq_lower(s->m_timer_irq); qemu_set_irq(s->irq, false); - diff = cpu->env.timecmp - now; + diff = s->mtimecmp - now; next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + muldiv64(diff, NANOSECONDS_PER_SECOND, @@ -99,9 +97,9 @@ static void ibex_timer_update_irqs(IbexTimerState *s) if (next < qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)) { /* We overflowed the timer, just set it as large as we can */ - timer_mod(cpu->env.timer, 0x7FFFFFFFFFFFFFFF); + timer_mod(s->mtimer, 0x7FFFFFFFFFFFFFFF); } else { - timer_mod(cpu->env.timer, next); + timer_mod(s->mtimer, next); } } @@ -120,11 +118,9 @@ static void ibex_timer_reset(DeviceState *dev) { IbexTimerState *s = IBEX_TIMER(dev); - CPUState *cpu = qemu_get_cpu(0); - CPURISCVState *env = cpu->env_ptr; - env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + s->mtimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &ibex_timer_cb, s); - env->timecmp = 0; + s->mtimecmp = 0; s->timer_ctrl = 0x00000000; s->timer_cfg0 = 0x00010000; diff --git a/include/hw/intc/riscv_aclint.h b/include/hw/intc/riscv_aclint.h index 26d4048687..693415eb6d 100644 --- a/include/hw/intc/riscv_aclint.h +++ b/include/hw/intc/riscv_aclint.h @@ -32,6 +32,8 @@ typedef struct RISCVAclintMTimerState { /*< private >*/ SysBusDevice parent_obj; uint64_t time_delta; + uint64_t *timecmp; + QEMUTimer **timers; /*< public >*/ MemoryRegion mmio; diff --git a/include/hw/timer/ibex_timer.h b/include/hw/timer/ibex_timer.h index 1a0a28d5fa..41f5c82a92 100644 --- a/include/hw/timer/ibex_timer.h +++ b/include/hw/timer/ibex_timer.h @@ -33,6 +33,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(IbexTimerState, IBEX_TIMER) struct IbexTimerState { /* */ SysBusDevice parent_obj; + uint64_t mtimecmp; + QEMUTimer *mtimer; /* Internal timer for M-mode interrupt */ /* */ MemoryRegion mmio; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 081cd05544..53335def23 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -307,7 +307,6 @@ struct CPUArchState { /* temporary htif regs */ uint64_t mfromhost; uint64_t mtohost; - uint64_t timecmp; /* physical memory protection */ pmp_table_t pmp_state; @@ -362,7 +361,6 @@ struct CPUArchState { float_status fp_status; /* Fields from here on are preserved across CPU reset. */ - QEMUTimer *timer; /* Internal timer */ hwaddr kernel_addr; hwaddr fdt_addr; diff --git a/target/riscv/machine.c b/target/riscv/machine.c index dc182ca811..b508b042cb 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -307,8 +307,8 @@ static const VMStateDescription vmstate_pmu_ctr_state = { const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", - .version_id = 3, - .minimum_version_id = 3, + .version_id = 4, + .minimum_version_id = 4, .post_load = riscv_cpu_post_load, .fields = (VMStateField[]) { VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), @@ -359,7 +359,6 @@ const VMStateDescription vmstate_riscv_cpu = { VMSTATE_UINTTL(env.mscratch, RISCVCPU), VMSTATE_UINT64(env.mfromhost, RISCVCPU), VMSTATE_UINT64(env.mtohost, RISCVCPU), - VMSTATE_UINT64(env.timecmp, RISCVCPU), VMSTATE_END_OF_LIST() }, From 43888c2f1823212b1064a6a94d65d8acaf954478 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:13:56 -0700 Subject: [PATCH 0399/1020] target/riscv: Add stimecmp support stimecmp allows the supervisor mode to update stimecmp CSR directly to program the next timer interrupt. This CSR is part of the Sstc extension which was ratified recently. Reviewed-by: Alistair Francis Signed-off-by: Atish Patra Message-Id: <20220824221357.41070-3-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 9 ++++ target/riscv/cpu.h | 5 ++ target/riscv/cpu_bits.h | 4 ++ target/riscv/csr.c | 86 +++++++++++++++++++++++++++++++++ target/riscv/machine.c | 1 + target/riscv/meson.build | 3 +- target/riscv/time_helper.c | 98 ++++++++++++++++++++++++++++++++++++++ target/riscv/time_helper.h | 30 ++++++++++++ 8 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 target/riscv/time_helper.c create mode 100644 target/riscv/time_helper.h diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 26d44df446..8ab36e82e1 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -23,6 +23,7 @@ #include "qemu/log.h" #include "cpu.h" #include "internals.h" +#include "time_helper.h" #include "exec/exec-all.h" #include "qapi/error.h" #include "qemu/error-report.h" @@ -101,6 +102,7 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin), ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia), ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia), + ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc), ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval), ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot), ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt), @@ -674,6 +676,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_resetvec(env, cpu->cfg.resetvec); +#ifndef CONFIG_USER_ONLY + if (cpu->cfg.ext_sstc) { + riscv_timer_init(cpu); + } +#endif /* CONFIG_USER_ONLY */ + /* Validate that MISA_MXL is set properly. */ switch (env->misa_mxl_max) { #ifdef TARGET_RISCV64 @@ -994,6 +1002,7 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, 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), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 53335def23..d2529b757a 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -308,6 +308,9 @@ struct CPUArchState { uint64_t mfromhost; uint64_t mtohost; + /* Sstc CSRs */ + uint64_t stimecmp; + /* physical memory protection */ pmp_table_t pmp_state; target_ulong mseccfg; @@ -361,6 +364,7 @@ struct CPUArchState { float_status fp_status; /* Fields from here on are preserved across CPU reset. */ + QEMUTimer *stimer; /* Internal timer for S-mode interrupt */ hwaddr kernel_addr; hwaddr fdt_addr; @@ -424,6 +428,7 @@ struct RISCVCPUConfig { bool ext_ifencei; bool ext_icsr; bool ext_zihintpause; + bool ext_sstc; bool ext_svinval; bool ext_svnapot; bool ext_svpbmt; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 6be5a9e9f0..ac17cf1515 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -206,6 +206,10 @@ #define CSR_STVAL 0x143 #define CSR_SIP 0x144 +/* Sstc supervisor CSRs */ +#define CSR_STIMECMP 0x14D +#define CSR_STIMECMPH 0x15D + /* Supervisor Protection and Translation */ #define CSR_SPTBR 0x180 #define CSR_SATP 0x180 diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 3ddf309055..04b06a2389 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -22,6 +22,7 @@ #include "qemu/timer.h" #include "cpu.h" #include "pmu.h" +#include "time_helper.h" #include "qemu/main-loop.h" #include "exec/exec-all.h" #include "sysemu/cpu-timers.h" @@ -815,6 +816,81 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException sstc(CPURISCVState *env, int csrno) +{ + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); + + if (!cpu->cfg.ext_sstc || !env->rdtime_fn) { + return RISCV_EXCP_ILLEGAL_INST; + } + + if (env->priv == PRV_M) { + return RISCV_EXCP_NONE; + } + + /* + * No need of separate function for rv32 as menvcfg stores both menvcfg + * menvcfgh for RV32. + */ + if (!(get_field(env->mcounteren, COUNTEREN_TM) && + get_field(env->menvcfg, MENVCFG_STCE))) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return smode(env, csrno); +} + +static RISCVException sstc_32(CPURISCVState *env, int csrno) +{ + if (riscv_cpu_mxl(env) != MXL_RV32) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return sstc(env, csrno); +} + +static RISCVException read_stimecmp(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->stimecmp; + return RISCV_EXCP_NONE; +} + +static RISCVException read_stimecmph(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->stimecmp >> 32; + return RISCV_EXCP_NONE; +} + +static RISCVException write_stimecmp(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu = env_archcpu(env); + + if (riscv_cpu_mxl(env) == MXL_RV32) { + env->stimecmp = deposit64(env->stimecmp, 0, 32, (uint64_t)val); + } else { + env->stimecmp = val; + } + + riscv_timer_write_timecmp(cpu, env->stimer, env->stimecmp, 0, MIP_STIP); + + return RISCV_EXCP_NONE; +} + +static RISCVException write_stimecmph(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu = env_archcpu(env); + + env->stimecmp = deposit64(env->stimecmp, 32, 32, (uint64_t)val); + riscv_timer_write_timecmp(cpu, env->stimer, env->stimecmp, 0, MIP_STIP); + + return RISCV_EXCP_NONE; +} + /* Machine constants */ #define M_MODE_INTERRUPTS ((uint64_t)(MIP_MSIP | MIP_MTIP | MIP_MEIP)) @@ -1723,6 +1799,12 @@ static RISCVException rmw_mip64(CPURISCVState *env, int csrno, new_val |= env->external_seip * MIP_SEIP; } + if (cpu->cfg.ext_sstc && (env->priv == PRV_M) && + get_field(env->menvcfg, MENVCFG_STCE)) { + /* sstc extension forbids STIP & VSTIP to be writeable in mip */ + mask = mask & ~(MIP_STIP | MIP_VSTIP); + } + if (mask) { old_mip = riscv_cpu_update_mip(cpu, mask, (new_val & mask)); } else { @@ -3594,6 +3676,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_SCAUSE] = { "scause", smode, read_scause, write_scause }, [CSR_STVAL] = { "stval", smode, read_stval, write_stval }, [CSR_SIP] = { "sip", smode, NULL, NULL, rmw_sip }, + [CSR_STIMECMP] = { "stimecmp", sstc, read_stimecmp, write_stimecmp, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_STIMECMPH] = { "stimecmph", sstc_32, read_stimecmph, write_stimecmph, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Supervisor Protection and Translation */ [CSR_SATP] = { "satp", smode, read_satp, write_satp }, diff --git a/target/riscv/machine.c b/target/riscv/machine.c index b508b042cb..622fface48 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -359,6 +359,7 @@ const VMStateDescription vmstate_riscv_cpu = { VMSTATE_UINTTL(env.mscratch, RISCVCPU), VMSTATE_UINT64(env.mfromhost, RISCVCPU), VMSTATE_UINT64(env.mtohost, RISCVCPU), + VMSTATE_UINT64(env.stimecmp, RISCVCPU), VMSTATE_END_OF_LIST() }, diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 6b9435d69a..ba25164d74 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -29,7 +29,8 @@ riscv_softmmu_ss.add(files( 'debug.c', 'monitor.c', 'machine.c', - 'pmu.c' + 'pmu.c', + 'time_helper.c' )) target_arch += {'riscv': riscv_ss} diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c new file mode 100644 index 0000000000..f3fb5eac7b --- /dev/null +++ b/target/riscv/time_helper.c @@ -0,0 +1,98 @@ +/* + * RISC-V timer helper implementation. + * + * Copyright (c) 2022 Rivos Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "cpu_bits.h" +#include "time_helper.h" +#include "hw/intc/riscv_aclint.h" + +static void riscv_stimer_cb(void *opaque) +{ + RISCVCPU *cpu = opaque; + riscv_cpu_update_mip(cpu, MIP_STIP, BOOL_TO_MASK(1)); +} + +/* + * Called when timecmp is written to update the QEMU timer or immediately + * trigger timer interrupt if mtimecmp <= current timer value. + */ +void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer *timer, + uint64_t timecmp, uint64_t delta, + uint32_t timer_irq) +{ + uint64_t diff, ns_diff, next; + CPURISCVState *env = &cpu->env; + RISCVAclintMTimerState *mtimer = env->rdtime_fn_arg; + uint32_t timebase_freq = mtimer->timebase_freq; + uint64_t rtc_r = env->rdtime_fn(env->rdtime_fn_arg) + delta; + + if (timecmp <= rtc_r) { + /* + * If we're setting an stimecmp value in the "past", + * immediately raise the timer interrupt + */ + riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(1)); + return; + } + + /* Clear the [V]STIP bit in mip */ + riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0)); + + /* otherwise, set up the future timer interrupt */ + diff = timecmp - rtc_r; + /* back to ns (note args switched in muldiv64) */ + ns_diff = muldiv64(diff, NANOSECONDS_PER_SECOND, timebase_freq); + + /* + * check if ns_diff overflowed and check if the addition would potentially + * overflow + */ + if ((NANOSECONDS_PER_SECOND > timebase_freq && ns_diff < diff) || + ns_diff > INT64_MAX) { + next = INT64_MAX; + } else { + /* + * as it is very unlikely qemu_clock_get_ns will return a value + * greater than INT64_MAX, no additional check is needed for an + * unsigned integer overflow. + */ + next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns_diff; + /* + * if ns_diff is INT64_MAX next may still be outside the range + * of a signed integer. + */ + next = MIN(next, INT64_MAX); + } + + timer_mod(timer, next); +} + +void riscv_timer_init(RISCVCPU *cpu) +{ + CPURISCVState *env; + + if (!cpu) { + return; + } + + env = &cpu->env; + env->stimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_stimer_cb, cpu); + env->stimecmp = 0; + +} diff --git a/target/riscv/time_helper.h b/target/riscv/time_helper.h new file mode 100644 index 0000000000..7b3cdcc350 --- /dev/null +++ b/target/riscv/time_helper.h @@ -0,0 +1,30 @@ +/* + * RISC-V timer header file. + * + * Copyright (c) 2022 Rivos Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef RISCV_TIME_HELPER_H +#define RISCV_TIME_HELPER_H + +#include "cpu.h" +#include "qemu/timer.h" + +void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer *timer, + uint64_t timecmp, uint64_t delta, + uint32_t timer_irq); +void riscv_timer_init(RISCVCPU *cpu); + +#endif From 3ec0fe18a31fabfe999b480e4c21847ac0d51560 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:13:57 -0700 Subject: [PATCH 0400/1020] target/riscv: Add vstimecmp support vstimecmp CSR allows the guest OS or to program the next guest timer interrupt directly. Thus, hypervisor no longer need to inject the timer interrupt to the guest if vstimecmp is used. This was ratified as a part of the Sstc extension. Reviewed-by: Alistair Francis Signed-off-by: Atish Patra Message-Id: <20220824221357.41070-4-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 4 ++ target/riscv/cpu_bits.h | 4 ++ target/riscv/cpu_helper.c | 11 +++-- target/riscv/csr.c | 88 ++++++++++++++++++++++++++++++++++++-- target/riscv/machine.c | 1 + target/riscv/time_helper.c | 16 +++++++ 6 files changed, 118 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index d2529b757a..d895a0af2c 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -311,6 +311,8 @@ struct CPUArchState { /* Sstc CSRs */ uint64_t stimecmp; + uint64_t vstimecmp; + /* physical memory protection */ pmp_table_t pmp_state; target_ulong mseccfg; @@ -365,6 +367,8 @@ struct CPUArchState { /* Fields from here on are preserved across CPU reset. */ QEMUTimer *stimer; /* Internal timer for S-mode interrupt */ + QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */ + bool vstime_irq; hwaddr kernel_addr; hwaddr fdt_addr; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index ac17cf1515..095dab19f5 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -257,6 +257,10 @@ #define CSR_VSIP 0x244 #define CSR_VSATP 0x280 +/* Sstc virtual CSRs */ +#define CSR_VSTIMECMP 0x24D +#define CSR_VSTIMECMPH 0x25D + #define CSR_MTINST 0x34a #define CSR_MTVAL2 0x34b diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 05c0c8d777..719c5d5d02 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -346,8 +346,9 @@ uint64_t riscv_cpu_all_pending(CPURISCVState *env) { uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN); uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; + uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0; - return (env->mip | vsgein) & env->mie; + return (env->mip | vsgein | vstip) & env->mie; } int riscv_cpu_mirq_pending(CPURISCVState *env) @@ -606,7 +607,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value) { CPURISCVState *env = &cpu->env; CPUState *cs = CPU(cpu); - uint64_t gein, vsgein = 0, old = env->mip; + uint64_t gein, vsgein = 0, vstip = 0, old = env->mip; bool locked = false; if (riscv_cpu_virt_enabled(env)) { @@ -614,6 +615,10 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value) vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; } + /* No need to update mip for VSTIP */ + mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask; + vstip = env->vstime_irq ? MIP_VSTIP : 0; + if (!qemu_mutex_iothread_locked()) { locked = true; qemu_mutex_lock_iothread(); @@ -621,7 +626,7 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, uint64_t value) env->mip = (env->mip & ~mask) | (value & mask); - if (env->mip | vsgein) { + if (env->mip | vsgein | vstip) { cpu_interrupt(cs, CPU_INTERRUPT_HARD); } else { cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 04b06a2389..1a35ac48cc 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -820,6 +820,7 @@ static RISCVException sstc(CPURISCVState *env, int csrno) { CPUState *cs = env_cpu(env); RISCVCPU *cpu = RISCV_CPU(cs); + bool hmode_check = false; if (!cpu->cfg.ext_sstc || !env->rdtime_fn) { return RISCV_EXCP_ILLEGAL_INST; @@ -838,7 +839,18 @@ static RISCVException sstc(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } - return smode(env, csrno); + if (riscv_cpu_virt_enabled(env)) { + if (!(get_field(env->hcounteren, COUNTEREN_TM) & + get_field(env->henvcfg, HENVCFG_STCE))) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; + } + } + + if ((csrno == CSR_VSTIMECMP) || (csrno == CSR_VSTIMECMPH)) { + hmode_check = true; + } + + return hmode_check ? hmode(env, csrno) : smode(env, csrno); } static RISCVException sstc_32(CPURISCVState *env, int csrno) @@ -850,17 +862,72 @@ static RISCVException sstc_32(CPURISCVState *env, int csrno) return sstc(env, csrno); } +static RISCVException read_vstimecmp(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->vstimecmp; + + return RISCV_EXCP_NONE; +} + +static RISCVException read_vstimecmph(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->vstimecmp >> 32; + + return RISCV_EXCP_NONE; +} + +static RISCVException write_vstimecmp(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu = env_archcpu(env); + + if (riscv_cpu_mxl(env) == MXL_RV32) { + env->vstimecmp = deposit64(env->vstimecmp, 0, 32, (uint64_t)val); + } else { + env->vstimecmp = val; + } + + riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp, + env->htimedelta, MIP_VSTIP); + + return RISCV_EXCP_NONE; +} + +static RISCVException write_vstimecmph(CPURISCVState *env, int csrno, + target_ulong val) +{ + RISCVCPU *cpu = env_archcpu(env); + + env->vstimecmp = deposit64(env->vstimecmp, 32, 32, (uint64_t)val); + riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp, + env->htimedelta, MIP_VSTIP); + + return RISCV_EXCP_NONE; +} + static RISCVException read_stimecmp(CPURISCVState *env, int csrno, target_ulong *val) { - *val = env->stimecmp; + if (riscv_cpu_virt_enabled(env)) { + *val = env->vstimecmp; + } else { + *val = env->stimecmp; + } + return RISCV_EXCP_NONE; } static RISCVException read_stimecmph(CPURISCVState *env, int csrno, target_ulong *val) { - *val = env->stimecmp >> 32; + if (riscv_cpu_virt_enabled(env)) { + *val = env->vstimecmp >> 32; + } else { + *val = env->stimecmp >> 32; + } + return RISCV_EXCP_NONE; } @@ -869,6 +936,10 @@ static RISCVException write_stimecmp(CPURISCVState *env, int csrno, { RISCVCPU *cpu = env_archcpu(env); + if (riscv_cpu_virt_enabled(env)) { + return write_vstimecmp(env, csrno, val); + } + if (riscv_cpu_mxl(env) == MXL_RV32) { env->stimecmp = deposit64(env->stimecmp, 0, 32, (uint64_t)val); } else { @@ -885,6 +956,10 @@ static RISCVException write_stimecmph(CPURISCVState *env, int csrno, { RISCVCPU *cpu = env_archcpu(env); + if (riscv_cpu_virt_enabled(env)) { + return write_vstimecmph(env, csrno, val); + } + env->stimecmp = deposit64(env->stimecmp, 32, 32, (uint64_t)val); riscv_timer_write_timecmp(cpu, env->stimer, env->stimecmp, 0, MIP_STIP); @@ -1814,6 +1889,7 @@ static RISCVException rmw_mip64(CPURISCVState *env, int csrno, if (csrno != CSR_HVIP) { gin = get_field(env->hstatus, HSTATUS_VGEIN); old_mip |= (env->hgeip & ((target_ulong)1 << gin)) ? MIP_VSEIP : 0; + old_mip |= env->vstime_irq ? MIP_VSTIP : 0; } if (ret_val) { @@ -3680,6 +3756,12 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_STIMECMPH] = { "stimecmph", sstc_32, read_stimecmph, write_stimecmph, .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTIMECMP] = { "vstimecmp", sstc, read_vstimecmp, + write_vstimecmp, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_VSTIMECMPH] = { "vstimecmph", sstc_32, read_vstimecmph, + write_vstimecmph, + .min_priv_ver = PRIV_VERSION_1_12_0 }, /* Supervisor Protection and Translation */ [CSR_SATP] = { "satp", smode, read_satp, write_satp }, diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 622fface48..4ba55705d1 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -92,6 +92,7 @@ static const VMStateDescription vmstate_hyper = { VMSTATE_UINTTL(env.hgeie, RISCVCPU), VMSTATE_UINTTL(env.hgeip, RISCVCPU), VMSTATE_UINT64(env.htimedelta, RISCVCPU), + VMSTATE_UINT64(env.vstimecmp, RISCVCPU), VMSTATE_UINTTL(env.hvictl, RISCVCPU), VMSTATE_UINT8_ARRAY(env.hviprio, RISCVCPU, 64), diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c index f3fb5eac7b..8cce667dfd 100644 --- a/target/riscv/time_helper.c +++ b/target/riscv/time_helper.c @@ -22,6 +22,14 @@ #include "time_helper.h" #include "hw/intc/riscv_aclint.h" +static void riscv_vstimer_cb(void *opaque) +{ + RISCVCPU *cpu = opaque; + CPURISCVState *env = &cpu->env; + env->vstime_irq = 1; + riscv_cpu_update_mip(cpu, MIP_VSTIP, BOOL_TO_MASK(1)); +} + static void riscv_stimer_cb(void *opaque) { RISCVCPU *cpu = opaque; @@ -47,10 +55,16 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer *timer, * If we're setting an stimecmp value in the "past", * immediately raise the timer interrupt */ + if (timer_irq == MIP_VSTIP) { + env->vstime_irq = 1; + } riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(1)); return; } + if (timer_irq == MIP_VSTIP) { + env->vstime_irq = 0; + } /* Clear the [V]STIP bit in mip */ riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0)); @@ -95,4 +109,6 @@ void riscv_timer_init(RISCVCPU *cpu) env->stimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_stimer_cb, cpu); env->stimecmp = 0; + env->vstimer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &riscv_vstimer_cb, cpu); + env->vstimecmp = 0; } From 14664483457b21235be42fbfb534e5ea881508b8 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:16:57 -0700 Subject: [PATCH 0401/1020] target/riscv: Add sscofpmf extension support The Sscofpmf ('Ss' for Privileged arch and Supervisor-level extensions, and 'cofpmf' for Count OverFlow and Privilege Mode Filtering) extension allows the perf to handle overflow interrupts and filtering support. This patch provides a framework for programmable counters to leverage the extension. As the extension doesn't have any provision for the overflow bit for fixed counters, the fixed events can also be monitoring using programmable counters. The underlying counters for cycle and instruction counters are always running. Thus, a separate timer device is programmed to handle the overflow. Tested-by: Heiko Stuebner Reviewed-by: Alistair Francis Signed-off-by: Atish Patra Signed-off-by: Atish Patra Message-Id: <20220824221701.41932-2-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 12 ++ target/riscv/cpu.h | 25 +++ target/riscv/cpu_bits.h | 55 ++++++ target/riscv/csr.c | 166 +++++++++++++++++- target/riscv/machine.c | 1 + target/riscv/pmu.c | 368 +++++++++++++++++++++++++++++++++++++++- target/riscv/pmu.h | 7 + 7 files changed, 623 insertions(+), 11 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8ab36e82e1..aee14a239a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -22,6 +22,7 @@ #include "qemu/ctype.h" #include "qemu/log.h" #include "cpu.h" +#include "pmu.h" #include "internals.h" #include "time_helper.h" #include "exec/exec-all.h" @@ -102,6 +103,7 @@ static const struct isa_ext_data isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin), ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia), ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia), + ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf), ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc), ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval), ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot), @@ -889,6 +891,15 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) set_misa(env, env->misa_mxl, ext); } +#ifndef CONFIG_USER_ONLY + if (cpu->cfg.pmu_num) { + if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) { + cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, + riscv_pmu_timer_cb, cpu); + } + } +#endif + riscv_cpu_register_gdb_regs_for_features(cs); qemu_init_vcpu(cs); @@ -993,6 +1004,7 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false), DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true), 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), DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index d895a0af2c..06751e1e3e 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -136,6 +136,8 @@ typedef struct PMUCTRState { /* Snapshort value of a counter in RV32 */ target_ulong mhpmcounterh_prev; bool started; + /* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */ + target_ulong irq_overflow_left; } PMUCTRState; struct CPUArchState { @@ -301,6 +303,9 @@ struct CPUArchState { /* PMU event selector configured values. First three are unused*/ target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS]; + /* PMU event selector configured values for RV32*/ + target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS]; + target_ulong sscratch; target_ulong mscratch; @@ -447,6 +452,7 @@ struct RISCVCPUConfig { bool ext_zmmul; bool ext_smaia; bool ext_ssaia; + bool ext_sscofpmf; bool rvv_ta_all_1s; bool rvv_ma_all_1s; @@ -493,6 +499,12 @@ struct ArchCPU { /* Configuration Settings */ RISCVCPUConfig cfg; + + QEMUTimer *pmu_timer; + /* A bitmask of Available programmable counters */ + uint32_t pmu_avail_ctrs; + /* Mapping of events to counters */ + GHashTable *pmu_event_ctr_map; }; static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext) @@ -753,6 +765,19 @@ enum { CSR_TABLE_SIZE = 0x1000 }; +/** + * The event id are encoded based on the encoding specified in the + * SBI specification v0.3 + */ + +enum riscv_pmu_event_idx { + RISCV_PMU_EVENT_HW_CPU_CYCLES = 0x01, + RISCV_PMU_EVENT_HW_INSTRUCTIONS = 0x02, + RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS = 0x10019, + RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS = 0x1001B, + RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021, +}; + /* CSR function table */ extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 095dab19f5..7be12cac2e 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -390,6 +390,37 @@ #define CSR_MHPMEVENT29 0x33d #define CSR_MHPMEVENT30 0x33e #define CSR_MHPMEVENT31 0x33f + +#define CSR_MHPMEVENT3H 0x723 +#define CSR_MHPMEVENT4H 0x724 +#define CSR_MHPMEVENT5H 0x725 +#define CSR_MHPMEVENT6H 0x726 +#define CSR_MHPMEVENT7H 0x727 +#define CSR_MHPMEVENT8H 0x728 +#define CSR_MHPMEVENT9H 0x729 +#define CSR_MHPMEVENT10H 0x72a +#define CSR_MHPMEVENT11H 0x72b +#define CSR_MHPMEVENT12H 0x72c +#define CSR_MHPMEVENT13H 0x72d +#define CSR_MHPMEVENT14H 0x72e +#define CSR_MHPMEVENT15H 0x72f +#define CSR_MHPMEVENT16H 0x730 +#define CSR_MHPMEVENT17H 0x731 +#define CSR_MHPMEVENT18H 0x732 +#define CSR_MHPMEVENT19H 0x733 +#define CSR_MHPMEVENT20H 0x734 +#define CSR_MHPMEVENT21H 0x735 +#define CSR_MHPMEVENT22H 0x736 +#define CSR_MHPMEVENT23H 0x737 +#define CSR_MHPMEVENT24H 0x738 +#define CSR_MHPMEVENT25H 0x739 +#define CSR_MHPMEVENT26H 0x73a +#define CSR_MHPMEVENT27H 0x73b +#define CSR_MHPMEVENT28H 0x73c +#define CSR_MHPMEVENT29H 0x73d +#define CSR_MHPMEVENT30H 0x73e +#define CSR_MHPMEVENT31H 0x73f + #define CSR_MHPMCOUNTER3H 0xb83 #define CSR_MHPMCOUNTER4H 0xb84 #define CSR_MHPMCOUNTER5H 0xb85 @@ -451,6 +482,7 @@ #define CSR_VSMTE 0x2c0 #define CSR_VSPMMASK 0x2c1 #define CSR_VSPMBASE 0x2c2 +#define CSR_SCOUNTOVF 0xda0 /* Crypto Extension */ #define CSR_SEED 0x015 @@ -628,6 +660,7 @@ typedef enum RISCVException { #define IRQ_VS_EXT 10 #define IRQ_M_EXT 11 #define IRQ_S_GEXT 12 +#define IRQ_PMU_OVF 13 #define IRQ_LOCAL_MAX 16 #define IRQ_LOCAL_GUEST_MAX (TARGET_LONG_BITS - 1) @@ -645,11 +678,13 @@ typedef enum RISCVException { #define MIP_VSEIP (1 << IRQ_VS_EXT) #define MIP_MEIP (1 << IRQ_M_EXT) #define MIP_SGEIP (1 << IRQ_S_GEXT) +#define MIP_LCOFIP (1 << IRQ_PMU_OVF) /* sip masks */ #define SIP_SSIP MIP_SSIP #define SIP_STIP MIP_STIP #define SIP_SEIP MIP_SEIP +#define SIP_LCOFIP MIP_LCOFIP /* MIE masks */ #define MIE_SEIE (1 << IRQ_S_EXT) @@ -803,4 +838,24 @@ typedef enum RISCVException { #define SEED_OPST_WAIT (0b01 << 30) #define SEED_OPST_ES16 (0b10 << 30) #define SEED_OPST_DEAD (0b11 << 30) +/* PMU related bits */ +#define MIE_LCOFIE (1 << IRQ_PMU_OVF) + +#define MHPMEVENT_BIT_OF BIT_ULL(63) +#define MHPMEVENTH_BIT_OF BIT(31) +#define MHPMEVENT_BIT_MINH BIT_ULL(62) +#define MHPMEVENTH_BIT_MINH BIT(30) +#define MHPMEVENT_BIT_SINH BIT_ULL(61) +#define MHPMEVENTH_BIT_SINH BIT(29) +#define MHPMEVENT_BIT_UINH BIT_ULL(60) +#define MHPMEVENTH_BIT_UINH BIT(28) +#define MHPMEVENT_BIT_VSINH BIT_ULL(59) +#define MHPMEVENTH_BIT_VSINH BIT(27) +#define MHPMEVENT_BIT_VUINH BIT_ULL(58) +#define MHPMEVENTH_BIT_VUINH BIT(26) + +#define MHPMEVENT_SSCOF_MASK _ULL(0xFFFF000000000000) +#define MHPMEVENT_IDX_MASK 0xFFFFF +#define MHPMEVENT_SSCOF_RESVD 16 + #endif diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 1a35ac48cc..888ddfc4dd 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -75,7 +75,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno) CPUState *cs = env_cpu(env); RISCVCPU *cpu = RISCV_CPU(cs); int ctr_index; - int base_csrno = CSR_HPMCOUNTER3; + int base_csrno = CSR_CYCLE; bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false; if (rv32 && csrno >= CSR_CYCLEH) { @@ -84,11 +84,18 @@ static RISCVException ctr(CPURISCVState *env, int csrno) } ctr_index = csrno - base_csrno; - if (!cpu->cfg.pmu_num || ctr_index >= (cpu->cfg.pmu_num)) { + if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) || + (csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) { + goto skip_ext_pmu_check; + } + + if ((!cpu->cfg.pmu_num || !(cpu->pmu_avail_ctrs & BIT(ctr_index)))) { /* No counter is enabled in PMU or the counter is out of range */ return RISCV_EXCP_ILLEGAL_INST; } +skip_ext_pmu_check: + if (env->priv == PRV_S) { switch (csrno) { case CSR_CYCLE: @@ -107,7 +114,6 @@ static RISCVException ctr(CPURISCVState *env, int csrno) } break; case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31: - ctr_index = csrno - CSR_CYCLE; if (!get_field(env->mcounteren, 1 << ctr_index)) { return RISCV_EXCP_ILLEGAL_INST; } @@ -131,7 +137,6 @@ static RISCVException ctr(CPURISCVState *env, int csrno) } break; case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H: - ctr_index = csrno - CSR_CYCLEH; if (!get_field(env->mcounteren, 1 << ctr_index)) { return RISCV_EXCP_ILLEGAL_INST; } @@ -161,7 +166,6 @@ static RISCVException ctr(CPURISCVState *env, int csrno) } break; case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31: - ctr_index = csrno - CSR_CYCLE; if (!get_field(env->hcounteren, 1 << ctr_index) && get_field(env->mcounteren, 1 << ctr_index)) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; @@ -189,7 +193,6 @@ static RISCVException ctr(CPURISCVState *env, int csrno) } break; case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H: - ctr_index = csrno - CSR_CYCLEH; if (!get_field(env->hcounteren, 1 << ctr_index) && get_field(env->mcounteren, 1 << ctr_index)) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; @@ -241,6 +244,18 @@ static RISCVException mctr32(CPURISCVState *env, int csrno) return mctr(env, csrno); } +static RISCVException sscofpmf(CPURISCVState *env, int csrno) +{ + CPUState *cs = env_cpu(env); + RISCVCPU *cpu = RISCV_CPU(cs); + + if (!cpu->cfg.ext_sscofpmf) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return RISCV_EXCP_NONE; +} + static RISCVException any(CPURISCVState *env, int csrno) { return RISCV_EXCP_NONE; @@ -683,9 +698,39 @@ static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val) static int write_mhpmevent(CPURISCVState *env, int csrno, target_ulong val) { int evt_index = csrno - CSR_MCOUNTINHIBIT; + uint64_t mhpmevt_val = val; env->mhpmevent_val[evt_index] = val; + if (riscv_cpu_mxl(env) == MXL_RV32) { + mhpmevt_val = mhpmevt_val | + ((uint64_t)env->mhpmeventh_val[evt_index] << 32); + } + riscv_pmu_update_event_map(env, mhpmevt_val, evt_index); + + return RISCV_EXCP_NONE; +} + +static int read_mhpmeventh(CPURISCVState *env, int csrno, target_ulong *val) +{ + int evt_index = csrno - CSR_MHPMEVENT3H + 3; + + *val = env->mhpmeventh_val[evt_index]; + + return RISCV_EXCP_NONE; +} + +static int write_mhpmeventh(CPURISCVState *env, int csrno, target_ulong val) +{ + int evt_index = csrno - CSR_MHPMEVENT3H + 3; + uint64_t mhpmevth_val = val; + uint64_t mhpmevt_val = env->mhpmevent_val[evt_index]; + + mhpmevt_val = mhpmevt_val | (mhpmevth_val << 32); + env->mhpmeventh_val[evt_index] = val; + + riscv_pmu_update_event_map(env, mhpmevt_val, evt_index); + return RISCV_EXCP_NONE; } @@ -693,12 +738,20 @@ static int write_mhpmcounter(CPURISCVState *env, int csrno, target_ulong val) { int ctr_idx = csrno - CSR_MCYCLE; PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; + uint64_t mhpmctr_val = val; counter->mhpmcounter_val = val; if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { counter->mhpmcounter_prev = get_ticks(false); - } else { + if (ctr_idx > 2) { + if (riscv_cpu_mxl(env) == MXL_RV32) { + mhpmctr_val = mhpmctr_val | + ((uint64_t)counter->mhpmcounterh_val << 32); + } + riscv_pmu_setup_timer(env, mhpmctr_val, ctr_idx); + } + } else { /* Other counters can keep incrementing from the given value */ counter->mhpmcounter_prev = val; } @@ -710,11 +763,17 @@ static int write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong val) { int ctr_idx = csrno - CSR_MCYCLEH; PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; + uint64_t mhpmctr_val = counter->mhpmcounter_val; + uint64_t mhpmctrh_val = val; counter->mhpmcounterh_val = val; + mhpmctr_val = mhpmctr_val | (mhpmctrh_val << 32); if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { counter->mhpmcounterh_prev = get_ticks(true); + if (ctr_idx > 2) { + riscv_pmu_setup_timer(env, mhpmctr_val, ctr_idx); + } } else { counter->mhpmcounterh_prev = val; } @@ -790,6 +849,32 @@ static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val) return riscv_pmu_read_ctr(env, val, true, ctr_index); } +static int read_scountovf(CPURISCVState *env, int csrno, target_ulong *val) +{ + int mhpmevt_start = CSR_MHPMEVENT3 - CSR_MCOUNTINHIBIT; + int i; + *val = 0; + target_ulong *mhpm_evt_val; + uint64_t of_bit_mask; + + if (riscv_cpu_mxl(env) == MXL_RV32) { + mhpm_evt_val = env->mhpmeventh_val; + of_bit_mask = MHPMEVENTH_BIT_OF; + } else { + mhpm_evt_val = env->mhpmevent_val; + of_bit_mask = MHPMEVENT_BIT_OF; + } + + for (i = mhpmevt_start; i < RV_MAX_MHPMEVENTS; i++) { + if ((get_field(env->mcounteren, BIT(i))) && + (mhpm_evt_val[i] & of_bit_mask)) { + *val |= BIT(i); + } + } + + return RISCV_EXCP_NONE; +} + static RISCVException read_time(CPURISCVState *env, int csrno, target_ulong *val) { @@ -969,7 +1054,8 @@ static RISCVException write_stimecmph(CPURISCVState *env, int csrno, /* Machine constants */ #define M_MODE_INTERRUPTS ((uint64_t)(MIP_MSIP | MIP_MTIP | MIP_MEIP)) -#define S_MODE_INTERRUPTS ((uint64_t)(MIP_SSIP | MIP_STIP | MIP_SEIP)) +#define S_MODE_INTERRUPTS ((uint64_t)(MIP_SSIP | MIP_STIP | MIP_SEIP | \ + MIP_LCOFIP)) #define VS_MODE_INTERRUPTS ((uint64_t)(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP)) #define HS_MODE_INTERRUPTS ((uint64_t)(MIP_SGEIP | VS_MODE_INTERRUPTS)) @@ -1010,7 +1096,8 @@ static const target_ulong vs_delegable_excps = DELEGABLE_EXCPS & static const target_ulong sstatus_v1_10_mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE | SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS | SSTATUS_SUM | SSTATUS_MXR | SSTATUS_VS; -static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP; +static const target_ulong sip_writable_mask = SIP_SSIP | MIP_USIP | MIP_UEIP | + SIP_LCOFIP; static const target_ulong hip_writable_mask = MIP_VSSIP; static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | MIP_VSEIP; static const target_ulong vsip_writable_mask = MIP_VSSIP; @@ -4071,6 +4158,65 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MHPMEVENT31] = { "mhpmevent31", any, read_mhpmevent, write_mhpmevent }, + [CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT4H] = { "mhpmevent4h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT5H] = { "mhpmevent5h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT6H] = { "mhpmevent6h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT7H] = { "mhpmevent7h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT8H] = { "mhpmevent8h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT9H] = { "mhpmevent9h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT10H] = { "mhpmevent10h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT11H] = { "mhpmevent11h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT12H] = { "mhpmevent12h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT13H] = { "mhpmevent13h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT14H] = { "mhpmevent14h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT15H] = { "mhpmevent15h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT16H] = { "mhpmevent16h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT17H] = { "mhpmevent17h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT18H] = { "mhpmevent18h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT19H] = { "mhpmevent19h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT20H] = { "mhpmevent20h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT21H] = { "mhpmevent21h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT22H] = { "mhpmevent22h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT23H] = { "mhpmevent23h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT24H] = { "mhpmevent24h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT25H] = { "mhpmevent25h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT26H] = { "mhpmevent26h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT27H] = { "mhpmevent27h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT28H] = { "mhpmevent28h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT29H] = { "mhpmevent29h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT30H] = { "mhpmevent30h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_MHPMEVENT31H] = { "mhpmevent31h", sscofpmf, read_mhpmeventh, + write_mhpmeventh }, + [CSR_HPMCOUNTER3H] = { "hpmcounter3h", ctr32, read_hpmcounterh }, [CSR_HPMCOUNTER4H] = { "hpmcounter4h", ctr32, read_hpmcounterh }, [CSR_HPMCOUNTER5H] = { "hpmcounter5h", ctr32, read_hpmcounterh }, @@ -4159,5 +4305,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mhpmcounterh }, [CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", mctr32, read_hpmcounterh, write_mhpmcounterh }, + [CSR_SCOUNTOVF] = { "scountovf", sscofpmf, read_scountovf }, + #endif /* !CONFIG_USER_ONLY */ }; diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 4ba55705d1..41098f6ad0 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -356,6 +356,7 @@ const VMStateDescription vmstate_riscv_cpu = { VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0, vmstate_pmu_ctr_state, PMUCTRState), VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS), + VMSTATE_UINTTL_ARRAY(env.mhpmeventh_val, RISCVCPU, RV_MAX_MHPMEVENTS), VMSTATE_UINTTL(env.sscratch, RISCVCPU), VMSTATE_UINTTL(env.mscratch, RISCVCPU), VMSTATE_UINT64(env.mfromhost, RISCVCPU), diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 000fe8da45..a5f504e53c 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -19,14 +19,378 @@ #include "qemu/osdep.h" #include "cpu.h" #include "pmu.h" +#include "sysemu/cpu-timers.h" + +#define RISCV_TIMEBASE_FREQ 1000000000 /* 1Ghz */ +#define MAKE_32BIT_MASK(shift, length) \ + (((uint32_t)(~0UL) >> (32 - (length))) << (shift)) + +static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx) +{ + if (ctr_idx < 3 || ctr_idx >= RV_MAX_MHPMCOUNTERS || + !(cpu->pmu_avail_ctrs & BIT(ctr_idx))) { + return false; + } else { + return true; + } +} + +static bool riscv_pmu_counter_enabled(RISCVCPU *cpu, uint32_t ctr_idx) +{ + CPURISCVState *env = &cpu->env; + + if (riscv_pmu_counter_valid(cpu, ctr_idx) && + !get_field(env->mcountinhibit, BIT(ctr_idx))) { + return true; + } else { + return false; + } +} + +static int riscv_pmu_incr_ctr_rv32(RISCVCPU *cpu, uint32_t ctr_idx) +{ + CPURISCVState *env = &cpu->env; + target_ulong max_val = UINT32_MAX; + PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; + bool virt_on = riscv_cpu_virt_enabled(env); + + /* Privilege mode filtering */ + if ((env->priv == PRV_M && + (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_MINH)) || + (env->priv == PRV_S && virt_on && + (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_VSINH)) || + (env->priv == PRV_U && virt_on && + (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_VUINH)) || + (env->priv == PRV_S && !virt_on && + (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_SINH)) || + (env->priv == PRV_U && !virt_on && + (env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_UINH))) { + return 0; + } + + /* Handle the overflow scenario */ + if (counter->mhpmcounter_val == max_val) { + if (counter->mhpmcounterh_val == max_val) { + counter->mhpmcounter_val = 0; + counter->mhpmcounterh_val = 0; + /* Generate interrupt only if OF bit is clear */ + if (!(env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_OF)) { + env->mhpmeventh_val[ctr_idx] |= MHPMEVENTH_BIT_OF; + riscv_cpu_update_mip(cpu, MIP_LCOFIP, BOOL_TO_MASK(1)); + } + } else { + counter->mhpmcounterh_val++; + } + } else { + counter->mhpmcounter_val++; + } + + return 0; +} + +static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu, uint32_t ctr_idx) +{ + CPURISCVState *env = &cpu->env; + PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; + uint64_t max_val = UINT64_MAX; + bool virt_on = riscv_cpu_virt_enabled(env); + + /* Privilege mode filtering */ + if ((env->priv == PRV_M && + (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_MINH)) || + (env->priv == PRV_S && virt_on && + (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_VSINH)) || + (env->priv == PRV_U && virt_on && + (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_VUINH)) || + (env->priv == PRV_S && !virt_on && + (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_SINH)) || + (env->priv == PRV_U && !virt_on && + (env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_UINH))) { + return 0; + } + + /* Handle the overflow scenario */ + if (counter->mhpmcounter_val == max_val) { + counter->mhpmcounter_val = 0; + /* Generate interrupt only if OF bit is clear */ + if (!(env->mhpmevent_val[ctr_idx] & MHPMEVENT_BIT_OF)) { + env->mhpmevent_val[ctr_idx] |= MHPMEVENT_BIT_OF; + riscv_cpu_update_mip(cpu, MIP_LCOFIP, BOOL_TO_MASK(1)); + } + } else { + counter->mhpmcounter_val++; + } + return 0; +} + +int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) +{ + uint32_t ctr_idx; + int ret; + CPURISCVState *env = &cpu->env; + gpointer value; + + if (!cpu->cfg.pmu_num) { + return 0; + } + value = g_hash_table_lookup(cpu->pmu_event_ctr_map, + GUINT_TO_POINTER(event_idx)); + if (!value) { + return -1; + } + + ctr_idx = GPOINTER_TO_UINT(value); + if (!riscv_pmu_counter_enabled(cpu, ctr_idx) || + get_field(env->mcountinhibit, BIT(ctr_idx))) { + return -1; + } + + if (riscv_cpu_mxl(env) == MXL_RV32) { + ret = riscv_pmu_incr_ctr_rv32(cpu, ctr_idx); + } else { + ret = riscv_pmu_incr_ctr_rv64(cpu, ctr_idx); + } + + return ret; +} bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env, uint32_t target_ctr) { - return (target_ctr == 0) ? true : false; + RISCVCPU *cpu; + uint32_t event_idx; + uint32_t ctr_idx; + + /* Fixed instret counter */ + if (target_ctr == 2) { + return true; + } + + cpu = RISCV_CPU(env_cpu(env)); + if (!cpu->pmu_event_ctr_map) { + return false; + } + + event_idx = RISCV_PMU_EVENT_HW_INSTRUCTIONS; + ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map, + GUINT_TO_POINTER(event_idx))); + if (!ctr_idx) { + return false; + } + + return target_ctr == ctr_idx ? true : false; } bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, uint32_t target_ctr) { - return (target_ctr == 2) ? true : false; + RISCVCPU *cpu; + uint32_t event_idx; + uint32_t ctr_idx; + + /* Fixed mcycle counter */ + if (target_ctr == 0) { + return true; + } + + cpu = RISCV_CPU(env_cpu(env)); + if (!cpu->pmu_event_ctr_map) { + return false; + } + + event_idx = RISCV_PMU_EVENT_HW_CPU_CYCLES; + ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map, + GUINT_TO_POINTER(event_idx))); + + /* Counter zero is not used for event_ctr_map */ + if (!ctr_idx) { + return false; + } + + return (target_ctr == ctr_idx) ? true : false; +} + +static gboolean pmu_remove_event_map(gpointer key, gpointer value, + gpointer udata) +{ + return (GPOINTER_TO_UINT(value) == GPOINTER_TO_UINT(udata)) ? true : false; +} + +static int64_t pmu_icount_ticks_to_ns(int64_t value) +{ + int64_t ret = 0; + + if (icount_enabled()) { + ret = icount_to_ns(value); + } else { + ret = (NANOSECONDS_PER_SECOND / RISCV_TIMEBASE_FREQ) * value; + } + + return ret; +} + +int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, + uint32_t ctr_idx) +{ + uint32_t event_idx; + RISCVCPU *cpu = RISCV_CPU(env_cpu(env)); + + if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->pmu_event_ctr_map) { + return -1; + } + + /* + * Expected mhpmevent value is zero for reset case. Remove the current + * mapping. + */ + if (!value) { + g_hash_table_foreach_remove(cpu->pmu_event_ctr_map, + pmu_remove_event_map, + GUINT_TO_POINTER(ctr_idx)); + return 0; + } + + event_idx = value & MHPMEVENT_IDX_MASK; + if (g_hash_table_lookup(cpu->pmu_event_ctr_map, + GUINT_TO_POINTER(event_idx))) { + return 0; + } + + switch (event_idx) { + case RISCV_PMU_EVENT_HW_CPU_CYCLES: + case RISCV_PMU_EVENT_HW_INSTRUCTIONS: + case RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS: + case RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS: + case RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS: + break; + default: + /* We don't support any raw events right now */ + return -1; + } + g_hash_table_insert(cpu->pmu_event_ctr_map, GUINT_TO_POINTER(event_idx), + GUINT_TO_POINTER(ctr_idx)); + + return 0; +} + +static void pmu_timer_trigger_irq(RISCVCPU *cpu, + enum riscv_pmu_event_idx evt_idx) +{ + uint32_t ctr_idx; + CPURISCVState *env = &cpu->env; + PMUCTRState *counter; + target_ulong *mhpmevent_val; + uint64_t of_bit_mask; + int64_t irq_trigger_at; + + if (evt_idx != RISCV_PMU_EVENT_HW_CPU_CYCLES && + evt_idx != RISCV_PMU_EVENT_HW_INSTRUCTIONS) { + return; + } + + ctr_idx = GPOINTER_TO_UINT(g_hash_table_lookup(cpu->pmu_event_ctr_map, + GUINT_TO_POINTER(evt_idx))); + if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) { + return; + } + + if (riscv_cpu_mxl(env) == MXL_RV32) { + mhpmevent_val = &env->mhpmeventh_val[ctr_idx]; + of_bit_mask = MHPMEVENTH_BIT_OF; + } else { + mhpmevent_val = &env->mhpmevent_val[ctr_idx]; + of_bit_mask = MHPMEVENT_BIT_OF; + } + + counter = &env->pmu_ctrs[ctr_idx]; + if (counter->irq_overflow_left > 0) { + irq_trigger_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + + counter->irq_overflow_left; + timer_mod_anticipate_ns(cpu->pmu_timer, irq_trigger_at); + counter->irq_overflow_left = 0; + return; + } + + if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) { + /* Generate interrupt only if OF bit is clear */ + if (!(*mhpmevent_val & of_bit_mask)) { + *mhpmevent_val |= of_bit_mask; + riscv_cpu_update_mip(cpu, MIP_LCOFIP, BOOL_TO_MASK(1)); + } + } +} + +/* Timer callback for instret and cycle counter overflow */ +void riscv_pmu_timer_cb(void *priv) +{ + RISCVCPU *cpu = priv; + + /* Timer event was triggered only for these events */ + pmu_timer_trigger_irq(cpu, RISCV_PMU_EVENT_HW_CPU_CYCLES); + pmu_timer_trigger_irq(cpu, RISCV_PMU_EVENT_HW_INSTRUCTIONS); +} + +int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx) +{ + uint64_t overflow_delta, overflow_at; + int64_t overflow_ns, overflow_left = 0; + RISCVCPU *cpu = RISCV_CPU(env_cpu(env)); + PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; + + if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf) { + return -1; + } + + if (value) { + overflow_delta = UINT64_MAX - value + 1; + } else { + overflow_delta = UINT64_MAX; + } + + /* + * QEMU supports only int64_t timers while RISC-V counters are uint64_t. + * Compute the leftover and save it so that it can be reprogrammed again + * when timer expires. + */ + if (overflow_delta > INT64_MAX) { + overflow_left = overflow_delta - INT64_MAX; + } + + if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || + riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + overflow_ns = pmu_icount_ticks_to_ns((int64_t)overflow_delta); + overflow_left = pmu_icount_ticks_to_ns(overflow_left) ; + } else { + return -1; + } + overflow_at = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + overflow_ns; + + if (overflow_at > INT64_MAX) { + overflow_left += overflow_at - INT64_MAX; + counter->irq_overflow_left = overflow_left; + overflow_at = INT64_MAX; + } + timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + + return 0; +} + + +int riscv_pmu_init(RISCVCPU *cpu, int num_counters) +{ + if (num_counters > (RV_MAX_MHPMCOUNTERS - 3)) { + return -1; + } + + cpu->pmu_event_ctr_map = g_hash_table_new(g_direct_hash, g_direct_equal); + if (!cpu->pmu_event_ctr_map) { + /* PMU support can not be enabled */ + qemu_log_mask(LOG_UNIMP, "PMU events can't be supported\n"); + cpu->cfg.pmu_num = 0; + return -1; + } + + /* Create a bitmask of available programmable counters */ + cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, num_counters); + + return 0; } diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 58a5bc3a40..036653627f 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -26,3 +26,10 @@ bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env, uint32_t target_ctr); bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, uint32_t target_ctr); +void riscv_pmu_timer_cb(void *priv); +int riscv_pmu_init(RISCVCPU *cpu, int num_counters); +int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, + uint32_t ctr_idx); +int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx); +int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, + uint32_t ctr_idx); From ade445ef85aa0cf711a311132cb458f11f6a6d12 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:16:58 -0700 Subject: [PATCH 0402/1020] target/riscv: Simplify counter predicate function All the hpmcounters and the fixed counters (CY, IR, TM) can be represented as a unified counter. Thus, the predicate function doesn't need handle each case separately. Simplify the predicate function so that we just handle things differently between RV32/RV64 and S/HS mode. Reviewed-by: Bin Meng Acked-by: Alistair Francis Signed-off-by: Atish Patra Message-Id: <20220824221701.41932-3-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 110 ++++----------------------------------------- 1 file changed, 9 insertions(+), 101 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 888ddfc4dd..2151e280a8 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -75,6 +75,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno) CPUState *cs = env_cpu(env); RISCVCPU *cpu = RISCV_CPU(cs); int ctr_index; + target_ulong ctr_mask; int base_csrno = CSR_CYCLE; bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false; @@ -83,122 +84,29 @@ static RISCVException ctr(CPURISCVState *env, int csrno) base_csrno += 0x80; } ctr_index = csrno - base_csrno; + ctr_mask = BIT(ctr_index); if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) || (csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) { goto skip_ext_pmu_check; } - if ((!cpu->cfg.pmu_num || !(cpu->pmu_avail_ctrs & BIT(ctr_index)))) { + if (!(cpu->pmu_avail_ctrs & ctr_mask)) { /* No counter is enabled in PMU or the counter is out of range */ return RISCV_EXCP_ILLEGAL_INST; } skip_ext_pmu_check: - if (env->priv == PRV_S) { - switch (csrno) { - case CSR_CYCLE: - if (!get_field(env->mcounteren, COUNTEREN_CY)) { - return RISCV_EXCP_ILLEGAL_INST; - } - break; - case CSR_TIME: - if (!get_field(env->mcounteren, COUNTEREN_TM)) { - return RISCV_EXCP_ILLEGAL_INST; - } - break; - case CSR_INSTRET: - if (!get_field(env->mcounteren, COUNTEREN_IR)) { - return RISCV_EXCP_ILLEGAL_INST; - } - break; - case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31: - if (!get_field(env->mcounteren, 1 << ctr_index)) { - return RISCV_EXCP_ILLEGAL_INST; - } - break; - } - if (rv32) { - switch (csrno) { - case CSR_CYCLEH: - if (!get_field(env->mcounteren, COUNTEREN_CY)) { - return RISCV_EXCP_ILLEGAL_INST; - } - break; - case CSR_TIMEH: - if (!get_field(env->mcounteren, COUNTEREN_TM)) { - return RISCV_EXCP_ILLEGAL_INST; - } - break; - case CSR_INSTRETH: - if (!get_field(env->mcounteren, COUNTEREN_IR)) { - return RISCV_EXCP_ILLEGAL_INST; - } - break; - case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H: - if (!get_field(env->mcounteren, 1 << ctr_index)) { - return RISCV_EXCP_ILLEGAL_INST; - } - break; - } - } + if (((env->priv == PRV_S) && (!get_field(env->mcounteren, ctr_mask))) || + ((env->priv == PRV_U) && (!get_field(env->scounteren, ctr_mask)))) { + return RISCV_EXCP_ILLEGAL_INST; } if (riscv_cpu_virt_enabled(env)) { - switch (csrno) { - case CSR_CYCLE: - if (!get_field(env->hcounteren, COUNTEREN_CY) && - get_field(env->mcounteren, COUNTEREN_CY)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_TIME: - if (!get_field(env->hcounteren, COUNTEREN_TM) && - get_field(env->mcounteren, COUNTEREN_TM)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_INSTRET: - if (!get_field(env->hcounteren, COUNTEREN_IR) && - get_field(env->mcounteren, COUNTEREN_IR)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31: - if (!get_field(env->hcounteren, 1 << ctr_index) && - get_field(env->mcounteren, 1 << ctr_index)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - } - if (rv32) { - switch (csrno) { - case CSR_CYCLEH: - if (!get_field(env->hcounteren, COUNTEREN_CY) && - get_field(env->mcounteren, COUNTEREN_CY)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_TIMEH: - if (!get_field(env->hcounteren, COUNTEREN_TM) && - get_field(env->mcounteren, COUNTEREN_TM)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_INSTRETH: - if (!get_field(env->hcounteren, COUNTEREN_IR) && - get_field(env->mcounteren, COUNTEREN_IR)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H: - if (!get_field(env->hcounteren, 1 << ctr_index) && - get_field(env->mcounteren, 1 << ctr_index)) { - return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; - } - break; - } + if (!get_field(env->hcounteren, ctr_mask) && + get_field(env->mcounteren, ctr_mask)) { + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } } #endif From 892320facd73136b48bb58af3bd742686eb05416 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:16:59 -0700 Subject: [PATCH 0403/1020] target/riscv: Add few cache related PMU events Qemu can monitor the following cache related PMU events through tlb_fill functions. 1. DTLB load/store miss 3. ITLB prefetch miss Increment the PMU counter in tlb_fill function. Reviewed-by: Alistair Francis Tested-by: Heiko Stuebner Signed-off-by: Atish Patra Signed-off-by: Atish Patra Message-Id: <20220824221701.41932-4-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_helper.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 719c5d5d02..67e4c0efd2 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -21,11 +21,13 @@ #include "qemu/log.h" #include "qemu/main-loop.h" #include "cpu.h" +#include "pmu.h" #include "exec/exec-all.h" #include "instmap.h" #include "tcg/tcg-op.h" #include "trace.h" #include "semihosting/common-semi.h" +#include "cpu_bits.h" int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch) { @@ -1189,6 +1191,28 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr, cpu_loop_exit_restore(cs, retaddr); } + +static void pmu_tlb_fill_incr_ctr(RISCVCPU *cpu, MMUAccessType access_type) +{ + enum riscv_pmu_event_idx pmu_event_type; + + switch (access_type) { + case MMU_INST_FETCH: + pmu_event_type = RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS; + break; + case MMU_DATA_LOAD: + pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS; + break; + case MMU_DATA_STORE: + pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS; + break; + default: + return; + } + + riscv_pmu_incr_ctr(cpu, pmu_event_type); +} + bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr) @@ -1287,6 +1311,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, } } } else { + pmu_tlb_fill_incr_ctr(cpu, access_type); /* Single stage lookup */ ret = get_physical_address(env, &pa, &prot, address, NULL, access_type, mmu_idx, true, false, false); From abd9a20665496aa4f3680fbbd42b5c389ea53d1c Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:17:00 -0700 Subject: [PATCH 0404/1020] hw/riscv: virt: Add PMU DT node to the device tree Qemu virt machine can support few cache events and cycle/instret counters. It also supports counter overflow for these events. Add a DT node so that OpenSBI/Linux kernel is aware of the virt machine capabilities. There are some dummy nodes added for testing as well. Acked-by: Alistair Francis Signed-off-by: Atish Patra Signed-off-by: Atish Patra Message-Id: <20220824221701.41932-5-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- hw/riscv/virt.c | 16 +++++++++++++ target/riscv/pmu.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++ target/riscv/pmu.h | 1 + 3 files changed, 74 insertions(+) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index ff8c0df5cd..befa9d2c26 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -30,6 +30,7 @@ #include "hw/char/serial.h" #include "target/riscv/cpu.h" #include "hw/core/sysbus-fdt.h" +#include "target/riscv/pmu.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/virt.h" #include "hw/riscv/boot.h" @@ -708,6 +709,20 @@ static void create_fdt_socket_aplic(RISCVVirtState *s, aplic_phandles[socket] = aplic_s_phandle; } +static void create_fdt_pmu(RISCVVirtState *s) +{ + char *pmu_name; + MachineState *mc = MACHINE(s); + RISCVCPU hart = s->soc[0].harts[0]; + + pmu_name = g_strdup_printf("/soc/pmu"); + qemu_fdt_add_subnode(mc->fdt, pmu_name); + qemu_fdt_setprop_string(mc->fdt, pmu_name, "compatible", "riscv,pmu"); + riscv_pmu_generate_fdt_node(mc->fdt, hart.cfg.pmu_num, pmu_name); + + g_free(pmu_name); +} + static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap, bool is_32_bit, uint32_t *phandle, uint32_t *irq_mmio_phandle, @@ -1036,6 +1051,7 @@ static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap, create_fdt_flash(s, memmap); create_fdt_fw_cfg(s, memmap); + create_fdt_pmu(s); update_bootargs: if (cmdline && *cmdline) { diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index a5f504e53c..b8e56d2b7b 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -20,11 +20,68 @@ #include "cpu.h" #include "pmu.h" #include "sysemu/cpu-timers.h" +#include "sysemu/device_tree.h" #define RISCV_TIMEBASE_FREQ 1000000000 /* 1Ghz */ #define MAKE_32BIT_MASK(shift, length) \ (((uint32_t)(~0UL) >> (32 - (length))) << (shift)) +/* + * To keep it simple, any event can be mapped to any programmable counters in + * QEMU. The generic cycle & instruction count events can also be monitored + * using programmable counters. In that case, mcycle & minstret must continue + * to provide the correct value as well. Heterogeneous PMU per hart is not + * supported yet. Thus, number of counters are same across all harts. + */ +void riscv_pmu_generate_fdt_node(void *fdt, int num_ctrs, char *pmu_name) +{ + uint32_t fdt_event_ctr_map[20] = {}; + uint32_t cmask; + + /* All the programmable counters can map to any event */ + cmask = MAKE_32BIT_MASK(3, num_ctrs); + + /* + * The event encoding is specified in the SBI specification + * Event idx is a 20bits wide number encoded as follows: + * event_idx[19:16] = type + * event_idx[15:0] = code + * The code field in cache events are encoded as follows: + * event_idx.code[15:3] = cache_id + * event_idx.code[2:1] = op_id + * event_idx.code[0:0] = result_id + */ + + /* SBI_PMU_HW_CPU_CYCLES: 0x01 : type(0x00) */ + fdt_event_ctr_map[0] = cpu_to_be32(0x00000001); + fdt_event_ctr_map[1] = cpu_to_be32(0x00000001); + fdt_event_ctr_map[2] = cpu_to_be32(cmask | 1 << 0); + + /* SBI_PMU_HW_INSTRUCTIONS: 0x02 : type(0x00) */ + fdt_event_ctr_map[3] = cpu_to_be32(0x00000002); + fdt_event_ctr_map[4] = cpu_to_be32(0x00000002); + fdt_event_ctr_map[5] = cpu_to_be32(cmask | 1 << 2); + + /* SBI_PMU_HW_CACHE_DTLB : 0x03 READ : 0x00 MISS : 0x00 type(0x01) */ + fdt_event_ctr_map[6] = cpu_to_be32(0x00010019); + fdt_event_ctr_map[7] = cpu_to_be32(0x00010019); + fdt_event_ctr_map[8] = cpu_to_be32(cmask); + + /* SBI_PMU_HW_CACHE_DTLB : 0x03 WRITE : 0x01 MISS : 0x00 type(0x01) */ + fdt_event_ctr_map[9] = cpu_to_be32(0x0001001B); + fdt_event_ctr_map[10] = cpu_to_be32(0x0001001B); + fdt_event_ctr_map[11] = cpu_to_be32(cmask); + + /* SBI_PMU_HW_CACHE_ITLB : 0x04 READ : 0x00 MISS : 0x00 type(0x01) */ + fdt_event_ctr_map[12] = cpu_to_be32(0x00010021); + fdt_event_ctr_map[13] = cpu_to_be32(0x00010021); + fdt_event_ctr_map[14] = cpu_to_be32(cmask); + + /* This a OpenSBI specific DT property documented in OpenSBI docs */ + qemu_fdt_setprop(fdt, pmu_name, "riscv,event-to-mhpmcounters", + fdt_event_ctr_map, sizeof(fdt_event_ctr_map)); +} + static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx) { if (ctr_idx < 3 || ctr_idx >= RV_MAX_MHPMCOUNTERS || diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 036653627f..3004ce37b6 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -31,5 +31,6 @@ int riscv_pmu_init(RISCVCPU *cpu, int num_counters); int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx); +void riscv_pmu_generate_fdt_node(void *fdt, int num_counters, char *pmu_name); int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); From f0551560b5c01b1dcbed1ac46ca0bd1155330f5f Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Wed, 24 Aug 2022 15:17:01 -0700 Subject: [PATCH 0405/1020] target/riscv: Update the privilege field for sscofpmf CSRs The sscofpmf extension was ratified as a part of priv spec v1.12. Mark the csr_ops accordingly. Reviewed-by: Weiwei Li Reviewed-by: Alistair Francis Signed-off-by: Atish Patra Message-Id: <20220824221701.41932-6-atishp@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 90 ++++++++++++++++++++++++++++++---------------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 2151e280a8..b96db1b62b 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -4067,63 +4067,92 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mhpmevent }, [CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT4H] = { "mhpmevent4h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT5H] = { "mhpmevent5h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT6H] = { "mhpmevent6h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT7H] = { "mhpmevent7h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT8H] = { "mhpmevent8h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT9H] = { "mhpmevent9h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT10H] = { "mhpmevent10h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT11H] = { "mhpmevent11h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT12H] = { "mhpmevent12h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT13H] = { "mhpmevent13h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT14H] = { "mhpmevent14h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT15H] = { "mhpmevent15h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT16H] = { "mhpmevent16h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT17H] = { "mhpmevent17h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT18H] = { "mhpmevent18h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT19H] = { "mhpmevent19h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT20H] = { "mhpmevent20h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT21H] = { "mhpmevent21h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT22H] = { "mhpmevent22h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT23H] = { "mhpmevent23h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT24H] = { "mhpmevent24h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT25H] = { "mhpmevent25h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT26H] = { "mhpmevent26h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT27H] = { "mhpmevent27h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT28H] = { "mhpmevent28h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT29H] = { "mhpmevent29h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT30H] = { "mhpmevent30h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_MHPMEVENT31H] = { "mhpmevent31h", sscofpmf, read_mhpmeventh, - write_mhpmeventh }, + write_mhpmeventh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, [CSR_HPMCOUNTER3H] = { "hpmcounter3h", ctr32, read_hpmcounterh }, [CSR_HPMCOUNTER4H] = { "hpmcounter4h", ctr32, read_hpmcounterh }, @@ -4213,7 +4242,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mhpmcounterh }, [CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", mctr32, read_hpmcounterh, write_mhpmcounterh }, - [CSR_SCOUNTOVF] = { "scountovf", sscofpmf, read_scountovf }, + [CSR_SCOUNTOVF] = { "scountovf", sscofpmf, read_scountovf, + .min_priv_ver = PRIV_VERSION_1_12_0 }, #endif /* !CONFIG_USER_ONLY */ }; From 5d07159d639603e31f570665946e0817da313302 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:31 +0200 Subject: [PATCH 0406/1020] qapi: fix example of query-ballon command Example output has an extra ',' delimiter. Fix it. Problem was noticed when trying to load the example into python's json library. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-2-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/machine.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qapi/machine.json b/qapi/machine.json index 6afd1936b0..5f1f50d3ed 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1074,7 +1074,7 @@ # # -> { "execute": "query-balloon" } # <- { "return": { -# "actual": 1073741824, +# "actual": 1073741824 # } # } # From 5be07b3e54b4eb9781fd0fb729e0ac7406499605 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:32 +0200 Subject: [PATCH 0407/1020] qapi: fix example of query-vnc command Example output has an extra ',' delimiter in member "websocket" and it lacks it in "family" member. Fix it. Problem was noticed when trying to load the example into python's json library. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-3-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/ui.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qapi/ui.json b/qapi/ui.json index cf58ab4283..286c5731d1 100644 --- a/qapi/ui.json +++ b/qapi/ui.json @@ -667,8 +667,8 @@ # { # "host":"127.0.0.1", # "service":"50401", -# "family":"ipv4" -# "websocket":false, +# "family":"ipv4", +# "websocket":false # } # ] # } From 612fb7cd5492f7f421cbcbb6d6118ca7eef62c91 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:33 +0200 Subject: [PATCH 0408/1020] qapi: fix example of query-dump-guest-memory-capability command Example output is missing closing curly brackets. Fix it. Problem was noticed when trying to load the example into python's json library. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-4-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/dump.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qapi/dump.json b/qapi/dump.json index 90859c5483..6fc215dd47 100644 --- a/qapi/dump.json +++ b/qapi/dump.json @@ -195,7 +195,7 @@ # # -> { "execute": "query-dump-guest-memory-capability" } # <- { "return": { "formats": -# ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] } +# ["elf", "kdump-zlib", "kdump-lzo", "kdump-snappy"] } } # ## { 'command': 'query-dump-guest-memory-capability', From ccc9ddbcbe5a0a8d7d2881bf6b17324016fb994b Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:34 +0200 Subject: [PATCH 0409/1020] qapi: fix example of BLOCK_JOB_READY event Example output is missing ',' delimiter. Fix it. Problem was noticed when trying to load the example into python's json library. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-5-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/block-core.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 2173e7734a..882b266532 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -5252,7 +5252,7 @@ # # <- { "event": "BLOCK_JOB_READY", # "data": { "device": "drive0", "type": "mirror", "speed": 0, -# "len": 2097152, "offset": 2097152 } +# "len": 2097152, "offset": 2097152 }, # "timestamp": { "seconds": 1265044230, "microseconds": 450486 } } # ## From dac318d3dfebfb89e0266ad12df2792bb33c5210 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:35 +0200 Subject: [PATCH 0410/1020] qapi: fix example of NIC_RX_FILTER_CHANGED event Example output has an extra ending curly bracket. Fix it. Problem was noticed when trying to load the example into python's json library. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-6-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/net.json | 1 - 1 file changed, 1 deletion(-) diff --git a/qapi/net.json b/qapi/net.json index 75ba2cb989..dd088c09c5 100644 --- a/qapi/net.json +++ b/qapi/net.json @@ -757,7 +757,6 @@ # "data": { "name": "vnet0", # "path": "/machine/peripheral/vnet0/virtio-backend" }, # "timestamp": { "seconds": 1368697518, "microseconds": 326866 } } -# } # ## { 'event': 'NIC_RX_FILTER_CHANGED', From 0cd5a5e9c9f3255d76e52b6f8a3790ba4044ce2e Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:36 +0200 Subject: [PATCH 0411/1020] qapi: fix example of DEVICE_UNPLUG_GUEST_ERROR event Example output is missing a ',' delimiter and it has an extra ending curly bracket. Fix it. Problem was noticed when trying to load the example into python's json library. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-7-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/qdev.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qapi/qdev.json b/qapi/qdev.json index 26cd10106b..2708fb4e99 100644 --- a/qapi/qdev.json +++ b/qapi/qdev.json @@ -150,10 +150,9 @@ # # Example: # -# <- { "event": "DEVICE_UNPLUG_GUEST_ERROR" +# <- { "event": "DEVICE_UNPLUG_GUEST_ERROR", # "data": { "device": "core1", # "path": "/machine/peripheral/core1" }, -# }, # "timestamp": { "seconds": 1615570772, "microseconds": 202844 } } # ## From e8796ac4b6f8a9f8d1d2c3c6a774d815d10d88c5 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:37 +0200 Subject: [PATCH 0412/1020] qapi: fix example of MEM_UNPLUG_ERROR event Example output was missing ',' delimiter. Fix it. Problem was noticed when trying to load the example into python's json library. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-8-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/machine.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qapi/machine.json b/qapi/machine.json index 5f1f50d3ed..4782eea2c3 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -1416,7 +1416,7 @@ # # Example: # -# <- { "event": "MEM_UNPLUG_ERROR" +# <- { "event": "MEM_UNPLUG_ERROR", # "data": { "device": "dimm1", # "msg": "acpi: device unplug for unsupported device" # }, From b6522938327141235b97ab38e40c6c4512587373 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:38 +0200 Subject: [PATCH 0413/1020] qapi: fix examples of blockdev-add with qcow2 The examples use "qcow2" driver with the wrong member name for BlockdevRef alternate type. This patch changes all wrong member names from "file" to "data-file" which is the correct member name in BlockdevOptionsQcow2 for the BlockdevRef field. Problem was noticed when using the example as a test case for Go bindings. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-9-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/block-core.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index 882b266532..f21fa235f2 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1541,8 +1541,8 @@ # -> { "execute": "blockdev-add", # "arguments": { "driver": "qcow2", # "node-name": "node1534", -# "file": { "driver": "file", -# "filename": "hd1.qcow2" }, +# "data-file": { "driver": "file", +# "filename": "hd1.qcow2" }, # "backing": null } } # # <- { "return": {} } @@ -4378,7 +4378,7 @@ # "arguments": { # "driver": "qcow2", # "node-name": "test1", -# "file": { +# "data-file": { # "driver": "file", # "filename": "test.qcow2" # } @@ -4395,7 +4395,7 @@ # "cache": { # "direct": true # }, -# "file": { +# "data-file": { # "driver": "file", # "filename": "/tmp/test.qcow2" # }, @@ -4477,7 +4477,7 @@ # "arguments": { # "driver": "qcow2", # "node-name": "node0", -# "file": { +# "data-file": { # "driver": "file", # "filename": "test.qcow2" # } From b4c32cbf06621117214f71501866514011434f43 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:39 +0200 Subject: [PATCH 0414/1020] qapi: fix example of query-hotpluggable-cpus command The example return type has the wrong member name. Fix it. Problem was noticed when using the example as a test case for Go bindings. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-10-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/machine.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qapi/machine.json b/qapi/machine.json index 4782eea2c3..abb2f48808 100644 --- a/qapi/machine.json +++ b/qapi/machine.json @@ -958,9 +958,9 @@ # # -> { "execute": "query-hotpluggable-cpus" } # <- {"return": [ -# { "props": { "core": 8 }, "type": "POWER8-spapr-cpu-core", +# { "props": { "core-id": 8 }, "type": "POWER8-spapr-cpu-core", # "vcpus-count": 1 }, -# { "props": { "core": 0 }, "type": "POWER8-spapr-cpu-core", +# { "props": { "core-id": 0 }, "type": "POWER8-spapr-cpu-core", # "vcpus-count": 1, "qom-path": "/machine/unattached/device[0]"} # ]}' # From 6e7a37ffc230d06852f1a8893097331d39df77c9 Mon Sep 17 00:00:00 2001 From: Victor Toso Date: Thu, 1 Sep 2022 10:58:40 +0200 Subject: [PATCH 0415/1020] qapi: fix examples of events missing timestamp I've used real timestamp and changing them one by one so they would not be all equal. Problem was noticed when using the example as a test case for Go bindings. Signed-off-by: Victor Toso Message-Id: <20220901085840.22520-11-victortoso@redhat.com> Signed-off-by: Markus Armbruster --- qapi/migration.json | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/qapi/migration.json b/qapi/migration.json index 81185d4311..88ecf86ac8 100644 --- a/qapi/migration.json +++ b/qapi/migration.json @@ -1995,16 +1995,23 @@ # } # <- { "return": { } } # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1432121972, "microseconds": 744001}, # "data": {"status": "created", "id": "snapsave0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1432122172, "microseconds": 744001}, # "data": {"status": "running", "id": "snapsave0"}} -# <- {"event": "STOP"} -# <- {"event": "RESUME"} +# <- {"event": "STOP", +# "timestamp": {"seconds": 1432122372, "microseconds": 744001} } +# <- {"event": "RESUME", +# "timestamp": {"seconds": 1432122572, "microseconds": 744001} } # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1432122772, "microseconds": 744001}, # "data": {"status": "waiting", "id": "snapsave0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1432122972, "microseconds": 744001}, # "data": {"status": "pending", "id": "snapsave0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1432123172, "microseconds": 744001}, # "data": {"status": "concluded", "id": "snapsave0"}} # -> {"execute": "query-jobs"} # <- {"return": [{"current-progress": 1, @@ -2056,16 +2063,23 @@ # } # <- { "return": { } } # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1472124172, "microseconds": 744001}, # "data": {"status": "created", "id": "snapload0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1472125172, "microseconds": 744001}, # "data": {"status": "running", "id": "snapload0"}} -# <- {"event": "STOP"} -# <- {"event": "RESUME"} +# <- {"event": "STOP", +# "timestamp": {"seconds": 1472125472, "microseconds": 744001} } +# <- {"event": "RESUME", +# "timestamp": {"seconds": 1472125872, "microseconds": 744001} } # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1472126172, "microseconds": 744001}, # "data": {"status": "waiting", "id": "snapload0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1472127172, "microseconds": 744001}, # "data": {"status": "pending", "id": "snapload0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1472128172, "microseconds": 744001}, # "data": {"status": "concluded", "id": "snapload0"}} # -> {"execute": "query-jobs"} # <- {"return": [{"current-progress": 1, @@ -2108,14 +2122,19 @@ # } # <- { "return": { } } # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1442124172, "microseconds": 744001}, # "data": {"status": "created", "id": "snapdelete0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1442125172, "microseconds": 744001}, # "data": {"status": "running", "id": "snapdelete0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1442126172, "microseconds": 744001}, # "data": {"status": "waiting", "id": "snapdelete0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1442127172, "microseconds": 744001}, # "data": {"status": "pending", "id": "snapdelete0"}} # <- {"event": "JOB_STATUS_CHANGE", +# "timestamp": {"seconds": 1442128172, "microseconds": 744001}, # "data": {"status": "concluded", "id": "snapdelete0"}} # -> {"execute": "query-jobs"} # <- {"return": [{"current-progress": 1, From a0bcec03761477371ff7c2e80dc07fff14222d92 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Mon, 1 Aug 2022 15:25:25 +0100 Subject: [PATCH 0416/1020] tpm_emulator: Avoid double initialization during migration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When resuming after a migration, the backend sends CMD_INIT to the emulator from the startup callback, then it sends the migration state from the vmstate to the emulator, then it sends CMD_INIT again. Skip the first CMD_INIT during a migration to avoid initializing the TPM twice. Signed-off-by: Ross Lagerwall Reviewed-by: Marc-AndrĂ© Lureau Tested-by: Stefan Berger Signed-off-by: Stefan Berger --- backends/tpm/tpm_emulator.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c index 87d061e9bb..9b50c5b3e2 100644 --- a/backends/tpm/tpm_emulator.c +++ b/backends/tpm/tpm_emulator.c @@ -32,6 +32,7 @@ #include "qemu/sockets.h" #include "qemu/lockable.h" #include "io/channel-socket.h" +#include "sysemu/runstate.h" #include "sysemu/tpm_backend.h" #include "sysemu/tpm_util.h" #include "tpm_int.h" @@ -383,6 +384,15 @@ err_exit: static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize) { + /* TPM startup will be done from post_load hook */ + if (runstate_check(RUN_STATE_INMIGRATE)) { + if (buffersize != 0) { + return tpm_emulator_set_buffer_size(tb, buffersize, NULL); + } + + return 0; + } + return tpm_emulator_startup_tpm_resume(tb, buffersize, false); } From f0ccce6a95f6ff947040692ef941230918181562 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Fri, 26 Aug 2022 15:38:41 +0100 Subject: [PATCH 0417/1020] tpm_crb: Avoid backend startup just before shutdown under Xen When running under Xen and the guest reboots, it boots into a new domain with a new QEMU process (and a new swtpm process if using the emulator backend). The existing reset function is triggered just before the old QEMU process exists which causes QEMU to startup the TPM backend and then immediately shut it down. This is probably harmless but when using the emulated backend, it wastes CPU and IO time reloading state, etc. Fix this by calling the reset function directly from realize() when running under Xen. During a reboot, this will be called by the QEMU process for the new domain. Signed-off-by: Ross Lagerwall Reviewed-by: Stefan Berger Message-id: 20220826143841.1515326-1-ross.lagerwall@citrix.com Signed-off-by: Stefan Berger --- hw/tpm/tpm_crb.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/tpm/tpm_crb.c b/hw/tpm/tpm_crb.c index 67db594c48..ea930da545 100644 --- a/hw/tpm/tpm_crb.c +++ b/hw/tpm/tpm_crb.c @@ -26,6 +26,7 @@ #include "sysemu/tpm_backend.h" #include "sysemu/tpm_util.h" #include "sysemu/reset.h" +#include "sysemu/xen.h" #include "tpm_prop.h" #include "tpm_ppi.h" #include "trace.h" @@ -308,7 +309,11 @@ static void tpm_crb_realize(DeviceState *dev, Error **errp) TPM_PPI_ADDR_BASE, OBJECT(s)); } - qemu_register_reset(tpm_crb_reset, dev); + if (xen_enabled()) { + tpm_crb_reset(dev); + } else { + qemu_register_reset(tpm_crb_reset, dev); + } } static void tpm_crb_class_init(ObjectClass *klass, void *data) From efef4756c7f66e51fd5bfa132680ee0fb585f7a5 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Mon, 12 Sep 2022 13:47:40 -0400 Subject: [PATCH 0418/1020] tpm_emulator: Use latest tpm_ioctl.h from swtpm project MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the latest tpm_ioctl.h from upstream swtpm project. Signed-off-by: Stefan Berger Reviewed-by: Marc-AndrĂ© Lureau Message-id: 20220912174741.1542330-2-stefanb@linux.ibm.com --- backends/tpm/tpm_ioctl.h | 96 +++++++++++++++++++++++++++++++--------- 1 file changed, 76 insertions(+), 20 deletions(-) diff --git a/backends/tpm/tpm_ioctl.h b/backends/tpm/tpm_ioctl.h index d67bf0283b..e506ef5160 100644 --- a/backends/tpm/tpm_ioctl.h +++ b/backends/tpm/tpm_ioctl.h @@ -5,10 +5,15 @@ * * This file is licensed under the terms of the 3-clause BSD license */ +#ifndef _TPM_IOCTL_H_ +#define _TPM_IOCTL_H_ -#ifndef TPM_IOCTL_H -#define TPM_IOCTL_H +#if defined(__CYGWIN__) +# define __USE_LINUX_IOCTL_DEFS +#endif +#include +#include #ifndef _WIN32 #include #include @@ -196,6 +201,48 @@ struct ptm_setbuffersize { } u; }; +#define PTM_GETINFO_SIZE (3 * 1024) +/* + * PTM_GET_INFO: Get info about the TPM implementation (from libtpms) + * + * This request allows to indirectly call TPMLIB_GetInfo(flags) and + * retrieve information from libtpms. + * Only one transaction is currently necessary for returning results + * to a client. Therefore, totlength and length will be the same if + * offset is 0. + */ +struct ptm_getinfo { + union { + struct { + uint64_t flags; + uint32_t offset; /* offset from where to read */ + uint32_t pad; /* 32 bit arch */ + } req; /* request */ + struct { + ptm_res tpm_result; + uint32_t totlength; + uint32_t length; + char buffer[PTM_GETINFO_SIZE]; + } resp; /* response */ + } u; +}; + +#define SWTPM_INFO_TPMSPECIFICATION ((uint64_t)1 << 0) +#define SWTPM_INFO_TPMATTRIBUTES ((uint64_t)1 << 1) + +/* + * PTM_LOCK_STORAGE: Lock the storage and retry n times + */ +struct ptm_lockstorage { + union { + struct { + uint32_t retries; /* number of retries */ + } req; /* request */ + struct { + ptm_res tpm_result; + } resp; /* reponse */ + } u; +}; typedef uint64_t ptm_cap; typedef struct ptm_est ptm_est; @@ -207,6 +254,8 @@ typedef struct ptm_getstate ptm_getstate; typedef struct ptm_setstate ptm_setstate; typedef struct ptm_getconfig ptm_getconfig; typedef struct ptm_setbuffersize ptm_setbuffersize; +typedef struct ptm_getinfo ptm_getinfo; +typedef struct ptm_lockstorage ptm_lockstorage; /* capability flags returned by PTM_GET_CAPABILITY */ #define PTM_CAP_INIT (1) @@ -223,6 +272,9 @@ typedef struct ptm_setbuffersize ptm_setbuffersize; #define PTM_CAP_GET_CONFIG (1 << 11) #define PTM_CAP_SET_DATAFD (1 << 12) #define PTM_CAP_SET_BUFFERSIZE (1 << 13) +#define PTM_CAP_GET_INFO (1 << 14) +#define PTM_CAP_SEND_COMMAND_HEADER (1 << 15) +#define PTM_CAP_LOCK_STORAGE (1 << 16) #ifndef _WIN32 enum { @@ -243,6 +295,8 @@ enum { PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig), PTM_SET_DATAFD = _IOR('P', 15, ptm_res), PTM_SET_BUFFERSIZE = _IOWR('P', 16, ptm_setbuffersize), + PTM_GET_INFO = _IOWR('P', 17, ptm_getinfo), + PTM_LOCK_STORAGE = _IOWR('P', 18, ptm_lockstorage), }; #endif @@ -257,23 +311,25 @@ enum { * and ptm_set_state:u.req.data) are 0xffffffff. */ enum { - CMD_GET_CAPABILITY = 1, - CMD_INIT, - CMD_SHUTDOWN, - CMD_GET_TPMESTABLISHED, - CMD_SET_LOCALITY, - CMD_HASH_START, - CMD_HASH_DATA, - CMD_HASH_END, - CMD_CANCEL_TPM_CMD, - CMD_STORE_VOLATILE, - CMD_RESET_TPMESTABLISHED, - CMD_GET_STATEBLOB, - CMD_SET_STATEBLOB, - CMD_STOP, - CMD_GET_CONFIG, - CMD_SET_DATAFD, - CMD_SET_BUFFERSIZE, + CMD_GET_CAPABILITY = 1, /* 0x01 */ + CMD_INIT, /* 0x02 */ + CMD_SHUTDOWN, /* 0x03 */ + CMD_GET_TPMESTABLISHED, /* 0x04 */ + CMD_SET_LOCALITY, /* 0x05 */ + CMD_HASH_START, /* 0x06 */ + CMD_HASH_DATA, /* 0x07 */ + CMD_HASH_END, /* 0x08 */ + CMD_CANCEL_TPM_CMD, /* 0x09 */ + CMD_STORE_VOLATILE, /* 0x0a */ + CMD_RESET_TPMESTABLISHED, /* 0x0b */ + CMD_GET_STATEBLOB, /* 0x0c */ + CMD_SET_STATEBLOB, /* 0x0d */ + CMD_STOP, /* 0x0e */ + CMD_GET_CONFIG, /* 0x0f */ + CMD_SET_DATAFD, /* 0x10 */ + CMD_SET_BUFFERSIZE, /* 0x11 */ + CMD_GET_INFO, /* 0x12 */ + CMD_LOCK_STORAGE, /* 0x13 */ }; -#endif /* TPM_IOCTL_H */ +#endif /* _TPM_IOCTL_H_ */ From 99bdcd2cc2d05833f5c11caca22193f8dd878ae9 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Mon, 12 Sep 2022 13:47:41 -0400 Subject: [PATCH 0419/1020] tpm_emulator: Have swtpm relock storage upon migration fall-back MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swtpm may release the lock once the last one of its state blobs has been migrated out. In case of VM migration failure QEMU now needs to notify swtpm that it should again take the lock, which it can otherwise only do once it has received the first TPM command from the VM. Only try to send the lock command if swtpm supports it. It will not have released the lock (and support shared storage setups) if it doesn't support the locking command since the functionality of releasing the lock upon state blob reception and the lock command were added to swtpm 'together'. If QEMU sends the lock command and the storage has already been locked no error is reported. If swtpm does not receive the lock command (from older version of QEMU), it will lock the storage once the first TPM command has been received. So sending the lock command is an optimization. Signed-off-by: Stefan Berger Reviewed-by: Marc-AndrĂ© Lureau Message-id: 20220912174741.1542330-3-stefanb@linux.ibm.com --- backends/tpm/tpm_emulator.c | 60 ++++++++++++++++++++++++++++++++++++- backends/tpm/trace-events | 2 ++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/backends/tpm/tpm_emulator.c b/backends/tpm/tpm_emulator.c index 9b50c5b3e2..49cc3d749d 100644 --- a/backends/tpm/tpm_emulator.c +++ b/backends/tpm/tpm_emulator.c @@ -35,6 +35,7 @@ #include "sysemu/runstate.h" #include "sysemu/tpm_backend.h" #include "sysemu/tpm_util.h" +#include "sysemu/runstate.h" #include "tpm_int.h" #include "tpm_ioctl.h" #include "migration/blocker.h" @@ -82,6 +83,9 @@ struct TPMEmulator { unsigned int established_flag_cached:1; TPMBlobBuffers state_blobs; + + bool relock_storage; + VMChangeStateEntry *vmstate; }; struct tpm_error { @@ -303,6 +307,35 @@ static int tpm_emulator_stop_tpm(TPMBackend *tb) return 0; } +static int tpm_emulator_lock_storage(TPMEmulator *tpm_emu) +{ + ptm_lockstorage pls; + + if (!TPM_EMULATOR_IMPLEMENTS_ALL_CAPS(tpm_emu, PTM_CAP_LOCK_STORAGE)) { + trace_tpm_emulator_lock_storage_cmd_not_supt(); + return 0; + } + + /* give failing side 300 * 10ms time to release lock */ + pls.u.req.retries = cpu_to_be32(300); + if (tpm_emulator_ctrlcmd(tpm_emu, CMD_LOCK_STORAGE, &pls, + sizeof(pls.u.req), sizeof(pls.u.resp)) < 0) { + error_report("tpm-emulator: Could not lock storage within 3 seconds: " + "%s", strerror(errno)); + return -1; + } + + pls.u.resp.tpm_result = be32_to_cpu(pls.u.resp.tpm_result); + if (pls.u.resp.tpm_result != 0) { + error_report("tpm-emulator: TPM result for CMD_LOCK_STORAGE: 0x%x %s", + pls.u.resp.tpm_result, + tpm_emulator_strerror(pls.u.resp.tpm_result)); + return -1; + } + + return 0; +} + static int tpm_emulator_set_buffer_size(TPMBackend *tb, size_t wanted_size, size_t *actual_size) @@ -853,13 +886,34 @@ static int tpm_emulator_pre_save(void *opaque) { TPMBackend *tb = opaque; TPMEmulator *tpm_emu = TPM_EMULATOR(tb); + int ret; trace_tpm_emulator_pre_save(); tpm_backend_finish_sync(tb); /* get the state blobs from the TPM */ - return tpm_emulator_get_state_blobs(tpm_emu); + ret = tpm_emulator_get_state_blobs(tpm_emu); + + tpm_emu->relock_storage = ret == 0; + + return ret; +} + +static void tpm_emulator_vm_state_change(void *opaque, bool running, + RunState state) +{ + TPMBackend *tb = opaque; + TPMEmulator *tpm_emu = TPM_EMULATOR(tb); + + trace_tpm_emulator_vm_state_change(running, state); + + if (!running || state != RUN_STATE_RUNNING || !tpm_emu->relock_storage) { + return; + } + + /* lock storage after migration fall-back */ + tpm_emulator_lock_storage(tpm_emu); } /* @@ -921,6 +975,9 @@ static void tpm_emulator_inst_init(Object *obj) tpm_emu->options = g_new0(TPMEmulatorOptions, 1); tpm_emu->cur_locty_number = ~0; qemu_mutex_init(&tpm_emu->mutex); + tpm_emu->vmstate = + qemu_add_vm_change_state_handler(tpm_emulator_vm_state_change, + tpm_emu); vmstate_register(NULL, VMSTATE_INSTANCE_ID_ANY, &vmstate_tpm_emulator, obj); @@ -970,6 +1027,7 @@ static void tpm_emulator_inst_finalize(Object *obj) tpm_sized_buffer_reset(&state_blobs->savestate); qemu_mutex_destroy(&tpm_emu->mutex); + qemu_del_vm_change_state_handler(tpm_emu->vmstate); vmstate_unregister(NULL, &vmstate_tpm_emulator, obj); } diff --git a/backends/tpm/trace-events b/backends/tpm/trace-events index 3298766dd7..1ecef42a07 100644 --- a/backends/tpm/trace-events +++ b/backends/tpm/trace-events @@ -20,6 +20,8 @@ tpm_emulator_set_buffer_size(uint32_t buffersize, uint32_t minsize, uint32_t max tpm_emulator_startup_tpm_resume(bool is_resume, size_t buffersize) "is_resume: %d, buffer size: %zu" tpm_emulator_get_tpm_established_flag(uint8_t flag) "got established flag: %d" tpm_emulator_cancel_cmd_not_supt(void) "Backend does not support CANCEL_TPM_CMD" +tpm_emulator_lock_storage_cmd_not_supt(void) "Backend does not support LOCK_STORAGE" +tpm_emulator_vm_state_change(int running, int state) "state change to running %d state %d" tpm_emulator_handle_device_opts_tpm12(void) "TPM Version 1.2" tpm_emulator_handle_device_opts_tpm2(void) "TPM Version 2" tpm_emulator_handle_device_opts_unspec(void) "TPM Version Unspecified" From d1e23cbaa403b2d816e1cb2acd61105d00c38b9b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 29 Apr 2022 18:28:35 -0700 Subject: [PATCH 0420/1020] target/nios2: Use semihosting/syscalls.h This separates guest file descriptors from host file descriptors, and utilizes shared infrastructure for integration with gdbstub. Signed-off-by: Richard Henderson --- target/nios2/nios2-semi.c | 296 +++++++------------------------------- 1 file changed, 50 insertions(+), 246 deletions(-) diff --git a/target/nios2/nios2-semi.c b/target/nios2/nios2-semi.c index 55061bb2dc..614fd76695 100644 --- a/target/nios2/nios2-semi.c +++ b/target/nios2/nios2-semi.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "cpu.h" #include "exec/gdbstub.h" +#include "semihosting/syscalls.h" #include "semihosting/softmmu-uaccess.h" #include "qemu/log.h" @@ -42,67 +43,6 @@ #define HOSTED_ISATTY 12 #define HOSTED_SYSTEM 13 -static int translate_openflags(int flags) -{ - int hf; - - if (flags & GDB_O_WRONLY) { - hf = O_WRONLY; - } else if (flags & GDB_O_RDWR) { - hf = O_RDWR; - } else { - hf = O_RDONLY; - } - - if (flags & GDB_O_APPEND) { - hf |= O_APPEND; - } - if (flags & GDB_O_CREAT) { - hf |= O_CREAT; - } - if (flags & GDB_O_TRUNC) { - hf |= O_TRUNC; - } - if (flags & GDB_O_EXCL) { - hf |= O_EXCL; - } - - return hf; -} - -static bool translate_stat(CPUNios2State *env, target_ulong addr, - struct stat *s) -{ - struct gdb_stat *p; - - p = lock_user(VERIFY_WRITE, addr, sizeof(struct gdb_stat), 0); - - if (!p) { - return false; - } - p->gdb_st_dev = cpu_to_be32(s->st_dev); - p->gdb_st_ino = cpu_to_be32(s->st_ino); - p->gdb_st_mode = cpu_to_be32(s->st_mode); - p->gdb_st_nlink = cpu_to_be32(s->st_nlink); - p->gdb_st_uid = cpu_to_be32(s->st_uid); - p->gdb_st_gid = cpu_to_be32(s->st_gid); - p->gdb_st_rdev = cpu_to_be32(s->st_rdev); - p->gdb_st_size = cpu_to_be64(s->st_size); -#ifdef _WIN32 - /* Windows stat is missing some fields. */ - p->gdb_st_blksize = 0; - p->gdb_st_blocks = 0; -#else - p->gdb_st_blksize = cpu_to_be64(s->st_blksize); - p->gdb_st_blocks = cpu_to_be64(s->st_blocks); -#endif - p->gdb_st_atime = cpu_to_be32(s->st_atime); - p->gdb_st_mtime = cpu_to_be32(s->st_mtime); - p->gdb_st_ctime = cpu_to_be32(s->st_ctime); - unlock_user(p, addr, sizeof(struct gdb_stat)); - return true; -} - static void nios2_semi_u32_cb(CPUState *cs, uint64_t ret, int err) { Nios2CPU *cpu = NIOS2_CPU(cs); @@ -142,22 +82,22 @@ static void nios2_semi_u64_cb(CPUState *cs, uint64_t ret, int err) */ #define GET_ARG(n) do { \ if (get_user_ual(arg ## n, args + (n) * 4)) { \ - result = -1; \ - errno = EFAULT; \ goto failed; \ } \ } while (0) +#define GET_ARG64(n) do { \ + if (get_user_ual(arg ## n, args + (n) * 4)) { \ + goto failed64; \ + } \ +} while (0) + void do_nios2_semihosting(CPUNios2State *env) { CPUState *cs = env_cpu(env); int nr; uint32_t args; target_ulong arg0, arg1, arg2, arg3; - void *p; - void *q; - uint32_t len; - uint32_t result; nr = env->regs[R_ARG0]; args = env->regs[R_ARG1]; @@ -165,234 +105,98 @@ void do_nios2_semihosting(CPUNios2State *env) case HOSTED_EXIT: gdb_exit(env->regs[R_ARG0]); exit(env->regs[R_ARG0]); + case HOSTED_OPEN: GET_ARG(0); GET_ARG(1); GET_ARG(2); GET_ARG(3); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "open,%s,%x,%x", arg0, (int)arg1, - arg2, arg3); - return; - } else { - p = lock_user_string(arg0); - if (!p) { - result = -1; - errno = EFAULT; - } else { - result = open(p, translate_openflags(arg2), arg3); - unlock_user(p, arg0, 0); - } - } + semihost_sys_open(cs, nios2_semi_u32_cb, arg0, arg1, arg2, arg3); break; + case HOSTED_CLOSE: - { - /* Ignore attempts to close stdin/out/err. */ - GET_ARG(0); - int fd = arg0; - if (fd > 2) { - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "close,%x", arg0); - return; - } else { - result = close(fd); - } - } else { - result = 0; - } - break; - } + GET_ARG(0); + semihost_sys_close(cs, nios2_semi_u32_cb, arg0); + break; + case HOSTED_READ: GET_ARG(0); GET_ARG(1); GET_ARG(2); - len = arg2; - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "read,%x,%x,%x", - arg0, arg1, len); - return; - } else { - p = lock_user(VERIFY_WRITE, arg1, len, 0); - if (!p) { - result = -1; - errno = EFAULT; - } else { - result = read(arg0, p, len); - unlock_user(p, arg1, len); - } - } + semihost_sys_read(cs, nios2_semi_u32_cb, arg0, arg1, arg2); break; + case HOSTED_WRITE: GET_ARG(0); GET_ARG(1); GET_ARG(2); - len = arg2; - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "write,%x,%x,%x", - arg0, arg1, len); - return; - } else { - p = lock_user(VERIFY_READ, arg1, len, 1); - if (!p) { - result = -1; - errno = EFAULT; - } else { - result = write(arg0, p, len); - unlock_user(p, arg0, 0); - } - } + semihost_sys_write(cs, nios2_semi_u32_cb, arg0, arg1, arg2); break; + case HOSTED_LSEEK: - { - uint64_t off; - GET_ARG(0); - GET_ARG(1); - GET_ARG(2); - GET_ARG(3); - off = (uint32_t)arg2 | ((uint64_t)arg1 << 32); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u64_cb, "lseek,%x,%lx,%x", - arg0, off, arg3); - } else { - off = lseek(arg0, off, arg3); - nios2_semi_u64_cb(cs, off, errno); - } - return; - } + GET_ARG64(0); + GET_ARG64(1); + GET_ARG64(2); + GET_ARG64(3); + semihost_sys_lseek(cs, nios2_semi_u64_cb, arg0, + deposit64(arg2, arg1, 32, 32), arg3); + break; + case HOSTED_RENAME: GET_ARG(0); GET_ARG(1); GET_ARG(2); GET_ARG(3); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "rename,%s,%s", - arg0, (int)arg1, arg2, (int)arg3); - return; - } else { - p = lock_user_string(arg0); - q = lock_user_string(arg2); - if (!p || !q) { - result = -1; - errno = EFAULT; - } else { - result = rename(p, q); - } - unlock_user(p, arg0, 0); - unlock_user(q, arg2, 0); - } + semihost_sys_rename(cs, nios2_semi_u32_cb, arg0, arg1, arg2, arg3); break; + case HOSTED_UNLINK: GET_ARG(0); GET_ARG(1); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "unlink,%s", - arg0, (int)arg1); - return; - } else { - p = lock_user_string(arg0); - if (!p) { - result = -1; - errno = EFAULT; - } else { - result = unlink(p); - unlock_user(p, arg0, 0); - } - } + semihost_sys_remove(cs, nios2_semi_u32_cb, arg0, arg1); break; + case HOSTED_STAT: GET_ARG(0); GET_ARG(1); GET_ARG(2); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "stat,%s,%x", - arg0, (int)arg1, arg2); - return; - } else { - struct stat s; - p = lock_user_string(arg0); - if (!p) { - result = -1; - errno = EFAULT; - } else { - result = stat(p, &s); - unlock_user(p, arg0, 0); - } - if (result == 0 && !translate_stat(env, arg2, &s)) { - result = -1; - errno = EFAULT; - } - } + semihost_sys_stat(cs, nios2_semi_u32_cb, arg0, arg1, arg2); break; + case HOSTED_FSTAT: GET_ARG(0); GET_ARG(1); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "fstat,%x,%x", - arg0, arg1); - return; - } else { - struct stat s; - result = fstat(arg0, &s); - if (result == 0 && !translate_stat(env, arg1, &s)) { - result = -1; - errno = EFAULT; - } - } + semihost_sys_fstat(cs, nios2_semi_u32_cb, arg0, arg1); break; + case HOSTED_GETTIMEOFDAY: - /* Only the tv parameter is used. tz is assumed NULL. */ GET_ARG(0); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "gettimeofday,%x,%x", - arg0, 0); - return; - } else { - struct gdb_timeval *p; - int64_t rt = g_get_real_time(); - p = lock_user(VERIFY_WRITE, arg0, sizeof(struct gdb_timeval), 0); - if (!p) { - result = -1; - errno = EFAULT; - } else { - result = 0; - p->tv_sec = cpu_to_be32(rt / G_USEC_PER_SEC); - p->tv_usec = cpu_to_be64(rt % G_USEC_PER_SEC); - unlock_user(p, arg0, sizeof(struct gdb_timeval)); - } - } + GET_ARG(1); + semihost_sys_gettimeofday(cs, nios2_semi_u32_cb, arg0, arg1); break; + case HOSTED_ISATTY: GET_ARG(0); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "isatty,%x", arg0); - return; - } else { - result = isatty(arg0); - } + semihost_sys_isatty(cs, nios2_semi_u32_cb, arg0); break; + case HOSTED_SYSTEM: GET_ARG(0); GET_ARG(1); - if (use_gdb_syscalls()) { - gdb_do_syscall(nios2_semi_u32_cb, "system,%s", - arg0, (int)arg1); - return; - } else { - p = lock_user_string(arg0); - if (!p) { - result = -1; - errno = EFAULT; - } else { - result = system(p); - unlock_user(p, arg0, 0); - } - } + semihost_sys_system(cs, nios2_semi_u32_cb, arg0, arg1); break; + default: qemu_log_mask(LOG_GUEST_ERROR, "nios2-semihosting: unsupported " "semihosting syscall %d\n", nr); - result = 0; + nios2_semi_u32_cb(cs, -1, ENOSYS); + break; + + failed: + nios2_semi_u32_cb(cs, -1, EFAULT); + break; + failed64: + nios2_semi_u64_cb(cs, -1, EFAULT); + break; } -failed: - nios2_semi_u32_cb(cs, result, errno); } From 78c2c68ddac7b1a73615d89363fffd8c01561123 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Jun 2022 15:19:46 -0700 Subject: [PATCH 0421/1020] target/nios2: Convert semihosting errno to gdb remote errno The semihosting abi used by nios2 uses the gdb remote protocol filesys errnos. Signed-off-by: Richard Henderson --- target/nios2/nios2-semi.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/target/nios2/nios2-semi.c b/target/nios2/nios2-semi.c index 614fd76695..f76e8588c5 100644 --- a/target/nios2/nios2-semi.c +++ b/target/nios2/nios2-semi.c @@ -43,6 +43,35 @@ #define HOSTED_ISATTY 12 #define HOSTED_SYSTEM 13 +static int host_to_gdb_errno(int err) +{ +#define E(X) case E##X: return GDB_E##X + switch (err) { + E(PERM); + E(NOENT); + E(INTR); + E(BADF); + E(ACCES); + E(FAULT); + E(BUSY); + E(EXIST); + E(NODEV); + E(NOTDIR); + E(ISDIR); + E(INVAL); + E(NFILE); + E(MFILE); + E(FBIG); + E(NOSPC); + E(SPIPE); + E(ROFS); + E(NAMETOOLONG); + default: + return GDB_EUNKNOWN; + } +#undef E +} + static void nios2_semi_u32_cb(CPUState *cs, uint64_t ret, int err) { Nios2CPU *cpu = NIOS2_CPU(cs); @@ -50,7 +79,7 @@ static void nios2_semi_u32_cb(CPUState *cs, uint64_t ret, int err) target_ulong args = env->regs[R_ARG1]; if (put_user_u32(ret, args) || - put_user_u32(err, args + 4)) { + put_user_u32(host_to_gdb_errno(err), args + 4)) { /* * The nios2 semihosting ABI does not provide any way to report this * error to the guest, so the best we can do is log it in qemu. @@ -69,7 +98,7 @@ static void nios2_semi_u64_cb(CPUState *cs, uint64_t ret, int err) if (put_user_u32(ret >> 32, args) || put_user_u32(ret, args + 4) || - put_user_u32(err, args + 8)) { + put_user_u32(host_to_gdb_errno(err), args + 8)) { /* No way to report this via nios2 semihosting ABI; just log it */ qemu_log_mask(LOG_GUEST_ERROR, "nios2-semihosting: return value " "discarded because argument block not writable\n"); From 950272506dbd8dcf8c74b63e9949d18397e6a0ec Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 29 Apr 2022 17:38:59 -0700 Subject: [PATCH 0422/1020] target/m68k: Use semihosting/syscalls.h This separates guest file descriptors from host file descriptors, and utilizes shared infrastructure for integration with gdbstub. Acked-by: Laurent Vivier Signed-off-by: Richard Henderson --- target/m68k/m68k-semi.c | 281 +++++++--------------------------------- 1 file changed, 49 insertions(+), 232 deletions(-) diff --git a/target/m68k/m68k-semi.c b/target/m68k/m68k-semi.c index d0697ddbd1..586a801034 100644 --- a/target/m68k/m68k-semi.c +++ b/target/m68k/m68k-semi.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec/gdbstub.h" +#include "semihosting/syscalls.h" #include "semihosting/softmmu-uaccess.h" #include "hw/boards.h" #include "qemu/log.h" @@ -40,56 +41,6 @@ #define HOSTED_ISATTY 12 #define HOSTED_SYSTEM 13 -static int translate_openflags(int flags) -{ - int hf; - - if (flags & GDB_O_WRONLY) - hf = O_WRONLY; - else if (flags & GDB_O_RDWR) - hf = O_RDWR; - else - hf = O_RDONLY; - - if (flags & GDB_O_APPEND) hf |= O_APPEND; - if (flags & GDB_O_CREAT) hf |= O_CREAT; - if (flags & GDB_O_TRUNC) hf |= O_TRUNC; - if (flags & GDB_O_EXCL) hf |= O_EXCL; - - return hf; -} - -static void translate_stat(CPUM68KState *env, target_ulong addr, struct stat *s) -{ - struct gdb_stat *p; - - p = lock_user(VERIFY_WRITE, addr, sizeof(struct gdb_stat), 0); - if (!p) { - /* FIXME - should this return an error code? */ - return; - } - p->gdb_st_dev = cpu_to_be32(s->st_dev); - p->gdb_st_ino = cpu_to_be32(s->st_ino); - p->gdb_st_mode = cpu_to_be32(s->st_mode); - p->gdb_st_nlink = cpu_to_be32(s->st_nlink); - p->gdb_st_uid = cpu_to_be32(s->st_uid); - p->gdb_st_gid = cpu_to_be32(s->st_gid); - p->gdb_st_rdev = cpu_to_be32(s->st_rdev); - p->gdb_st_size = cpu_to_be64(s->st_size); -#ifdef _WIN32 - /* Windows stat is missing some fields. */ - p->gdb_st_blksize = 0; - p->gdb_st_blocks = 0; -#else - p->gdb_st_blksize = cpu_to_be64(s->st_blksize); - p->gdb_st_blocks = cpu_to_be64(s->st_blocks); -#endif - p->gdb_st_atime = cpu_to_be32(s->st_atime); - p->gdb_st_mtime = cpu_to_be32(s->st_mtime); - p->gdb_st_ctime = cpu_to_be32(s->st_ctime); - unlock_user(p, addr, sizeof(struct gdb_stat)); -} - static void m68k_semi_u32_cb(CPUState *cs, uint64_t ret, int err) { M68kCPU *cpu = M68K_CPU(cs); @@ -129,248 +80,109 @@ static void m68k_semi_u64_cb(CPUState *cs, uint64_t ret, int err) */ #define GET_ARG(n) do { \ if (get_user_ual(arg ## n, args + (n) * 4)) { \ - result = -1; \ - errno = EFAULT; \ goto failed; \ } \ } while (0) +#define GET_ARG64(n) do { \ + if (get_user_ual(arg ## n, args + (n) * 4)) { \ + goto failed64; \ + } \ +} while (0) + + void do_m68k_semihosting(CPUM68KState *env, int nr) { CPUState *cs = env_cpu(env); uint32_t args; target_ulong arg0, arg1, arg2, arg3; - void *p; - void *q; - uint32_t len; - uint32_t result; args = env->dregs[1]; switch (nr) { case HOSTED_EXIT: gdb_exit(env->dregs[0]); exit(env->dregs[0]); + case HOSTED_OPEN: GET_ARG(0); GET_ARG(1); GET_ARG(2); GET_ARG(3); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "open,%s,%x,%x", arg0, (int)arg1, - arg2, arg3); - return; - } else { - p = lock_user_string(arg0); - if (!p) { - /* FIXME - check error code? */ - result = -1; - } else { - result = open(p, translate_openflags(arg2), arg3); - unlock_user(p, arg0, 0); - } - } + semihost_sys_open(cs, m68k_semi_u32_cb, arg0, arg1, arg2, arg3); break; + case HOSTED_CLOSE: - { - /* Ignore attempts to close stdin/out/err. */ - GET_ARG(0); - int fd = arg0; - if (fd > 2) { - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "close,%x", arg0); - return; - } else { - result = close(fd); - } - } else { - result = 0; - } - break; - } + GET_ARG(0); + semihost_sys_close(cs, m68k_semi_u32_cb, arg0); + break; + case HOSTED_READ: GET_ARG(0); GET_ARG(1); GET_ARG(2); - len = arg2; - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "read,%x,%x,%x", - arg0, arg1, len); - return; - } else { - p = lock_user(VERIFY_WRITE, arg1, len, 0); - if (!p) { - /* FIXME - check error code? */ - result = -1; - } else { - result = read(arg0, p, len); - unlock_user(p, arg1, len); - } - } + semihost_sys_read(cs, m68k_semi_u32_cb, arg0, arg1, arg2); break; + case HOSTED_WRITE: GET_ARG(0); GET_ARG(1); GET_ARG(2); - len = arg2; - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "write,%x,%x,%x", - arg0, arg1, len); - return; - } else { - p = lock_user(VERIFY_READ, arg1, len, 1); - if (!p) { - /* FIXME - check error code? */ - result = -1; - } else { - result = write(arg0, p, len); - unlock_user(p, arg0, 0); - } - } + semihost_sys_write(cs, m68k_semi_u32_cb, arg0, arg1, arg2); break; + case HOSTED_LSEEK: - { - uint64_t off; - GET_ARG(0); - GET_ARG(1); - GET_ARG(2); - GET_ARG(3); - off = (uint32_t)arg2 | ((uint64_t)arg1 << 32); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u64_cb, "fseek,%x,%lx,%x", - arg0, off, arg3); - } else { - off = lseek(arg0, off, arg3); - m68k_semi_u64_cb(cs, off, errno); - } - return; - } + GET_ARG64(0); + GET_ARG64(1); + GET_ARG64(2); + GET_ARG64(3); + semihost_sys_lseek(cs, m68k_semi_u64_cb, arg0, + deposit64(arg2, arg1, 32, 32), arg3); + break; + case HOSTED_RENAME: GET_ARG(0); GET_ARG(1); GET_ARG(2); GET_ARG(3); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "rename,%s,%s", - arg0, (int)arg1, arg2, (int)arg3); - return; - } else { - p = lock_user_string(arg0); - q = lock_user_string(arg2); - if (!p || !q) { - /* FIXME - check error code? */ - result = -1; - } else { - result = rename(p, q); - } - unlock_user(p, arg0, 0); - unlock_user(q, arg2, 0); - } + semihost_sys_rename(cs, m68k_semi_u32_cb, arg0, arg1, arg2, arg3); break; + case HOSTED_UNLINK: GET_ARG(0); GET_ARG(1); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "unlink,%s", - arg0, (int)arg1); - return; - } else { - p = lock_user_string(arg0); - if (!p) { - /* FIXME - check error code? */ - result = -1; - } else { - result = unlink(p); - unlock_user(p, arg0, 0); - } - } + semihost_sys_remove(cs, m68k_semi_u32_cb, arg0, arg1); break; + case HOSTED_STAT: GET_ARG(0); GET_ARG(1); GET_ARG(2); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "stat,%s,%x", - arg0, (int)arg1, arg2); - return; - } else { - struct stat s; - p = lock_user_string(arg0); - if (!p) { - /* FIXME - check error code? */ - result = -1; - } else { - result = stat(p, &s); - unlock_user(p, arg0, 0); - } - if (result == 0) { - translate_stat(env, arg2, &s); - } - } + semihost_sys_stat(cs, m68k_semi_u32_cb, arg0, arg1, arg2); break; + case HOSTED_FSTAT: GET_ARG(0); GET_ARG(1); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "fstat,%x,%x", - arg0, arg1); - return; - } else { - struct stat s; - result = fstat(arg0, &s); - if (result == 0) { - translate_stat(env, arg1, &s); - } - } + semihost_sys_fstat(cs, m68k_semi_u32_cb, arg0, arg1); break; + case HOSTED_GETTIMEOFDAY: GET_ARG(0); GET_ARG(1); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "gettimeofday,%x,%x", - arg0, arg1); - return; - } else { - struct gdb_timeval *p; - int64_t rt = g_get_real_time(); - p = lock_user(VERIFY_WRITE, arg0, sizeof(struct gdb_timeval), 0); - if (!p) { - /* FIXME - check error code? */ - result = -1; - } else { - result = 0; - p->tv_sec = cpu_to_be32(rt / G_USEC_PER_SEC); - p->tv_usec = cpu_to_be64(rt % G_USEC_PER_SEC); - unlock_user(p, arg0, sizeof(struct gdb_timeval)); - } - } + semihost_sys_gettimeofday(cs, m68k_semi_u32_cb, arg0, arg1); break; + case HOSTED_ISATTY: GET_ARG(0); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "isatty,%x", arg0); - return; - } else { - result = isatty(arg0); - } + semihost_sys_isatty(cs, m68k_semi_u32_cb, arg0); break; + case HOSTED_SYSTEM: GET_ARG(0); GET_ARG(1); - if (use_gdb_syscalls()) { - gdb_do_syscall(m68k_semi_u32_cb, "system,%s", - arg0, (int)arg1); - return; - } else { - p = lock_user_string(arg0); - if (!p) { - /* FIXME - check error code? */ - result = -1; - } else { - result = system(p); - unlock_user(p, arg0, 0); - } - } + semihost_sys_system(cs, m68k_semi_u32_cb, arg0, arg1); break; + case HOSTED_INIT_SIM: /* * FIXME: This is wrong for boards where RAM does not start at @@ -379,10 +191,15 @@ void do_m68k_semihosting(CPUM68KState *env, int nr) env->dregs[1] = current_machine->ram_size; env->aregs[7] = current_machine->ram_size; return; + default: cpu_abort(env_cpu(env), "Unsupported semihosting syscall %d\n", nr); - result = 0; + + failed: + m68k_semi_u32_cb(cs, -1, EFAULT); + break; + failed64: + m68k_semi_u64_cb(cs, -1, EFAULT); + break; } -failed: - m68k_semi_u32_cb(cs, result, errno); } From 7327e60237c36e9aa089141de547ca224ec5f3be Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 20 Jun 2022 15:22:14 -0700 Subject: [PATCH 0423/1020] target/m68k: Convert semihosting errno to gdb remote errno The semihosting abi used by m68k uses the gdb remote protocol filesys errnos. Acked-by: Laurent Vivier Signed-off-by: Richard Henderson --- target/m68k/m68k-semi.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/target/m68k/m68k-semi.c b/target/m68k/m68k-semi.c index 586a801034..87b1314925 100644 --- a/target/m68k/m68k-semi.c +++ b/target/m68k/m68k-semi.c @@ -41,6 +41,35 @@ #define HOSTED_ISATTY 12 #define HOSTED_SYSTEM 13 +static int host_to_gdb_errno(int err) +{ +#define E(X) case E##X: return GDB_E##X + switch (err) { + E(PERM); + E(NOENT); + E(INTR); + E(BADF); + E(ACCES); + E(FAULT); + E(BUSY); + E(EXIST); + E(NODEV); + E(NOTDIR); + E(ISDIR); + E(INVAL); + E(NFILE); + E(MFILE); + E(FBIG); + E(NOSPC); + E(SPIPE); + E(ROFS); + E(NAMETOOLONG); + default: + return GDB_EUNKNOWN; + } +#undef E +} + static void m68k_semi_u32_cb(CPUState *cs, uint64_t ret, int err) { M68kCPU *cpu = M68K_CPU(cs); @@ -48,7 +77,7 @@ static void m68k_semi_u32_cb(CPUState *cs, uint64_t ret, int err) target_ulong args = env->dregs[1]; if (put_user_u32(ret, args) || - put_user_u32(err, args + 4)) { + put_user_u32(host_to_gdb_errno(err), args + 4)) { /* * The m68k semihosting ABI does not provide any way to report this * error to the guest, so the best we can do is log it in qemu. @@ -67,7 +96,7 @@ static void m68k_semi_u64_cb(CPUState *cs, uint64_t ret, int err) target_ulong args = env->dregs[1]; if (put_user_u32(ret >> 32, args) || put_user_u32(ret, args + 4) || - put_user_u32(err, args + 8)) { + put_user_u32(host_to_gdb_errno(err), args + 8)) { /* No way to report this via m68k semihosting ABI; just log it */ qemu_log_mask(LOG_GUEST_ERROR, "m68k-semihosting: return value " "discarded because argument block not writable\n"); From 5202861b20d77b1d638da5f10af0f51ebcfc61bf Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 15:12:24 +0100 Subject: [PATCH 0424/1020] semihosting: Allow optional use of semihosting from userspace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently our semihosting implementations generally prohibit use of semihosting calls in system emulation from the guest userspace. This is a very long standing behaviour justified originally "to provide some semblance of security" (since code with access to the semihosting ABI can do things like read and write arbitrary files on the host system). However, it is sometimes useful to be able to run trusted guest code which performs semihosting calls from guest userspace, notably for test code. Add a command line suboption to the existing semihosting-config option group so that you can explicitly opt in to semihosting from guest userspace with -semihosting-config userspace=on (There is no equivalent option for the user-mode emulator, because there by definition all code runs in userspace and has access to semihosting already.) This commit adds the infrastructure for the command line option and adds a bool 'is_user' parameter to the function semihosting_userspace_enabled() that target code can use to check whether it should be permitting the semihosting call for userspace. It mechanically makes all the callsites pass 'false', so they continue checking "is semihosting enabled in general". Subsequent commits will make each target that implements semihosting honour the userspace=on option by passing the correct value and removing whatever "don't do this for userspace" checking they were doing by hand. Signed-off-by: Peter Maydell Acked-by: Alex BennĂ©e Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson Message-Id: <20220822141230.3658237-2-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- include/semihosting/semihost.h | 10 ++++++++-- qemu-options.hx | 11 +++++++++-- semihosting/config.c | 10 ++++++++-- softmmu/vl.c | 2 +- stubs/semihost.c | 2 +- target/arm/translate-a64.c | 2 +- target/arm/translate.c | 6 +++--- target/m68k/op_helper.c | 2 +- target/nios2/translate.c | 2 +- target/xtensa/translate.c | 6 +++--- 10 files changed, 36 insertions(+), 17 deletions(-) diff --git a/include/semihosting/semihost.h b/include/semihosting/semihost.h index 93a3c21b44..efd2efa25a 100644 --- a/include/semihosting/semihost.h +++ b/include/semihosting/semihost.h @@ -27,7 +27,7 @@ typedef enum SemihostingTarget { } SemihostingTarget; #ifdef CONFIG_USER_ONLY -static inline bool semihosting_enabled(void) +static inline bool semihosting_enabled(bool is_user) { return true; } @@ -52,7 +52,13 @@ static inline const char *semihosting_get_cmdline(void) return NULL; } #else /* !CONFIG_USER_ONLY */ -bool semihosting_enabled(void); +/** + * semihosting_enabled: + * @is_user: true if guest code is in usermode (i.e. not privileged) + * + * Return true if guest code is allowed to make semihosting calls. + */ +bool semihosting_enabled(bool is_user); SemihostingTarget semihosting_get_target(void); const char *semihosting_get_arg(int i); int semihosting_get_argc(void); diff --git a/qemu-options.hx b/qemu-options.hx index 31c04f7eea..1bb02363ab 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4627,12 +4627,12 @@ SRST information about the facilities this enables. ERST DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config, - "-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]\n" \ + "-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,userspace=on|off][,arg=str[,...]]\n" \ " semihosting configuration\n", QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV) SRST -``-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]`` +``-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,userspace=on|off][,arg=str[,...]]`` Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V only). @@ -4659,6 +4659,13 @@ SRST Send the output to a chardev backend output for native or auto output when not in gdb + ``userspace=on|off`` + Allows code running in guest userspace to access the semihosting + interface. The default is that only privileged guest code can + make semihosting calls. Note that setting ``userspace=on`` should + only be used if all guest code is trusted (for example, in + bare-metal test case code). + ``arg=str1,arg=str2,...`` Allows the user to pass input arguments, and can be used multiple times to build up a list. The old-style diff --git a/semihosting/config.c b/semihosting/config.c index e171d4d6bc..89a1759687 100644 --- a/semihosting/config.c +++ b/semihosting/config.c @@ -34,6 +34,9 @@ QemuOptsList qemu_semihosting_config_opts = { { .name = "enable", .type = QEMU_OPT_BOOL, + }, { + .name = "userspace", + .type = QEMU_OPT_BOOL, }, { .name = "target", .type = QEMU_OPT_STRING, @@ -50,6 +53,7 @@ QemuOptsList qemu_semihosting_config_opts = { typedef struct SemihostingConfig { bool enabled; + bool userspace_enabled; SemihostingTarget target; char **argv; int argc; @@ -59,9 +63,9 @@ typedef struct SemihostingConfig { static SemihostingConfig semihosting; static const char *semihost_chardev; -bool semihosting_enabled(void) +bool semihosting_enabled(bool is_user) { - return semihosting.enabled; + return semihosting.enabled && (!is_user || semihosting.userspace_enabled); } SemihostingTarget semihosting_get_target(void) @@ -137,6 +141,8 @@ int qemu_semihosting_config_options(const char *optarg) if (opts != NULL) { semihosting.enabled = qemu_opt_get_bool(opts, "enable", true); + semihosting.userspace_enabled = qemu_opt_get_bool(opts, "userspace", + false); const char *target = qemu_opt_get(opts, "target"); /* setup of chardev is deferred until they are initialised */ semihost_chardev = qemu_opt_get(opts, "chardev"); diff --git a/softmmu/vl.c b/softmmu/vl.c index dea4005e47..263f029a8e 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -1822,7 +1822,7 @@ static void qemu_apply_machine_options(QDict *qdict) { object_set_properties_from_keyval(OBJECT(current_machine), qdict, false, &error_fatal); - if (semihosting_enabled() && !semihosting_get_argc()) { + if (semihosting_enabled(false) && !semihosting_get_argc()) { /* fall back to the -kernel/-append */ semihosting_arg_fallback(current_machine->kernel_filename, current_machine->kernel_cmdline); } diff --git a/stubs/semihost.c b/stubs/semihost.c index f486651afb..d65c9fd5dc 100644 --- a/stubs/semihost.c +++ b/stubs/semihost.c @@ -23,7 +23,7 @@ QemuOptsList qemu_semihosting_config_opts = { }; /* Queries to config status default to off */ -bool semihosting_enabled(void) +bool semihosting_enabled(bool is_user) { return false; } diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 163df8c615..3decc8da57 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -2219,7 +2219,7 @@ static void disas_exc(DisasContext *s, uint32_t insn) * it is required for halting debug disabled: it will UNDEF. * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction. */ - if (semihosting_enabled() && imm16 == 0xf000) { + if (semihosting_enabled(false) && imm16 == 0xf000) { #ifndef CONFIG_USER_ONLY /* In system mode, don't allow userspace access to semihosting, * to provide some semblance of security (and for consistency diff --git a/target/arm/translate.c b/target/arm/translate.c index 9474e4b44b..b1e013270d 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1169,7 +1169,7 @@ static inline void gen_hlt(DisasContext *s, int imm) * semihosting, to provide some semblance of security * (and for consistency with our 32-bit semihosting). */ - if (semihosting_enabled() && + if (semihosting_enabled(false) && #ifndef CONFIG_USER_ONLY s->current_el != 0 && #endif @@ -6556,7 +6556,7 @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a) /* BKPT is OK with ECI set and leaves it untouched */ s->eci_handled = true; if (arm_dc_feature(s, ARM_FEATURE_M) && - semihosting_enabled() && + semihosting_enabled(false) && #ifndef CONFIG_USER_ONLY !IS_USER(s) && #endif @@ -8764,7 +8764,7 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a) { const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456; - if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled() && + if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled(false) && #ifndef CONFIG_USER_ONLY !IS_USER(s) && #endif diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index d9937ca8dc..4b3dfec130 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -203,7 +203,7 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw) cf_rte(env); return; case EXCP_HALT_INSN: - if (semihosting_enabled() + if (semihosting_enabled(false) && (env->sr & SR_S) != 0 && (env->pc & 3) == 0 && cpu_lduw_code(env, env->pc - 4) == 0x4e71 diff --git a/target/nios2/translate.c b/target/nios2/translate.c index c588e8e885..ff631a42f6 100644 --- a/target/nios2/translate.c +++ b/target/nios2/translate.c @@ -818,7 +818,7 @@ static void gen_break(DisasContext *dc, uint32_t code, uint32_t flags) #ifndef CONFIG_USER_ONLY /* The semihosting instruction is "break 1". */ R_TYPE(instr, code); - if (semihosting_enabled() && instr.imm5 == 1) { + if (semihosting_enabled(false) && instr.imm5 == 1) { t_gen_helper_raise_exception(dc, EXCP_SEMIHOST); return; } diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index 8b864ef925..afae8a1bea 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -2366,9 +2366,9 @@ static uint32_t test_exceptions_simcall(DisasContext *dc, bool ill = true; #else /* Between RE.2 and RE.3 simcall opcode's become nop for the hardware. */ - bool ill = dc->config->hw_version <= 250002 && !semihosting_enabled(); + bool ill = dc->config->hw_version <= 250002 && !semihosting_enabled(false); #endif - if (ill || !semihosting_enabled()) { + if (ill || !semihosting_enabled(false)) { qemu_log_mask(LOG_GUEST_ERROR, "SIMCALL but semihosting is disabled\n"); } return ill ? XTENSA_OP_ILL : 0; @@ -2378,7 +2378,7 @@ static void translate_simcall(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { #ifndef CONFIG_USER_ONLY - if (semihosting_enabled()) { + if (semihosting_enabled(false)) { gen_helper_simcall(cpu_env); } #endif From 19b26317e9eb0c4dfd42e341ba7c4474c6d53ff9 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 15:12:25 +0100 Subject: [PATCH 0425/1020] target/arm: Honour -semihosting-config userspace=on Honour the commandline -semihosting-config userspace=on option, instead of never permitting userspace semihosting calls in system emulation mode, by passing the correct value to the is_userspace argument of semihosting_enabled(), instead of manually checking and always forbidding semihosting if the guest is in userspace and this isn't the linux-user build. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822141230.3658237-3-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/translate-a64.c | 12 +----------- target/arm/translate.c | 16 ++++------------ 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 3decc8da57..9bed336b47 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -2219,17 +2219,7 @@ static void disas_exc(DisasContext *s, uint32_t insn) * it is required for halting debug disabled: it will UNDEF. * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction. */ - if (semihosting_enabled(false) && imm16 == 0xf000) { -#ifndef CONFIG_USER_ONLY - /* In system mode, don't allow userspace access to semihosting, - * to provide some semblance of security (and for consistency - * with our 32-bit semihosting). - */ - if (s->current_el == 0) { - unallocated_encoding(s); - break; - } -#endif + if (semihosting_enabled(s->current_el == 0) && imm16 == 0xf000) { gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); } else { unallocated_encoding(s); diff --git a/target/arm/translate.c b/target/arm/translate.c index b1e013270d..5aaccbbf71 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -1169,10 +1169,7 @@ static inline void gen_hlt(DisasContext *s, int imm) * semihosting, to provide some semblance of security * (and for consistency with our 32-bit semihosting). */ - if (semihosting_enabled(false) && -#ifndef CONFIG_USER_ONLY - s->current_el != 0 && -#endif + if (semihosting_enabled(s->current_el != 0) && (imm == (s->thumb ? 0x3c : 0xf000))) { gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); return; @@ -6556,10 +6553,7 @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a) /* BKPT is OK with ECI set and leaves it untouched */ s->eci_handled = true; if (arm_dc_feature(s, ARM_FEATURE_M) && - semihosting_enabled(false) && -#ifndef CONFIG_USER_ONLY - !IS_USER(s) && -#endif + semihosting_enabled(s->current_el == 0) && (a->imm == 0xab)) { gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); } else { @@ -8764,10 +8758,8 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a) { const uint32_t semihost_imm = s->thumb ? 0xab : 0x123456; - if (!arm_dc_feature(s, ARM_FEATURE_M) && semihosting_enabled(false) && -#ifndef CONFIG_USER_ONLY - !IS_USER(s) && -#endif + if (!arm_dc_feature(s, ARM_FEATURE_M) && + semihosting_enabled(s->current_el == 0) && (a->imm == semihost_imm)) { gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); } else { From a52417e1eeb4501993e29145d16faac59e8465ca Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 15:12:26 +0100 Subject: [PATCH 0426/1020] target/m68k: Honour -semihosting-config userspace=on Honour the commandline -semihosting-config userspace=on option, instead of never permitting userspace semihosting calls in system emulation mode, by passing the correct value to the is_userspace argument of semihosting_enabled(), instead of manually checking and always forbidding semihosting if the guest is in userspace. (Note that target/m68k doesn't support semihosting at all in the linux-user build.) Signed-off-by: Peter Maydell Reviewed-by: Laurent Vivier Reviewed-by: Richard Henderson Message-Id: <20220822141230.3658237-4-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/m68k/op_helper.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index 4b3dfec130..a96a034050 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -203,8 +203,7 @@ static void cf_interrupt_all(CPUM68KState *env, int is_hw) cf_rte(env); return; case EXCP_HALT_INSN: - if (semihosting_enabled(false) - && (env->sr & SR_S) != 0 + if (semihosting_enabled((env->sr & SR_S) == 0) && (env->pc & 3) == 0 && cpu_lduw_code(env, env->pc - 4) == 0x4e71 && cpu_ldl_code(env, env->pc) == 0x4e7bf000) { From b35d74015b0262260b7dbb75c80ea85aeebab89b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 15:12:27 +0100 Subject: [PATCH 0427/1020] target/mips: Honour -semihosting-config userspace=on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Honour the commandline -semihosting-config userspace=on option, instead of always permitting userspace semihosting calls in system emulation mode, by passing the correct value to the is_userspace argument of semihosting_enabled(). Note that this is a behaviour change: if the user wants to do semihosting calls from userspace they must now specifically enable them on the command line. MIPS semihosting is not implemented for linux-user builds. Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson Message-Id: <20220822141230.3658237-5-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/mips/tcg/micromips_translate.c.inc | 6 +++--- target/mips/tcg/mips16e_translate.c.inc | 2 +- target/mips/tcg/nanomips_translate.c.inc | 4 ++-- target/mips/tcg/translate.c | 9 +++++---- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/target/mips/tcg/micromips_translate.c.inc b/target/mips/tcg/micromips_translate.c.inc index b2c696f891..632895cc9e 100644 --- a/target/mips/tcg/micromips_translate.c.inc +++ b/target/mips/tcg/micromips_translate.c.inc @@ -825,7 +825,7 @@ static void gen_pool16c_insn(DisasContext *ctx) generate_exception_break(ctx, extract32(ctx->opcode, 0, 4)); break; case SDBBP16: - if (is_uhi(extract32(ctx->opcode, 0, 4))) { + if (is_uhi(ctx, extract32(ctx->opcode, 0, 4))) { ctx->base.is_jmp = DISAS_SEMIHOST; } else { /* @@ -941,7 +941,7 @@ static void gen_pool16c_r6_insn(DisasContext *ctx) break; case R6_SDBBP16: /* SDBBP16 */ - if (is_uhi(extract32(ctx->opcode, 6, 4))) { + if (is_uhi(ctx, extract32(ctx->opcode, 6, 4))) { ctx->base.is_jmp = DISAS_SEMIHOST; } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { @@ -1310,7 +1310,7 @@ static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs) generate_exception_end(ctx, EXCP_SYSCALL); break; case SDBBP: - if (is_uhi(extract32(ctx->opcode, 16, 10))) { + if (is_uhi(ctx, extract32(ctx->opcode, 16, 10))) { ctx->base.is_jmp = DISAS_SEMIHOST; } else { check_insn(ctx, ISA_MIPS_R1); diff --git a/target/mips/tcg/mips16e_translate.c.inc b/target/mips/tcg/mips16e_translate.c.inc index 7568933e23..918b15d55c 100644 --- a/target/mips/tcg/mips16e_translate.c.inc +++ b/target/mips/tcg/mips16e_translate.c.inc @@ -951,7 +951,7 @@ static int decode_ase_mips16e(CPUMIPSState *env, DisasContext *ctx) } break; case RR_SDBBP: - if (is_uhi(extract32(ctx->opcode, 5, 6))) { + if (is_uhi(ctx, extract32(ctx->opcode, 5, 6))) { ctx->base.is_jmp = DISAS_SEMIHOST; } else { /* diff --git a/target/mips/tcg/nanomips_translate.c.inc b/target/mips/tcg/nanomips_translate.c.inc index b3aff22c18..812c111e3c 100644 --- a/target/mips/tcg/nanomips_translate.c.inc +++ b/target/mips/tcg/nanomips_translate.c.inc @@ -3694,7 +3694,7 @@ static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx) generate_exception_end(ctx, EXCP_BREAK); break; case NM_SDBBP: - if (is_uhi(extract32(ctx->opcode, 0, 19))) { + if (is_uhi(ctx, extract32(ctx->opcode, 0, 19))) { ctx->base.is_jmp = DISAS_SEMIHOST; } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { @@ -4633,7 +4633,7 @@ static int decode_isa_nanomips(CPUMIPSState *env, DisasContext *ctx) generate_exception_end(ctx, EXCP_BREAK); break; case NM_SDBBP16: - if (is_uhi(extract32(ctx->opcode, 0, 3))) { + if (is_uhi(ctx, extract32(ctx->opcode, 0, 3))) { ctx->base.is_jmp = DISAS_SEMIHOST; } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 0d936e2648..c3f92ea652 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -12082,12 +12082,13 @@ static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base, tcg_temp_free_i32(t0); } -static inline bool is_uhi(int sdbbp_code) +static inline bool is_uhi(DisasContext *ctx, int sdbbp_code) { #ifdef CONFIG_USER_ONLY return false; #else - return semihosting_enabled() && sdbbp_code == 1; + bool is_user = (ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM; + return semihosting_enabled(is_user) && sdbbp_code == 1; #endif } @@ -13898,7 +13899,7 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) } break; case R6_OPC_SDBBP: - if (is_uhi(extract32(ctx->opcode, 6, 20))) { + if (is_uhi(ctx, extract32(ctx->opcode, 6, 20))) { ctx->base.is_jmp = DISAS_SEMIHOST; } else { if (ctx->hflags & MIPS_HFLAG_SBRI) { @@ -14310,7 +14311,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) gen_cl(ctx, op1, rd, rs); break; case OPC_SDBBP: - if (is_uhi(extract32(ctx->opcode, 6, 20))) { + if (is_uhi(ctx, extract32(ctx->opcode, 6, 20))) { ctx->base.is_jmp = DISAS_SEMIHOST; } else { /* From cab9f19370b5e26afbc7f62e08293507bf2a5f6b Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 15:12:28 +0100 Subject: [PATCH 0428/1020] target/nios2: Honour -semihosting-config userspace=on Honour the commandline -semihosting-config userspace=on option, instead of always permitting userspace semihosting calls in system emulation mode, by passing the correct value to the is_userspace argument of semihosting_enabled(). Note that this is a behaviour change: if the user wants to do semihosting calls from userspace they must now specifically enable them on the command line. nios2 semihosting is not implemented for linux-user builds. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822141230.3658237-6-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/nios2/translate.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/nios2/translate.c b/target/nios2/translate.c index ff631a42f6..8dc0a32c6c 100644 --- a/target/nios2/translate.c +++ b/target/nios2/translate.c @@ -817,8 +817,9 @@ static void gen_break(DisasContext *dc, uint32_t code, uint32_t flags) { #ifndef CONFIG_USER_ONLY /* The semihosting instruction is "break 1". */ + bool is_user = FIELD_EX32(dc->tb_flags, TBFLAGS, U); R_TYPE(instr, code); - if (semihosting_enabled(false) && instr.imm5 == 1) { + if (semihosting_enabled(is_user) && instr.imm5 == 1) { t_gen_helper_raise_exception(dc, EXCP_SEMIHOST); return; } From 870ab98bee4312caf0ced42999e295f741aba853 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 15:12:29 +0100 Subject: [PATCH 0429/1020] target/xtensa: Honour -semihosting-config userspace=on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Honour the commandline -semihosting-config userspace=on option, instead of always permitting userspace semihosting calls in system emulation mode, by passing the correct value to the is_userspace argument of semihosting_enabled(). Note that this is a behaviour change: if the user wants to do semihosting calls from userspace they must now specifically enable them on the command line. xtensa semihosting is not implemented for linux-user builds. Signed-off-by: Peter Maydell Acked-by: Max Filippov Reviewed-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson Message-Id: <20220822141230.3658237-7-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/xtensa/translate.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c index afae8a1bea..bdd4690a5c 100644 --- a/target/xtensa/translate.c +++ b/target/xtensa/translate.c @@ -2362,13 +2362,14 @@ static uint32_t test_exceptions_simcall(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { + bool is_semi = semihosting_enabled(dc->cring != 0); #ifdef CONFIG_USER_ONLY bool ill = true; #else /* Between RE.2 and RE.3 simcall opcode's become nop for the hardware. */ - bool ill = dc->config->hw_version <= 250002 && !semihosting_enabled(false); + bool ill = dc->config->hw_version <= 250002 && !is_semi; #endif - if (ill || !semihosting_enabled(false)) { + if (ill || !is_semi) { qemu_log_mask(LOG_GUEST_ERROR, "SIMCALL but semihosting is disabled\n"); } return ill ? XTENSA_OP_ILL : 0; @@ -2378,7 +2379,7 @@ static void translate_simcall(DisasContext *dc, const OpcodeArg arg[], const uint32_t par[]) { #ifndef CONFIG_USER_ONLY - if (semihosting_enabled(false)) { + if (semihosting_enabled(dc->cring != 0)) { gen_helper_simcall(cpu_env); } #endif From 7d7fb11615809839ff858328134c6a0abad27ea4 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 15:12:30 +0100 Subject: [PATCH 0430/1020] target/riscv: Honour -semihosting-config userspace=on and enable=on The riscv target incorrectly enabled semihosting always, whether the user asked for it or not. Call semihosting_enabled() passing the correct value to the is_userspace argument, which fixes this and also handles the userspace=on argument. Because we do this at translate time, we no longer need to check the privilege level in riscv_cpu_do_interrupt(). Note that this is a behaviour change: we used to default to semihosting being enabled, and now the user must pass "-semihosting-config enable=on" if they want it. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Message-Id: <20220822141230.3658237-8-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/riscv/cpu_helper.c | 9 +++------ target/riscv/insn_trans/trans_privileged.c.inc | 3 ++- target/riscv/translate.c | 1 + 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 67e4c0efd2..278d163803 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -1589,12 +1589,9 @@ void riscv_cpu_do_interrupt(CPUState *cs) target_ulong mtval2 = 0; if (cause == RISCV_EXCP_SEMIHOST) { - if (env->priv >= PRV_S) { - do_common_semihosting(cs); - env->pc += 4; - return; - } - cause = RISCV_EXCP_BREAKPOINT; + do_common_semihosting(cs); + env->pc += 4; + return; } if (!async) { diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc index 46f96ad74d..3281408a87 100644 --- a/target/riscv/insn_trans/trans_privileged.c.inc +++ b/target/riscv/insn_trans/trans_privileged.c.inc @@ -52,7 +52,8 @@ static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a) * that no exception will be raised when fetching them. */ - if ((pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) { + if (semihosting_enabled(ctx->mem_idx < PRV_S) && + (pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) { pre = opcode_at(&ctx->base, pre_addr); ebreak = opcode_at(&ctx->base, ebreak_addr); post = opcode_at(&ctx->base, post_addr); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 8925a44c6e..db123da5ec 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -28,6 +28,7 @@ #include "exec/translator.h" #include "exec/log.h" +#include "semihosting/semihost.h" #include "instmap.h" #include "internals.h" From 3b16766b5ae7f61079e3ae674e140219c4cdbe85 Mon Sep 17 00:00:00 2001 From: Hao Wu Date: Thu, 18 Aug 2022 17:20:15 -0700 Subject: [PATCH 0431/1020] target/arm: Add cortex-a35 Add cortex A35 core and enable it for virt board. Signed-off-by: Hao Wu Reviewed-by: Joe Komlodi Reviewed-by: Peter Maydell Message-Id: <20220819002015.1663247-1-wuhaotsh@google.com> Signed-off-by: Richard Henderson --- docs/system/arm/virt.rst | 1 + hw/arm/virt.c | 1 + target/arm/cpu64.c | 80 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+) diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst index 3b6ba69a9a..20442ea2c1 100644 --- a/docs/system/arm/virt.rst +++ b/docs/system/arm/virt.rst @@ -52,6 +52,7 @@ Supported guest CPU types: - ``cortex-a7`` (32-bit) - ``cortex-a15`` (32-bit; the default) +- ``cortex-a35`` (64-bit) - ``cortex-a53`` (64-bit) - ``cortex-a57`` (64-bit) - ``cortex-a72`` (64-bit) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 1a6480fd2a..0961e053e5 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -199,6 +199,7 @@ static const int a15irqmap[] = { static const char *valid_cpus[] = { ARM_CPU_TYPE_NAME("cortex-a7"), ARM_CPU_TYPE_NAME("cortex-a15"), + ARM_CPU_TYPE_NAME("cortex-a35"), ARM_CPU_TYPE_NAME("cortex-a53"), ARM_CPU_TYPE_NAME("cortex-a57"), ARM_CPU_TYPE_NAME("cortex-a72"), diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 78e27f778a..9d1ea32057 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -36,6 +36,85 @@ #include "hw/qdev-properties.h" #include "internals.h" +static void aarch64_a35_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + cpu->dtb_compatible = "arm,cortex-a35"; + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); + set_feature(&cpu->env, ARM_FEATURE_EL2); + set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); + + /* From B2.2 AArch64 identification registers. */ + cpu->midr = 0x411fd040; + cpu->revidr = 0; + cpu->ctr = 0x84448004; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; + cpu->isar.id_isar0 = 0x02101110; + cpu->isar.id_isar1 = 0x13112111; + cpu->isar.id_isar2 = 0x21232042; + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_aa64pfr0 = 0x00002222; + cpu->isar.id_aa64pfr1 = 0; + cpu->isar.id_aa64dfr0 = 0x10305106; + cpu->isar.id_aa64dfr1 = 0; + cpu->isar.id_aa64isar0 = 0x00011120; + cpu->isar.id_aa64isar1 = 0; + cpu->isar.id_aa64mmfr0 = 0x00101122; + cpu->isar.id_aa64mmfr1 = 0; + cpu->clidr = 0x0a200023; + cpu->dcz_blocksize = 4; + + /* From B2.4 AArch64 Virtual Memory control registers */ + cpu->reset_sctlr = 0x00c50838; + + /* From B2.10 AArch64 performance monitor registers */ + cpu->isar.reset_pmcr_el0 = 0x410a3000; + + /* From B2.29 Cache ID registers */ + cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ + cpu->ccsidr[2] = 0x703fe03a; /* 512KB L2 cache */ + + /* From B3.5 VGIC Type register */ + cpu->gic_num_lrs = 4; + cpu->gic_vpribits = 5; + cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; + + /* From C6.4 Debug ID Register */ + cpu->isar.dbgdidr = 0x3516d000; + /* From C6.5 Debug Device ID Register */ + cpu->isar.dbgdevid = 0x00110f13; + /* From C6.6 Debug Device ID Register 1 */ + cpu->isar.dbgdevid1 = 0x2; + + /* From Cortex-A35 SIMD and Floating-point Support r1p0 */ + /* From 3.2 AArch32 register summary */ + cpu->reset_fpsid = 0x41034043; + + /* From 2.2 AArch64 register summary */ + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x12111111; + cpu->isar.mvfr2 = 0x00000043; + + /* These values are the same with A53/A57/A72. */ + define_cortex_a72_a57_a53_cp_reginfo(cpu); +} static void aarch64_a57_initfn(Object *obj) { @@ -1158,6 +1237,7 @@ static void aarch64_a64fx_initfn(Object *obj) } static const ARMCPUInfo aarch64_cpus[] = { + { .name = "cortex-a35", .initfn = aarch64_a35_initfn }, { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, { .name = "cortex-a53", .initfn = aarch64_a53_initfn }, { .name = "cortex-a72", .initfn = aarch64_a72_initfn }, From 3b9a030e846dd42a53f9f5bdcdd0228bb898e01b Mon Sep 17 00:00:00 2001 From: Enrik Berkhan Date: Fri, 12 Aug 2022 16:35:19 +0200 Subject: [PATCH 0432/1020] hw/arm/bcm2835_property: Add support for RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In more recent Raspbian OS Linux kernels, the fb driver gives up immediately if RPI_FIRMWARE_FRAMEBUFFER_GET_NUM_DISPLAYS fails or no displays are reported. This change simply always reports one display. It makes bcm2835_fb work again with these more recent kernels. Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Enrik Berkhan Message-Id: <20220812143519.59134-1-Enrik.Berkhan@inka.de> Signed-off-by: Richard Henderson --- hw/misc/bcm2835_property.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/misc/bcm2835_property.c b/hw/misc/bcm2835_property.c index e94e951057..890ae7bae5 100644 --- a/hw/misc/bcm2835_property.c +++ b/hw/misc/bcm2835_property.c @@ -270,6 +270,10 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value) stl_le_phys(&s->dma_as, value + 12, 0); resplen = 4; break; + case 0x00040013: /* Get number of displays */ + stl_le_phys(&s->dma_as, value + 12, 1); + resplen = 4; + break; case 0x00060001: /* Get DMA channels */ /* channels 2-5 */ From dde4d028dc829cb70d285bb943ebdc049692fa27 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 19 Aug 2022 12:00:47 +0100 Subject: [PATCH 0433/1020] target/arm: Make cpregs 0, c0, c{3-15}, {0-7} correctly RAZ in v8 In the AArch32 ID register scheme, coprocessor registers with encoding cp15, 0, c0, c{0-7}, {0-7} are all in the space covered by what in v6 and v7 was called the "CPUID scheme", and are supposed to RAZ if they're not allocated to a specific ID register. For our pre-v8 CPUs we get this right, because the regdefs in id_pre_v8_midr_cp_reginfo[] cover these RAZ requirements. However for v8 we failed to put in the necessary patterns to cover this, so we end up UNDEFing on everything we didn't have an ID register for. This is a problem because in Armv8 some encodings in 0, c0, c3, {0-7} are now being used for new ID registers, and guests might thus start trying to read them. (We already have one of these: ID_PFR2.) For v8 CPUs, we already have regdefs for 0, c0, c{0-2}, {0-7} (that is, the space is completely allocated with no reserved spaces). Add entries to v8_idregs[] covering 0, c0, c3, {0-7}: * c3, {0-2} is the reserved AArch32 space corresponding to the AArch64 MVFR[012]_EL1 * c3, {3,5,6,7} are reserved RAZ for both AArch32 and AArch64 (in fact some of these are given defined meanings in Armv8.6, but we don't implement them yet) * c3, 4 is ID_PFR2 (already defined) We then programmatically add RAZ patterns for AArch32 for 0, c0, c{4..15}, {0-7}: * c4-c7 are unused, and not shared with AArch64 (these are the encodings corresponding to where the AArch64 specific ID registers live in the system register space) * c8-c15 weren't required to RAZ in v6/v7, but v8 extends the AArch32 reserved-should-RAZ space to cover these; the equivalent area of the AArch64 sysreg space is not defined as must-RAZ Note that the architecture allows some registers in this space to return an UNKNOWN value; we always return 0. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220819110052.2942289-2-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/helper.c | 65 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 5 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index d7bc467a2a..c171770b03 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -7345,11 +7345,16 @@ void register_cp_regs_for_features(ARMCPU *cpu) define_arm_cp_regs(cpu, not_v7_cp_reginfo); } if (arm_feature(env, ARM_FEATURE_V8)) { - /* AArch64 ID registers, which all have impdef reset values. + /* + * v8 ID registers, which all have impdef reset values. * Note that within the ID register ranges the unused slots * must all RAZ, not UNDEF; future architecture versions may * define new registers here. + * ID registers which are AArch64 views of the AArch32 ID registers + * which already existed in v6 and v7 are handled elsewhere, + * in v6_idregs[]. */ + int i; ARMCPRegInfo v8_idregs[] = { /* * ID_AA64PFR0_EL1 is not a plain ARM_CP_CONST in system @@ -7539,7 +7544,34 @@ void register_cp_regs_for_features(ARMCPU *cpu) .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, .resetvalue = cpu->isar.mvfr2 }, - { .name = "MVFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + /* + * "0, c0, c3, {0,1,2}" are the encodings corresponding to + * AArch64 MVFR[012]_EL1. Define the STATE_AA32 encoding + * as RAZ, since it is in the "reserved for future ID + * registers, RAZ" part of the AArch32 encoding space. + */ + { .name = "RES_0_C0_C3_0", .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 0, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, + .resetvalue = 0 }, + { .name = "RES_0_C0_C3_1", .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 1, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, + .resetvalue = 0 }, + { .name = "RES_0_C0_C3_2", .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 2, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, + .resetvalue = 0 }, + /* + * Other encodings in "0, c0, c3, ..." are STATE_BOTH because + * they're also RAZ for AArch64, and in v8 are gradually + * being filled with AArch64-view-of-AArch32-ID-register + * for new ID registers. + */ + { .name = "RES_0_C0_C3_3", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 3, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, @@ -7549,17 +7581,17 @@ void register_cp_regs_for_features(ARMCPU *cpu) .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, .resetvalue = cpu->isar.id_pfr2 }, - { .name = "MVFR5_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + { .name = "RES_0_C0_C3_5", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, .resetvalue = 0 }, - { .name = "MVFR6_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + { .name = "RES_0_C0_C3_6", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, .resetvalue = 0 }, - { .name = "MVFR7_EL1_RESERVED", .state = ARM_CP_STATE_AA64, + { .name = "RES_0_C0_C3_7", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, @@ -7625,6 +7657,29 @@ void register_cp_regs_for_features(ARMCPU *cpu) } define_arm_cp_regs(cpu, v8_idregs); define_arm_cp_regs(cpu, v8_cp_reginfo); + + for (i = 4; i < 16; i++) { + /* + * Encodings in "0, c0, {c4-c7}, {0-7}" are RAZ for AArch32. + * For pre-v8 cores there are RAZ patterns for these in + * id_pre_v8_midr_cp_reginfo[]; for v8 we do that here. + * v8 extends the "must RAZ" part of the ID register space + * to also cover c0, 0, c{8-15}, {0-7}. + * These are STATE_AA32 because in the AArch64 sysreg space + * c4-c7 is where the AArch64 ID registers live (and we've + * already defined those in v8_idregs[]), and c8-c15 are not + * "must RAZ" for AArch64. + */ + g_autofree char *name = g_strdup_printf("RES_0_C0_C%d_X", i); + ARMCPRegInfo v8_aa32_raz_idregs = { + .name = name, + .state = ARM_CP_STATE_AA32, + .cp = 15, .opc1 = 0, .crn = 0, .crm = i, .opc2 = CP_ANY, + .access = PL1_R, .type = ARM_CP_CONST, + .accessfn = access_aa64_tid3, + .resetvalue = 0 }; + define_one_arm_cp_reg(cpu, &v8_aa32_raz_idregs); + } } /* From 62b6f5e2f0a029810791dde6e02f86ad8575a02c Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 19 Aug 2022 12:00:48 +0100 Subject: [PATCH 0434/1020] target/arm: Sort KVM reads of AArch32 ID registers into encoding order The code that reads the AArch32 ID registers from KVM in kvm_arm_get_host_cpu_features() does so almost but not quite in encoding order. Move the read of ID_PFR2 down so it's really in encoding order. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220819110052.2942289-3-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/kvm64.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 9b9dd46d78..84c4c85f40 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -608,8 +608,6 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ARM64_SYS_REG(3, 0, 0, 1, 0)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr1, ARM64_SYS_REG(3, 0, 0, 1, 1)); - err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, - ARM64_SYS_REG(3, 0, 0, 3, 4)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr0, ARM64_SYS_REG(3, 0, 0, 1, 2)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr0, @@ -643,6 +641,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ARM64_SYS_REG(3, 0, 0, 3, 1)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, ARM64_SYS_REG(3, 0, 0, 3, 2)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, + ARM64_SYS_REG(3, 0, 0, 3, 4)); /* * DBGDIDR is a bit complicated because the kernel doesn't From 32957aad8ce3cd4f923b464efb80645963479ff8 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 19 Aug 2022 12:00:49 +0100 Subject: [PATCH 0435/1020] target/arm: Implement ID_MMFR5 In Armv8.6 a new AArch32 ID register ID_MMFR5 is defined. Implement this; we want to be able to use it to report to the guest that we implement FEAT_ETS. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220819110052.2942289-4-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/cpu.h | 1 + target/arm/helper.c | 4 ++-- target/arm/kvm64.c | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 5168e3d837..fcc5927587 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -975,6 +975,7 @@ struct ArchCPU { uint32_t id_mmfr2; uint32_t id_mmfr3; uint32_t id_mmfr4; + uint32_t id_mmfr5; uint32_t id_pfr0; uint32_t id_pfr1; uint32_t id_pfr2; diff --git a/target/arm/helper.c b/target/arm/helper.c index c171770b03..0737851925 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -7586,11 +7586,11 @@ void register_cp_regs_for_features(ARMCPU *cpu) .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, .resetvalue = 0 }, - { .name = "RES_0_C0_C3_6", .state = ARM_CP_STATE_BOTH, + { .name = "ID_MMFR5", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = 0 }, + .resetvalue = cpu->isar.id_mmfr5 }, { .name = "RES_0_C0_C3_7", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 7, .access = PL1_R, .type = ARM_CP_CONST, diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 84c4c85f40..2d737c443e 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -643,6 +643,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ARM64_SYS_REG(3, 0, 0, 3, 2)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, ARM64_SYS_REG(3, 0, 0, 3, 4)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5, + ARM64_SYS_REG(3, 0, 0, 3, 6)); /* * DBGDIDR is a bit complicated because the kernel doesn't From d22c564958ffa6bd40be34c6ea3333ee7ef73b68 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 19 Aug 2022 12:00:50 +0100 Subject: [PATCH 0436/1020] target/arm: Implement ID_DFR1 In Armv8.6, a new AArch32 ID register ID_DFR1 is defined; implement it. We don't have any CPUs with features that they need to advertise here yet, but plumbing in the ID register gives it the right name when debugging and will help in future when we do add a CPU that has non-zero ID_DFR1 fields. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220819110052.2942289-5-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/cpu.h | 1 + target/arm/helper.c | 4 ++-- target/arm/kvm64.c | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index fcc5927587..fa24ce9f96 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -983,6 +983,7 @@ struct ArchCPU { uint32_t mvfr1; uint32_t mvfr2; uint32_t id_dfr0; + uint32_t id_dfr1; uint32_t dbgdidr; uint32_t dbgdevid; uint32_t dbgdevid1; diff --git a/target/arm/helper.c b/target/arm/helper.c index 0737851925..7ff03f1a4b 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -7581,11 +7581,11 @@ void register_cp_regs_for_features(ARMCPU *cpu) .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, .resetvalue = cpu->isar.id_pfr2 }, - { .name = "RES_0_C0_C3_5", .state = ARM_CP_STATE_BOTH, + { .name = "ID_DFR1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 5, .access = PL1_R, .type = ARM_CP_CONST, .accessfn = access_aa64_tid3, - .resetvalue = 0 }, + .resetvalue = cpu->isar.id_dfr1 }, { .name = "ID_MMFR5", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 0, .crm = 3, .opc2 = 6, .access = PL1_R, .type = ARM_CP_CONST, diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 2d737c443e..1197253d12 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -643,6 +643,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ARM64_SYS_REG(3, 0, 0, 3, 2)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_pfr2, ARM64_SYS_REG(3, 0, 0, 3, 4)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_dfr1, + ARM64_SYS_REG(3, 0, 0, 3, 5)); err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_mmfr5, ARM64_SYS_REG(3, 0, 0, 3, 6)); From 3fe72e213eae33daaea88685878a571bd5ef3e08 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 19 Aug 2022 12:00:51 +0100 Subject: [PATCH 0437/1020] target/arm: Advertise FEAT_ETS for '-cpu max' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The architectural feature FEAT_ETS (Enhanced Translation Synchronization) is a set of tightened guarantees about memory ordering involving translation table walks: * if memory access RW1 is ordered-before memory access RW2 then it is also ordered-before any translation table walk generated by RW2 that generates a translation fault, address size fault or access fault * TLB maintenance on non-exec-permission translations is guaranteed complete after a DSB (ie it does not need the context synchronization event that you have to have if you don’t have FEAT_ETS) For QEMU’s implementation we don’t reorder translation table walk accesses, and we guarantee to finish the TLB maintenance as soon as the TLB op is done (the tlb_flush functions will complete at the end of the TLB, and TLB ops always end the TB because they’re sysreg writes). So we’re already compliant and all we need to do is say so in the ID registers for the 'max' CPU. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220819110052.2942289-6-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- docs/system/arm/emulation.rst | 1 + target/arm/cpu64.c | 1 + target/arm/cpu_tcg.c | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst index 8e494c8bea..811358fd0a 100644 --- a/docs/system/arm/emulation.rst +++ b/docs/system/arm/emulation.rst @@ -24,6 +24,7 @@ the following architecture extensions: - FEAT_Debugv8p4 (Debug changes for v8.4) - FEAT_DotProd (Advanced SIMD dot product instructions) - FEAT_DoubleFault (Double Fault Extension) +- FEAT_ETS (Enhanced Translation Synchronization) - FEAT_FCMA (Floating-point complex number instructions) - FEAT_FHM (Floating-point half-precision multiplication instructions) - FEAT_FP16 (Half-precision floating-point data processing) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 9d1ea32057..3ac5e197a7 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -1122,6 +1122,7 @@ static void aarch64_max_initfn(Object *obj) t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */ t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* FEAT_PAN2 */ t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */ + t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */ t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */ cpu->isar.id_aa64mmfr1 = t; diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index 3099b38e32..f63f8cdd95 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -67,6 +67,10 @@ void aa32_max_features(ARMCPU *cpu) t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX*/ cpu->isar.id_mmfr4 = t; + t = cpu->isar.id_mmfr5; + t = FIELD_DP32(t, ID_MMFR5, ETS, 1); /* FEAT_ETS */ + cpu->isar.id_mmfr5 = t; + t = cpu->isar.id_pfr0; t = FIELD_DP32(t, ID_PFR0, CSV2, 2); /* FEAT_CVS2 */ t = FIELD_DP32(t, ID_PFR0, DIT, 1); /* FEAT_DIT */ From bb7d902154f7f17c9127631c42a21fbbc805cb40 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 19 Aug 2022 12:00:52 +0100 Subject: [PATCH 0438/1020] target/arm: Add missing space in comment Fix a missing space before a comment terminator. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220819110052.2942289-7-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/cpu_tcg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index f63f8cdd95..b714c61d94 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -64,7 +64,7 @@ void aa32_max_features(ARMCPU *cpu) t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* FEAT_AA32HPD */ t = FIELD_DP32(t, ID_MMFR4, AC2, 1); /* ACTLR2, HACTLR2 */ t = FIELD_DP32(t, ID_MMFR4, CNP, 1); /* FEAT_TTCNP */ - t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX*/ + t = FIELD_DP32(t, ID_MMFR4, XNX, 1); /* FEAT_XNX */ cpu->isar.id_mmfr4 = t; t = cpu->isar.id_mmfr5; From 76e25d41d44c49eb0fe399064a719702a3023102 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:49 +0100 Subject: [PATCH 0439/1020] target/arm: Don't corrupt high half of PMOVSR when cycle counter overflows When the cycle counter overflows, we are intended to set bit 31 in PMOVSR to indicate this. However a missing ULL suffix means that we end up setting all of bits 63-31. Fix the bug. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-2-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 7ff03f1a4b..e4824e01b8 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1186,7 +1186,7 @@ static void pmccntr_op_start(CPUARMState *env) uint64_t overflow_mask = env->cp15.c9_pmcr & PMCRLC ? \ 1ull << 63 : 1ull << 31; if (env->cp15.c15_ccnt & ~new_pmccntr & overflow_mask) { - env->cp15.c9_pmovsr |= (1 << 31); + env->cp15.c9_pmovsr |= (1ULL << 31); pmu_update_irq(env); } From c117c0649ce4022f518a7f0bc14bf7b036c89de3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:50 +0100 Subject: [PATCH 0440/1020] target/arm: Correct value returned by pmu_counter_mask() pmu_counter_mask() accidentally returns a value with bits [63:32] set, because the expression it returns is evaluated as a signed value that gets sign-extended to 64 bits. Force the whole expression to be evaluated with 64-bit arithmetic with ULL suffixes. The main effect of this bug was that a guest could write to the bits in the high half of registers like PMCNTENSET_EL0 that are supposed to be RES0. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-3-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/internals.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index b8fefdff67..83526166de 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1296,7 +1296,7 @@ static inline uint32_t pmu_num_counters(CPUARMState *env) /* Bits allowed to be set/cleared for PMCNTEN* and PMINTEN* */ static inline uint64_t pmu_counter_mask(CPUARMState *env) { - return (1 << 31) | ((1 << pmu_num_counters(env)) - 1); + return (1ULL << 31) | ((1ULL << pmu_num_counters(env)) - 1); } #ifdef TARGET_AARCH64 From 01765386a88868ae993bcbb39f111501fe690035 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:51 +0100 Subject: [PATCH 0441/1020] target/arm: Don't mishandle count when enabling or disabling PMU counters The PMU cycle and event counter infrastructure design requires that operations on the PMU register fields are wrapped in pmu_op_start() and pmu_op_finish() calls (or their more specific pmmcntr and pmevcntr equivalents). This includes any changes to registers which affect whether the counter should be enabled or disabled, but we forgot to do this. The effect of this bug is that in sequences like: * disable the cycle counter (PMCCNTR) using the PMCNTEN register * write a value such as 0xfffff000 to the PMCCNTR * restart the counter by writing to PMCNTEN the value written to the cycle counter is corrupted, and it starts counting from the wrong place. (Essentially, we fail to record that the QEMU_CLOCK_VIRTUAL timestamp when the counter should be considered to have started counting is the point when PMCNTEN is written to enable the counter.) Add the necessary bracketing calls, so that updates to the various registers which affect whether the PMU is counting are handled correctly. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-4-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/helper.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/target/arm/helper.c b/target/arm/helper.c index e4824e01b8..a348c7407d 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1079,6 +1079,14 @@ static CPAccessResult pmreg_access_ccntr(CPUARMState *env, return pmreg_access(env, ri, isread); } +/* + * Bits in MDCR_EL2 and MDCR_EL3 which pmu_counter_enabled() looks at. + * We use these to decide whether we need to wrap a write to MDCR_EL2 + * or MDCR_EL3 in pmu_op_start()/pmu_op_finish() calls. + */ +#define MDCR_EL2_PMU_ENABLE_BITS (MDCR_HPME | MDCR_HPMD | MDCR_HPMN) +#define MDCR_EL3_PMU_ENABLE_BITS (MDCR_SPME) + /* Returns true if the counter (pass 31 for PMCCNTR) should count events using * the current EL, security state, and register configuration. */ @@ -1432,15 +1440,19 @@ static uint64_t pmccfiltr_read_a32(CPUARMState *env, const ARMCPRegInfo *ri) static void pmcntenset_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + pmu_op_start(env); value &= pmu_counter_mask(env); env->cp15.c9_pmcnten |= value; + pmu_op_finish(env); } static void pmcntenclr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + pmu_op_start(env); value &= pmu_counter_mask(env); env->cp15.c9_pmcnten &= ~value; + pmu_op_finish(env); } static void pmovsr_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4681,7 +4693,39 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + /* + * Some MDCR_EL3 bits affect whether PMU counters are running: + * if we are trying to change any of those then we must + * bracket this update with PMU start/finish calls. + */ + bool pmu_op = (env->cp15.mdcr_el3 ^ value) & MDCR_EL3_PMU_ENABLE_BITS; + + if (pmu_op) { + pmu_op_start(env); + } env->cp15.mdcr_el3 = value & SDCR_VALID_MASK; + if (pmu_op) { + pmu_op_finish(env); + } +} + +static void mdcr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* + * Some MDCR_EL2 bits affect whether PMU counters are running: + * if we are trying to change any of those then we must + * bracket this update with PMU start/finish calls. + */ + bool pmu_op = (env->cp15.mdcr_el2 ^ value) & MDCR_EL2_PMU_ENABLE_BITS; + + if (pmu_op) { + pmu_op_start(env); + } + env->cp15.mdcr_el2 = value; + if (pmu_op) { + pmu_op_finish(env); + } } static const ARMCPRegInfo v8_cp_reginfo[] = { @@ -7724,6 +7768,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) ARMCPRegInfo mdcr_el2 = { .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1, + .writefn = mdcr_el2_write, .access = PL2_RW, .resetvalue = pmu_num_counters(env), .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el2), }; From b57aa7bdc3b4f16b216bd854e86431146729a640 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:52 +0100 Subject: [PATCH 0442/1020] target/arm: Ignore PMCR.D when PMCR.LC is set The architecture requires that if PMCR.LC is set (for a 64-bit cycle counter) then PMCR.D (which enables the clock divider so the counter ticks every 64 cycles rather than every cycle) should be ignored. We were always honouring PMCR.D; fix the bug so we correctly ignore it in this situation. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-5-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/helper.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index a348c7407d..f1b20de16d 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1172,6 +1172,17 @@ static void pmu_update_irq(CPUARMState *env) (env->cp15.c9_pminten & env->cp15.c9_pmovsr)); } +static bool pmccntr_clockdiv_enabled(CPUARMState *env) +{ + /* + * Return true if the clock divider is enabled and the cycle counter + * is supposed to tick only once every 64 clock cycles. This is + * controlled by PMCR.D, but if PMCR.LC is set to enable the long + * (64-bit) cycle counter PMCR.D has no effect. + */ + return (env->cp15.c9_pmcr & (PMCRD | PMCRLC)) == PMCRD; +} + /* * Ensure c15_ccnt is the guest-visible count so that operations such as * enabling/disabling the counter or filtering, modifying the count itself, @@ -1184,8 +1195,7 @@ static void pmccntr_op_start(CPUARMState *env) if (pmu_counter_enabled(env, 31)) { uint64_t eff_cycles = cycles; - if (env->cp15.c9_pmcr & PMCRD) { - /* Increment once every 64 processor clock cycles */ + if (pmccntr_clockdiv_enabled(env)) { eff_cycles /= 64; } @@ -1228,8 +1238,7 @@ static void pmccntr_op_finish(CPUARMState *env) #endif uint64_t prev_cycles = env->cp15.c15_ccnt_delta; - if (env->cp15.c9_pmcr & PMCRD) { - /* Increment once every 64 processor clock cycles */ + if (pmccntr_clockdiv_enabled(env)) { prev_cycles /= 64; } env->cp15.c15_ccnt_delta = prev_cycles - env->cp15.c15_ccnt; From 872d20343de4f1af45a31270f47cc54cc474bf55 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:53 +0100 Subject: [PATCH 0443/1020] target/arm: Honour MDCR_EL2.HPMD in Secure EL2 The logic in pmu_counter_enabled() for handling the 'prohibit event counting' bits MDCR_EL2.HPMD and MDCR_EL3.SPME is written in a way that assumes that EL2 is never Secure. This used to be true, but the architecture now permits Secure EL2, and QEMU can emulate this. Refactor the prohibit logic so that we effectively OR together the various prohibit bits when they apply, rather than trying to construct an if-else ladder where any particular state of the CPU ends up in exactly one branch of the ladder. This fixes the Secure EL2 case and also is a better structure for adding the PMUv8.5 bits MDCR_EL2.HCCD and MDCR_EL3.SCCD. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-6-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/helper.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index f1b20de16d..b792694df0 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1094,7 +1094,7 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) { uint64_t filter; bool e, p, u, nsk, nsu, nsh, m; - bool enabled, prohibited, filtered; + bool enabled, prohibited = false, filtered; bool secure = arm_is_secure(env); int el = arm_current_el(env); uint64_t mdcr_el2 = arm_mdcr_el2_eff(env); @@ -1112,15 +1112,12 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) } enabled = e && (env->cp15.c9_pmcnten & (1 << counter)); - if (!secure) { - if (el == 2 && (counter < hpmn || counter == 31)) { - prohibited = mdcr_el2 & MDCR_HPMD; - } else { - prohibited = false; - } - } else { - prohibited = arm_feature(env, ARM_FEATURE_EL3) && - !(env->cp15.mdcr_el3 & MDCR_SPME); + /* Is event counting prohibited? */ + if (el == 2 && (counter < hpmn || counter == 31)) { + prohibited = mdcr_el2 & MDCR_HPMD; + } + if (secure) { + prohibited = prohibited || !(env->cp15.mdcr_el3 & MDCR_SPME); } if (prohibited && counter == 31) { From f1dd2506ee75b21a604e5a8b6e1c0fd00a435f7e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:54 +0100 Subject: [PATCH 0444/1020] target/arm: Detect overflow when calculating next PMU interrupt In pmccntr_op_finish() and pmevcntr_op_finish() we calculate the next point at which we will get an overflow and need to fire the PMU interrupt or set the overflow flag. We do this by calculating the number of nanoseconds to the overflow event and then adding it to qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL). However, we don't check whether that signed addition overflows, which can happen if the next PMU interrupt would happen massively far in the future (250 years or more). Since QEMU assumes that "when the QEMU_CLOCK_VIRTUAL rolls over" is "never", the sensible behaviour in this situation is simply to not try to set the timer if it would be beyond that point. Detect the overflow, and skip setting the timer in that case. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-7-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/helper.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index b792694df0..11a7a57710 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1227,10 +1227,13 @@ static void pmccntr_op_finish(CPUARMState *env) int64_t overflow_in = cycles_ns_per(remaining_cycles); if (overflow_in > 0) { - int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - overflow_in; - ARMCPU *cpu = env_archcpu(env); - timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + int64_t overflow_at; + + if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + overflow_in, &overflow_at)) { + ARMCPU *cpu = env_archcpu(env); + timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + } } #endif @@ -1275,10 +1278,13 @@ static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter) int64_t overflow_in = pm_events[event_idx].ns_per_count(delta); if (overflow_in > 0) { - int64_t overflow_at = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - overflow_in; - ARMCPU *cpu = env_archcpu(env); - timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + int64_t overflow_at; + + if (!sadd64_overflow(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), + overflow_in, &overflow_at)) { + ARMCPU *cpu = env_archcpu(env); + timer_mod_anticipate_ns(cpu->pmu_timer, overflow_at); + } } #endif From a793bcd0272d9d25c942184ee18c7ed4dc75dc0d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:55 +0100 Subject: [PATCH 0445/1020] target/arm: Rename pmu_8_n feature test functions Our feature test functions that check the PMU version are named isar_feature_{aa32,aa64,any}_pmu_8_{1,4}. This doesn't match the current Arm ARM official feature names, which are FEAT_PMUv3p1 and FEAT_PMUv3p4. Rename these functions to _pmuv3p1 and _pmuv3p4. This commit was created with: sed -i -e 's/pmu_8_/pmuv3p/g' target/arm/*.[ch] Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-8-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/cpu.h | 16 ++++++++-------- target/arm/helper.c | 18 +++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index fa24ce9f96..d86e51992a 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3712,14 +3712,14 @@ static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id) return FIELD_EX32(id->id_mmfr3, ID_MMFR3, PAN) >= 2; } -static inline bool isar_feature_aa32_pmu_8_1(const ARMISARegisters *id) +static inline bool isar_feature_aa32_pmuv3p1(const ARMISARegisters *id) { /* 0xf means "non-standard IMPDEF PMU" */ return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 4 && FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; } -static inline bool isar_feature_aa32_pmu_8_4(const ARMISARegisters *id) +static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id) { /* 0xf means "non-standard IMPDEF PMU" */ return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 5 && @@ -4038,13 +4038,13 @@ static inline bool isar_feature_aa64_sme(const ARMISARegisters *id) return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0; } -static inline bool isar_feature_aa64_pmu_8_1(const ARMISARegisters *id) +static inline bool isar_feature_aa64_pmuv3p1(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 4 && FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; } -static inline bool isar_feature_aa64_pmu_8_4(const ARMISARegisters *id) +static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 5 && FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; @@ -4213,14 +4213,14 @@ static inline bool isar_feature_any_predinv(const ARMISARegisters *id) return isar_feature_aa64_predinv(id) || isar_feature_aa32_predinv(id); } -static inline bool isar_feature_any_pmu_8_1(const ARMISARegisters *id) +static inline bool isar_feature_any_pmuv3p1(const ARMISARegisters *id) { - return isar_feature_aa64_pmu_8_1(id) || isar_feature_aa32_pmu_8_1(id); + return isar_feature_aa64_pmuv3p1(id) || isar_feature_aa32_pmuv3p1(id); } -static inline bool isar_feature_any_pmu_8_4(const ARMISARegisters *id) +static inline bool isar_feature_any_pmuv3p4(const ARMISARegisters *id) { - return isar_feature_aa64_pmu_8_4(id) || isar_feature_aa32_pmu_8_4(id); + return isar_feature_aa64_pmuv3p4(id) || isar_feature_aa32_pmuv3p4(id); } static inline bool isar_feature_any_ccidx(const ARMISARegisters *id) diff --git a/target/arm/helper.c b/target/arm/helper.c index 11a7a57710..987ac19fe8 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -879,16 +879,16 @@ static int64_t instructions_ns_per(uint64_t icount) } #endif -static bool pmu_8_1_events_supported(CPUARMState *env) +static bool pmuv3p1_events_supported(CPUARMState *env) { /* For events which are supported in any v8.1 PMU */ - return cpu_isar_feature(any_pmu_8_1, env_archcpu(env)); + return cpu_isar_feature(any_pmuv3p1, env_archcpu(env)); } -static bool pmu_8_4_events_supported(CPUARMState *env) +static bool pmuv3p4_events_supported(CPUARMState *env) { /* For events which are supported in any v8.1 PMU */ - return cpu_isar_feature(any_pmu_8_4, env_archcpu(env)); + return cpu_isar_feature(any_pmuv3p4, env_archcpu(env)); } static uint64_t zero_event_get_count(CPUARMState *env) @@ -922,17 +922,17 @@ static const pm_event pm_events[] = { }, #endif { .number = 0x023, /* STALL_FRONTEND */ - .supported = pmu_8_1_events_supported, + .supported = pmuv3p1_events_supported, .get_count = zero_event_get_count, .ns_per_count = zero_event_ns_per, }, { .number = 0x024, /* STALL_BACKEND */ - .supported = pmu_8_1_events_supported, + .supported = pmuv3p1_events_supported, .get_count = zero_event_get_count, .ns_per_count = zero_event_ns_per, }, { .number = 0x03c, /* STALL */ - .supported = pmu_8_4_events_supported, + .supported = pmuv3p4_events_supported, .get_count = zero_event_get_count, .ns_per_count = zero_event_ns_per, }, @@ -6400,7 +6400,7 @@ static void define_pmu_regs(ARMCPU *cpu) g_free(pmevtyper_name); g_free(pmevtyper_el0_name); } - if (cpu_isar_feature(aa32_pmu_8_1, cpu)) { + if (cpu_isar_feature(aa32_pmuv3p1, cpu)) { ARMCPRegInfo v81_pmu_regs[] = { { .name = "PMCEID2", .state = ARM_CP_STATE_AA32, .cp = 15, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 4, @@ -6413,7 +6413,7 @@ static void define_pmu_regs(ARMCPU *cpu) }; define_arm_cp_regs(cpu, v81_pmu_regs); } - if (cpu_isar_feature(any_pmu_8_4, cpu)) { + if (cpu_isar_feature(any_pmuv3p4, cpu)) { static const ARMCPRegInfo v84_pmmir = { .name = "PMMIR_EL1", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .opc1 = 0, .crn = 9, .crm = 14, .opc2 = 6, From 0b42f4fab9d3e994efa44e17cb76c15b269bcbda Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:56 +0100 Subject: [PATCH 0446/1020] target/arm: Implement FEAT_PMUv3p5 cycle counter disable bits FEAT_PMUv3p5 introduces new bits which disable the cycle counter from counting: * MDCR_EL2.HCCD disables the counter when in EL2 * MDCR_EL3.SCCD disables the counter when Secure Add the code to support these bits. (Note that there is a third documented counter-disable bit, MDCR_EL3.MCCD, which disables the counter when in EL3. This is not present until FEAT_PMUv3p7, so is out of scope for now.) Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-9-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/cpu.h | 20 ++++++++++++++++++++ target/arm/helper.c | 21 +++++++++++++++++---- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index d86e51992a..41e74df104 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1334,6 +1334,8 @@ FIELD(CPTR_EL3, TTA, 20, 1) FIELD(CPTR_EL3, TAM, 30, 1) FIELD(CPTR_EL3, TCPAC, 31, 1) +#define MDCR_SCCD (1U << 23) /* MDCR_EL3 */ +#define MDCR_HCCD (1U << 23) /* MDCR_EL2 */ #define MDCR_EPMAD (1U << 21) #define MDCR_EDAD (1U << 20) #define MDCR_SPME (1U << 17) /* MDCR_EL3 */ @@ -3726,6 +3728,13 @@ static inline bool isar_feature_aa32_pmuv3p4(const ARMISARegisters *id) FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; } +static inline bool isar_feature_aa32_pmuv3p5(const ARMISARegisters *id) +{ + /* 0xf means "non-standard IMPDEF PMU" */ + return FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) >= 6 && + FIELD_EX32(id->id_dfr0, ID_DFR0, PERFMON) != 0xf; +} + static inline bool isar_feature_aa32_hpd(const ARMISARegisters *id) { return FIELD_EX32(id->id_mmfr4, ID_MMFR4, HPDS) != 0; @@ -4050,6 +4059,12 @@ static inline bool isar_feature_aa64_pmuv3p4(const ARMISARegisters *id) FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; } +static inline bool isar_feature_aa64_pmuv3p5(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) >= 6 && + FIELD_EX64(id->id_aa64dfr0, ID_AA64DFR0, PMUVER) != 0xf; +} + static inline bool isar_feature_aa64_rcpc_8_3(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64isar1, ID_AA64ISAR1, LRCPC) != 0; @@ -4223,6 +4238,11 @@ static inline bool isar_feature_any_pmuv3p4(const ARMISARegisters *id) return isar_feature_aa64_pmuv3p4(id) || isar_feature_aa32_pmuv3p4(id); } +static inline bool isar_feature_any_pmuv3p5(const ARMISARegisters *id) +{ + return isar_feature_aa64_pmuv3p5(id) || isar_feature_aa32_pmuv3p5(id); +} + static inline bool isar_feature_any_ccidx(const ARMISARegisters *id) { return isar_feature_aa64_ccidx(id) || isar_feature_aa32_ccidx(id); diff --git a/target/arm/helper.c b/target/arm/helper.c index 987ac19fe8..0d1f23de09 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1084,8 +1084,8 @@ static CPAccessResult pmreg_access_ccntr(CPUARMState *env, * We use these to decide whether we need to wrap a write to MDCR_EL2 * or MDCR_EL3 in pmu_op_start()/pmu_op_finish() calls. */ -#define MDCR_EL2_PMU_ENABLE_BITS (MDCR_HPME | MDCR_HPMD | MDCR_HPMN) -#define MDCR_EL3_PMU_ENABLE_BITS (MDCR_SPME) +#define MDCR_EL2_PMU_ENABLE_BITS (MDCR_HPME | MDCR_HPMD | MDCR_HPMN | MDCR_HCCD) +#define MDCR_EL3_PMU_ENABLE_BITS (MDCR_SPME | MDCR_SCCD) /* Returns true if the counter (pass 31 for PMCCNTR) should count events using * the current EL, security state, and register configuration. @@ -1120,8 +1120,21 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) prohibited = prohibited || !(env->cp15.mdcr_el3 & MDCR_SPME); } - if (prohibited && counter == 31) { - prohibited = env->cp15.c9_pmcr & PMCRDP; + if (counter == 31) { + /* + * The cycle counter defaults to running. PMCR.DP says "disable + * the cycle counter when event counting is prohibited". + * Some MDCR bits disable the cycle counter specifically. + */ + prohibited = prohibited && env->cp15.c9_pmcr & PMCRDP; + if (cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { + if (secure) { + prohibited = prohibited || (env->cp15.mdcr_el3 & MDCR_SCCD); + } + if (el == 2) { + prohibited = prohibited || (mdcr_el2 & MDCR_HCCD); + } + } } if (counter == 31) { From 47b385dae8e95e833114285625f4db796c52e8a3 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:57 +0100 Subject: [PATCH 0447/1020] target/arm: Support 64-bit event counters for FEAT_PMUv3p5 With FEAT_PMUv3p5, the event counters are now 64 bit, rather than 32 bit. (Previously, only the cycle counter could be 64 bit, and other event counters were always 32 bits). For any given event counter, whether the overflow event is noted for overflow from bit 31 or from bit 63 is controlled by a combination of PMCR.LP, MDCR_EL2.HLP and MDCR_EL2.HPMN. Implement the 64-bit event counter handling. We choose to make our counters always 64 bits, and mask out the top 32 bits on read or write of PMXEVCNTR for CPUs which don't have FEAT_PMUv3p5. (Note that the changes to pmenvcntr_op_start() and pmenvcntr_op_finish() bring their logic closer into line with that of pmccntr_op_start() and pmccntr_op_finish(), which already had to cope with the overflow being either at 32 or 64 bits.) Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-10-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- target/arm/cpu.h | 1 + target/arm/helper.c | 62 ++++++++++++++++++++++++++++++++++++------ target/arm/internals.h | 3 +- 3 files changed, 57 insertions(+), 9 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 41e74df104..33cdbc0143 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1334,6 +1334,7 @@ FIELD(CPTR_EL3, TTA, 20, 1) FIELD(CPTR_EL3, TAM, 30, 1) FIELD(CPTR_EL3, TCPAC, 31, 1) +#define MDCR_HLP (1U << 26) /* MDCR_EL2 */ #define MDCR_SCCD (1U << 23) /* MDCR_EL3 */ #define MDCR_HCCD (1U << 23) /* MDCR_EL2 */ #define MDCR_EPMAD (1U << 21) diff --git a/target/arm/helper.c b/target/arm/helper.c index 0d1f23de09..1a57d2e1d6 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1084,7 +1084,8 @@ static CPAccessResult pmreg_access_ccntr(CPUARMState *env, * We use these to decide whether we need to wrap a write to MDCR_EL2 * or MDCR_EL3 in pmu_op_start()/pmu_op_finish() calls. */ -#define MDCR_EL2_PMU_ENABLE_BITS (MDCR_HPME | MDCR_HPMD | MDCR_HPMN | MDCR_HCCD) +#define MDCR_EL2_PMU_ENABLE_BITS \ + (MDCR_HPME | MDCR_HPMD | MDCR_HPMN | MDCR_HCCD | MDCR_HLP) #define MDCR_EL3_PMU_ENABLE_BITS (MDCR_SPME | MDCR_SCCD) /* Returns true if the counter (pass 31 for PMCCNTR) should count events using @@ -1193,6 +1194,32 @@ static bool pmccntr_clockdiv_enabled(CPUARMState *env) return (env->cp15.c9_pmcr & (PMCRD | PMCRLC)) == PMCRD; } +static bool pmevcntr_is_64_bit(CPUARMState *env, int counter) +{ + /* Return true if the specified event counter is configured to be 64 bit */ + + /* This isn't intended to be used with the cycle counter */ + assert(counter < 31); + + if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { + return false; + } + + if (arm_feature(env, ARM_FEATURE_EL2)) { + /* + * MDCR_EL2.HLP still applies even when EL2 is disabled in the + * current security state, so we don't use arm_mdcr_el2_eff() here. + */ + bool hlp = env->cp15.mdcr_el2 & MDCR_HLP; + int hpmn = env->cp15.mdcr_el2 & MDCR_HPMN; + + if (hpmn != 0 && counter >= hpmn) { + return hlp; + } + } + return env->cp15.c9_pmcr & PMCRLP; +} + /* * Ensure c15_ccnt is the guest-visible count so that operations such as * enabling/disabling the counter or filtering, modifying the count itself, @@ -1269,9 +1296,11 @@ static void pmevcntr_op_start(CPUARMState *env, uint8_t counter) } if (pmu_counter_enabled(env, counter)) { - uint32_t new_pmevcntr = count - env->cp15.c14_pmevcntr_delta[counter]; + uint64_t new_pmevcntr = count - env->cp15.c14_pmevcntr_delta[counter]; + uint64_t overflow_mask = pmevcntr_is_64_bit(env, counter) ? + 1ULL << 63 : 1ULL << 31; - if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & INT32_MIN) { + if (env->cp15.c14_pmevcntr[counter] & ~new_pmevcntr & overflow_mask) { env->cp15.c9_pmovsr |= (1 << counter); pmu_update_irq(env); } @@ -1286,9 +1315,13 @@ static void pmevcntr_op_finish(CPUARMState *env, uint8_t counter) #ifndef CONFIG_USER_ONLY uint16_t event = env->cp15.c14_pmevtyper[counter] & PMXEVTYPER_EVTCOUNT; uint16_t event_idx = supported_event_map[event]; - uint64_t delta = UINT32_MAX - - (uint32_t)env->cp15.c14_pmevcntr[counter] + 1; - int64_t overflow_in = pm_events[event_idx].ns_per_count(delta); + uint64_t delta = -(env->cp15.c14_pmevcntr[counter] + 1); + int64_t overflow_in; + + if (!pmevcntr_is_64_bit(env, counter)) { + delta = (uint32_t)delta; + } + overflow_in = pm_events[event_idx].ns_per_count(delta); if (overflow_in > 0) { int64_t overflow_at; @@ -1375,6 +1408,8 @@ static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { unsigned int i; + uint64_t overflow_mask, new_pmswinc; + for (i = 0; i < pmu_num_counters(env); i++) { /* Increment a counter's count iff: */ if ((value & (1 << i)) && /* counter's bit is set */ @@ -1388,9 +1423,12 @@ static void pmswinc_write(CPUARMState *env, const ARMCPRegInfo *ri, * Detect if this write causes an overflow since we can't predict * PMSWINC overflows like we can for other events */ - uint32_t new_pmswinc = env->cp15.c14_pmevcntr[i] + 1; + new_pmswinc = env->cp15.c14_pmevcntr[i] + 1; - if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & INT32_MIN) { + overflow_mask = pmevcntr_is_64_bit(env, i) ? + 1ULL << 63 : 1ULL << 31; + + if (env->cp15.c14_pmevcntr[i] & ~new_pmswinc & overflow_mask) { env->cp15.c9_pmovsr |= (1 << i); pmu_update_irq(env); } @@ -1597,6 +1635,10 @@ static uint64_t pmxevtyper_read(CPUARMState *env, const ARMCPRegInfo *ri) static void pmevcntr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value, uint8_t counter) { + if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { + /* Before FEAT_PMUv3p5, top 32 bits of event counters are RES0 */ + value &= MAKE_64BIT_MASK(0, 32); + } if (counter < pmu_num_counters(env)) { pmevcntr_op_start(env, counter); env->cp15.c14_pmevcntr[counter] = value; @@ -1616,6 +1658,10 @@ static uint64_t pmevcntr_read(CPUARMState *env, const ARMCPRegInfo *ri, pmevcntr_op_start(env, counter); ret = env->cp15.c14_pmevcntr[counter]; pmevcntr_op_finish(env, counter); + if (!cpu_isar_feature(any_pmuv3p5, env_archcpu(env))) { + /* Before FEAT_PMUv3p5, top 32 bits of event counters are RES0 */ + ret &= MAKE_64BIT_MASK(0, 32); + } return ret; } else { /* We opt to behave as a RAZ/WI when attempts to access PM[X]EVCNTR diff --git a/target/arm/internals.h b/target/arm/internals.h index 83526166de..bf60cd5f84 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1256,6 +1256,7 @@ enum MVEECIState { /* Definitions for the PMU registers */ #define PMCRN_MASK 0xf800 #define PMCRN_SHIFT 11 +#define PMCRLP 0x80 #define PMCRLC 0x40 #define PMCRDP 0x20 #define PMCRX 0x10 @@ -1267,7 +1268,7 @@ enum MVEECIState { * Mask of PMCR bits writable by guest (not including WO bits like C, P, * which can be written as 1 to trigger behaviour but which stay RAZ). */ -#define PMCR_WRITABLE_MASK (PMCRLC | PMCRDP | PMCRX | PMCRD | PMCRE) +#define PMCR_WRITABLE_MASK (PMCRLP | PMCRLC | PMCRDP | PMCRX | PMCRD | PMCRE) #define PMXEVTYPER_P 0x80000000 #define PMXEVTYPER_U 0x40000000 From e31e0f56616ae88cda22da8d5a257c2fcee4de2a Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 22 Aug 2022 14:23:58 +0100 Subject: [PATCH 0448/1020] target/arm: Report FEAT_PMUv3p5 for TCG '-cpu max' Update the ID registers for TCG's '-cpu max' to report a FEAT_PMUv3p5 compliant PMU. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-Id: <20220822132358.3524971-11-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- docs/system/arm/emulation.rst | 1 + target/arm/cpu64.c | 2 +- target/arm/cpu_tcg.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst index 811358fd0a..be7bbffe59 100644 --- a/docs/system/arm/emulation.rst +++ b/docs/system/arm/emulation.rst @@ -53,6 +53,7 @@ the following architecture extensions: - FEAT_PMULL (PMULL, PMULL2 instructions) - FEAT_PMUv3p1 (PMU Extensions v3.1) - FEAT_PMUv3p4 (PMU Extensions v3.4) +- FEAT_PMUv3p5 (PMU Extensions v3.5) - FEAT_RAS (Reliability, availability, and serviceability) - FEAT_RASv1p1 (RAS Extension v1.1) - FEAT_RDM (Advanced SIMD rounding double multiply accumulate instructions) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index 3ac5e197a7..e6314e86d2 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -1152,7 +1152,7 @@ static void aarch64_max_initfn(Object *obj) t = cpu->isar.id_aa64dfr0; t = FIELD_DP64(t, ID_AA64DFR0, DEBUGVER, 9); /* FEAT_Debugv8p4 */ - t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 5); /* FEAT_PMUv3p4 */ + t = FIELD_DP64(t, ID_AA64DFR0, PMUVER, 6); /* FEAT_PMUv3p5 */ cpu->isar.id_aa64dfr0 = t; t = cpu->isar.id_aa64smfr0; diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c index b714c61d94..98b5ba2160 100644 --- a/target/arm/cpu_tcg.c +++ b/target/arm/cpu_tcg.c @@ -85,7 +85,7 @@ void aa32_max_features(ARMCPU *cpu) t = cpu->isar.id_dfr0; t = FIELD_DP32(t, ID_DFR0, COPDBG, 9); /* FEAT_Debugv8p4 */ t = FIELD_DP32(t, ID_DFR0, COPSDBG, 9); /* FEAT_Debugv8p4 */ - t = FIELD_DP32(t, ID_DFR0, PERFMON, 5); /* FEAT_PMUv3p4 */ + t = FIELD_DP32(t, ID_DFR0, PERFMON, 6); /* FEAT_PMUv3p5 */ cpu->isar.id_dfr0 = t; } From f92bd43480bf2da36354e148d139ef2aac12d3f2 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 23 Aug 2022 17:04:16 +0100 Subject: [PATCH 0449/1020] target/arm: Remove useless TARGET_BIG_ENDIAN check in armv7m_load_kernel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Arm system emulation targets always have TARGET_BIG_ENDIAN clear, so there is no need to have handling in armv7m_load_kernel() for the case when it is defined. Remove the unnecessary code. Side notes: * our M-profile implementation is always little-endian (that is, it makes the IMPDEF choice that the read-only AIRCR.ENDIANNESS is 0) * if we did want to handle big-endian ELF files here we should do it the way that hw/arm/boot.c:arm_load_elf() does, by looking at the ELF header to see what endianness the file itself is Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220823160417.3858216-2-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- hw/arm/armv7m.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index 990861ee5e..fa4c2c735d 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -572,17 +572,10 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size) { ssize_t image_size; uint64_t entry; - int big_endian; AddressSpace *as; int asidx; CPUState *cs = CPU(cpu); -#if TARGET_BIG_ENDIAN - big_endian = 1; -#else - big_endian = 0; -#endif - if (arm_feature(&cpu->env, ARM_FEATURE_EL3)) { asidx = ARMASIdx_S; } else { @@ -593,7 +586,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size) if (kernel_filename) { image_size = load_elf_as(kernel_filename, NULL, NULL, NULL, &entry, NULL, NULL, - NULL, big_endian, EM_ARM, 1, 0, as); + NULL, 0, EM_ARM, 1, 0, as); if (image_size < 0) { image_size = load_image_targphys_as(kernel_filename, 0, mem_size, as); From 761c532ab1ebe9d345c9afe4fb9c2c4b26c58582 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 23 Aug 2022 17:04:17 +0100 Subject: [PATCH 0450/1020] target/arm: Make boards pass base address to armv7m_load_kernel() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently armv7m_load_kernel() takes the size of the block of memory where it should load the initial guest image, but assumes that it should always load it at address 0. This happens to be true of all our M-profile boards at the moment, but it isn't guaranteed to always be so: M-profile CPUs can be configured (via init-svtor and init-nsvtor, which match equivalent hardware configuration signals) to have the initial vector table at any address, not just zero. (For instance the Teeny board has the boot ROM at address 0x0200_0000.) Add a base address argument to armv7m_load_kernel(), so that callers now pass in both base address and size. All the current callers pass 0, so this is not a behaviour change. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220823160417.3858216-3-peter.maydell@linaro.org> Signed-off-by: Richard Henderson --- hw/arm/armv7m.c | 5 +++-- hw/arm/aspeed.c | 1 + hw/arm/microbit.c | 2 +- hw/arm/mps2-tz.c | 2 +- hw/arm/mps2.c | 2 +- hw/arm/msf2-som.c | 2 +- hw/arm/musca.c | 3 ++- hw/arm/netduino2.c | 2 +- hw/arm/netduinoplus2.c | 2 +- hw/arm/stellaris.c | 2 +- hw/arm/stm32vldiscovery.c | 2 +- include/hw/arm/boot.h | 5 ++++- 12 files changed, 18 insertions(+), 12 deletions(-) diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c index fa4c2c735d..50a9507c0b 100644 --- a/hw/arm/armv7m.c +++ b/hw/arm/armv7m.c @@ -568,7 +568,8 @@ static void armv7m_reset(void *opaque) cpu_reset(CPU(cpu)); } -void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size) +void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, + hwaddr mem_base, int mem_size) { ssize_t image_size; uint64_t entry; @@ -588,7 +589,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size) &entry, NULL, NULL, NULL, 0, EM_ARM, 1, 0, as); if (image_size < 0) { - image_size = load_image_targphys_as(kernel_filename, 0, + image_size = load_image_targphys_as(kernel_filename, mem_base, mem_size, as); } if (image_size < 0) { diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index b3bbe06f8f..bc3ecdb619 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -1430,6 +1430,7 @@ static void aspeed_minibmc_machine_init(MachineState *machine) armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + 0, AST1030_INTERNAL_FLASH_SIZE); } diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c index e9494334ce..50df362088 100644 --- a/hw/arm/microbit.c +++ b/hw/arm/microbit.c @@ -57,7 +57,7 @@ static void microbit_init(MachineState *machine) mr, -1); armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, - s->nrf51.flash_size); + 0, s->nrf51.flash_size); } static void microbit_machine_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c index 4017392bf5..394192b9b2 100644 --- a/hw/arm/mps2-tz.c +++ b/hw/arm/mps2-tz.c @@ -1197,7 +1197,7 @@ static void mps2tz_common_init(MachineState *machine) } armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, - boot_ram_size(mms)); + 0, boot_ram_size(mms)); } static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address, diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c index bb76fa6889..a86a994dba 100644 --- a/hw/arm/mps2.c +++ b/hw/arm/mps2.c @@ -450,7 +450,7 @@ static void mps2_common_init(MachineState *machine) mmc->fpga_type == FPGA_AN511 ? 47 : 13)); armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, - 0x400000); + 0, 0x400000); } static void mps2_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c index d9f881690e..a6df473ec9 100644 --- a/hw/arm/msf2-som.c +++ b/hw/arm/msf2-som.c @@ -98,7 +98,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine) sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line); armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, - soc->envm_size); + 0, soc->envm_size); } static void emcraft_sf2_machine_init(MachineClass *mc) diff --git a/hw/arm/musca.c b/hw/arm/musca.c index 7a83f7dda7..6eeee57c9d 100644 --- a/hw/arm/musca.c +++ b/hw/arm/musca.c @@ -597,7 +597,8 @@ static void musca_init(MachineState *machine) "cfg_sec_resp", 0)); } - armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000); + armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, + 0, 0x2000000); } static void musca_class_init(ObjectClass *oc, void *data) diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c index 3365da11bf..83753d53a3 100644 --- a/hw/arm/netduino2.c +++ b/hw/arm/netduino2.c @@ -49,7 +49,7 @@ static void netduino2_init(MachineState *machine) sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, - FLASH_SIZE); + 0, FLASH_SIZE); } static void netduino2_machine_init(MachineClass *mc) diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c index 76cea8e489..515c081605 100644 --- a/hw/arm/netduinoplus2.c +++ b/hw/arm/netduinoplus2.c @@ -50,7 +50,7 @@ static void netduinoplus2_init(MachineState *machine) armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, - FLASH_SIZE); + 0, FLASH_SIZE); } static void netduinoplus2_machine_init(MachineClass *mc) diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c index 12c673c917..a9e96c37f8 100644 --- a/hw/arm/stellaris.c +++ b/hw/arm/stellaris.c @@ -1302,7 +1302,7 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board) create_unimplemented_device("hibernation", 0x400fc000, 0x1000); create_unimplemented_device("flash-control", 0x400fd000, 0x1000); - armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size); + armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, 0, flash_size); } /* FIXME: Figure out how to generate these from stellaris_boards. */ diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c index 04036da3ee..67675e952f 100644 --- a/hw/arm/stm32vldiscovery.c +++ b/hw/arm/stm32vldiscovery.c @@ -53,7 +53,7 @@ static void stm32vldiscovery_init(MachineState *machine) armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, - FLASH_SIZE); + 0, FLASH_SIZE); } static void stm32vldiscovery_machine_init(MachineClass *mc) diff --git a/include/hw/arm/boot.h b/include/hw/arm/boot.h index c7ebae156e..f18cc3064f 100644 --- a/include/hw/arm/boot.h +++ b/include/hw/arm/boot.h @@ -25,13 +25,16 @@ typedef enum { * armv7m_load_kernel: * @cpu: CPU * @kernel_filename: file to load + * @mem_base: base address to load image at (should be where the + * CPU expects to find its vector table on reset) * @mem_size: mem_size: maximum image size to load * * Load the guest image for an ARMv7M system. This must be called by * any ARMv7M board. (This is necessary to ensure that the CPU resets * correctly on system reset, as well as for kernel loading.) */ -void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size); +void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, + hwaddr mem_base, int mem_size); /* arm_boot.c */ struct arm_boot_info { From 00d60cfcbda54b86ad9e09b20c7b71250dd6b19b Mon Sep 17 00:00:00 2001 From: zhenwei pi Date: Tue, 2 Aug 2022 15:37:20 +0800 Subject: [PATCH 0451/1020] monitor: Support specified vCPU registers Originally we have to get all the vCPU registers and parse the specified one. To improve the performance of this usage, allow user specified vCPU id to query registers. Run a VM with 16 vCPU, use bcc tool to track the latency of 'hmp_info_registers': 'info registers -a' uses about 3ms; 'info registers 12' uses about 150us. Cc: Darren Kenny Reviewed-by: Markus Armbruster Signed-off-by: zhenwei pi Reviewed-by: Darren Kenny Message-Id: <20220802073720.1236988-2-pizhenwei@bytedance.com> Signed-off-by: Dr. David Alan Gilbert --- hmp-commands-info.hx | 8 +++++--- monitor/misc.c | 10 ++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index 188d9ece3b..e012035541 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -100,9 +100,11 @@ ERST { .name = "registers", - .args_type = "cpustate_all:-a", - .params = "[-a]", - .help = "show the cpu registers (-a: all - show register info for all cpus)", + .args_type = "cpustate_all:-a,vcpu:i?", + .params = "[-a|vcpu]", + .help = "show the cpu registers (-a: show register info for all cpus;" + " vcpu: specific vCPU to query; show the current CPU's registers if" + " no argument is specified)", .cmd = hmp_info_registers, }, diff --git a/monitor/misc.c b/monitor/misc.c index 3d2312ba8d..6436a8786b 100644 --- a/monitor/misc.c +++ b/monitor/misc.c @@ -307,6 +307,7 @@ int monitor_get_cpu_index(Monitor *mon) static void hmp_info_registers(Monitor *mon, const QDict *qdict) { bool all_cpus = qdict_get_try_bool(qdict, "cpustate_all", false); + int vcpu = qdict_get_try_int(qdict, "vcpu", -1); CPUState *cs; if (all_cpus) { @@ -315,13 +316,18 @@ static void hmp_info_registers(Monitor *mon, const QDict *qdict) cpu_dump_state(cs, NULL, CPU_DUMP_FPU); } } else { - cs = mon_get_cpu(mon); + cs = vcpu >= 0 ? qemu_get_cpu(vcpu) : mon_get_cpu(mon); if (!cs) { - monitor_printf(mon, "No CPU available\n"); + if (vcpu >= 0) { + monitor_printf(mon, "CPU#%d not available\n", vcpu); + } else { + monitor_printf(mon, "No CPU available\n"); + } return; } + monitor_printf(mon, "\nCPU#%d\n", cs->cpu_index); cpu_dump_state(cs, NULL, CPU_DUMP_FPU); } } From 3183bb3f441ba5b9da570f7f5f9abdc3313ba311 Mon Sep 17 00:00:00 2001 From: Dongli Zhang Date: Wed, 31 Aug 2022 14:39:43 -0700 Subject: [PATCH 0452/1020] monitor/hmp: print trace as option in help for log command The below is printed when printing help information in qemu-system-x86_64 command line, and when CONFIG_TRACE_LOG is enabled: ---------------------------- $ qemu-system-x86_64 -d help ... ... trace:PATTERN enable trace events Use "-d trace:help" to get a list of trace events. ---------------------------- However, the options of "trace:PATTERN" are only printed by "qemu-system-x86_64 -d help", but missing in hmp "help log" command. Fixes: c84ea00dc2 ("log: add "-d trace:PATTERN"") Cc: Joe Jin Signed-off-by: Dongli Zhang Message-Id: <20220831213943.8155-1-dongli.zhang@oracle.com> Reviewed-by: Markus Armbruster Signed-off-by: Dr. David Alan Gilbert --- monitor/hmp.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/monitor/hmp.c b/monitor/hmp.c index 15ca04735c..a3375d0341 100644 --- a/monitor/hmp.c +++ b/monitor/hmp.c @@ -285,10 +285,15 @@ void help_cmd(Monitor *mon, const char *name) if (!strcmp(name, "log")) { const QEMULogItem *item; monitor_printf(mon, "Log items (comma separated):\n"); - monitor_printf(mon, "%-10s %s\n", "none", "remove all logs"); + monitor_printf(mon, "%-15s %s\n", "none", "remove all logs"); for (item = qemu_log_items; item->mask != 0; item++) { - monitor_printf(mon, "%-10s %s\n", item->name, item->help); + monitor_printf(mon, "%-15s %s\n", item->name, item->help); } +#ifdef CONFIG_TRACE_LOG + monitor_printf(mon, "trace:PATTERN enable trace events\n"); + monitor_printf(mon, "\nUse \"log trace:help\" to get a list of " + "trace events.\n\n"); +#endif return; } From 22269b0436cc8e4aaac975b4c8cb01b343d09661 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Thu, 8 Sep 2022 19:35:03 +0100 Subject: [PATCH 0453/1020] hmp: Fix ordering of text MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix the ordering of the help text so it's always after the commands being defined. A few had got out of order. Keep 'info' at the end. Signed-off-by: Dr. David Alan Gilbert Reviewed-by: Daniel P. BerrangĂ© --- hmp-commands.hx | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/hmp-commands.hx b/hmp-commands.hx index 182e639d14..8ab8000acd 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -1742,23 +1742,6 @@ SRST *icount* for the reference may be observed with ``info replay`` command. ERST - { - .name = "info", - .args_type = "item:s?", - .params = "[subcommand]", - .help = "show various information about the system state", - .cmd = hmp_info_help, - .sub_table = hmp_info_cmds, - .flags = "p", - }, - -SRST -``calc_dirty_rate`` *second* - Start a round of dirty rate measurement with the period specified in *second*. - The result of the dirty rate measurement may be observed with ``info - dirty_rate`` command. -ERST - { .name = "calc_dirty_rate", .args_type = "dirty_ring:-r,dirty_bitmap:-b,second:l,sample_pages_per_GB:l?", @@ -1770,10 +1753,10 @@ ERST }, SRST -``set_vcpu_dirty_limit`` - Set dirty page rate limit on virtual CPU, the information about all the - virtual CPU dirty limit status can be observed with ``info vcpu_dirty_limit`` - command. +``calc_dirty_rate`` *second* + Start a round of dirty rate measurement with the period specified in *second*. + The result of the dirty rate measurement may be observed with ``info + dirty_rate`` command. ERST { @@ -1786,8 +1769,8 @@ ERST }, SRST -``cancel_vcpu_dirty_limit`` - Cancel dirty page rate limit on virtual CPU, the information about all the +``set_vcpu_dirty_limit`` + Set dirty page rate limit on virtual CPU, the information about all the virtual CPU dirty limit status can be observed with ``info vcpu_dirty_limit`` command. ERST @@ -1800,3 +1783,20 @@ ERST "\n\t\t\t\t\t limit on a specified virtual cpu", .cmd = hmp_cancel_vcpu_dirty_limit, }, + +SRST +``cancel_vcpu_dirty_limit`` + Cancel dirty page rate limit on virtual CPU, the information about all the + virtual CPU dirty limit status can be observed with ``info vcpu_dirty_limit`` + command. +ERST + + { + .name = "info", + .args_type = "item:s?", + .params = "[subcommand]", + .help = "show various information about the system state", + .cmd = hmp_info_help, + .sub_table = hmp_info_cmds, + .flags = "p", + }, From 52281c6d11ec68b802e8a264780df2c4b981e6bc Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Sep 2022 02:15:34 +0200 Subject: [PATCH 0454/1020] KVM: use store-release to mark dirty pages as harvested MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following scenario can happen if QEMU sets more RESET flags while the KVM_RESET_DIRTY_RINGS ioctl is ongoing on another host CPU: CPU0 CPU1 CPU2 ------------------------ ------------------ ------------------------ fill gfn0 store-rel flags for gfn0 fill gfn1 store-rel flags for gfn1 load-acq flags for gfn0 set RESET for gfn0 load-acq flags for gfn1 set RESET for gfn1 do ioctl! -----------> ioctl(RESET_RINGS) fill gfn2 store-rel flags for gfn2 load-acq flags for gfn2 set RESET for gfn2 process gfn0 process gfn1 process gfn2 do ioctl! etc. The three load-acquire in CPU0 synchronize with the three store-release in CPU2, but CPU0 and CPU1 are only synchronized up to gfn1 and CPU1 may miss gfn2's fields other than flags. The kernel must be able to cope with invalid values of the fields, and userspace *will* invoke the ioctl once more. However, once the RESET flag is cleared on gfn2, it is lost forever, therefore in the above scenario CPU1 must read the correct value of gfn2's fields. Therefore RESET must be set with a store-release, that will synchronize with KVM's load-acquire in CPU1. Cc: Gavin Shan Reviewed-by: Peter Xu Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 136c8eaed3..7c8ce18bdd 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -728,7 +728,23 @@ static bool dirty_gfn_is_dirtied(struct kvm_dirty_gfn *gfn) static void dirty_gfn_set_collected(struct kvm_dirty_gfn *gfn) { - gfn->flags = KVM_DIRTY_GFN_F_RESET; + /* + * Use a store-release so that the CPU that executes KVM_RESET_DIRTY_RINGS + * sees the full content of the ring: + * + * CPU0 CPU1 CPU2 + * ------------------------------------------------------------------------------ + * fill gfn0 + * store-rel flags for gfn0 + * load-acq flags for gfn0 + * store-rel RESET for gfn0 + * ioctl(RESET_RINGS) + * load-acq flags for gfn0 + * check if flags have RESET + * + * The synchronization goes from CPU2 to CPU0 to CPU1. + */ + qatomic_store_release(&gfn->flags, KVM_DIRTY_GFN_F_RESET); } /* From 958e1dd1300f37f18b2161dfb4eb806fc8c19b44 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 18 Sep 2022 00:27:12 +0200 Subject: [PATCH 0455/1020] target/i386: Raise #GP on unaligned m128 accesses when required. Many instructions which load/store 128-bit values are supposed to raise #GP when the memory operand isn't 16-byte aligned. This includes: - Instructions explicitly requiring memory alignment (Exceptions Type 1 in the "AVX and SSE Instruction Exception Specification" section of the SDM) - Legacy SSE instructions that load/store 128-bit values (Exceptions Types 2 and 4). This change sets MO_ALIGN_16 on 128-bit memory accesses that require 16-byte alignment. It adds cpu_record_sigbus and cpu_do_unaligned_access hooks that simulate a #GP exception in qemu-user and qemu-system, respectively. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/217 Reviewed-by: Richard Henderson Signed-off-by: Ricky Zhou Message-Id: <20220830034816.57091-2-ricky@rzhou.org> [Do not bother checking PREFIX_VEX, since AVX is not supported. - Paolo] Signed-off-by: Paolo Bonzini --- target/i386/tcg/excp_helper.c | 13 +++++++++ target/i386/tcg/helper-tcg.h | 28 +++++++++++------- target/i386/tcg/sysemu/excp_helper.c | 8 ++++++ target/i386/tcg/tcg-cpu.c | 2 ++ target/i386/tcg/translate.c | 43 ++++++++++++++++------------ target/i386/tcg/user/excp_helper.c | 7 +++++ 6 files changed, 72 insertions(+), 29 deletions(-) diff --git a/target/i386/tcg/excp_helper.c b/target/i386/tcg/excp_helper.c index c1ffa1c0ef..7c3c8dc7fe 100644 --- a/target/i386/tcg/excp_helper.c +++ b/target/i386/tcg/excp_helper.c @@ -140,3 +140,16 @@ G_NORETURN void raise_exception_ra(CPUX86State *env, int exception_index, { raise_interrupt2(env, exception_index, 0, 0, 0, retaddr); } + +G_NORETURN void handle_unaligned_access(CPUX86State *env, vaddr vaddr, + MMUAccessType access_type, + uintptr_t retaddr) +{ + /* + * Unaligned accesses are currently only triggered by SSE/AVX + * instructions that impose alignment requirements on memory + * operands. These instructions raise #GP(0) upon accessing an + * unaligned address. + */ + raise_exception_ra(env, EXCP0D_GPF, retaddr); +} diff --git a/target/i386/tcg/helper-tcg.h b/target/i386/tcg/helper-tcg.h index 34167e2e29..cd1723389a 100644 --- a/target/i386/tcg/helper-tcg.h +++ b/target/i386/tcg/helper-tcg.h @@ -42,17 +42,6 @@ void x86_cpu_do_interrupt(CPUState *cpu); bool x86_cpu_exec_interrupt(CPUState *cpu, int int_req); #endif -/* helper.c */ -#ifdef CONFIG_USER_ONLY -void x86_cpu_record_sigsegv(CPUState *cs, vaddr addr, - MMUAccessType access_type, - bool maperr, uintptr_t ra); -#else -bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size, - MMUAccessType access_type, int mmu_idx, - bool probe, uintptr_t retaddr); -#endif - void breakpoint_handler(CPUState *cs); /* n must be a constant to be efficient */ @@ -78,6 +67,23 @@ G_NORETURN void raise_exception_err_ra(CPUX86State *env, int exception_index, int error_code, uintptr_t retaddr); G_NORETURN void raise_interrupt(CPUX86State *nenv, int intno, int is_int, int error_code, int next_eip_addend); +G_NORETURN void handle_unaligned_access(CPUX86State *env, vaddr vaddr, + MMUAccessType access_type, + uintptr_t retaddr); +#ifdef CONFIG_USER_ONLY +void x86_cpu_record_sigsegv(CPUState *cs, vaddr addr, + MMUAccessType access_type, + bool maperr, uintptr_t ra); +void x86_cpu_record_sigbus(CPUState *cs, vaddr addr, + MMUAccessType access_type, uintptr_t ra); +#else +bool x86_cpu_tlb_fill(CPUState *cs, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); +G_NORETURN void x86_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr); +#endif /* cc_helper.c */ extern const uint8_t parity_table[256]; diff --git a/target/i386/tcg/sysemu/excp_helper.c b/target/i386/tcg/sysemu/excp_helper.c index 48feba7e75..796dc2a1f3 100644 --- a/target/i386/tcg/sysemu/excp_helper.c +++ b/target/i386/tcg/sysemu/excp_helper.c @@ -439,3 +439,11 @@ bool x86_cpu_tlb_fill(CPUState *cs, vaddr addr, int size, } return true; } + +G_NORETURN void x86_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, + MMUAccessType access_type, + int mmu_idx, uintptr_t retaddr) +{ + X86CPU *cpu = X86_CPU(cs); + handle_unaligned_access(&cpu->env, vaddr, access_type, retaddr); +} diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c index 6fdfdf9598..d3c2b8fb49 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -75,10 +75,12 @@ static const struct TCGCPUOps x86_tcg_ops = { #ifdef CONFIG_USER_ONLY .fake_user_interrupt = x86_cpu_do_interrupt, .record_sigsegv = x86_cpu_record_sigsegv, + .record_sigbus = x86_cpu_record_sigbus, #else .tlb_fill = x86_cpu_tlb_fill, .do_interrupt = x86_cpu_do_interrupt, .cpu_exec_interrupt = x86_cpu_exec_interrupt, + .do_unaligned_access = x86_cpu_do_unaligned_access, .debug_excp_handler = breakpoint_handler, .debug_check_breakpoint = x86_debug_check_breakpoint, #endif /* !CONFIG_USER_ONLY */ diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index d6420df31d..8ec91d17af 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2738,21 +2738,23 @@ static inline void gen_stq_env_A0(DisasContext *s, int offset) tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, s->mem_index, MO_LEUQ); } -static inline void gen_ldo_env_A0(DisasContext *s, int offset) +static inline void gen_ldo_env_A0(DisasContext *s, int offset, bool align) { int mem_index = s->mem_index; - tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, MO_LEUQ); + tcg_gen_qemu_ld_i64(s->tmp1_i64, s->A0, mem_index, + MO_LEUQ | (align ? MO_ALIGN_16 : 0)); tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0))); tcg_gen_addi_tl(s->tmp0, s->A0, 8); tcg_gen_qemu_ld_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ); tcg_gen_st_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1))); } -static inline void gen_sto_env_A0(DisasContext *s, int offset) +static inline void gen_sto_env_A0(DisasContext *s, int offset, bool align) { int mem_index = s->mem_index; tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(0))); - tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, MO_LEUQ); + tcg_gen_qemu_st_i64(s->tmp1_i64, s->A0, mem_index, + MO_LEUQ | (align ? MO_ALIGN_16 : 0)); tcg_gen_addi_tl(s->tmp0, s->A0, 8); tcg_gen_ld_i64(s->tmp1_i64, cpu_env, offset + offsetof(ZMMReg, ZMM_Q(1))); tcg_gen_qemu_st_i64(s->tmp1_i64, s->tmp0, mem_index, MO_LEUQ); @@ -3131,7 +3133,7 @@ static const struct SSEOpHelper_table6 sse_op_table6[256] = { [0x25] = UNARY_OP(pmovsxdq, SSE41, SSE_OPF_MMX), [0x28] = BINARY_OP(pmuldq, SSE41, SSE_OPF_MMX), [0x29] = BINARY_OP(pcmpeqq, SSE41, SSE_OPF_MMX), - [0x2a] = SPECIAL_OP(SSE41), /* movntqda */ + [0x2a] = SPECIAL_OP(SSE41), /* movntdqa */ [0x2b] = BINARY_OP(packusdw, SSE41, SSE_OPF_MMX), [0x30] = UNARY_OP(pmovzxbw, SSE41, SSE_OPF_MMX), [0x31] = UNARY_OP(pmovzxbd, SSE41, SSE_OPF_MMX), @@ -3294,17 +3296,17 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, break; case 0x1e7: /* movntdq */ case 0x02b: /* movntps */ - case 0x12b: /* movntps */ + case 0x12b: /* movntpd */ if (mod == 3) goto illegal_op; gen_lea_modrm(env, s, modrm); - gen_sto_env_A0(s, ZMM_OFFSET(reg)); + gen_sto_env_A0(s, ZMM_OFFSET(reg), true); break; case 0x3f0: /* lddqu */ if (mod == 3) goto illegal_op; gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, ZMM_OFFSET(reg)); + gen_ldo_env_A0(s, ZMM_OFFSET(reg), false); break; case 0x22b: /* movntss */ case 0x32b: /* movntsd */ @@ -3373,7 +3375,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x26f: /* movdqu xmm, ea */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, ZMM_OFFSET(reg)); + gen_ldo_env_A0(s, ZMM_OFFSET(reg), + /* movaps, movapd, movdqa */ + b == 0x028 || b == 0x128 || b == 0x16f); } else { rm = (modrm & 7) | REX_B(s); gen_op_movo(s, ZMM_OFFSET(reg), ZMM_OFFSET(rm)); @@ -3432,7 +3436,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x212: /* movsldup */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, ZMM_OFFSET(reg)); + gen_ldo_env_A0(s, ZMM_OFFSET(reg), true); } else { rm = (modrm & 7) | REX_B(s); gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(0)), @@ -3474,7 +3478,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x216: /* movshdup */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, ZMM_OFFSET(reg)); + gen_ldo_env_A0(s, ZMM_OFFSET(reg), true); } else { rm = (modrm & 7) | REX_B(s); gen_op_movl(s, offsetof(CPUX86State, xmm_regs[reg].ZMM_L(1)), @@ -3568,7 +3572,9 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, case 0x27f: /* movdqu ea, xmm */ if (mod != 3) { gen_lea_modrm(env, s, modrm); - gen_sto_env_A0(s, ZMM_OFFSET(reg)); + gen_sto_env_A0(s, ZMM_OFFSET(reg), + /* movaps, movapd, movdqa */ + b == 0x029 || b == 0x129 || b == 0x17f); } else { rm = (modrm & 7) | REX_B(s); gen_op_movo(s, ZMM_OFFSET(rm), ZMM_OFFSET(reg)); @@ -3724,7 +3730,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, if (mod != 3) { gen_lea_modrm(env, s, modrm); op2_offset = offsetof(CPUX86State,xmm_t0); - gen_ldo_env_A0(s, op2_offset); + /* FIXME: should be 64-bit access if b1 == 0. */ + gen_ldo_env_A0(s, op2_offset, !!b1); } else { rm = (modrm & 7) | REX_B(s); op2_offset = ZMM_OFFSET(rm); @@ -3913,11 +3920,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, tcg_gen_st16_tl(s->tmp0, cpu_env, op2_offset + offsetof(ZMMReg, ZMM_W(0))); break; - case 0x2a: /* movntqda */ - gen_ldo_env_A0(s, op1_offset); + case 0x2a: /* movntdqa */ + gen_ldo_env_A0(s, op1_offset, true); return; default: - gen_ldo_env_A0(s, op2_offset); + gen_ldo_env_A0(s, op2_offset, true); } } if (!op6->fn[b1].op1) { @@ -4499,7 +4506,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, } else { op2_offset = offsetof(CPUX86State, xmm_t0); gen_lea_modrm(env, s, modrm); - gen_ldo_env_A0(s, op2_offset); + gen_ldo_env_A0(s, op2_offset, true); } val = x86_ldub_code(env, s); @@ -4606,7 +4613,7 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, break; default: /* 128 bit access */ - gen_ldo_env_A0(s, op2_offset); + gen_ldo_env_A0(s, op2_offset, true); break; } } else { diff --git a/target/i386/tcg/user/excp_helper.c b/target/i386/tcg/user/excp_helper.c index cd507e2a1b..b3bdb7831a 100644 --- a/target/i386/tcg/user/excp_helper.c +++ b/target/i386/tcg/user/excp_helper.c @@ -48,3 +48,10 @@ void x86_cpu_record_sigsegv(CPUState *cs, vaddr addr, cpu_loop_exit_restore(cs, ra); } + +void x86_cpu_record_sigbus(CPUState *cs, vaddr addr, + MMUAccessType access_type, uintptr_t ra) +{ + X86CPU *cpu = X86_CPU(cs); + handle_unaligned_access(&cpu->env, addr, access_type, ra); +} From 21adec30f62e4e700e0e217da756723e189d7b29 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 Sep 2022 12:06:02 +0200 Subject: [PATCH 0456/1020] kvm: fix memory leak on failure to read stats descriptors Reported by Coverity as CID 1490142. Since the size is constant and the lifetime is the same as the StatsDescriptors struct, embed the struct directly instead of using a separate allocation. Suggested-by: Richard Henderson Signed-off-by: Paolo Bonzini --- accel/kvm/kvm-all.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 7c8ce18bdd..5acab1767f 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3908,7 +3908,7 @@ exit: typedef struct StatsDescriptors { const char *ident; /* cache key, currently the StatsTarget */ struct kvm_stats_desc *kvm_stats_desc; - struct kvm_stats_header *kvm_stats_header; + struct kvm_stats_header kvm_stats_header; QTAILQ_ENTRY(StatsDescriptors) next; } StatsDescriptors; @@ -3939,7 +3939,7 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd descriptors = g_new0(StatsDescriptors, 1); /* Read stats header */ - kvm_stats_header = g_malloc(sizeof(*kvm_stats_header)); + kvm_stats_header = &descriptors->kvm_stats_header; ret = read(stats_fd, kvm_stats_header, sizeof(*kvm_stats_header)); if (ret != sizeof(*kvm_stats_header)) { error_setg(errp, "KVM stats: failed to read stats header: " @@ -3964,7 +3964,6 @@ static StatsDescriptors *find_stats_descriptors(StatsTarget target, int stats_fd g_free(kvm_stats_desc); return NULL; } - descriptors->kvm_stats_header = kvm_stats_header; descriptors->kvm_stats_desc = kvm_stats_desc; descriptors->ident = ident; QTAILQ_INSERT_TAIL(&stats_descriptors, descriptors, next); @@ -3989,7 +3988,7 @@ static void query_stats(StatsResultList **result, StatsTarget target, return; } - kvm_stats_header = descriptors->kvm_stats_header; + kvm_stats_header = &descriptors->kvm_stats_header; kvm_stats_desc = descriptors->kvm_stats_desc; size_desc = sizeof(*kvm_stats_desc) + kvm_stats_header->name_size; @@ -4054,7 +4053,7 @@ static void query_stats_schema(StatsSchemaList **result, StatsTarget target, return; } - kvm_stats_header = descriptors->kvm_stats_header; + kvm_stats_header = &descriptors->kvm_stats_header; kvm_stats_desc = descriptors->kvm_stats_desc; size_desc = sizeof(*kvm_stats_desc) + kvm_stats_header->name_size; From c4ef328bdc5dac319c8a1bdbe6d4108382b41584 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 Sep 2022 12:17:45 +0200 Subject: [PATCH 0457/1020] spapr_pci: fix leak in spapr_phb_vfio_get_loc_code Overwriting "path" in the second call to g_strdup_printf() causes a memory leak, even if the variable itself is g_autofree. Reported by Coverity as CID 1460454. Signed-off-by: Paolo Bonzini --- hw/ppc/spapr_pci.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 67e9d468aa..57c8a4f085 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -800,6 +800,7 @@ static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev) } /* Construct and read from host device tree the loc-code */ + g_free(path); path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", devspec); if (!g_file_get_contents(path, &buf, NULL, NULL)) { return NULL; From 2ff2004bb858e8760c2e381b05a3144897c5161d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 Sep 2022 12:22:56 +0200 Subject: [PATCH 0458/1020] coverity: add new RISC-V component Signed-off-by: Paolo Bonzini --- scripts/coverity-scan/COMPONENTS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/coverity-scan/COMPONENTS.md b/scripts/coverity-scan/COMPONENTS.md index 3aad9cdfaf..fc1608932e 100644 --- a/scripts/coverity-scan/COMPONENTS.md +++ b/scripts/coverity-scan/COMPONENTS.md @@ -146,3 +146,6 @@ tests loongarch ~ (/qemu)?((/include)?/hw/(loongarch/.*|.*/loongarch.*)|/target/loongarch/.*) + +riscv + ~ (/qemu)?((/include)?/hw/riscv/.*|/target/riscv/.*|/hw/.*/(riscv_|ibex_|sifive_).*) From b00e2c68c5864b4158afc924d868f5c5611a0362 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 Sep 2022 12:26:28 +0200 Subject: [PATCH 0459/1020] coverity: put NUBus under m68k component It is only used by the Q800 emulation, so put it under that architecture. Signed-off-by: Paolo Bonzini --- scripts/coverity-scan/COMPONENTS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/coverity-scan/COMPONENTS.md b/scripts/coverity-scan/COMPONENTS.md index fc1608932e..0e6ab4936e 100644 --- a/scripts/coverity-scan/COMPONENTS.md +++ b/scripts/coverity-scan/COMPONENTS.md @@ -22,7 +22,7 @@ i386 ~ (/qemu)?((/include)?/hw/i386/.*|/target/i386/.*|/hw/intc/[^/]*apic[^/]*\.c) m68k - ~ (/qemu)?((/include)?/hw/m68k/.*|/target/m68k/.*|(/include)?/hw(/.*)?/mcf.*) + ~ (/qemu)?((/include)?/hw/m68k/.*|/target/m68k/.*|(/include)?/hw(/.*)?/mcf.*|(/include)?/hw/nubus/.*) microblaze ~ (/qemu)?((/include)?/hw/microblaze/.*|/target/microblaze/.*) From 57e3069641d057a9ca90bb603c86477d5b331ecd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 Sep 2022 12:32:44 +0200 Subject: [PATCH 0460/1020] smbios: sanitize type from external type before checking have_fields_bitmap test_bit uses header->type as an offset; if the file incorrectly specifies a type greater than 127, smbios_entry_add will read and write garbage. To fix this, just pass the smbios data through, assuming the user knows what to do. Reported by Coverity as CID 1487255. Signed-off-by: Paolo Bonzini --- hw/smbios/smbios.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index 60349ee402..4c9f664830 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -1205,13 +1205,15 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) return; } - if (test_bit(header->type, have_fields_bitmap)) { - error_setg(errp, - "can't load type %d struct, fields already specified!", - header->type); - return; + if (header->type <= SMBIOS_MAX_TYPE) { + if (test_bit(header->type, have_fields_bitmap)) { + error_setg(errp, + "can't load type %d struct, fields already specified!", + header->type); + return; + } + set_bit(header->type, have_binfile_bitmap); } - set_bit(header->type, have_binfile_bitmap); if (header->type == 4) { smbios_type4_count++; From ac9e723fb6baaf9d9afa31f81c57f38ef7610616 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 Sep 2022 12:59:46 +0200 Subject: [PATCH 0461/1020] tests: unit: simplify test-visitor-serialization list tests test-visitor-serialization list tests is using an "if" to pick either the first element of the list or the next one. This was done presumably to mimic the code that creates the list, which has to fill in either the head pointer or the next pointer of the last element. However, the code in the insert phase is a pretty standard singly-linked list insertion, while the one in the visit phase looks weird and even looks at the first item twice: this is confusing because the test puts in 32 items and finishes with an assertion that i == 33. So, move the "else" step in a separate switch statement, and change the do...while loop to a while, because cur_head has already been initialized beforehand. Signed-off-by: Paolo Bonzini --- tests/unit/test-visitor-serialization.c | 157 +++++++++++------------- 1 file changed, 69 insertions(+), 88 deletions(-) diff --git a/tests/unit/test-visitor-serialization.c b/tests/unit/test-visitor-serialization.c index 907263d030..667e8fed82 100644 --- a/tests/unit/test-visitor-serialization.c +++ b/tests/unit/test-visitor-serialization.c @@ -427,131 +427,117 @@ static void test_primitive_lists(gconstpointer opaque) ops->deserialize((void **)&pl_copy_ptr, serialize_data, visit_primitive_list, &error_abort); - i = 0; + + switch (pl_copy.type) { + case PTYPE_STRING: + cur_head = pl_copy.value.strings; + break; + case PTYPE_INTEGER: + cur_head = pl_copy.value.integers; + break; + case PTYPE_S8: + cur_head = pl_copy.value.s8_integers; + break; + case PTYPE_S16: + cur_head = pl_copy.value.s16_integers; + break; + case PTYPE_S32: + cur_head = pl_copy.value.s32_integers; + break; + case PTYPE_S64: + cur_head = pl_copy.value.s64_integers; + break; + case PTYPE_U8: + cur_head = pl_copy.value.u8_integers; + break; + case PTYPE_U16: + cur_head = pl_copy.value.u16_integers; + break; + case PTYPE_U32: + cur_head = pl_copy.value.u32_integers; + break; + case PTYPE_U64: + cur_head = pl_copy.value.u64_integers; + break; + case PTYPE_NUMBER: + cur_head = pl_copy.value.numbers; + break; + case PTYPE_BOOLEAN: + cur_head = pl_copy.value.booleans; + break; + default: + g_assert_not_reached(); + } /* compare our deserialized list of primitives to the original */ - do { + i = 0; + while (cur_head) { switch (pl_copy.type) { case PTYPE_STRING: { - strList *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.strings; - } + strList *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpstr(pt->value.string, ==, ptr->value); break; } case PTYPE_INTEGER: { - intList *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.integers; - } + intList *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.integer, ==, ptr->value); break; } case PTYPE_S8: { - int8List *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.s8_integers; - } + int8List *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.s8, ==, ptr->value); break; } case PTYPE_S16: { - int16List *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.s16_integers; - } + int16List *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.s16, ==, ptr->value); break; } case PTYPE_S32: { - int32List *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.s32_integers; - } + int32List *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.s32, ==, ptr->value); break; } case PTYPE_S64: { - int64List *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.s64_integers; - } + int64List *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.s64, ==, ptr->value); break; } case PTYPE_U8: { - uint8List *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.u8_integers; - } + uint8List *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.u8, ==, ptr->value); break; } case PTYPE_U16: { - uint16List *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.u16_integers; - } + uint16List *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.u16, ==, ptr->value); break; } case PTYPE_U32: { - uint32List *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.u32_integers; - } + uint32List *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.u32, ==, ptr->value); break; } case PTYPE_U64: { - uint64List *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.u64_integers; - } + uint64List *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(pt->value.u64, ==, ptr->value); break; } case PTYPE_NUMBER: { - numberList *ptr; GString *double_expected = g_string_new(""); GString *double_actual = g_string_new(""); - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.numbers; - } + numberList *ptr = cur_head; + cur_head = ptr->next; /* we serialize with %f for our reference visitors, so rather than * fuzzy floating math to test "equality", just compare the * formatted values @@ -564,13 +550,8 @@ static void test_primitive_lists(gconstpointer opaque) break; } case PTYPE_BOOLEAN: { - boolList *ptr; - if (cur_head) { - ptr = cur_head; - cur_head = ptr->next; - } else { - cur_head = ptr = pl_copy.value.booleans; - } + boolList *ptr = cur_head; + cur_head = ptr->next; g_assert_cmpint(!!pt->value.boolean, ==, !!ptr->value); break; } @@ -578,9 +559,9 @@ static void test_primitive_lists(gconstpointer opaque) g_assert_not_reached(); } i++; - } while (cur_head); + } - g_assert_cmpint(i, ==, 33); + g_assert_cmpint(i, ==, 32); ops->cleanup(serialize_data); dealloc_helper(&pl, visit_primitive_list, &error_abort); From 5dc51100394206b4ca3fdcafb008de8f99fc4676 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 Sep 2022 13:01:27 +0200 Subject: [PATCH 0462/1020] tests: test-qga: close socket on failure to connect Reported by Coverity as CID 1432543. Signed-off-by: Paolo Bonzini --- tests/unit/test-qga.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c index a05a4628ed..d27ff94d13 100644 --- a/tests/unit/test-qga.c +++ b/tests/unit/test-qga.c @@ -32,6 +32,7 @@ static int connect_qga(char *path) g_usleep(G_USEC_PER_SEC); } if (i++ == 10) { + close(s); return -1; } } while (ret == -1); From b3a58a6ae346f14075af0df7f9903ad389c33dbd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 5 Sep 2022 13:09:07 +0200 Subject: [PATCH 0463/1020] tests: unit: add NULL-pointer check In CID 1432593, Coverity complains that the result of qdict_crumple() might leak if it is not a dictionary. This is not a practical concern since the test would fail immediately with a NULL pointer dereference in qdict_size(). However, it is not nice to depend on qdict_size() crashing, so add an explicit assertion that that the crumpled object was indeed a dictionary. Signed-off-by: Paolo Bonzini --- tests/unit/check-block-qdict.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/check-block-qdict.c b/tests/unit/check-block-qdict.c index 5a25825093..751c58e737 100644 --- a/tests/unit/check-block-qdict.c +++ b/tests/unit/check-block-qdict.c @@ -504,7 +504,7 @@ static void qdict_crumple_test_empty(void) src = qdict_new(); dst = qobject_to(QDict, qdict_crumple(src, &error_abort)); - + g_assert(dst); g_assert_cmpint(qdict_size(dst), ==, 0); qobject_unref(src); From 4ce4a1a71452028960d641438bb5289cff410ae8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Sep 2022 09:47:01 +0200 Subject: [PATCH 0464/1020] tests/tcg: i386: fix typos in 3DNow! instructions Signed-off-by: Paolo Bonzini --- tests/tcg/i386/x86.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/tcg/i386/x86.csv b/tests/tcg/i386/x86.csv index d5d0c17f1b..c43bf42dd3 100644 --- a/tests/tcg/i386/x86.csv +++ b/tests/tcg/i386/x86.csv @@ -1469,16 +1469,16 @@ "PFCMPEQ mm1, mm2/m64","PFCMPEQ mm2/m64, mm1","pfcmpeq mm2/m64, mm1","0F 0F B0 /r","V","V","3DNOW","amd","rw,r","","" "PFCMPGE mm1, mm2/m64","PFCMPGE mm2/m64, mm1","pfcmpge mm2/m64, mm1","0F 0F 90 /r","V","V","3DNOW","amd","rw,r","","" "PFCMPGT mm1, mm2/m64","PFCMPGT mm2/m64, mm1","pfcmpgt mm2/m64, mm1","0F 0F A0 /r","V","V","3DNOW","amd","rw,r","","" -"PFCPIT1 mm1, mm2/m64","PFCPIT1 mm2/m64, mm1","pfcpit1 mm2/m64, mm1","0F 0F A6 /r","V","V","3DNOW","amd","rw,r","","" "PFMAX mm1, mm2/m64","PFMAX mm2/m64, mm1","pfmax mm2/m64, mm1","0F 0F A4 /r","V","V","3DNOW","amd","rw,r","","" "PFMIN mm1, mm2/m64","PFMIN mm2/m64, mm1","pfmin mm2/m64, mm1","0F 0F 94 /r","V","V","3DNOW","amd","rw,r","","" "PFMUL mm1, mm2/m64","PFMUL mm2/m64, mm1","pfmul mm2/m64, mm1","0F 0F B4 /r","V","V","3DNOW","amd","rw,r","","" "PFNACC mm1, mm2/m64","PFNACC mm2/m64, mm1","pfnacc mm2/m64, mm1","0F 0F 8A /r","V","V","3DNOW","amd","rw,r","","" "PFPNACC mm1, mm2/m64","PFPNACC mm2/m64, mm1","pfpnacc mm2/m64, mm1","0F 0F 8E /r","V","V","3DNOW","amd","rw,r","","" "PFRCP mm1, mm2/m64","PFRCP mm2/m64, mm1","pfrcp mm2/m64, mm1","0F 0F 96 /r","V","V","3DNOW","amd","rw,r","","" +"PFRCPIT1 mm1, mm2/m64","PFRCPIT1 mm2/m64, mm1","pfrcpit1 mm2/m64, mm1","0F 0F A6 /r","V","V","3DNOW","amd","rw,r","","" "PFRCPIT2 mm1, mm2/m64","PFRCPIT2 mm2/m64, mm1","pfrcpit2 mm2/m64, mm1","0F 0F B6 /r","V","V","3DNOW","amd","rw,r","","" "PFRSQIT1 mm1, mm2/m64","PFRSQIT1 mm2/m64, mm1","pfrsqit1 mm2/m64, mm1","0F 0F A7 /r","V","V","3DNOW","amd","rw,r","","" -"PFSQRT mm1, mm2/m64","PFSQRT mm2/m64, mm1","pfsqrt mm2/m64, mm1","0F 0F 97 /r","V","V","3DNOW","amd","rw,r","","" +"PFRSQRT mm1, mm2/m64","PFRSQRT mm2/m64, mm1","pfrsqrt mm2/m64, mm1","0F 0F 97 /r","V","V","3DNOW","amd","rw,r","","" "PFSUB mm1, mm2/m64","PFSUB mm2/m64, mm1","pfsub mm2/m64, mm1","0F 0F 9A /r","V","V","3DNOW","amd","rw,r","","" "PFSUBR mm1, mm2/m64","PFSUBR mm2/m64, mm1","pfsubr mm2/m64, mm1","0F 0F AA /r","V","V","3DNOW","amd","rw,r","","" "PHADDD mm1, mm2/m64","PHADDD mm2/m64, mm1","phaddd mm2/m64, mm1","0F 38 02 /r","V","V","SSSE3","","rw,r","","" From 3ff17902c48bfb4e7ce20acf6f00c33fb6e0ed60 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 15:38:03 +0800 Subject: [PATCH 0465/1020] hw/loongarch: Remove vga device when loongarch init Remove the vga device when loongarch machine init and we will support other display device in the future. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-2-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/Kconfig | 1 - hw/loongarch/virt.c | 3 --- 2 files changed, 4 deletions(-) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index a99aa387c3..73c52b093e 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -2,7 +2,6 @@ config LOONGARCH_VIRT bool select PCI select PCI_EXPRESS_GENERIC_BRIDGE - imply VGA_PCI imply VIRTIO_VGA imply PCI_DEVICES select ISA_BUS diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 5cc0b05538..b56820ecda 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -378,9 +378,6 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); } - /* VGA setup */ - pci_vga_init(pci_bus); - /* * There are some invalid guest memory access. * Create some unimplemented devices to emulate this. From feae45dc427ed8e0cf01e4730f2f798374536137 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 16:53:36 +0800 Subject: [PATCH 0466/1020] hw/loongarch: Support fw_cfg dma function Support fw_cfg dma function for LoongArch virt machine. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-3-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/Kconfig | 1 + hw/loongarch/fw_cfg.c | 3 ++- hw/loongarch/virt.c | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index 73c52b093e..1deea83626 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -16,3 +16,4 @@ config LOONGARCH_VIRT select SMBIOS select ACPI_PCI select ACPI_HW_REDUCED + select FW_CFG_DMA diff --git a/hw/loongarch/fw_cfg.c b/hw/loongarch/fw_cfg.c index f6503d5607..f15a17416c 100644 --- a/hw/loongarch/fw_cfg.c +++ b/hw/loongarch/fw_cfg.c @@ -23,7 +23,8 @@ FWCfgState *loongarch_fw_cfg_init(ram_addr_t ram_size, MachineState *ms) int max_cpus = ms->smp.max_cpus; int smp_cpus = ms->smp.cpus; - fw_cfg = fw_cfg_init_mem_wide(VIRT_FWCFG_BASE + 8, VIRT_FWCFG_BASE, 8, 0, NULL); + fw_cfg = fw_cfg_init_mem_wide(VIRT_FWCFG_BASE + 8, VIRT_FWCFG_BASE, 8, + VIRT_FWCFG_BASE + 16, &address_space_memory); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index b56820ecda..4f833a2044 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -118,7 +118,7 @@ static void fdt_add_fw_cfg_node(const LoongArchMachineState *lams) qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "qemu,fw-cfg-mmio"); qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", - 2, base, 2, 0x8); + 2, base, 2, 0x18); qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0); g_free(nodename); } From 525207cd77adb181b4ef61d0b7669f52f737e9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 1 Sep 2022 15:04:14 +0400 Subject: [PATCH 0467/1020] tests: mark io-command test as skipped if socat is missing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-AndrĂ© Lureau Reviewed-by: Daniel P. BerrangĂ© Message-Id: <20220901110414.2892954-1-marcandre.lureau@redhat.com> Signed-off-by: Thomas Huth --- tests/unit/test-io-channel-command.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/test-io-channel-command.c b/tests/unit/test-io-channel-command.c index 99056e07c0..aa09c559cd 100644 --- a/tests/unit/test-io-channel-command.c +++ b/tests/unit/test-io-channel-command.c @@ -41,7 +41,8 @@ static void test_io_channel_command_fifo(bool async) unlink(TEST_FIFO); if (access("/bin/socat", X_OK) < 0) { - return; /* Pretend success if socat is not present */ + g_test_skip("socat is missing"); + return; } if (mkfifo(TEST_FIFO, 0600) < 0) { abort(); From 5bf060252274f3b12ee2a58687493a3dff2c8a6c Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Mon, 5 Sep 2022 21:04:33 -0400 Subject: [PATCH 0468/1020] tests/vm: update NetBSD to 9.3 Update NetBSD to 9.3 Signed-off-by: Brad Smith Message-Id: Signed-off-by: Thomas Huth --- tests/vm/netbsd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/vm/netbsd b/tests/vm/netbsd index da6773ff59..aa54338dfa 100755 --- a/tests/vm/netbsd +++ b/tests/vm/netbsd @@ -22,8 +22,8 @@ class NetBSDVM(basevm.BaseVM): name = "netbsd" arch = "x86_64" - link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.2/images/NetBSD-9.2-amd64.iso" - csum = "5ee0ea101f73386b9b424f5d1041e371db3c42fdd6f4e4518dc79c4a08f31d43091ebe93425c9f0dcaaed2b51131836fe6774f33f89030b58d64709b35fda72f" + link = "https://cdn.netbsd.org/pub/NetBSD/NetBSD-9.3/images/NetBSD-9.3-amd64.iso" + csum = "2bfce544f762a579f61478e7106c436fc48731ff25cf6f79b392ba5752e6f5ec130364286f7471716290a5f033637cf56aacee7fedb91095face59adf36300c3" size = "20G" pkgs = [ # tools From 039fb5490695438d013b1c4ff8c63aadf441a99b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Thu, 8 Sep 2022 21:28:14 +0800 Subject: [PATCH 0469/1020] .gitlab-ci.d/windows.yml: Drop the sed processing in the 64-bit build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The sed processing of build/config-host.mak seems to be no longer needed, and there is no such in the 32-bit build too. Drop it. Signed-off-by: Bin Meng Message-Id: <20220908132817.1831008-5-bmeng.cn@gmail.com> Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Thomas Huth --- .gitlab-ci.d/windows.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index da6013904a..86a4339c48 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -60,7 +60,6 @@ msys2-64bit: - $env:MSYS = 'winsymlinks:native' # Enable native Windows symlink - .\msys64\usr\bin\bash -lc './configure --target-list=x86_64-softmmu --enable-capstone --without-default-devices' - - .\msys64\usr\bin\bash -lc "sed -i '/^ROMS=/d' build/config-host.mak" - .\msys64\usr\bin\bash -lc 'make' - .\msys64\usr\bin\bash -lc 'make check' From d1592cbe07fa7b653aa9dde2eb8dafbe1de16885 Mon Sep 17 00:00:00 2001 From: Patrick Venture Date: Tue, 6 Sep 2022 09:31:38 -0700 Subject: [PATCH 0470/1020] tests/qtest: npcm7xx-emc-test: Skip checking MAC The register tests walks all the registers to verify they are initially 0 when appropriate. However, if the MAC address is set in the register space, this should not be checked against 0. Reviewed-by: Hao Wu Signed-off-by: Patrick Venture Message-Id: <20220906163138.2831353-1-venture@google.com> Signed-off-by: Thomas Huth --- tests/qtest/npcm7xx_emc-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c index c373d24e1e..b046f1d76a 100644 --- a/tests/qtest/npcm7xx_emc-test.c +++ b/tests/qtest/npcm7xx_emc-test.c @@ -381,7 +381,8 @@ static void test_init(gconstpointer test_data) #undef CHECK_REG - for (i = 0; i < NUM_CAMML_REGS; ++i) { + /* Skip over the MAC address registers, which is BASE+0 */ + for (i = 1; i < NUM_CAMML_REGS; ++i) { g_assert_cmpuint(emc_read(qts, mod, REG_CAMM_BASE + i * 2), ==, 0); g_assert_cmpuint(emc_read(qts, mod, REG_CAML_BASE + i * 2), ==, From a772ddc1c013c3ff54cd6bc5f1e4a9107093fc01 Mon Sep 17 00:00:00 2001 From: Mauro Matteo Cascella Date: Fri, 2 Sep 2022 15:38:53 +0200 Subject: [PATCH 0471/1020] qtest/fuzz-lsi53c895a-test: set guest RAM to 2G MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit test_lsi_do_msgout_cancel_req does not run on machines with small size memory. Reduce guest memory from 4G to 2G to alleviate the problem. Reported-by: Bin Meng Signed-off-by: Mauro Matteo Cascella Message-Id: <20220902133853.834065-1-mcascell@redhat.com> Reviewed-by: Philippe Mathieu-DaudĂ© Tested-by: Bin Meng Reviewed-by: Alexander Bulekov Signed-off-by: Thomas Huth --- tests/qtest/fuzz-lsi53c895a-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/fuzz-lsi53c895a-test.c b/tests/qtest/fuzz-lsi53c895a-test.c index b23d3ecf45..434c16bf42 100644 --- a/tests/qtest/fuzz-lsi53c895a-test.c +++ b/tests/qtest/fuzz-lsi53c895a-test.c @@ -21,7 +21,7 @@ static void test_lsi_do_msgout_cancel_req(void) return; } - s = qtest_init("-M q35 -m 4G -display none -nodefaults " + s = qtest_init("-M q35 -m 2G -display none -nodefaults " "-device lsi53c895a,id=scsi " "-device scsi-hd,drive=disk0 " "-drive file=null-co://,id=disk0,if=none,format=raw"); From fa7ce0b0282300c8c06a6c6857949168ec31a762 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 2 Sep 2022 01:38:07 +0200 Subject: [PATCH 0472/1020] tests/tcg: i386: add MMX and 3DNow! tests Adjust the test-avx.py generator to produce tests specifically for MMX and 3DNow. Using a separate generator introduces some code duplication, but is a simpler approach because of test-avx's extra complexity to support 3- and 4-operand AVX instructions. If needed, a common library can be introduced later. While at it, for consistency move all the -cpu max rules to the same place. Signed-off-by: Paolo Bonzini --- tests/tcg/i386/Makefile.target | 24 ++- tests/tcg/i386/test-3dnow.c | 3 + tests/tcg/i386/test-avx.py | 1 - tests/tcg/i386/test-mmx.c | 315 +++++++++++++++++++++++++++++++ tests/tcg/i386/test-mmx.py | 244 ++++++++++++++++++++++++ tests/tcg/x86_64/Makefile.target | 1 - 6 files changed, 583 insertions(+), 5 deletions(-) create mode 100644 tests/tcg/i386/test-3dnow.c create mode 100644 tests/tcg/i386/test-mmx.c create mode 100755 tests/tcg/i386/test-mmx.py diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index be21b81b96..599f192529 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -7,8 +7,8 @@ VPATH += $(I386_SRC) I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c)) ALL_X86_TESTS=$(I386_SRCS:.c=) -SKIP_I386_TESTS=test-i386-ssse3 test-avx -X86_64_TESTS:=$(filter test-i386-bmi2 test-i386-ssse3 test-avx, $(ALL_X86_TESTS)) +SKIP_I386_TESTS=test-i386-ssse3 test-avx test-3dnow test-mmx +X86_64_TESTS:=$(filter test-i386-bmi2 $(SKIP_I386_TESTS), $(ALL_X86_TESTS)) test-i386-sse-exceptions: CFLAGS += -msse4.1 -mfpmath=sse run-test-i386-sse-exceptions: QEMU_OPTS += -cpu max @@ -82,9 +82,27 @@ run-plugin-sha512-sse-with-%: QEMU_OPTS+=-cpu max TESTS+=sha512-sse -CLEANFILES += test-avx.h +CLEANFILES += test-avx.h test-mmx.h test-3dnow.h +test-3dnow.h: test-mmx.py x86.csv + $(PYTHON) $(I386_SRC)/test-mmx.py $(I386_SRC)/x86.csv $@ 3DNOW + +test-mmx.h: test-mmx.py x86.csv + $(PYTHON) $(I386_SRC)/test-mmx.py $(I386_SRC)/x86.csv $@ MMX SSE SSE2 SSE3 SSSE3 + test-avx.h: test-avx.py x86.csv $(PYTHON) $(I386_SRC)/test-avx.py $(I386_SRC)/x86.csv $@ +test-3dnow: CFLAGS += -masm=intel -O -I. +run-test-3dnow: QEMU_OPTS += -cpu max +run-plugin-test-3dnow: QEMU_OPTS += -cpu max +test-3dnow: test-3dnow.h + +test-mmx: CFLAGS += -masm=intel -O -I. +run-test-mmx: QEMU_OPTS += -cpu max +run-plugin-test-mmx: QEMU_OPTS += -cpu max +test-mmx: test-mmx.h + test-avx: CFLAGS += -masm=intel -O -I. +run-test-avx: QEMU_OPTS += -cpu max +run-plugin-test-avx: QEMU_OPTS += -cpu max test-avx: test-avx.h diff --git a/tests/tcg/i386/test-3dnow.c b/tests/tcg/i386/test-3dnow.c new file mode 100644 index 0000000000..67abc68677 --- /dev/null +++ b/tests/tcg/i386/test-3dnow.c @@ -0,0 +1,3 @@ +#define EMMS "femms" +#define TEST_FILE "test-3dnow.h" +#include "test-mmx.c" diff --git a/tests/tcg/i386/test-avx.py b/tests/tcg/i386/test-avx.py index 6eb455a8b4..2516c66445 100755 --- a/tests/tcg/i386/test-avx.py +++ b/tests/tcg/i386/test-avx.py @@ -7,7 +7,6 @@ import sys from fnmatch import fnmatch archs = [ - # TODO: MMX? "SSE", "SSE2", "SSE3", "SSSE3", "SSE4_1", "SSE4_2", ] diff --git a/tests/tcg/i386/test-mmx.c b/tests/tcg/i386/test-mmx.c new file mode 100644 index 0000000000..09e5d583ff --- /dev/null +++ b/tests/tcg/i386/test-mmx.c @@ -0,0 +1,315 @@ +#include +#include +#include +#include + +#ifndef TEST_FILE +#define TEST_FILE "test-mmx.h" +#endif +#ifndef EMMS +#define EMMS "emms" +#endif + +typedef void (*testfn)(void); + +typedef struct { + uint64_t q0, q1; +} __attribute__((aligned(16))) v2di; + +typedef struct { + uint64_t mm[8]; + v2di xmm[8]; + uint64_t r[16]; + uint64_t flags; + uint32_t ff; + uint64_t pad; + v2di mem[4]; + v2di mem0[4]; +} reg_state; + +typedef struct { + int n; + testfn fn; + const char *s; + reg_state *init; +} TestDef; + +reg_state initI; +reg_state initF32; +reg_state initF64; + +static void dump_mmx(int n, const uint64_t *r, int ff) +{ + if (ff == 32) { + float v[2]; + memcpy(v, r, sizeof(v)); + printf("MM%d = %016lx %8g %8g\n", n, *r, v[1], v[0]); + } else { + printf("MM%d = %016lx\n", n, *r); + } +} + +static void dump_xmm(const char *name, int n, const v2di *r, int ff) +{ + printf("%s%d = %016lx %016lx\n", + name, n, r->q1, r->q0); + if (ff == 32) { + float v[4]; + memcpy(v, r, sizeof(v)); + printf(" %8g %8g %8g %8g\n", + v[3], v[2], v[1], v[0]); + } +} + +static void dump_regs(reg_state *s, int ff) +{ + int i; + + for (i = 0; i < 8; i++) { + dump_mmx(i, &s->mm[i], ff); + } + for (i = 0; i < 4; i++) { + dump_xmm("mem", i, &s->mem0[i], 0); + } +} + +static void compare_state(const reg_state *a, const reg_state *b) +{ + int i; + for (i = 0; i < 8; i++) { + if (a->mm[i] != b->mm[i]) { + printf("MM%d = %016lx\n", i, b->mm[i]); + } + } + for (i = 0; i < 16; i++) { + if (a->r[i] != b->r[i]) { + printf("r%d = %016lx\n", i, b->r[i]); + } + } + for (i = 0; i < 8; i++) { + if (memcmp(&a->xmm[i], &b->xmm[i], 8)) { + dump_xmm("xmm", i, &b->xmm[i], a->ff); + } + } + for (i = 0; i < 4; i++) { + if (memcmp(&a->mem0[i], &a->mem[i], 16)) { + dump_xmm("mem", i, &a->mem[i], a->ff); + } + } + if (a->flags != b->flags) { + printf("FLAGS = %016lx\n", b->flags); + } +} + +#define LOADMM(r, o) "movq " #r ", " #o "[%0]\n\t" +#define LOADXMM(r, o) "movdqa " #r ", " #o "[%0]\n\t" +#define STOREMM(r, o) "movq " #o "[%1], " #r "\n\t" +#define STOREXMM(r, o) "movdqa " #o "[%1], " #r "\n\t" +#define MMREG(F) \ + F(mm0, 0x00) \ + F(mm1, 0x08) \ + F(mm2, 0x10) \ + F(mm3, 0x18) \ + F(mm4, 0x20) \ + F(mm5, 0x28) \ + F(mm6, 0x30) \ + F(mm7, 0x38) +#define XMMREG(F) \ + F(xmm0, 0x040) \ + F(xmm1, 0x050) \ + F(xmm2, 0x060) \ + F(xmm3, 0x070) \ + F(xmm4, 0x080) \ + F(xmm5, 0x090) \ + F(xmm6, 0x0a0) \ + F(xmm7, 0x0b0) +#define LOADREG(r, o) "mov " #r ", " #o "[rax]\n\t" +#define STOREREG(r, o) "mov " #o "[rax], " #r "\n\t" +#define REG(F) \ + F(rbx, 0xc8) \ + F(rcx, 0xd0) \ + F(rdx, 0xd8) \ + F(rsi, 0xe0) \ + F(rdi, 0xe8) \ + F(r8, 0x100) \ + F(r9, 0x108) \ + F(r10, 0x110) \ + F(r11, 0x118) \ + F(r12, 0x120) \ + F(r13, 0x128) \ + F(r14, 0x130) \ + F(r15, 0x138) \ + +static void run_test(const TestDef *t) +{ + reg_state result; + reg_state *init = t->init; + memcpy(init->mem, init->mem0, sizeof(init->mem)); + printf("%5d %s\n", t->n, t->s); + asm volatile( + MMREG(LOADMM) + XMMREG(LOADXMM) + "sub rsp, 128\n\t" + "push rax\n\t" + "push rbx\n\t" + "push rcx\n\t" + "push rdx\n\t" + "push %1\n\t" + "push %2\n\t" + "mov rax, %0\n\t" + "pushf\n\t" + "pop rbx\n\t" + "shr rbx, 8\n\t" + "shl rbx, 8\n\t" + "mov rcx, 0x140[rax]\n\t" + "and rcx, 0xff\n\t" + "or rbx, rcx\n\t" + "push rbx\n\t" + "popf\n\t" + REG(LOADREG) + "mov rax, 0xc0[rax]\n\t" + "call [rsp]\n\t" + "mov [rsp], rax\n\t" + "mov rax, 8[rsp]\n\t" + REG(STOREREG) + "mov rbx, [rsp]\n\t" + "mov 0xc0[rax], rbx\n\t" + "mov rbx, 0\n\t" + "mov 0xf0[rax], rbx\n\t" + "mov 0xf8[rax], rbx\n\t" + "pushf\n\t" + "pop rbx\n\t" + "and rbx, 0xff\n\t" + "mov 0x140[rax], rbx\n\t" + "add rsp, 16\n\t" + "pop rdx\n\t" + "pop rcx\n\t" + "pop rbx\n\t" + "pop rax\n\t" + "add rsp, 128\n\t" + MMREG(STOREMM) + EMMS "\n\t" + XMMREG(STOREXMM) + : : "r"(init), "r"(&result), "r"(t->fn) + : "memory", "cc", + "rsi", "rdi", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", + "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", + "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", + "xmm12", "xmm13", "xmm14", "xmm15" + ); + compare_state(init, &result); +} + +#define TEST(n, cmd, type) \ +static void __attribute__((naked)) test_##n(void) \ +{ \ + asm volatile(cmd); \ + asm volatile("ret"); \ +} +#include TEST_FILE + + +static const TestDef test_table[] = { +#define TEST(n, cmd, type) {n, test_##n, cmd, &init##type}, +#include TEST_FILE + {-1, NULL, "", NULL} +}; + +static void run_all(void) +{ + const TestDef *t; + for (t = test_table; t->fn; t++) { + run_test(t); + } +} + +#define ARRAY_LEN(x) (sizeof(x) / sizeof(x[0])) + +float val_f32[] = {2.0, -1.0, 4.8, 0.8, 3, -42.0, 5e6, 7.5, 8.3}; +uint64_t val_i64[] = { + 0x3d6b3b6a9e4118f2lu, 0x355ae76d2774d78clu, + 0xd851c54a56bf1f29lu, 0x4a84d1d50bf4c4fflu, + 0x5826475e2c5fd799lu, 0xfd32edc01243f5e9lu, +}; + +v2di deadbeef = {0xa5a5a5a5deadbeefull, 0xa5a5a5a5deadbeefull}; + +void init_f32reg(uint64_t *r) +{ + static int n; + float v[2]; + int i; + for (i = 0; i < 2; i++) { + v[i] = val_f32[n++]; + if (n == ARRAY_LEN(val_f32)) { + n = 0; + } + } + memcpy(r, v, sizeof(*r)); +} + +void init_intreg(uint64_t *r) +{ + static uint64_t mask; + static int n; + + *r = val_i64[n] ^ mask; + n++; + if (n == ARRAY_LEN(val_i64)) { + n = 0; + mask *= 0x104C11DB7; + } +} + +static void init_all(reg_state *s) +{ + int i; + + for (i = 0; i < 16; i++) { + init_intreg(&s->r[i]); + } + s->r[3] = (uint64_t)&s->mem[0]; /* rdx */ + s->r[5] = (uint64_t)&s->mem[2]; /* rdi */ + s->r[6] = 0; + s->r[7] = 0; + s->flags = 2; + for (i = 0; i < 8; i++) { + s->xmm[i] = deadbeef; + memcpy(&s->mm[i], &s->xmm[i], sizeof(s->mm[i])); + } + for (i = 0; i < 2; i++) { + s->mem0[i] = deadbeef; + } +} + +int main(int argc, char *argv[]) +{ + init_all(&initI); + init_intreg(&initI.mm[5]); + init_intreg(&initI.mm[6]); + init_intreg(&initI.mm[7]); + init_intreg(&initI.mem0[1].q0); + init_intreg(&initI.mem0[1].q1); + printf("Int:\n"); + dump_regs(&initI, 0); + + init_all(&initF32); + init_f32reg(&initF32.mm[5]); + init_f32reg(&initF32.mm[6]); + init_f32reg(&initF32.mm[7]); + init_f32reg(&initF32.mem0[1].q0); + init_f32reg(&initF32.mem0[1].q1); + initF32.ff = 32; + printf("F32:\n"); + dump_regs(&initF32, 32); + + if (argc > 1) { + int n = atoi(argv[1]); + run_test(&test_table[n]); + } else { + run_all(); + } + return 0; +} diff --git a/tests/tcg/i386/test-mmx.py b/tests/tcg/i386/test-mmx.py new file mode 100755 index 0000000000..392315e176 --- /dev/null +++ b/tests/tcg/i386/test-mmx.py @@ -0,0 +1,244 @@ +#! /usr/bin/env python3 + +# Generate test-avx.h from x86.csv + +import csv +import sys +from fnmatch import fnmatch + +ignore = set(["EMMS", "FEMMS", "FISTTP", + "LDMXCSR", "VLDMXCSR", "STMXCSR", "VSTMXCSR"]) + +imask = { + 'PALIGNR': 0x3f, + 'PEXTRB': 0x0f, + 'PEXTRW': 0x07, + 'PEXTRD': 0x03, + 'PEXTRQ': 0x01, + 'PINSRB': 0x0f, + 'PINSRW': 0x07, + 'PINSRD': 0x03, + 'PINSRQ': 0x01, + 'PSHUF[DW]': 0xff, + 'PSHUF[LH]W': 0xff, + 'PS[LR][AL][WDQ]': 0x3f, +} + +def strip_comments(x): + for l in x: + if l != '' and l[0] != '#': + yield l + +def reg_w(w): + if w == 8: + return 'al' + elif w == 16: + return 'ax' + elif w == 32: + return 'eax' + elif w == 64: + return 'rax' + raise Exception("bad reg_w %d" % w) + +def mem_w(w): + if w == 8: + t = "BYTE" + elif w == 16: + t = "WORD" + elif w == 32: + t = "DWORD" + elif w == 64: + t = "QWORD" + else: + raise Exception() + + return t + " PTR 32[rdx]" + +class MMArg(): + isxmm = True + + def __init__(self, mw): + if mw not in [0, 32, 64]: + raise Exception("Bad /m width: %s" % w) + self.mw = mw + self.ismem = mw != 0 + def regstr(self, n): + if n < 0: + return mem_w(self.mw) + else: + return "mm%d" % (n, ) + +def match(op, pattern): + return fnmatch(op, pattern) + +class ArgImm8u(): + isxmm = False + ismem = False + def __init__(self, op): + for k, v in imask.items(): + if match(op, k): + self.mask = imask[k]; + return + raise Exception("Unknown immediate") + def vals(self): + mask = self.mask + yield 0 + n = 0 + while n != mask: + n += 1 + while (n & ~mask) != 0: + n += (n & ~mask) + yield n + +class ArgRM(): + isxmm = False + def __init__(self, rw, mw): + if rw not in [8, 16, 32, 64]: + raise Exception("Bad r/w width: %s" % w) + if mw not in [0, 8, 16, 32, 64]: + raise Exception("Bad r/w width: %s" % w) + self.rw = rw + self.mw = mw + self.ismem = mw != 0 + def regstr(self, n): + if n < 0: + return mem_w(self.mw) + else: + return reg_w(self.rw) + +class ArgMem(): + isxmm = False + ismem = True + def __init__(self, w): + if w not in [8, 16, 32, 64, 128, 256]: + raise Exception("Bad mem width: %s" % w) + self.w = w + def regstr(self, n): + return mem_w(self.w) + +class SkipInstruction(Exception): + pass + +def ArgGenerator(arg, op): + if arg[:2] == 'mm': + if "/" in arg: + r, m = arg.split('/') + if (m[0] != 'm'): + raise Exception("Expected /m: %s", arg) + return MMArg(int(m[1:])); + else: + return MMArg(0); + elif arg[:4] == 'imm8': + return ArgImm8u(op); + elif arg[0] == 'r': + if '/m' in arg: + r, m = arg.split('/') + if (m[0] != 'm'): + raise Exception("Expected /m: %s", arg) + mw = int(m[1:]) + if r == 'r': + rw = mw + else: + rw = int(r[1:]) + return ArgRM(rw, mw) + + return ArgRM(int(arg[1:]), 0); + elif arg[0] == 'm': + return ArgMem(int(arg[1:])) + else: + raise SkipInstruction + +class InsnGenerator: + def __init__(self, op, args): + self.op = op + if op[0:2] == "PF": + self.optype = 'F32' + else: + self.optype = 'I' + + try: + self.args = list(ArgGenerator(a, op) for a in args) + if len(self.args) > 0 and self.args[-1] is None: + self.args = self.args[:-1] + except SkipInstruction: + raise + except Exception as e: + raise Exception("Bad arg %s: %s" % (op, e)) + + def gen(self): + regs = (5, 6, 7) + dest = 4 + + nreg = len(self.args) + if nreg == 0: + yield self.op + return + if isinstance(self.args[-1], ArgImm8u): + nreg -= 1 + immarg = self.args[-1] + else: + immarg = None + memarg = -1 + for n, arg in enumerate(self.args): + if arg.ismem: + memarg = n + + if nreg == 1: + regset = [(regs[0],)] + if memarg == 0: + regset += [(-1,)] + elif nreg == 2: + regset = [ + (regs[0], regs[1]), + (regs[0], regs[0]), + ] + if memarg == 0: + regset += [(-1, regs[0])] + elif memarg == 1: + regset += [(dest, -1)] + else: + raise Exception("Too many regs: %s(%d)" % (self.op, nreg)) + + for regv in regset: + argstr = [] + for i in range(nreg): + arg = self.args[i] + argstr.append(arg.regstr(regv[i])) + if immarg is None: + yield self.op + ' ' + ','.join(argstr) + else: + for immval in immarg.vals(): + yield self.op + ' ' + ','.join(argstr) + ',' + str(immval) + +def split0(s): + if s == '': + return [] + return s.split(',') + +def main(): + n = 0 + if len(sys.argv) <= 3: + print("Usage: test-mmx.py x86.csv test-mmx.h CPUID...") + exit(1) + csvfile = open(sys.argv[1], 'r', newline='') + archs = sys.argv[3:] + with open(sys.argv[2], "w") as outf: + outf.write("// Generated by test-mmx.py. Do not edit.\n") + for row in csv.reader(strip_comments(csvfile)): + insn = row[0].replace(',', '').split() + if insn[0] in ignore: + continue + cpuid = row[6] + if cpuid in archs: + try: + g = InsnGenerator(insn[0], insn[1:]) + for insn in g.gen(): + outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype)) + n += 1 + except SkipInstruction: + pass + outf.write("#undef TEST\n") + csvfile.close() + +if __name__ == "__main__": + main() diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target index 861a0966f4..6895db1c43 100644 --- a/tests/tcg/x86_64/Makefile.target +++ b/tests/tcg/x86_64/Makefile.target @@ -17,7 +17,6 @@ TESTS=$(MULTIARCH_TESTS) endif run-test-i386-ssse3: QEMU_OPTS += -cpu max -run-test-avx: QEMU_OPTS += -cpu max run-plugin-test-i386-ssse3-%: QEMU_OPTS += -cpu max test-x86_64: LDFLAGS+=-lm -lc From e02907cc12df4765cc92f8b0c193a10c1841c82e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 9 Sep 2022 10:21:31 +0200 Subject: [PATCH 0473/1020] tests/tcg: refine MMX support in SSE tests Extend the support to memory operands, and skip MMX instructions that were introduced in SSE times, because they are now covered in test-mmx. Signed-off-by: Paolo Bonzini --- tests/tcg/i386/test-avx.py | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/tests/tcg/i386/test-avx.py b/tests/tcg/i386/test-avx.py index 2516c66445..e16a3d8bee 100755 --- a/tests/tcg/i386/test-avx.py +++ b/tests/tcg/i386/test-avx.py @@ -103,7 +103,11 @@ class XMMArg(): class MMArg(): isxmm = True - ismem = False # TODO + def __init__(self, mw): + if mw not in [0, 32, 64]: + raise Exception("Bad mem width: %s" % mw) + self.mw = mw + self.ismem = mw != 0 def regstr(self, n): return "mm%d" % (n & 7) @@ -169,6 +173,9 @@ class ArgMem(): def regstr(self, n): return mem_w(self.w) +class SkipInstruction(Exception): + pass + def ArgGenerator(arg, op): if arg[:3] == 'xmm' or arg[:3] == "ymm": if "/" in arg: @@ -179,7 +186,13 @@ def ArgGenerator(arg, op): else: return XMMArg(arg[0], 0); elif arg[:2] == 'mm': - return MMArg(); + if "/" in arg: + r, m = arg.split('/') + if (m[0] != 'm'): + raise Exception("Expected /m: %s", arg) + return MMArg(int(m[1:])); + else: + return MMArg(0); elif arg[:4] == 'imm8': return ArgImm8u(op); elif arg == '': @@ -217,8 +230,12 @@ class InsnGenerator: try: self.args = list(ArgGenerator(a, op) for a in args) + if not any((x.isxmm for x in self.args)): + raise SkipInstruction if len(self.args) > 0 and self.args[-1] is None: self.args = self.args[:-1] + except SkipInstruction: + raise except Exception as e: raise Exception("Bad arg %s: %s" % (op, e)) @@ -339,10 +356,13 @@ def main(): continue cpuid = row[6] if cpuid in archs: - g = InsnGenerator(insn[0], insn[1:]) - for insn in g.gen(): - outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype)) - n += 1 + try: + g = InsnGenerator(insn[0], insn[1:]) + for insn in g.gen(): + outf.write('TEST(%d, "%s", %s)\n' % (n, insn, g.optype)) + n += 1 + except SkipInstruction: + pass outf.write("#undef TEST\n") csvfile.close() From e121d7606bc9041619d8c6e0524a1ccdbbdd6547 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 11 Sep 2022 15:04:54 +0200 Subject: [PATCH 0474/1020] tests/tcg: remove old SSE tests The new testsuite is much more comprehensive, so remove the old one; it is also buggy (the pinsrw test uses incorrect constraints, with = instead of +, and the golden output for the fxsave tests differs depending on how the C library uses SSE and AVX instructions). Signed-off-by: Paolo Bonzini --- tests/tcg/i386/test-i386.c | 573 ------------------------------------- 1 file changed, 573 deletions(-) diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c index e6b308a2c0..864c4e620d 100644 --- a/tests/tcg/i386/test-i386.c +++ b/tests/tcg/i386/test-i386.c @@ -34,15 +34,8 @@ #endif //#define LINUX_VM86_IOPL_FIX //#define TEST_P4_FLAGS -#ifdef __SSE__ -#define TEST_SSE #define TEST_CMOV 1 #define TEST_FCOMI 1 -#else -#undef TEST_SSE -#define TEST_CMOV 1 -#define TEST_FCOMI 1 -#endif #if defined(__x86_64__) #define FMT64X "%016lx" @@ -2104,568 +2097,6 @@ static void test_enter(void) TEST_ENTER("w", uint16_t, 31); } -#ifdef TEST_SSE - -typedef int __m64 __attribute__ ((vector_size(8))); -typedef float __m128 __attribute__ ((vector_size(16))); - -typedef union { - double d[2]; - float s[4]; - uint32_t l[4]; - uint64_t q[2]; - __m128 dq; -} XMMReg; - -static uint64_t __attribute__((aligned(16))) test_values[4][2] = { - { 0x456723c698694873, 0xdc515cff944a58ec }, - { 0x1f297ccd58bad7ab, 0x41f21efba9e3e146 }, - { 0x007c62c2085427f8, 0x231be9e8cde7438d }, - { 0x0f76255a085427f8, 0xc233e9e8c4c9439a }, -}; - -#define SSE_OP(op)\ -{\ - asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\ - printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\ - #op,\ - a.q[1], a.q[0],\ - b.q[1], b.q[0],\ - r.q[1], r.q[0]);\ -} - -#define SSE_OP2(op)\ -{\ - int i;\ - for(i=0;i<2;i++) {\ - a.q[0] = test_values[2*i][0];\ - a.q[1] = test_values[2*i][1];\ - b.q[0] = test_values[2*i+1][0];\ - b.q[1] = test_values[2*i+1][1];\ - SSE_OP(op);\ - }\ -} - -#define MMX_OP2(op)\ -{\ - int i;\ - for(i=0;i<2;i++) {\ - a.q[0] = test_values[2*i][0];\ - b.q[0] = test_values[2*i+1][0];\ - asm volatile (#op " %2, %0" : "=y" (r.q[0]) : "0" (a.q[0]), "y" (b.q[0]));\ - printf("%-9s: a=" FMT64X " b=" FMT64X " r=" FMT64X "\n",\ - #op,\ - a.q[0],\ - b.q[0],\ - r.q[0]);\ - }\ - SSE_OP2(op);\ -} - -#define SHUF_OP(op, ib)\ -{\ - a.q[0] = test_values[0][0];\ - a.q[1] = test_values[0][1];\ - b.q[0] = test_values[1][0];\ - b.q[1] = test_values[1][1];\ - asm volatile (#op " $" #ib ", %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\ - printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\ - #op,\ - a.q[1], a.q[0],\ - b.q[1], b.q[0],\ - ib,\ - r.q[1], r.q[0]);\ -} - -#define PSHUF_OP(op, ib)\ -{\ - int i;\ - for(i=0;i<2;i++) {\ - a.q[0] = test_values[2*i][0];\ - a.q[1] = test_values[2*i][1];\ - asm volatile (#op " $" #ib ", %1, %0" : "=x" (r.dq) : "x" (a.dq));\ - printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\ - #op,\ - a.q[1], a.q[0],\ - ib,\ - r.q[1], r.q[0]);\ - }\ -} - -#define SHIFT_IM(op, ib)\ -{\ - int i;\ - for(i=0;i<2;i++) {\ - a.q[0] = test_values[2*i][0];\ - a.q[1] = test_values[2*i][1];\ - asm volatile (#op " $" #ib ", %0" : "=x" (r.dq) : "0" (a.dq));\ - printf("%-9s: a=" FMT64X "" FMT64X " ib=%02x r=" FMT64X "" FMT64X "\n",\ - #op,\ - a.q[1], a.q[0],\ - ib,\ - r.q[1], r.q[0]);\ - }\ -} - -#define SHIFT_OP(op, ib)\ -{\ - int i;\ - SHIFT_IM(op, ib);\ - for(i=0;i<2;i++) {\ - a.q[0] = test_values[2*i][0];\ - a.q[1] = test_values[2*i][1];\ - b.q[0] = ib;\ - b.q[1] = 0;\ - asm volatile (#op " %2, %0" : "=x" (r.dq) : "0" (a.dq), "x" (b.dq));\ - printf("%-9s: a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\ - #op,\ - a.q[1], a.q[0],\ - b.q[1], b.q[0],\ - r.q[1], r.q[0]);\ - }\ -} - -#define MOVMSK(op)\ -{\ - int i, reg;\ - for(i=0;i<2;i++) {\ - a.q[0] = test_values[2*i][0];\ - a.q[1] = test_values[2*i][1];\ - asm volatile (#op " %1, %0" : "=r" (reg) : "x" (a.dq));\ - printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\ - #op,\ - a.q[1], a.q[0],\ - reg);\ - }\ -} - -#define SSE_OPS(a) \ -SSE_OP(a ## ps);\ -SSE_OP(a ## ss); - -#define SSE_OPD(a) \ -SSE_OP(a ## pd);\ -SSE_OP(a ## sd); - -#define SSE_COMI(op, field)\ -{\ - unsigned long eflags;\ - XMMReg a, b;\ - a.field[0] = a1;\ - b.field[0] = b1;\ - asm volatile (#op " %2, %1\n"\ - "pushf\n"\ - "pop %0\n"\ - : "=rm" (eflags)\ - : "x" (a.dq), "x" (b.dq));\ - printf("%-9s: a=%f b=%f cc=%04lx\n",\ - #op, a1, b1,\ - eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\ -} - -void test_sse_comi(double a1, double b1) -{ - SSE_COMI(ucomiss, s); - SSE_COMI(ucomisd, d); - SSE_COMI(comiss, s); - SSE_COMI(comisd, d); -} - -#define CVT_OP_XMM(op)\ -{\ - asm volatile (#op " %1, %0" : "=x" (r.dq) : "x" (a.dq));\ - printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "" FMT64X "\n",\ - #op,\ - a.q[1], a.q[0],\ - r.q[1], r.q[0]);\ -} - -/* Force %xmm0 usage to avoid the case where both register index are 0 - to test instruction decoding more extensively */ -#define CVT_OP_XMM2MMX(op)\ -{\ - asm volatile (#op " %1, %0" : "=y" (r.q[0]) : "x" (a.dq) \ - : "%xmm0"); \ - asm volatile("emms\n"); \ - printf("%-9s: a=" FMT64X "" FMT64X " r=" FMT64X "\n",\ - #op,\ - a.q[1], a.q[0],\ - r.q[0]);\ -} - -#define CVT_OP_MMX2XMM(op)\ -{\ - asm volatile (#op " %1, %0" : "=x" (r.dq) : "y" (a.q[0]));\ - asm volatile("emms\n"); \ - printf("%-9s: a=" FMT64X " r=" FMT64X "" FMT64X "\n",\ - #op,\ - a.q[0],\ - r.q[1], r.q[0]);\ -} - -#define CVT_OP_REG2XMM(op)\ -{\ - asm volatile (#op " %1, %0" : "=x" (r.dq) : "r" (a.l[0]));\ - printf("%-9s: a=%08x r=" FMT64X "" FMT64X "\n",\ - #op,\ - a.l[0],\ - r.q[1], r.q[0]);\ -} - -#define CVT_OP_XMM2REG(op)\ -{\ - asm volatile (#op " %1, %0" : "=r" (r.l[0]) : "x" (a.dq));\ - printf("%-9s: a=" FMT64X "" FMT64X " r=%08x\n",\ - #op,\ - a.q[1], a.q[0],\ - r.l[0]);\ -} - -struct fpxstate { - uint16_t fpuc; - uint16_t fpus; - uint16_t fptag; - uint16_t fop; - uint32_t fpuip; - uint16_t cs_sel; - uint16_t dummy0; - uint32_t fpudp; - uint16_t ds_sel; - uint16_t dummy1; - uint32_t mxcsr; - uint32_t mxcsr_mask; - uint8_t fpregs1[8 * 16]; - uint8_t xmm_regs[8 * 16]; - uint8_t dummy2[224]; -}; - -static struct fpxstate fpx_state __attribute__((aligned(16))); -static struct fpxstate fpx_state2 __attribute__((aligned(16))); - -void test_fxsave(void) -{ - struct fpxstate *fp = &fpx_state; - struct fpxstate *fp2 = &fpx_state2; - int i, nb_xmm; - XMMReg a, b; - a.q[0] = test_values[0][0]; - a.q[1] = test_values[0][1]; - b.q[0] = test_values[1][0]; - b.q[1] = test_values[1][1]; - - asm("movdqa %2, %%xmm0\n" - "movdqa %3, %%xmm7\n" -#if defined(__x86_64__) - "movdqa %2, %%xmm15\n" -#endif - " fld1\n" - " fldpi\n" - " fldln2\n" - " fxsave %0\n" - " fxrstor %0\n" - " fxsave %1\n" - " fninit\n" - : "=m" (*(uint32_t *)fp2), "=m" (*(uint32_t *)fp) - : "m" (a), "m" (b)); - printf("fpuc=%04x\n", fp->fpuc); - printf("fpus=%04x\n", fp->fpus); - printf("fptag=%04x\n", fp->fptag); - for(i = 0; i < 3; i++) { - printf("ST%d: " FMT64X " %04x\n", - i, - *(uint64_t *)&fp->fpregs1[i * 16], - *(uint16_t *)&fp->fpregs1[i * 16 + 8]); - } - printf("mxcsr=%08x\n", fp->mxcsr & 0x1f80); -#if defined(__x86_64__) - nb_xmm = 16; -#else - nb_xmm = 8; -#endif - for(i = 0; i < nb_xmm; i++) { - printf("xmm%d: " FMT64X "" FMT64X "\n", - i, - *(uint64_t *)&fp->xmm_regs[i * 16], - *(uint64_t *)&fp->xmm_regs[i * 16 + 8]); - } -} - -void test_sse(void) -{ - XMMReg r, a, b; - int i; - - MMX_OP2(punpcklbw); - MMX_OP2(punpcklwd); - MMX_OP2(punpckldq); - MMX_OP2(packsswb); - MMX_OP2(pcmpgtb); - MMX_OP2(pcmpgtw); - MMX_OP2(pcmpgtd); - MMX_OP2(packuswb); - MMX_OP2(punpckhbw); - MMX_OP2(punpckhwd); - MMX_OP2(punpckhdq); - MMX_OP2(packssdw); - MMX_OP2(pcmpeqb); - MMX_OP2(pcmpeqw); - MMX_OP2(pcmpeqd); - - MMX_OP2(paddq); - MMX_OP2(pmullw); - MMX_OP2(psubusb); - MMX_OP2(psubusw); - MMX_OP2(pminub); - MMX_OP2(pand); - MMX_OP2(paddusb); - MMX_OP2(paddusw); - MMX_OP2(pmaxub); - MMX_OP2(pandn); - - MMX_OP2(pmulhuw); - MMX_OP2(pmulhw); - - MMX_OP2(psubsb); - MMX_OP2(psubsw); - MMX_OP2(pminsw); - MMX_OP2(por); - MMX_OP2(paddsb); - MMX_OP2(paddsw); - MMX_OP2(pmaxsw); - MMX_OP2(pxor); - MMX_OP2(pmuludq); - MMX_OP2(pmaddwd); - MMX_OP2(psadbw); - MMX_OP2(psubb); - MMX_OP2(psubw); - MMX_OP2(psubd); - MMX_OP2(psubq); - MMX_OP2(paddb); - MMX_OP2(paddw); - MMX_OP2(paddd); - - MMX_OP2(pavgb); - MMX_OP2(pavgw); - - asm volatile ("pinsrw $1, %1, %0" : "=y" (r.q[0]) : "r" (0x12345678)); - printf("%-9s: r=" FMT64X "\n", "pinsrw", r.q[0]); - - asm volatile ("pinsrw $5, %1, %0" : "=x" (r.dq) : "r" (0x12345678)); - printf("%-9s: r=" FMT64X "" FMT64X "\n", "pinsrw", r.q[1], r.q[0]); - - a.q[0] = test_values[0][0]; - a.q[1] = test_values[0][1]; - asm volatile ("pextrw $1, %1, %0" : "=r" (r.l[0]) : "y" (a.q[0])); - printf("%-9s: r=%08x\n", "pextrw", r.l[0]); - - asm volatile ("pextrw $5, %1, %0" : "=r" (r.l[0]) : "x" (a.dq)); - printf("%-9s: r=%08x\n", "pextrw", r.l[0]); - - asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "y" (a.q[0])); - printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]); - - asm volatile ("pmovmskb %1, %0" : "=r" (r.l[0]) : "x" (a.dq)); - printf("%-9s: r=%08x\n", "pmovmskb", r.l[0]); - - { - r.q[0] = -1; - r.q[1] = -1; - - a.q[0] = test_values[0][0]; - a.q[1] = test_values[0][1]; - b.q[0] = test_values[1][0]; - b.q[1] = test_values[1][1]; - asm volatile("maskmovq %1, %0" : - : "y" (a.q[0]), "y" (b.q[0]), "D" (&r) - : "memory"); - printf("%-9s: r=" FMT64X " a=" FMT64X " b=" FMT64X "\n", - "maskmov", - r.q[0], - a.q[0], - b.q[0]); - asm volatile("maskmovdqu %1, %0" : - : "x" (a.dq), "x" (b.dq), "D" (&r) - : "memory"); - printf("%-9s: r=" FMT64X "" FMT64X " a=" FMT64X "" FMT64X " b=" FMT64X "" FMT64X "\n", - "maskmov", - r.q[1], r.q[0], - a.q[1], a.q[0], - b.q[1], b.q[0]); - } - - asm volatile ("emms"); - - SSE_OP2(punpcklqdq); - SSE_OP2(punpckhqdq); - SSE_OP2(andps); - SSE_OP2(andpd); - SSE_OP2(andnps); - SSE_OP2(andnpd); - SSE_OP2(orps); - SSE_OP2(orpd); - SSE_OP2(xorps); - SSE_OP2(xorpd); - - SSE_OP2(unpcklps); - SSE_OP2(unpcklpd); - SSE_OP2(unpckhps); - SSE_OP2(unpckhpd); - - SHUF_OP(shufps, 0x78); - SHUF_OP(shufpd, 0x02); - - PSHUF_OP(pshufd, 0x78); - PSHUF_OP(pshuflw, 0x78); - PSHUF_OP(pshufhw, 0x78); - - SHIFT_OP(psrlw, 7); - SHIFT_OP(psrlw, 16); - SHIFT_OP(psraw, 7); - SHIFT_OP(psraw, 16); - SHIFT_OP(psllw, 7); - SHIFT_OP(psllw, 16); - - SHIFT_OP(psrld, 7); - SHIFT_OP(psrld, 32); - SHIFT_OP(psrad, 7); - SHIFT_OP(psrad, 32); - SHIFT_OP(pslld, 7); - SHIFT_OP(pslld, 32); - - SHIFT_OP(psrlq, 7); - SHIFT_OP(psrlq, 32); - SHIFT_OP(psllq, 7); - SHIFT_OP(psllq, 32); - - SHIFT_IM(psrldq, 16); - SHIFT_IM(psrldq, 7); - SHIFT_IM(pslldq, 16); - SHIFT_IM(pslldq, 7); - - MOVMSK(movmskps); - MOVMSK(movmskpd); - - /* FPU specific ops */ - - { - uint32_t mxcsr; - asm volatile("stmxcsr %0" : "=m" (mxcsr)); - printf("mxcsr=%08x\n", mxcsr & 0x1f80); - asm volatile("ldmxcsr %0" : : "m" (mxcsr)); - } - - test_sse_comi(2, -1); - test_sse_comi(2, 2); - test_sse_comi(2, 3); - test_sse_comi(2, q_nan.d); - test_sse_comi(q_nan.d, -1); - - for(i = 0; i < 2; i++) { - a.s[0] = 2.7; - a.s[1] = 3.4; - a.s[2] = 4; - a.s[3] = -6.3; - b.s[0] = 45.7; - b.s[1] = 353.4; - b.s[2] = 4; - b.s[3] = 56.3; - if (i == 1) { - a.s[0] = q_nan.d; - b.s[3] = q_nan.d; - } - - SSE_OPS(add); - SSE_OPS(mul); - SSE_OPS(sub); - SSE_OPS(min); - SSE_OPS(div); - SSE_OPS(max); - SSE_OPS(sqrt); - SSE_OPS(cmpeq); - SSE_OPS(cmplt); - SSE_OPS(cmple); - SSE_OPS(cmpunord); - SSE_OPS(cmpneq); - SSE_OPS(cmpnlt); - SSE_OPS(cmpnle); - SSE_OPS(cmpord); - - - a.d[0] = 2.7; - a.d[1] = -3.4; - b.d[0] = 45.7; - b.d[1] = -53.4; - if (i == 1) { - a.d[0] = q_nan.d; - b.d[1] = q_nan.d; - } - SSE_OPD(add); - SSE_OPD(mul); - SSE_OPD(sub); - SSE_OPD(min); - SSE_OPD(div); - SSE_OPD(max); - SSE_OPD(sqrt); - SSE_OPD(cmpeq); - SSE_OPD(cmplt); - SSE_OPD(cmple); - SSE_OPD(cmpunord); - SSE_OPD(cmpneq); - SSE_OPD(cmpnlt); - SSE_OPD(cmpnle); - SSE_OPD(cmpord); - } - - /* float to float/int */ - a.s[0] = 2.7; - a.s[1] = 3.4; - a.s[2] = 4; - a.s[3] = -6.3; - CVT_OP_XMM(cvtps2pd); - CVT_OP_XMM(cvtss2sd); - CVT_OP_XMM2MMX(cvtps2pi); - CVT_OP_XMM2MMX(cvttps2pi); - CVT_OP_XMM2REG(cvtss2si); - CVT_OP_XMM2REG(cvttss2si); - CVT_OP_XMM(cvtps2dq); - CVT_OP_XMM(cvttps2dq); - - a.d[0] = 2.6; - a.d[1] = -3.4; - CVT_OP_XMM(cvtpd2ps); - CVT_OP_XMM(cvtsd2ss); - CVT_OP_XMM2MMX(cvtpd2pi); - CVT_OP_XMM2MMX(cvttpd2pi); - CVT_OP_XMM2REG(cvtsd2si); - CVT_OP_XMM2REG(cvttsd2si); - CVT_OP_XMM(cvtpd2dq); - CVT_OP_XMM(cvttpd2dq); - - /* sse/mmx moves */ - CVT_OP_XMM2MMX(movdq2q); - CVT_OP_MMX2XMM(movq2dq); - - /* int to float */ - a.l[0] = -6; - a.l[1] = 2; - a.l[2] = 100; - a.l[3] = -60000; - CVT_OP_MMX2XMM(cvtpi2ps); - CVT_OP_MMX2XMM(cvtpi2pd); - CVT_OP_REG2XMM(cvtsi2ss); - CVT_OP_REG2XMM(cvtsi2sd); - CVT_OP_XMM(cvtdq2ps); - CVT_OP_XMM(cvtdq2pd); - - /* XXX: test PNI insns */ -#if 0 - SSE_OP2(movshdup); -#endif - asm volatile ("emms"); -} - -#endif - #define TEST_CONV_RAX(op)\ {\ unsigned long a, r;\ @@ -2756,9 +2187,5 @@ int main(int argc, char **argv) #endif test_enter(); test_conv(); -#ifdef TEST_SSE - test_sse(); - test_fxsave(); -#endif return 0; } From 5e03b6daf66dfb0f5512a0dfc9e21e749b6f67b7 Mon Sep 17 00:00:00 2001 From: Claudio Fontana Date: Thu, 8 Sep 2022 10:14:41 +0200 Subject: [PATCH 0475/1020] audio: add help option for -audio and -audiodev add a simple help option for -audio and -audiodev to show the list of available drivers, and document them. Signed-off-by: Claudio Fontana Message-Id: <20220908081441.7111-1-cfontana@suse.de> Signed-off-by: Paolo Bonzini --- audio/audio.c | 19 +++++++++++++++++++ audio/audio.h | 1 + qemu-options.hx | 10 ++++++---- softmmu/vl.c | 9 +++++++-- 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 76b8735b44..cfa4119c05 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -32,6 +32,7 @@ #include "qapi/qapi-visit-audio.h" #include "qemu/cutils.h" #include "qemu/module.h" +#include "qemu/help_option.h" #include "sysemu/sysemu.h" #include "sysemu/replay.h" #include "sysemu/runstate.h" @@ -2101,10 +2102,28 @@ static void audio_validate_opts(Audiodev *dev, Error **errp) } } +void audio_help(void) +{ + int i; + + printf("Available audio drivers:\n"); + + for (i = 0; i < AUDIODEV_DRIVER__MAX; i++) { + audio_driver *driver = audio_driver_lookup(AudiodevDriver_str(i)); + if (driver) { + printf("%s\n", driver->name); + } + } +} + void audio_parse_option(const char *opt) { Audiodev *dev = NULL; + if (is_help_option(opt)) { + audio_help(); + exit(EXIT_SUCCESS); + } Visitor *v = qobject_input_visitor_new_str(opt, "driver", &error_fatal); visit_type_Audiodev(v, NULL, &dev, &error_fatal); visit_free(v); diff --git a/audio/audio.h b/audio/audio.h index 27e67079a0..01bdc567fb 100644 --- a/audio/audio.h +++ b/audio/audio.h @@ -171,6 +171,7 @@ void audio_sample_from_uint64(void *samples, int pos, void audio_define(Audiodev *audio); void audio_parse_option(const char *opt); bool audio_init_audiodevs(void); +void audio_help(void); void audio_legacy_help(void); AudioState *audio_state_by_name(const char *name); diff --git a/qemu-options.hx b/qemu-options.hx index 1bb02363ab..d8b5ce5b43 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -704,10 +704,11 @@ SRST ``-audio [driver=]driver,model=value[,prop[=value][,...]]`` This option is a shortcut for configuring both the guest audio hardware and the host audio backend in one go. - The host backend options are the same as with the corresponding - ``-audiodev`` options below. The guest hardware model can be set with - ``model=modelname``. Use ``model=help`` to list the available device - types. + The driver option is the same as with the corresponding ``-audiodev`` option below. + The guest hardware model can be set with ``model=modelname``. + + Use ``driver=help`` to list the available drivers, + and ``model=help`` to list the available device types. The following two example do exactly the same, to show how ``-audio`` can be used to shorten the command line length: @@ -721,6 +722,7 @@ ERST DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, "-audiodev [driver=]driver,id=id[,prop[=value][,...]]\n" " specifies the audio backend to use\n" + " Use ``-audiodev help`` to list the available drivers\n" " id= identifier of the backend\n" " timer-period= timer period in microseconds\n" " in|out.mixing-engine= use mixing engine to mix streams inside QEMU\n" diff --git a/softmmu/vl.c b/softmmu/vl.c index 263f029a8e..e62b9cc35d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2842,11 +2842,16 @@ void qemu_init(int argc, char **argv, char **envp) audio_parse_option(optarg); break; case QEMU_OPTION_audio: { - QDict *dict = keyval_parse(optarg, "driver", NULL, &error_fatal); + bool help; char *model; Audiodev *dev = NULL; Visitor *v; - + QDict *dict = keyval_parse(optarg, "driver", &help, &error_fatal); + if (help || (qdict_haskey(dict, "driver") && + is_help_option(qdict_get_str(dict, "driver")))) { + audio_help(); + exit(EXIT_SUCCESS); + } if (!qdict_haskey(dict, "id")) { qdict_put_str(dict, "id", "audiodev0"); } From 034668c329bb3e257a1f259571bd462938522e7a Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 18 Sep 2022 09:15:22 +0200 Subject: [PATCH 0476/1020] target/i386: correctly mask SSE4a bit indices in register operands SSE4a instructions EXTRQ and INSERTQ have two bit index operands, that can be immediates or taken from an XMM register. In both cases, the fields are 6-bit wide and the top two bits in the byte are ignored. translate.c is doing that correctly for the immediate case, but not for the XMM case, so fix it. Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index c0766de18d..3504bca36a 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -926,7 +926,7 @@ static inline uint64_t helper_extrq(uint64_t src, int shift, int len) void helper_extrq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s) { - d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), s->ZMM_B(1), s->ZMM_B(0)); + d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), s->ZMM_B(1) & 63, s->ZMM_B(0) & 63); } void helper_extrq_i(CPUX86State *env, ZMMReg *d, int index, int length) @@ -948,7 +948,7 @@ static inline uint64_t helper_insertq(uint64_t src, int shift, int len) void helper_insertq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s) { - d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9), s->ZMM_B(8)); + d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 63); } void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length) From ca4b1b43bc5ac25c56a3a7a4a2252d6fdc8dcf02 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 18 Sep 2022 09:52:24 +0200 Subject: [PATCH 0477/1020] target/i386: fix INSERTQ implementation INSERTQ is defined to not modify any bits in the lower 64 bits of the destination, other than the ones being replaced with bits from the source operand. QEMU instead is using unshifted bits from the source for those bits. Signed-off-by: Paolo Bonzini --- target/i386/ops_sse.h | 10 +++++----- target/i386/ops_sse_header.h | 2 +- target/i386/tcg/translate.c | 14 ++++++++++++-- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h index 3504bca36a..7bf8bb967d 100644 --- a/target/i386/ops_sse.h +++ b/target/i386/ops_sse.h @@ -934,7 +934,7 @@ void helper_extrq_i(CPUX86State *env, ZMMReg *d, int index, int length) d->ZMM_Q(0) = helper_extrq(d->ZMM_Q(0), index, length); } -static inline uint64_t helper_insertq(uint64_t src, int shift, int len) +static inline uint64_t helper_insertq(uint64_t dest, uint64_t src, int shift, int len) { uint64_t mask; @@ -943,17 +943,17 @@ static inline uint64_t helper_insertq(uint64_t src, int shift, int len) } else { mask = (1ULL << len) - 1; } - return (src & ~(mask << shift)) | ((src & mask) << shift); + return (dest & ~(mask << shift)) | ((src & mask) << shift); } void helper_insertq_r(CPUX86State *env, ZMMReg *d, ZMMReg *s) { - d->ZMM_Q(0) = helper_insertq(s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 63); + d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), s->ZMM_Q(0), s->ZMM_B(9) & 63, s->ZMM_B(8) & 63); } -void helper_insertq_i(CPUX86State *env, ZMMReg *d, int index, int length) +void helper_insertq_i(CPUX86State *env, ZMMReg *d, ZMMReg *s, int index, int length) { - d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), index, length); + d->ZMM_Q(0) = helper_insertq(d->ZMM_Q(0), s->ZMM_Q(0), index, length); } #endif diff --git a/target/i386/ops_sse_header.h b/target/i386/ops_sse_header.h index d99464afb0..400b24c091 100644 --- a/target/i386/ops_sse_header.h +++ b/target/i386/ops_sse_header.h @@ -193,7 +193,7 @@ DEF_HELPER_3(rcpss, void, env, ZMMReg, ZMMReg) DEF_HELPER_3(extrq_r, void, env, ZMMReg, ZMMReg) DEF_HELPER_4(extrq_i, void, env, ZMMReg, int, int) DEF_HELPER_3(insertq_r, void, env, ZMMReg, ZMMReg) -DEF_HELPER_4(insertq_i, void, env, ZMMReg, int, int) +DEF_HELPER_5(insertq_i, void, env, ZMMReg, ZMMReg, int, int) DEF_HELPER_3(glue(haddps, SUFFIX), void, env, ZMMReg, ZMMReg) DEF_HELPER_3(glue(haddpd, SUFFIX), void, env, ZMMReg, ZMMReg) DEF_HELPER_3(glue(hsubps, SUFFIX), void, env, ZMMReg, ZMMReg) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 8ec91d17af..5f31a59fb8 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3506,10 +3506,20 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b, gen_helper_extrq_i(cpu_env, s->ptr0, tcg_const_i32(bit_index), tcg_const_i32(field_length)); - else - gen_helper_insertq_i(cpu_env, s->ptr0, + else { + if (mod != 3) { + gen_lea_modrm(env, s, modrm); + op2_offset = offsetof(CPUX86State, xmm_t0); + gen_ldq_env_A0(s, offsetof(CPUX86State, xmm_t0.ZMM_D(0))); + } else { + rm = (modrm & 7) | REX_B(s); + op2_offset = ZMM_OFFSET(rm); + } + tcg_gen_addi_ptr(s->ptr1, cpu_env, op2_offset); + gen_helper_insertq_i(cpu_env, s->ptr0, s->ptr1, tcg_const_i32(bit_index), tcg_const_i32(field_length)); + } } break; case 0x7e: /* movd ea, mm */ From 5c2f60bd1b6fc7164118a6270eefbf0b6dafc4ae Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 24 Aug 2022 17:44:45 +0200 Subject: [PATCH 0478/1020] target/i386: REPZ and REPNZ are mutually exclusive The later prefix wins if both are present, make it show in s->prefix too. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index 5f31a59fb8..eaa56b0f48 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -4733,9 +4733,11 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) switch (b) { case 0xf3: prefixes |= PREFIX_REPZ; + prefixes &= ~PREFIX_REPNZ; goto next_byte; case 0xf2: prefixes |= PREFIX_REPNZ; + prefixes &= ~PREFIX_REPZ; goto next_byte; case 0xf0: prefixes |= PREFIX_LOCK; From efcca7ef172a6844423670aa62f93099feb58b8c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 23 Aug 2022 15:50:48 +0200 Subject: [PATCH 0479/1020] target/i386: introduce insn_get_addr The "O" operand type in the Intel SDM needs to load an 8- to 64-bit unsigned value, while insn_get is limited to 32 bits. Extract the code out of disas_insn and into a separate function. Reviewed-by: Richard Henderson Signed-off-by: Paolo Bonzini --- target/i386/tcg/translate.c | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index eaa56b0f48..44af8c107f 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -2289,6 +2289,31 @@ static void gen_ldst_modrm(CPUX86State *env, DisasContext *s, int modrm, } } +static target_ulong insn_get_addr(CPUX86State *env, DisasContext *s, MemOp ot) +{ + target_ulong ret; + + switch (ot) { + case MO_8: + ret = x86_ldub_code(env, s); + break; + case MO_16: + ret = x86_lduw_code(env, s); + break; + case MO_32: + ret = x86_ldl_code(env, s); + break; +#ifdef TARGET_X86_64 + case MO_64: + ret = x86_ldq_code(env, s); + break; +#endif + default: + g_assert_not_reached(); + } + return ret; +} + static inline uint32_t insn_get(CPUX86State *env, DisasContext *s, MemOp ot) { uint32_t ret; @@ -5851,16 +5876,7 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu) target_ulong offset_addr; ot = mo_b_d(b, dflag); - switch (s->aflag) { -#ifdef TARGET_X86_64 - case MO_64: - offset_addr = x86_ldq_code(env, s); - break; -#endif - default: - offset_addr = insn_get(env, s, s->aflag); - break; - } + offset_addr = insn_get_addr(env, s, s->aflag); tcg_gen_movi_tl(s->A0, offset_addr); gen_add_A0_ds_seg(s); if ((b & 2) == 0) { From 9ee37d3bb89c8743e8b1a0e69af8efb6e25bb7db Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 14 Sep 2022 16:19:36 +0200 Subject: [PATCH 0480/1020] build: remove extra parentheses causing missing rebuilds Because of two stray parentheses at the end of the definition of ninja-cmd-goals, the test that is last in the .check-TESTSUITENAME.deps variable will not be rebuilt. Fix that. Signed-off-by: Paolo Bonzini --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 13234f2aa4..b576cba5a8 100644 --- a/Makefile +++ b/Makefile @@ -145,7 +145,7 @@ NINJAFLAGS = $(if $V,-v) $(if $(MAKE.n), -n) $(if $(MAKE.k), -k0) \ $(filter-out -j, $(lastword -j1 $(filter -l% -j%, $(MAKEFLAGS)))) \ -d keepdepfile ninja-cmd-goals = $(or $(MAKECMDGOALS), all) -ninja-cmd-goals += $(foreach g, $(MAKECMDGOALS), $(.ninja-goals.$g)))) +ninja-cmd-goals += $(foreach g, $(MAKECMDGOALS), $(.ninja-goals.$g)) makefile-targets := build.ninja ctags TAGS cscope dist clean uninstall # "ninja -t targets" also lists all prerequisites. If build system From df22fbb751dc72f321218c3fb192730a47ad59a9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 19 Sep 2022 15:40:44 +0200 Subject: [PATCH 0481/1020] qboot: update to latest submodule Include patch "Place setup_data at location specified by host" from Jason A. Donenfeld. Cc: Jason A. Donenfeld Signed-off-by: Paolo Bonzini --- roms/qboot | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roms/qboot b/roms/qboot index a5300c4949..8ca302e86d 160000 --- a/roms/qboot +++ b/roms/qboot @@ -1 +1 @@ -Subproject commit a5300c4949b8d4de2d34bedfaed66793f48ec948 +Subproject commit 8ca302e86d685fa05b16e2b208888243da319941 From caa0a12e0112b4496b4a6b7832e56da5e50481c6 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Mon, 6 Jun 2022 15:23:25 -0700 Subject: [PATCH 0482/1020] Hexagon (target/hexagon) remove unused encodings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove encodings guarded by ifdef that is not defined Signed-off-by: Taylor Simpson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220606222327.7682-4-tsimpson@quicinc.com> --- target/hexagon/imported/encode_pp.def | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/target/hexagon/imported/encode_pp.def b/target/hexagon/imported/encode_pp.def index 939c6fc55f..d71c04cd30 100644 --- a/target/hexagon/imported/encode_pp.def +++ b/target/hexagon/imported/encode_pp.def @@ -944,13 +944,6 @@ MPY_ENC(F2_dfmpyfix, "1000","ddddd","0","0","1","0","11") MPY_ENC(F2_dfmin, "1000","ddddd","0","0","1","1","11") MPY_ENC(F2_dfmax, "1000","ddddd","0","1","0","0","11") MPY_ENC(F2_dfmpyll, "1000","ddddd","0","1","0","1","11") -#ifdef ADD_DP_OPS -MPY_ENC(F2_dfdivcheat, "1000","ddddd","0","0","0","1","00") - -MPY_ENC(F2_dffixupn, "1000","ddddd","0","1","0","1","11") -MPY_ENC(F2_dffixupd, "1000","ddddd","0","1","1","0","11") -MPY_ENC(F2_dfrecipa, "1000","ddddd","0","1","1","1","ee") -#endif MPY_ENC(M7_dcmpyrw, "1000","ddddd","0","0","0","1","10") MPY_ENC(M7_dcmpyrwc, "1000","ddddd","0","0","1","1","10") @@ -1024,15 +1017,6 @@ MPY_ENC(M5_vdmacbsu, "1010","xxxxx","0","1","0","0","01") MPY_ENC(F2_dfmpylh, "1010","xxxxx","0","0","0","0","11") MPY_ENC(F2_dfmpyhh, "1010","xxxxx","0","0","0","1","11") -#ifdef ADD_DP_OPS -MPY_ENC(F2_dfmpyhh, "1010","xxxxx","0","0","1","0","11") -MPY_ENC(F2_dffma, "1010","xxxxx","0","0","0","0","11") -MPY_ENC(F2_dffms, "1010","xxxxx","0","0","0","1","11") - -MPY_ENC(F2_dffma_lib, "1010","xxxxx","0","0","1","0","11") -MPY_ENC(F2_dffms_lib, "1010","xxxxx","0","0","1","1","11") -MPY_ENC(F2_dffma_sc, "1010","xxxxx","0","1","1","1","uu") -#endif MPY_ENC(M7_dcmpyrw_acc, "1010","xxxxx","0","0","0","1","10") @@ -1547,15 +1531,8 @@ SH2_RR_ENC(F2_conv_df2d, "0000","111","0","0 00","ddddd") SH2_RR_ENC(F2_conv_df2ud, "0000","111","0","0 01","ddddd") SH2_RR_ENC(F2_conv_ud2df, "0000","111","0","0 10","ddddd") SH2_RR_ENC(F2_conv_d2df, "0000","111","0","0 11","ddddd") -#ifdef ADD_DP_OPS -SH2_RR_ENC(F2_dffixupr, "0000","111","0","1 00","ddddd") -SH2_RR_ENC(F2_dfsqrtcheat, "0000","111","0","1 01","ddddd") -#endif SH2_RR_ENC(F2_conv_df2d_chop, "0000","111","0","1 10","ddddd") SH2_RR_ENC(F2_conv_df2ud_chop,"0000","111","0","1 11","ddddd") -#ifdef ADD_DP_OPS -SH2_RR_ENC(F2_dfinvsqrta, "0000","111","1","0 ee","ddddd") -#endif From 8888ee42af726b9aba8245022fd4b7350a12acd3 Mon Sep 17 00:00:00 2001 From: Matheus Tavares Bernardino Date: Fri, 16 Sep 2022 12:06:27 -0300 Subject: [PATCH 0483/1020] Hexagon (tests/tcg/hexagon): add fmin/fmax tests for signed zero Signed-off-by: Matheus Tavares Bernardino Signed-off-by: Taylor Simpson Reviewed-by: Taylor Simpson Tested-by: Taylor Simpson --- tests/tcg/hexagon/usr.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/tcg/hexagon/usr.c b/tests/tcg/hexagon/usr.c index a531511cec..fb4514989c 100644 --- a/tests/tcg/hexagon/usr.c +++ b/tests/tcg/hexagon/usr.c @@ -86,6 +86,7 @@ const uint32_t SF_QNaN_neg = 0xffc00000; const uint32_t SF_SNaN_neg = 0xffb00000; const uint32_t SF_HEX_NaN = 0xffffffff; const uint32_t SF_zero = 0x00000000; +const uint32_t SF_zero_neg = 0x80000000; const uint32_t SF_one = 0x3f800000; const uint32_t SF_one_recip = 0x3f7f0001; /* 0.9960... */ const uint32_t SF_one_invsqrta = 0x3f7f0000; /* 0.99609375 */ @@ -100,6 +101,7 @@ const uint64_t DF_QNaN_neg = 0xfff8000000000000ULL; const uint64_t DF_SNaN_neg = 0xfff7000000000000ULL; const uint64_t DF_HEX_NaN = 0xffffffffffffffffULL; const uint64_t DF_zero = 0x0000000000000000ULL; +const uint64_t DF_zero_neg = 0x8000000000000000ULL; const uint64_t DF_any = 0x3f80000000000000ULL; const uint64_t DF_one = 0x3ff0000000000000ULL; const uint64_t DF_one_hh = 0x3ff001ff80000000ULL; /* 1.00048... */ @@ -933,6 +935,8 @@ int main() TEST_R_OP_RR(sfmin, SF_QNaN, SF_one, SF_one, USR_CLEAR); TEST_R_OP_RR(sfmin, SF_SNaN, SF_QNaN, SF_HEX_NaN, USR_FPINVF); TEST_R_OP_RR(sfmin, SF_QNaN, SF_SNaN, SF_HEX_NaN, USR_FPINVF); + TEST_R_OP_RR(sfmin, SF_zero, SF_zero_neg, SF_zero_neg, USR_CLEAR); + TEST_R_OP_RR(sfmin, SF_zero_neg, SF_zero, SF_zero_neg, USR_CLEAR); TEST_R_OP_RR(sfmax, SF_one, SF_small_neg, SF_one, USR_CLEAR); TEST_R_OP_RR(sfmax, SF_one, SF_SNaN, SF_one, USR_FPINVF); @@ -941,6 +945,8 @@ int main() TEST_R_OP_RR(sfmax, SF_QNaN, SF_one, SF_one, USR_CLEAR); TEST_R_OP_RR(sfmax, SF_SNaN, SF_QNaN, SF_HEX_NaN, USR_FPINVF); TEST_R_OP_RR(sfmax, SF_QNaN, SF_SNaN, SF_HEX_NaN, USR_FPINVF); + TEST_R_OP_RR(sfmax, SF_zero, SF_zero_neg, SF_zero, USR_CLEAR); + TEST_R_OP_RR(sfmax, SF_zero_neg, SF_zero, SF_zero, USR_CLEAR); TEST_R_OP_RR(sfadd, SF_one, SF_QNaN, SF_HEX_NaN, USR_CLEAR); TEST_R_OP_RR(sfadd, SF_one, SF_SNaN, SF_HEX_NaN, USR_FPINVF); @@ -1003,6 +1009,8 @@ int main() TEST_P_OP_PP(dfmin, DF_QNaN, DF_any, DF_any, USR_CLEAR); TEST_P_OP_PP(dfmin, DF_SNaN, DF_QNaN, DF_HEX_NaN, USR_FPINVF); TEST_P_OP_PP(dfmin, DF_QNaN, DF_SNaN, DF_HEX_NaN, USR_FPINVF); + TEST_P_OP_PP(dfmin, DF_zero, DF_zero_neg, DF_zero_neg, USR_CLEAR); + TEST_P_OP_PP(dfmin, DF_zero_neg, DF_zero, DF_zero_neg, USR_CLEAR); TEST_P_OP_PP(dfmax, DF_any, DF_small_neg, DF_any, USR_CLEAR); TEST_P_OP_PP(dfmax, DF_any, DF_SNaN, DF_any, USR_FPINVF); @@ -1011,6 +1019,8 @@ int main() TEST_P_OP_PP(dfmax, DF_QNaN, DF_any, DF_any, USR_CLEAR); TEST_P_OP_PP(dfmax, DF_SNaN, DF_QNaN, DF_HEX_NaN, USR_FPINVF); TEST_P_OP_PP(dfmax, DF_QNaN, DF_SNaN, DF_HEX_NaN, USR_FPINVF); + TEST_P_OP_PP(dfmax, DF_zero, DF_zero_neg, DF_zero, USR_CLEAR); + TEST_P_OP_PP(dfmax, DF_zero_neg, DF_zero, DF_zero, USR_CLEAR); TEST_XP_OP_PP(dfmpyhh, DF_one, DF_one, DF_one, DF_one_hh, USR_CLEAR); TEST_XP_OP_PP(dfmpyhh, DF_zero, DF_any, DF_QNaN, DF_HEX_NaN, USR_CLEAR); From ee413a52c1bc36abbdbf097da0c9143b9a88220d Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 15:33:57 +0800 Subject: [PATCH 0484/1020] hw/loongarch: Add interrupt information to FDT table Add interrupt information to FDT table, such as interrupt controller info, compatiable info, etc. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-4-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/virt.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 4f833a2044..68b59a6c9f 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -158,6 +158,33 @@ static void fdt_add_pcie_node(const LoongArchMachineState *lams) qemu_fdt_dumpdtb(ms->fdt, lams->fdt_size); } +static void fdt_add_irqchip_node(LoongArchMachineState *lams) +{ + MachineState *ms = MACHINE(lams); + char *nodename; + uint32_t irqchip_phandle; + + irqchip_phandle = qemu_fdt_alloc_phandle(ms->fdt); + qemu_fdt_setprop_cell(ms->fdt, "/", "interrupt-parent", irqchip_phandle); + + nodename = g_strdup_printf("/intc@%lx", VIRT_IOAPIC_REG_BASE); + qemu_fdt_add_subnode(ms->fdt, nodename); + qemu_fdt_setprop_cell(ms->fdt, nodename, "#interrupt-cells", 3); + qemu_fdt_setprop(ms->fdt, nodename, "interrupt-controller", NULL, 0); + qemu_fdt_setprop_cell(ms->fdt, nodename, "#address-cells", 0x2); + qemu_fdt_setprop_cell(ms->fdt, nodename, "#size-cells", 0x2); + qemu_fdt_setprop(ms->fdt, nodename, "ranges", NULL, 0); + + qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", + "loongarch,ls7a"); + + qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", + 2, VIRT_IOAPIC_REG_BASE, + 2, PCH_PIC_ROUTE_ENTRY_OFFSET); + + qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", irqchip_phandle); + g_free(nodename); +} #define PM_BASE 0x10080000 #define PM_SIZE 0x100 @@ -697,6 +724,7 @@ static void loongarch_init(MachineState *machine) } /* Initialize the IO interrupt subsystem */ loongarch_irq_init(lams); + fdt_add_irqchip_node(lams); lams->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&lams->machine_done); fdt_add_pcie_node(lams); From a1f7d78e564a453ea07159efaa1af9a7210ddeda Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 15:50:35 +0800 Subject: [PATCH 0485/1020] hw/loongarch: Add platform bus support Add platform bus support and add the bus information such as address, size, irq number to FDT table. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-5-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/Kconfig | 1 + hw/loongarch/virt.c | 33 +++++++++++++++++++++++++++++++++ include/hw/loongarch/virt.h | 1 + include/hw/pci-host/ls7a.h | 5 +++++ 4 files changed, 40 insertions(+) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index 1deea83626..fef55c5638 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -8,6 +8,7 @@ config LOONGARCH_VIRT select SERIAL select SERIAL_ISA select VIRTIO_PCI + select PLATFORM_BUS select LOONGARCH_IPI select LOONGARCH_PCH_PIC select LOONGARCH_PCH_MSI diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 68b59a6c9f..5fd3834c0a 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -37,6 +37,8 @@ #include "hw/mem/nvdimm.h" #include "sysemu/device_tree.h" #include +#include "hw/core/sysbus-fdt.h" +#include "hw/platform-bus.h" static void create_fdt(LoongArchMachineState *lams) { @@ -345,6 +347,31 @@ static DeviceState *create_acpi_ged(DeviceState *pch_pic, LoongArchMachineState return dev; } +static DeviceState *create_platform_bus(DeviceState *pch_pic) +{ + DeviceState *dev; + SysBusDevice *sysbus; + int i, irq; + MemoryRegion *sysmem = get_system_memory(); + + dev = qdev_new(TYPE_PLATFORM_BUS_DEVICE); + dev->id = g_strdup(TYPE_PLATFORM_BUS_DEVICE); + qdev_prop_set_uint32(dev, "num_irqs", VIRT_PLATFORM_BUS_NUM_IRQS); + qdev_prop_set_uint32(dev, "mmio_size", VIRT_PLATFORM_BUS_SIZE); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); + + sysbus = SYS_BUS_DEVICE(dev); + for (i = 0; i < VIRT_PLATFORM_BUS_NUM_IRQS; i++) { + irq = VIRT_PLATFORM_BUS_IRQ - PCH_PIC_IRQ_OFFSET + i; + sysbus_connect_irq(sysbus, i, qdev_get_gpio_in(pch_pic, irq)); + } + + memory_region_add_subregion(sysmem, + VIRT_PLATFORM_BUS_BASEADDRESS, + sysbus_mmio_get_region(sysbus, 0)); + return dev; +} + static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState *lams) { DeviceState *gpex_dev; @@ -420,6 +447,8 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * memory_region_add_subregion(get_system_memory(), PM_BASE, pm_mem); /* acpi ged */ lams->acpi_ged = create_acpi_ged(pch_pic, lams); + /* platform bus */ + lams->platform_bus_dev = create_platform_bus(pch_pic); } static void loongarch_irq_init(LoongArchMachineState *lams) @@ -725,6 +754,10 @@ static void loongarch_init(MachineState *machine) /* Initialize the IO interrupt subsystem */ loongarch_irq_init(lams); fdt_add_irqchip_node(lams); + platform_bus_add_all_fdt_nodes(machine->fdt, "/intc", + VIRT_PLATFORM_BUS_BASEADDRESS, + VIRT_PLATFORM_BUS_SIZE, + VIRT_PLATFORM_BUS_IRQ); lams->machine_done.notify = virt_machine_done; qemu_add_machine_init_done_notifier(&lams->machine_done); fdt_add_pcie_node(lams); diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 92b84de1c5..64c90b80d2 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -49,6 +49,7 @@ struct LoongArchMachineState { char *oem_table_id; DeviceState *acpi_ged; int fdt_size; + DeviceState *platform_bus_dev; }; #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt") diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h index cdde0af1f8..9bd875ca8b 100644 --- a/include/hw/pci-host/ls7a.h +++ b/include/hw/pci-host/ls7a.h @@ -42,4 +42,9 @@ #define VIRT_RTC_REG_BASE (VIRT_MISC_REG_BASE + 0x00050100) #define VIRT_RTC_LEN 0x100 #define VIRT_SCI_IRQ (PCH_PIC_IRQ_OFFSET + 4) + +#define VIRT_PLATFORM_BUS_BASEADDRESS 0x16000000 +#define VIRT_PLATFORM_BUS_SIZE 0x2000000 +#define VIRT_PLATFORM_BUS_NUM_IRQS 2 +#define VIRT_PLATFORM_BUS_IRQ 69 #endif From e27e535768129834cf6debed4575a161f7013dda Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 16:37:21 +0800 Subject: [PATCH 0486/1020] hw/loongarch: Add hotplug handler for machine Add hotplug handler for LoongArch virt machine and now only support the dynamic sysbus device. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-6-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/virt.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 5fd3834c0a..eedff10758 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -803,9 +803,35 @@ static void loongarch_machine_initfn(Object *obj) lams->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); } +static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev); + MachineClass *mc = MACHINE_GET_CLASS(lams); + + if (device_is_dynamic_sysbus(mc, dev)) { + if (lams->platform_bus_dev) { + platform_bus_link_device(PLATFORM_BUS_DEVICE(lams->platform_bus_dev), + SYS_BUS_DEVICE(dev)); + } + } +} + +static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, + DeviceState *dev) +{ + MachineClass *mc = MACHINE_GET_CLASS(machine); + + if (device_is_dynamic_sysbus(mc, dev)) { + return HOTPLUG_HANDLER(machine); + } + return NULL; +} + static void loongarch_class_init(ObjectClass *oc, void *data) { MachineClass *mc = MACHINE_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); mc->desc = "Loongson-3A5000 LS7A1000 machine"; mc->init = loongarch_init; @@ -818,6 +844,8 @@ static void loongarch_class_init(ObjectClass *oc, void *data) mc->block_default_type = IF_VIRTIO; mc->default_boot_order = "c"; mc->no_cdrom = 1; + mc->get_hotplug_handler = virt_machine_get_hotplug_handler; + hc->plug = loongarch_machine_device_plug_cb; object_class_property_add(oc, "acpi", "OnOffAuto", loongarch_get_acpi, loongarch_set_acpi, @@ -833,6 +861,10 @@ static const TypeInfo loongarch_machine_types[] = { .instance_size = sizeof(LoongArchMachineState), .class_init = loongarch_class_init, .instance_init = loongarch_machine_initfn, + .interfaces = (InterfaceInfo[]) { + { TYPE_HOTPLUG_HANDLER }, + { } + }, } }; From f8ab9aa2883c91fb14eb583febf6a301373c8f62 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Wed, 10 Aug 2022 16:41:52 +0800 Subject: [PATCH 0487/1020] hw/loongarch: Add RAMFB to dynamic_sysbus_devices list Add RAMFB device to dynamic_sysbus_devices list so that it can be hotpluged to the machine. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-7-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/virt.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index eedff10758..0dd57935b0 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -39,6 +39,7 @@ #include #include "hw/core/sysbus-fdt.h" #include "hw/platform-bus.h" +#include "hw/display/ramfb.h" static void create_fdt(LoongArchMachineState *lams) { @@ -852,6 +853,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data) NULL, NULL); object_class_property_set_description(oc, "acpi", "Enable ACPI"); + machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE); } static const TypeInfo loongarch_machine_types[] = { From 1cd5db2e8836dc2e1e8fe83f6a2fc101c539df0c Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Fri, 19 Aug 2022 11:16:37 +0800 Subject: [PATCH 0488/1020] hw/loongarch: Fix acpi ged irq number in dsdt table In dsdt, acpi ged irq should use gsi number, and the VIRT_SCI_IRQ means it. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-8-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/acpi-build.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index d0f01a6485..95e30975a8 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -367,7 +367,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) if (lams->acpi_ged) { build_ged_aml(dsdt, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(lams->acpi_ged), - VIRT_SCI_IRQ - PCH_PIC_IRQ_OFFSET, AML_SYSTEM_MEMORY, + VIRT_SCI_IRQ, AML_SYSTEM_MEMORY, VIRT_GED_EVT_ADDR); } From c3da26f314ad918ad36ca1373ea7c7f1aa036a87 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Thu, 25 Aug 2022 11:36:59 +0800 Subject: [PATCH 0489/1020] hw/loongarch: Support memory hotplug Add hotplug/unplug interface for memory device. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-9-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/Kconfig | 2 + hw/loongarch/acpi-build.c | 32 +++++++++--- hw/loongarch/virt.c | 105 +++++++++++++++++++++++++++++++++++++- 3 files changed, 132 insertions(+), 7 deletions(-) diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig index fef55c5638..17d15b6c90 100644 --- a/hw/loongarch/Kconfig +++ b/hw/loongarch/Kconfig @@ -4,6 +4,7 @@ config LOONGARCH_VIRT select PCI_EXPRESS_GENERIC_BRIDGE imply VIRTIO_VGA imply PCI_DEVICES + imply NVDIMM select ISA_BUS select SERIAL select SERIAL_ISA @@ -18,3 +19,4 @@ config LOONGARCH_VIRT select ACPI_PCI select ACPI_HW_REDUCED select FW_CFG_DMA + select DIMM diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index 95e30975a8..92ee62c11a 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -186,6 +186,12 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_srat_memory(table_data, VIRT_HIGHMEM_BASE, machine->ram_size - VIRT_LOWMEM_SIZE, 0, MEM_AFFINITY_ENABLED); + if (ms->device_memory) { + build_srat_memory(table_data, ms->device_memory->base, + memory_region_size(&ms->device_memory->mr), + 0, MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED); + } + acpi_table_end(linker, &table); } @@ -335,6 +341,25 @@ static void build_uart_device_aml(Aml *table) aml_append(table, scope); } +static void +build_la_ged_aml(Aml *dsdt, MachineState *machine) +{ + uint32_t event; + LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); + + build_ged_aml(dsdt, "\\_SB."GED_DEVICE, + HOTPLUG_HANDLER(lams->acpi_ged), + VIRT_SCI_IRQ, AML_SYSTEM_MEMORY, + VIRT_GED_EVT_ADDR); + event = object_property_get_uint(OBJECT(lams->acpi_ged), + "ged-event", &error_abort); + if (event & ACPI_GED_MEM_HOTPLUG_EVT) { + build_memory_hotplug_aml(dsdt, machine->ram_slots, "\\_SB", NULL, + AML_SYSTEM_MEMORY, + VIRT_GED_MEM_ADDR); + } +} + /* build DSDT */ static void build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) @@ -364,12 +389,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) build_gpex_pci0_int(dsdt); build_uart_device_aml(dsdt); - if (lams->acpi_ged) { - build_ged_aml(dsdt, "\\_SB."GED_DEVICE, - HOTPLUG_HANDLER(lams->acpi_ged), - VIRT_SCI_IRQ, AML_SYSTEM_MEMORY, - VIRT_GED_EVT_ADDR); - } + build_la_ged_aml(dsdt, machine); scope = aml_scope("\\_SB.PCI0"); /* Build PCI0._CRS */ diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index 0dd57935b0..fe175e873b 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -40,6 +40,7 @@ #include "hw/core/sysbus-fdt.h" #include "hw/platform-bus.h" #include "hw/display/ramfb.h" +#include "hw/mem/pc-dimm.h" static void create_fdt(LoongArchMachineState *lams) { @@ -718,6 +719,35 @@ static void loongarch_init(MachineState *machine) machine->ram, offset, highram_size); memory_region_add_subregion(address_space_mem, 0x90000000, &lams->highmem); memmap_add_entry(0x90000000, highram_size, 1); + + /* initialize device memory address space */ + if (machine->ram_size < machine->maxram_size) { + machine->device_memory = g_malloc0(sizeof(*machine->device_memory)); + ram_addr_t device_mem_size = machine->maxram_size - machine->ram_size; + + if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) { + error_report("unsupported amount of memory slots: %"PRIu64, + machine->ram_slots); + exit(EXIT_FAILURE); + } + + if (QEMU_ALIGN_UP(machine->maxram_size, + TARGET_PAGE_SIZE) != machine->maxram_size) { + error_report("maximum memory size must by aligned to multiple of " + "%d bytes", TARGET_PAGE_SIZE); + exit(EXIT_FAILURE); + } + /* device memory base is the top of high memory address. */ + machine->device_memory->base = 0x90000000 + highram_size; + machine->device_memory->base = + ROUND_UP(machine->device_memory->base, 1 * GiB); + + memory_region_init(&machine->device_memory->mr, OBJECT(lams), + "device-memory", device_mem_size); + memory_region_add_subregion(address_space_mem, machine->device_memory->base, + &machine->device_memory->mr); + } + /* Add isa io region */ memory_region_init_alias(&lams->isa_io, NULL, "isa-io", get_system_io(), 0, VIRT_ISA_IO_SIZE); @@ -804,6 +834,73 @@ static void loongarch_machine_initfn(Object *obj) lams->oem_table_id = g_strndup(ACPI_BUILD_APPNAME8, 8); } +static bool memhp_type_supported(DeviceState *dev) +{ + /* we only support pc dimm now */ + return object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) && + !object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM); +} + +static void virt_mem_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) +{ + pc_dimm_pre_plug(PC_DIMM(dev), MACHINE(hotplug_dev), NULL, errp); +} + +static void virt_machine_device_pre_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (memhp_type_supported(dev)) { + virt_mem_pre_plug(hotplug_dev, dev, errp); + } +} + +static void virt_mem_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev); + + /* the acpi ged is always exist */ + hotplug_handler_unplug_request(HOTPLUG_HANDLER(lams->acpi_ged), dev, + errp); +} + +static void virt_machine_device_unplug_request(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (memhp_type_supported(dev)) { + virt_mem_unplug_request(hotplug_dev, dev, errp); + } +} + +static void virt_mem_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev); + + hotplug_handler_unplug(HOTPLUG_HANDLER(lams->acpi_ged), dev, errp); + pc_dimm_unplug(PC_DIMM(dev), MACHINE(lams)); + qdev_unrealize(dev); +} + +static void virt_machine_device_unplug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + if (memhp_type_supported(dev)) { + virt_mem_unplug(hotplug_dev, dev, errp); + } +} + +static void virt_mem_plug(HotplugHandler *hotplug_dev, + DeviceState *dev, Error **errp) +{ + LoongArchMachineState *lams = LOONGARCH_MACHINE(hotplug_dev); + + pc_dimm_plug(PC_DIMM(dev), MACHINE(lams)); + hotplug_handler_plug(HOTPLUG_HANDLER(lams->acpi_ged), + dev, &error_abort); +} + static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { @@ -815,6 +912,8 @@ static void loongarch_machine_device_plug_cb(HotplugHandler *hotplug_dev, platform_bus_link_device(PLATFORM_BUS_DEVICE(lams->platform_bus_dev), SYS_BUS_DEVICE(dev)); } + } else if (memhp_type_supported(dev)) { + virt_mem_plug(hotplug_dev, dev, errp); } } @@ -823,7 +922,8 @@ static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine, { MachineClass *mc = MACHINE_GET_CLASS(machine); - if (device_is_dynamic_sysbus(mc, dev)) { + if (device_is_dynamic_sysbus(mc, dev) || + memhp_type_supported(dev)) { return HOTPLUG_HANDLER(machine); } return NULL; @@ -847,6 +947,9 @@ static void loongarch_class_init(ObjectClass *oc, void *data) mc->no_cdrom = 1; mc->get_hotplug_handler = virt_machine_get_hotplug_handler; hc->plug = loongarch_machine_device_plug_cb; + hc->pre_plug = virt_machine_device_pre_plug; + hc->unplug_request = virt_machine_device_unplug_request; + hc->unplug = virt_machine_device_unplug; object_class_property_add(oc, "acpi", "OnOffAuto", loongarch_get_acpi, loongarch_set_acpi, From 1895b967922890f76ad0ba8eefad6019e0328606 Mon Sep 17 00:00:00 2001 From: Xiaojuan Yang Date: Thu, 25 Aug 2022 11:57:33 +0800 Subject: [PATCH 0490/1020] hw/loongarch: Improve acpi dsdt table Cleanup the previous pci information in acpi dsdt table. And using the common acpi_dsdt_add_gpex function to build the gpex and pci information. Signed-off-by: Xiaojuan Yang Acked-by: Song Gao Message-Id: <20220908094623.73051-10-yangxiaojuan@loongson.cn> Signed-off-by: Song Gao --- hw/loongarch/acpi-build.c | 159 +++++------------------------------- hw/loongarch/virt.c | 1 + include/hw/loongarch/virt.h | 1 + 3 files changed, 21 insertions(+), 140 deletions(-) diff --git a/hw/loongarch/acpi-build.c b/hw/loongarch/acpi-build.c index 92ee62c11a..378a6d9d38 100644 --- a/hw/loongarch/acpi-build.c +++ b/hw/loongarch/acpi-build.c @@ -30,6 +30,7 @@ #include "qom/qom-qobject.h" #include "hw/acpi/generic_event_device.h" +#include "hw/pci-host/gpex.h" #define ACPI_BUILD_ALIGN_SIZE 0x1000 #define ACPI_BUILD_TABLE_SIZE 0x20000 @@ -206,108 +207,6 @@ struct AcpiBuildState { MemoryRegion *linker_mr; } AcpiBuildState; -static void build_gpex_pci0_int(Aml *table) -{ - Aml *sb_scope = aml_scope("_SB"); - Aml *pci0_scope = aml_scope("PCI0"); - Aml *prt_pkg = aml_varpackage(128); - int slot, pin; - - for (slot = 0; slot < PCI_SLOT_MAX; slot++) { - for (pin = 0; pin < PCI_NUM_PINS; pin++) { - Aml *pkg = aml_package(4); - aml_append(pkg, aml_int((slot << 16) | 0xFFFF)); - aml_append(pkg, aml_int(pin)); - aml_append(pkg, aml_int(0)); - aml_append(pkg, aml_int(80 + (slot + pin) % 4)); - aml_append(prt_pkg, pkg); - } - } - aml_append(pci0_scope, aml_name_decl("_PRT", prt_pkg)); - aml_append(sb_scope, pci0_scope); - aml_append(table, sb_scope); -} - -static void build_dbg_aml(Aml *table) -{ - Aml *field; - Aml *method; - Aml *while_ctx; - Aml *scope = aml_scope("\\"); - Aml *buf = aml_local(0); - Aml *len = aml_local(1); - Aml *idx = aml_local(2); - - aml_append(scope, - aml_operation_region("DBG", AML_SYSTEM_IO, aml_int(0x0402), 0x01)); - field = aml_field("DBG", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE); - aml_append(field, aml_named_field("DBGB", 8)); - aml_append(scope, field); - - method = aml_method("DBUG", 1, AML_NOTSERIALIZED); - - aml_append(method, aml_to_hexstring(aml_arg(0), buf)); - aml_append(method, aml_to_buffer(buf, buf)); - aml_append(method, aml_subtract(aml_sizeof(buf), aml_int(1), len)); - aml_append(method, aml_store(aml_int(0), idx)); - - while_ctx = aml_while(aml_lless(idx, len)); - aml_append(while_ctx, - aml_store(aml_derefof(aml_index(buf, idx)), aml_name("DBGB"))); - aml_append(while_ctx, aml_increment(idx)); - aml_append(method, while_ctx); - aml_append(method, aml_store(aml_int(0x0A), aml_name("DBGB"))); - aml_append(scope, method); - aml_append(table, scope); -} - -static Aml *build_osc_method(void) -{ - Aml *if_ctx; - Aml *if_ctx2; - Aml *else_ctx; - Aml *method; - Aml *a_cwd1 = aml_name("CDW1"); - Aml *a_ctrl = aml_local(0); - - method = aml_method("_OSC", 4, AML_NOTSERIALIZED); - aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1")); - - if_ctx = aml_if(aml_equal( - aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766"))); - aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2")); - aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3")); - aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl)); - - /* - * Always allow native PME, AER (no dependencies) - * Allow SHPC (PCI bridges can have SHPC controller) - */ - aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl)); - - if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1)))); - /* Unknown revision */ - aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1)); - aml_append(if_ctx, if_ctx2); - - if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl))); - /* Capabilities bits were masked */ - aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1)); - aml_append(if_ctx, if_ctx2); - - /* Update DWORD3 in the buffer */ - aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3"))); - aml_append(method, if_ctx); - - else_ctx = aml_else(); - /* Unrecognized UUID */ - aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1)); - aml_append(method, else_ctx); - - aml_append(method, aml_return(aml_arg(3))); - return method; -} - static void build_uart_device_aml(Aml *table) { Aml *dev; @@ -360,57 +259,37 @@ build_la_ged_aml(Aml *dsdt, MachineState *machine) } } +static void build_pci_device_aml(Aml *scope, LoongArchMachineState *lams) +{ + struct GPEXConfig cfg = { + .mmio64.base = VIRT_PCI_MEM_BASE, + .mmio64.size = VIRT_PCI_MEM_SIZE, + .pio.base = VIRT_PCI_IO_BASE, + .pio.size = VIRT_PCI_IO_SIZE, + .ecam.base = VIRT_PCI_CFG_BASE, + .ecam.size = VIRT_PCI_CFG_SIZE, + .irq = PCH_PIC_IRQ_OFFSET + VIRT_DEVICE_IRQS, + .bus = lams->pci_bus, + }; + + acpi_dsdt_add_gpex(scope, &cfg); +} + /* build DSDT */ static void build_dsdt(GArray *table_data, BIOSLinker *linker, MachineState *machine) { - Aml *dsdt, *sb_scope, *scope, *dev, *crs, *pkg; - int root_bus_limit = 0x7F; + Aml *dsdt, *scope, *pkg; LoongArchMachineState *lams = LOONGARCH_MACHINE(machine); AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = lams->oem_id, .oem_table_id = lams->oem_table_id }; acpi_table_begin(&table, table_data); - dsdt = init_aml_allocator(); - - build_dbg_aml(dsdt); - - sb_scope = aml_scope("_SB"); - dev = aml_device("PCI0"); - aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08"))); - aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03"))); - aml_append(dev, aml_name_decl("_ADR", aml_int(0))); - aml_append(dev, aml_name_decl("_BBN", aml_int(0))); - aml_append(dev, aml_name_decl("_UID", aml_int(1))); - aml_append(dev, build_osc_method()); - aml_append(sb_scope, dev); - aml_append(dsdt, sb_scope); - - build_gpex_pci0_int(dsdt); build_uart_device_aml(dsdt); + build_pci_device_aml(dsdt, lams); build_la_ged_aml(dsdt, machine); - scope = aml_scope("\\_SB.PCI0"); - /* Build PCI0._CRS */ - crs = aml_resource_template(); - aml_append(crs, - aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE, - 0x0000, 0x0, root_bus_limit, - 0x0000, root_bus_limit + 1)); - aml_append(crs, - aml_dword_io(AML_MIN_FIXED, AML_MAX_FIXED, - AML_POS_DECODE, AML_ENTIRE_RANGE, - 0x0000, 0x0000, 0xFFFF, 0x18000000, 0x10000)); - aml_append(crs, - aml_dword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED, - AML_CACHEABLE, AML_READ_WRITE, - 0, VIRT_PCI_MEM_BASE, - VIRT_PCI_MEM_BASE + VIRT_PCI_MEM_SIZE - 1, - 0, VIRT_PCI_MEM_BASE)); - aml_append(scope, aml_name_decl("_CRS", crs)); - aml_append(dsdt, scope); - /* System State Package */ scope = aml_scope("\\"); pkg = aml_package(4); diff --git a/hw/loongarch/virt.c b/hw/loongarch/virt.c index fe175e873b..29df99727d 100644 --- a/hw/loongarch/virt.c +++ b/hw/loongarch/virt.c @@ -387,6 +387,7 @@ static void loongarch_devices_init(DeviceState *pch_pic, LoongArchMachineState * d = SYS_BUS_DEVICE(gpex_dev); sysbus_realize_and_unref(d, &error_fatal); pci_bus = PCI_HOST_BRIDGE(gpex_dev)->bus; + lams->pci_bus = pci_bus; /* Map only part size_ecam bytes of ECAM space */ ecam_alias = g_new0(MemoryRegion, 1); diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h index 64c90b80d2..09f1c88ee5 100644 --- a/include/hw/loongarch/virt.h +++ b/include/hw/loongarch/virt.h @@ -50,6 +50,7 @@ struct LoongArchMachineState { DeviceState *acpi_ged; int fdt_size; DeviceState *platform_bus_dev; + PCIBus *pci_bus; }; #define TYPE_LOONGARCH_MACHINE MACHINE_TYPE_NAME("virt") From a65c9527fd78dbea7f6f24f8c581a91281f355d9 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 2 Sep 2022 18:51:24 +0200 Subject: [PATCH 0491/1020] tests: Fix error strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They were copy-pasted from e1000e and never changed. Signed-off-by: Juan Quintela Message-Id: <20220902165126.1482-7-quintela@redhat.com> Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Thomas Huth --- tests/qtest/e1000-test.c | 2 +- tests/qtest/es1370-test.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/e1000-test.c b/tests/qtest/e1000-test.c index c387984ef6..4e0d7a5607 100644 --- a/tests/qtest/e1000-test.c +++ b/tests/qtest/e1000-test.c @@ -35,7 +35,7 @@ static void *e1000_get_driver(void *obj, const char *interface) return &e1000->dev; } - fprintf(stderr, "%s not present in e1000e\n", interface); + fprintf(stderr, "%s not present in e1000\n", interface); g_assert_not_reached(); } diff --git a/tests/qtest/es1370-test.c b/tests/qtest/es1370-test.c index adccdac1be..97ab65c435 100644 --- a/tests/qtest/es1370-test.c +++ b/tests/qtest/es1370-test.c @@ -28,7 +28,7 @@ static void *es1370_get_driver(void *obj, const char *interface) return &es1370->dev; } - fprintf(stderr, "%s not present in e1000e\n", interface); + fprintf(stderr, "%s not present in es1370\n", interface); g_assert_not_reached(); } From abad185c6bf5bea46a999b623690ef42ea20cb02 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 2 Sep 2022 18:51:25 +0200 Subject: [PATCH 0492/1020] meson-build: Enable CONFIG_REPLICATION only when replication is set Signed-off-by: Juan Quintela Message-Id: <20220902165126.1482-8-quintela@redhat.com> Signed-off-by: Thomas Huth --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index c2adb7caf4..3885fc1076 100644 --- a/meson.build +++ b/meson.build @@ -1878,7 +1878,7 @@ config_host_data.set('CONFIG_DEBUG_STACK_USAGE', get_option('debug_stack_usage') config_host_data.set('CONFIG_GPROF', get_option('gprof')) config_host_data.set('CONFIG_LIVE_BLOCK_MIGRATION', get_option('live_block_migration').allowed()) config_host_data.set('CONFIG_QOM_CAST_DEBUG', get_option('qom_cast_debug')) -config_host_data.set('CONFIG_REPLICATION', get_option('live_block_migration').allowed()) +config_host_data.set('CONFIG_REPLICATION', get_option('replication').allowed()) # has_header config_host_data.set('CONFIG_EPOLL', cc.has_header('sys/epoll.h')) From b3ad62c14f6905fe28fcd276f3029525b44bbe18 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 2 Sep 2022 19:34:45 +0200 Subject: [PATCH 0493/1020] bios-tables-test: Make oem-fields tests be consistent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every other test function is named: test_acpi__() Just make this test the same. Once there, rename "acpi/oem-fields" to "acpi/piix4/oem-fields" so it is consistent with everything else. Signed-off-by: Juan Quintela Message-Id: <20220902173452.1904-2-quintela@redhat.com> Reviewed-by: Ani Sinha Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Thomas Huth --- tests/qtest/bios-tables-test.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 36783966b0..a62f8f9c08 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1671,7 +1671,7 @@ static void test_oem_fields(test_data *data) } } -static void test_acpi_oem_fields_pc(void) +static void test_acpi_piix4_oem_fields(void) { test_data data; char *args; @@ -1691,7 +1691,7 @@ static void test_acpi_oem_fields_pc(void) g_free(args); } -static void test_acpi_oem_fields_q35(void) +static void test_acpi_q35_oem_fields(void) { test_data data; char *args; @@ -1711,7 +1711,7 @@ static void test_acpi_oem_fields_q35(void) g_free(args); } -static void test_acpi_oem_fields_microvm(void) +static void test_acpi_microvm_oem_fields(void) { test_data data; char *args; @@ -1728,7 +1728,7 @@ static void test_acpi_oem_fields_microvm(void) g_free(args); } -static void test_acpi_oem_fields_virt(void) +static void test_acpi_virt_oem_fields(void) { test_data data = { .machine = "virt", @@ -1766,13 +1766,13 @@ int main(int argc, char *argv[]) if (ret) { return ret; } - qtest_add_func("acpi/q35/oem-fields", test_acpi_oem_fields_q35); + qtest_add_func("acpi/q35/oem-fields", test_acpi_q35_oem_fields); if (tpm_model_is_available("-machine q35", "tpm-tis")) { qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis); qtest_add_func("acpi/q35/tpm12-tis", test_acpi_q35_tcg_tpm12_tis); } qtest_add_func("acpi/piix4", test_acpi_piix4_tcg); - qtest_add_func("acpi/oem-fields", test_acpi_oem_fields_pc); + qtest_add_func("acpi/piix4/oem-fields", test_acpi_piix4_oem_fields); qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge); qtest_add_func("acpi/piix4/pci-hotplug/no_root_hotplug", test_acpi_piix4_no_root_hotplug); @@ -1819,7 +1819,7 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); qtest_add_func("acpi/microvm/ioapic2", test_acpi_microvm_ioapic2_tcg); - qtest_add_func("acpi/microvm/oem-fields", test_acpi_oem_fields_microvm); + qtest_add_func("acpi/microvm/oem-fields", test_acpi_microvm_oem_fields); if (has_tcg) { qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs); if (strcmp(arch, "x86_64") == 0) { @@ -1844,7 +1844,7 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp); qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb); - qtest_add_func("acpi/virt/oem-fields", test_acpi_oem_fields_virt); + qtest_add_func("acpi/virt/oem-fields", test_acpi_virt_oem_fields); qtest_add_func("acpi/virt/viot", test_acpi_virt_viot); } } From d007981ae1d56924f5f532a6c458980d675f3ca6 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 2 Sep 2022 19:34:46 +0200 Subject: [PATCH 0494/1020] bios-tables-test: Sort all x86_64 tests by machine type No code change here, just move test around. Signed-off-by: Juan Quintela Message-Id: <20220902173452.1904-3-quintela@redhat.com> Reviewed-by: Ani Sinha Signed-off-by: Thomas Huth --- tests/qtest/bios-tables-test.c | 62 +++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index a62f8f9c08..21d9d77dd4 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1766,11 +1766,6 @@ int main(int argc, char *argv[]) if (ret) { return ret; } - qtest_add_func("acpi/q35/oem-fields", test_acpi_q35_oem_fields); - if (tpm_model_is_available("-machine q35", "tpm-tis")) { - qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis); - qtest_add_func("acpi/q35/tpm12-tis", test_acpi_q35_tcg_tpm12_tis); - } qtest_add_func("acpi/piix4", test_acpi_piix4_tcg); qtest_add_func("acpi/piix4/oem-fields", test_acpi_piix4_oem_fields); qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge); @@ -1780,54 +1775,51 @@ int main(int argc, char *argv[]) test_acpi_piix4_no_bridge_hotplug); qtest_add_func("acpi/piix4/pci-hotplug/off", test_acpi_piix4_no_acpi_pci_hotplug); - qtest_add_func("acpi/q35", test_acpi_q35_tcg); - qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge); - qtest_add_func("acpi/q35/multif-bridge", test_acpi_q35_multif_bridge); - qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64); qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi); - qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi); - qtest_add_func("acpi/q35/smbus/ipmi", test_acpi_q35_tcg_smbus_ipmi); qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp); - qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp); qtest_add_func("acpi/piix4/memhp", test_acpi_piix4_tcg_memhp); - qtest_add_func("acpi/q35/memhp", test_acpi_q35_tcg_memhp); qtest_add_func("acpi/piix4/numamem", test_acpi_piix4_tcg_numamem); - qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem); qtest_add_func("acpi/piix4/nosmm", test_acpi_piix4_tcg_nosmm); qtest_add_func("acpi/piix4/smm-compat", test_acpi_piix4_tcg_smm_compat); qtest_add_func("acpi/piix4/smm-compat-nosmm", test_acpi_piix4_tcg_smm_compat_nosmm); qtest_add_func("acpi/piix4/nohpet", test_acpi_piix4_tcg_nohpet); + qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm); + qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); +#ifdef CONFIG_POSIX + qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); +#endif + + qtest_add_func("acpi/q35", test_acpi_q35_tcg); + qtest_add_func("acpi/q35/oem-fields", test_acpi_q35_oem_fields); + if (tpm_model_is_available("-machine q35", "tpm-tis")) { + qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis); + qtest_add_func("acpi/q35/tpm12-tis", test_acpi_q35_tcg_tpm12_tis); + } + qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge); + qtest_add_func("acpi/q35/multif-bridge", test_acpi_q35_multif_bridge); + qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64); + qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi); + qtest_add_func("acpi/q35/smbus/ipmi", test_acpi_q35_tcg_smbus_ipmi); + qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp); + qtest_add_func("acpi/q35/memhp", test_acpi_q35_tcg_memhp); + qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem); qtest_add_func("acpi/q35/nosmm", test_acpi_q35_tcg_nosmm); qtest_add_func("acpi/q35/smm-compat", test_acpi_q35_tcg_smm_compat); qtest_add_func("acpi/q35/smm-compat-nosmm", test_acpi_q35_tcg_smm_compat_nosmm); qtest_add_func("acpi/q35/nohpet", test_acpi_q35_tcg_nohpet); - qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm); qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); - qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); #ifdef CONFIG_POSIX - qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst); #endif qtest_add_func("acpi/q35/applesmc", test_acpi_q35_applesmc); qtest_add_func("acpi/q35/pvpanic-isa", test_acpi_q35_pvpanic_isa); - qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); - qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); - qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); - qtest_add_func("acpi/microvm/ioapic2", test_acpi_microvm_ioapic2_tcg); - qtest_add_func("acpi/microvm/oem-fields", test_acpi_microvm_oem_fields); if (has_tcg) { qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs); - if (strcmp(arch, "x86_64") == 0) { - qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg); -#ifdef CONFIG_POSIX - qtest_add_func("acpi/microvm/acpierst", test_acpi_microvm_acpi_erst); -#endif - } } if (has_kvm) { qtest_add_func("acpi/q35/kvm/xapic", test_acpi_q35_kvm_xapic); @@ -1838,6 +1830,20 @@ int main(int argc, char *argv[]) qtest_add_func("acpi/q35/cxl", test_acpi_q35_cxl); #endif qtest_add_func("acpi/q35/slic", test_acpi_q35_slic); + + qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); + qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); + qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); + qtest_add_func("acpi/microvm/ioapic2", test_acpi_microvm_ioapic2_tcg); + qtest_add_func("acpi/microvm/oem-fields", test_acpi_microvm_oem_fields); + if (has_tcg) { + if (strcmp(arch, "x86_64") == 0) { + qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg); +#ifdef CONFIG_POSIX + qtest_add_func("acpi/microvm/acpierst", test_acpi_microvm_acpi_erst); +#endif + } + } } else if (strcmp(arch, "aarch64") == 0) { if (has_tcg) { qtest_add_func("acpi/virt", test_acpi_virt_tcg); From 34b1f2c62095c483e10c591ec02e91c7d365ea2a Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 2 Sep 2022 19:34:47 +0200 Subject: [PATCH 0495/1020] bios-tables-test: Only run test for machine types compiled in MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Juan Quintela Message-Id: <20220902173452.1904-4-quintela@redhat.com> Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Thomas Huth --- tests/qtest/bios-tables-test.c | 147 ++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 68 deletions(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 21d9d77dd4..46a46fe0aa 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1766,82 +1766,93 @@ int main(int argc, char *argv[]) if (ret) { return ret; } - qtest_add_func("acpi/piix4", test_acpi_piix4_tcg); - qtest_add_func("acpi/piix4/oem-fields", test_acpi_piix4_oem_fields); - qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge); - qtest_add_func("acpi/piix4/pci-hotplug/no_root_hotplug", - test_acpi_piix4_no_root_hotplug); - qtest_add_func("acpi/piix4/pci-hotplug/no_bridge_hotplug", - test_acpi_piix4_no_bridge_hotplug); - qtest_add_func("acpi/piix4/pci-hotplug/off", - test_acpi_piix4_no_acpi_pci_hotplug); - qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi); - qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp); - qtest_add_func("acpi/piix4/memhp", test_acpi_piix4_tcg_memhp); - qtest_add_func("acpi/piix4/numamem", test_acpi_piix4_tcg_numamem); - qtest_add_func("acpi/piix4/nosmm", test_acpi_piix4_tcg_nosmm); - qtest_add_func("acpi/piix4/smm-compat", - test_acpi_piix4_tcg_smm_compat); - qtest_add_func("acpi/piix4/smm-compat-nosmm", - test_acpi_piix4_tcg_smm_compat_nosmm); - qtest_add_func("acpi/piix4/nohpet", test_acpi_piix4_tcg_nohpet); - qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm); - qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat); + if (qtest_has_machine(MACHINE_PC)) { + qtest_add_func("acpi/piix4", test_acpi_piix4_tcg); + qtest_add_func("acpi/piix4/oem-fields", test_acpi_piix4_oem_fields); + qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge); + qtest_add_func("acpi/piix4/pci-hotplug/no_root_hotplug", + test_acpi_piix4_no_root_hotplug); + qtest_add_func("acpi/piix4/pci-hotplug/no_bridge_hotplug", + test_acpi_piix4_no_bridge_hotplug); + qtest_add_func("acpi/piix4/pci-hotplug/off", + test_acpi_piix4_no_acpi_pci_hotplug); + qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi); + qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp); + qtest_add_func("acpi/piix4/memhp", test_acpi_piix4_tcg_memhp); + qtest_add_func("acpi/piix4/numamem", test_acpi_piix4_tcg_numamem); + qtest_add_func("acpi/piix4/nosmm", test_acpi_piix4_tcg_nosmm); + qtest_add_func("acpi/piix4/smm-compat", + test_acpi_piix4_tcg_smm_compat); + qtest_add_func("acpi/piix4/smm-compat-nosmm", + test_acpi_piix4_tcg_smm_compat_nosmm); + qtest_add_func("acpi/piix4/nohpet", test_acpi_piix4_tcg_nohpet); + qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm); + qtest_add_func("acpi/piix4/acpihmat", + test_acpi_piix4_tcg_acpi_hmat); #ifdef CONFIG_POSIX - qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); + qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); #endif - - qtest_add_func("acpi/q35", test_acpi_q35_tcg); - qtest_add_func("acpi/q35/oem-fields", test_acpi_q35_oem_fields); - if (tpm_model_is_available("-machine q35", "tpm-tis")) { - qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis); - qtest_add_func("acpi/q35/tpm12-tis", test_acpi_q35_tcg_tpm12_tis); } - qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge); - qtest_add_func("acpi/q35/multif-bridge", test_acpi_q35_multif_bridge); - qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64); - qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi); - qtest_add_func("acpi/q35/smbus/ipmi", test_acpi_q35_tcg_smbus_ipmi); - qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp); - qtest_add_func("acpi/q35/memhp", test_acpi_q35_tcg_memhp); - qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem); - qtest_add_func("acpi/q35/nosmm", test_acpi_q35_tcg_nosmm); - qtest_add_func("acpi/q35/smm-compat", - test_acpi_q35_tcg_smm_compat); - qtest_add_func("acpi/q35/smm-compat-nosmm", - test_acpi_q35_tcg_smm_compat_nosmm); - qtest_add_func("acpi/q35/nohpet", test_acpi_q35_tcg_nohpet); - qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); - qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); + if (qtest_has_machine(MACHINE_Q35)) { + qtest_add_func("acpi/q35", test_acpi_q35_tcg); + qtest_add_func("acpi/q35/oem-fields", test_acpi_q35_oem_fields); + if (tpm_model_is_available("-machine q35", "tpm-tis")) { + qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis); + qtest_add_func("acpi/q35/tpm12-tis", + test_acpi_q35_tcg_tpm12_tis); + } + qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge); + qtest_add_func("acpi/q35/multif-bridge", + test_acpi_q35_multif_bridge); + qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64); + qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi); + qtest_add_func("acpi/q35/smbus/ipmi", test_acpi_q35_tcg_smbus_ipmi); + qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp); + qtest_add_func("acpi/q35/memhp", test_acpi_q35_tcg_memhp); + qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem); + qtest_add_func("acpi/q35/nosmm", test_acpi_q35_tcg_nosmm); + qtest_add_func("acpi/q35/smm-compat", + test_acpi_q35_tcg_smm_compat); + qtest_add_func("acpi/q35/smm-compat-nosmm", + test_acpi_q35_tcg_smm_compat_nosmm); + qtest_add_func("acpi/q35/nohpet", test_acpi_q35_tcg_nohpet); + qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); + qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat); #ifdef CONFIG_POSIX - qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst); + qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst); #endif - qtest_add_func("acpi/q35/applesmc", test_acpi_q35_applesmc); - qtest_add_func("acpi/q35/pvpanic-isa", test_acpi_q35_pvpanic_isa); - if (has_tcg) { - qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs); + qtest_add_func("acpi/q35/applesmc", test_acpi_q35_applesmc); + qtest_add_func("acpi/q35/pvpanic-isa", test_acpi_q35_pvpanic_isa); + if (has_tcg) { + qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs); + } + 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/viot", test_acpi_q35_viot); +#ifdef CONFIG_POSIX + qtest_add_func("acpi/q35/cxl", test_acpi_q35_cxl); +#endif + qtest_add_func("acpi/q35/slic", test_acpi_q35_slic); } - 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/viot", test_acpi_q35_viot); + if (qtest_has_machine("microvm")) { + qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); + qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); + qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); + qtest_add_func("acpi/microvm/ioapic2", + test_acpi_microvm_ioapic2_tcg); + qtest_add_func("acpi/microvm/oem-fields", + test_acpi_microvm_oem_fields); + if (has_tcg) { + if (strcmp(arch, "x86_64") == 0) { + qtest_add_func("acpi/microvm/pcie", + test_acpi_microvm_pcie_tcg); #ifdef CONFIG_POSIX - qtest_add_func("acpi/q35/cxl", test_acpi_q35_cxl); -#endif - qtest_add_func("acpi/q35/slic", test_acpi_q35_slic); - - qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); - qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); - qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); - qtest_add_func("acpi/microvm/ioapic2", test_acpi_microvm_ioapic2_tcg); - qtest_add_func("acpi/microvm/oem-fields", test_acpi_microvm_oem_fields); - if (has_tcg) { - if (strcmp(arch, "x86_64") == 0) { - qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg); -#ifdef CONFIG_POSIX - qtest_add_func("acpi/microvm/acpierst", test_acpi_microvm_acpi_erst); + qtest_add_func("acpi/microvm/acpierst", + test_acpi_microvm_acpi_erst); #endif + } } } } else if (strcmp(arch, "aarch64") == 0) { From 08ed0988d6d589a9cb4d092765bd8f2272d1e8e9 Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 2 Sep 2022 19:34:48 +0200 Subject: [PATCH 0496/1020] tests: Only run intel-hda-tests if machine type is compiled in Signed-off-by: Juan Quintela Message-Id: <20220902173452.1904-5-quintela@redhat.com> Reviewed-by: Ani Sinha Signed-off-by: Thomas Huth --- tests/qtest/intel-hda-test.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tests/qtest/intel-hda-test.c b/tests/qtest/intel-hda-test.c index a58c98e4d1..d4a8db6fd6 100644 --- a/tests/qtest/intel-hda-test.c +++ b/tests/qtest/intel-hda-test.c @@ -18,7 +18,7 @@ /* Tests only initialization so far. TODO: Replace with functional tests */ static void ich6_test(void) { - qtest_start("-device intel-hda,id=" HDA_ID CODEC_DEVICES); + qtest_start("-machine pc -device intel-hda,id=" HDA_ID CODEC_DEVICES); qtest_end(); } @@ -65,9 +65,12 @@ static void test_issue542_ich6(void) int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); - qtest_add_func("/intel-hda/ich6", ich6_test); - qtest_add_func("/intel-hda/ich9", ich9_test); - qtest_add_func("/intel-hda/fuzz/issue542", test_issue542_ich6); - + if (qtest_has_machine("pc")) { + qtest_add_func("/intel-hda/ich6", ich6_test); + } + if (qtest_has_machine("q35")) { + qtest_add_func("/intel-hda/ich9", ich9_test); + qtest_add_func("/intel-hda/fuzz/issue542", test_issue542_ich6); + } return g_test_run(); } From 1dbea8185281f9c6c09a2fe8c333c6e26c5c741f Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Fri, 2 Sep 2022 19:34:49 +0200 Subject: [PATCH 0497/1020] tests: sb16 has both pc and q35 tests Check that the machines are compiled in before calling it Signed-off-by: Juan Quintela Message-Id: <20220902173452.1904-6-quintela@redhat.com> Signed-off-by: Thomas Huth --- tests/qtest/fuzz-sb16-test.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/qtest/fuzz-sb16-test.c b/tests/qtest/fuzz-sb16-test.c index a65826b943..add2a2ad39 100644 --- a/tests/qtest/fuzz-sb16-test.c +++ b/tests/qtest/fuzz-sb16-test.c @@ -57,9 +57,13 @@ int main(int argc, char **argv) { g_test_init(&argc, &argv, NULL); - qtest_add_func("fuzz/test_fuzz_sb16/1c", test_fuzz_sb16_0x1c); - qtest_add_func("fuzz/test_fuzz_sb16/91", test_fuzz_sb16_0x91); - qtest_add_func("fuzz/test_fuzz_sb16/d4", test_fuzz_sb16_0xd4); + if (qtest_has_machine("q35")) { + qtest_add_func("fuzz/test_fuzz_sb16/1c", test_fuzz_sb16_0x1c); + } + if (qtest_has_machine("pc")) { + qtest_add_func("fuzz/test_fuzz_sb16/91", test_fuzz_sb16_0x91); + qtest_add_func("fuzz/test_fuzz_sb16/d4", test_fuzz_sb16_0xd4); + } return g_test_run(); } From 7eab180f903931a5fac16b253d115706f008eade Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Tue, 20 Sep 2022 11:27:10 +0200 Subject: [PATCH 0498/1020] gitlab-ci: Update the FreeBSD 13 job from 13.0 to 13.1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The FreeBSD 13 job in our CI started failing since the python port stopped working after 13.1 has been released. Thus update our CI job to FreeBSD 13.1 to get it working again. Suggested-by: Daniel P. BerrangĂ© Message-Id: <20220920102041.45067-1-thuth@redhat.com> Reviewed-by: Daniel P. BerrangĂ© Signed-off-by: Thomas Huth --- .gitlab-ci.d/cirrus.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.d/cirrus.yml b/.gitlab-ci.d/cirrus.yml index 609c364308..d70da61248 100644 --- a/.gitlab-ci.d/cirrus.yml +++ b/.gitlab-ci.d/cirrus.yml @@ -63,7 +63,7 @@ x64-freebsd-13-build: NAME: freebsd-13 CIRRUS_VM_INSTANCE_TYPE: freebsd_instance CIRRUS_VM_IMAGE_SELECTOR: image_family - CIRRUS_VM_IMAGE_NAME: freebsd-13-0 + CIRRUS_VM_IMAGE_NAME: freebsd-13-1 CIRRUS_VM_CPUS: 8 CIRRUS_VM_RAM: 8G UPDATE_COMMAND: pkg update From 582a098e6ca00dd42f317dad8affd13e5a20bc42 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 27 Jul 2022 11:21:33 +0200 Subject: [PATCH 0499/1020] qga: Replace 'blacklist' command line and config file options by 'block-rpcs' MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's use a more appropriate wording for this command line and config file option. The old ones are still accepted for compatibility reasons, but marked as deprecated now so that it could be removed in a future version of QEMU. This change is based on earlier patches from Philippe Mathieu-DaudĂ©, with the idea for the new option name suggested by BALATON Zoltan. And while we're at it, replace the "?" in the help text with "help" since that does not have the problem of conflicting with the wildcard character of the shells. Message-Id: <20220727092135.302915-2-thuth@redhat.com> Reviewed-by: Daniel P. BerrangĂ© Reviewed-by: Konstantin Kostiuk Signed-off-by: Thomas Huth --- docs/about/deprecated.rst | 19 +++++++++++++++++++ docs/interop/qemu-ga.rst | 8 ++++---- qga/main.c | 18 +++++++++++++----- tests/data/test-qga-config | 2 +- tests/unit/test-qga.c | 2 +- 5 files changed, 38 insertions(+), 11 deletions(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index c75a25daad..8c914dfe0f 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -370,3 +370,22 @@ be deleted from this tree. New deployments should use the Rust version, and existing systems should consider moving to it. The command line and feature set is very close and moving should be simple. + + +QEMU guest agent +---------------- + +``--blacklist`` command line option (since 7.2) +''''''''''''''''''''''''''''''''''''''''''''''' + +``--blacklist`` has been replaced by ``--block-rpcs`` (which is a better +wording for what this option does). The short form ``-b`` still stays +the same and thus is the preferred way for scripts that should run with +both, older and future versions of QEMU. + +``blacklist`` config file option (since 7.2) +'''''''''''''''''''''''''''''''''''''''''''' + +The ``blacklist`` config file option has been renamed to ``block-rpcs`` +(to be in sync with the renaming of the corresponding command line +option). diff --git a/docs/interop/qemu-ga.rst b/docs/interop/qemu-ga.rst index 3063357bb5..a9183802d1 100644 --- a/docs/interop/qemu-ga.rst +++ b/docs/interop/qemu-ga.rst @@ -79,10 +79,10 @@ Options Daemonize after startup (detach from terminal). -.. option:: -b, --blacklist=LIST +.. option:: -b, --block-rpcs=LIST - Comma-separated list of RPCs to disable (no spaces, ``?`` to list - available RPCs). + Comma-separated list of RPCs to disable (no spaces, use ``help`` to + list available RPCs). .. option:: -D, --dump-conf @@ -125,7 +125,7 @@ pidfile string fsfreeze-hook string statedir string verbose boolean -blacklist string list +block-rpcs string list ============= =========== See also diff --git a/qga/main.c b/qga/main.c index 5f1efa2333..74e5c9b10c 100644 --- a/qga/main.c +++ b/qga/main.c @@ -260,8 +260,8 @@ QEMU_COPYRIGHT "\n" #ifdef _WIN32 " -s, --service service commands: install, uninstall, vss-install, vss-uninstall\n" #endif -" -b, --blacklist comma-separated list of RPCs to disable (no spaces, \"?\"\n" -" to list available RPCs)\n" +" -b, --block-rpcs comma-separated list of RPCs to disable (no spaces,\n" +" use \"help\" to list available RPCs)\n" " -D, --dump-conf dump a qemu-ga config file based on current config\n" " options / command-line parameters to stdout\n" " -r, --retry-path attempt re-opening path if it's unavailable or closed\n" @@ -963,6 +963,7 @@ static void config_load(GAConfig *config) GError *gerr = NULL; GKeyFile *keyfile; g_autofree char *conf = g_strdup(g_getenv("QGA_CONF")) ?: get_relocated_path(QGA_CONF_DEFAULT); + const gchar *blockrpcs_key = "block-rpcs"; /* read system config */ keyfile = g_key_file_new(); @@ -1009,9 +1010,15 @@ static void config_load(GAConfig *config) config->retry_path = g_key_file_get_boolean(keyfile, "general", "retry-path", &gerr); } + if (g_key_file_has_key(keyfile, "general", "blacklist", NULL)) { + g_warning("config using deprecated 'blacklist' key, should be replaced" + " with the 'block-rpcs' key."); + blockrpcs_key = "blacklist"; + } + if (g_key_file_has_key(keyfile, "general", blockrpcs_key, NULL)) { config->bliststr = - g_key_file_get_string(keyfile, "general", "blacklist", &gerr); + g_key_file_get_string(keyfile, "general", blockrpcs_key, &gerr); config->blacklist = g_list_concat(config->blacklist, split_list(config->bliststr, ",")); } @@ -1073,7 +1080,7 @@ static void config_dump(GAConfig *config) g_key_file_set_boolean(keyfile, "general", "retry-path", config->retry_path); tmp = list_join(config->blacklist, ','); - g_key_file_set_string(keyfile, "general", "blacklist", tmp); + g_key_file_set_string(keyfile, "general", "block-rpcs", tmp); g_free(tmp); tmp = g_key_file_to_data(keyfile, NULL, &error); @@ -1105,7 +1112,8 @@ static void config_parse(GAConfig *config, int argc, char **argv) { "method", 1, NULL, 'm' }, { "path", 1, NULL, 'p' }, { "daemonize", 0, NULL, 'd' }, - { "blacklist", 1, NULL, 'b' }, + { "block-rpcs", 1, NULL, 'b' }, + { "blacklist", 1, NULL, 'b' }, /* deprecated alias for 'block-rpcs' */ #ifdef _WIN32 { "service", 1, NULL, 's' }, #endif diff --git a/tests/data/test-qga-config b/tests/data/test-qga-config index 4bb721a4a1..b6b7bc9dfd 100644 --- a/tests/data/test-qga-config +++ b/tests/data/test-qga-config @@ -5,4 +5,4 @@ path=/path/to/org.qemu.guest_agent.0 pidfile=/var/foo/qemu-ga.pid statedir=/var/state verbose=true -blacklist=guest-ping;guest-get-time +block-rpcs=guest-ping;guest-get-time diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c index a05a4628ed..099d789092 100644 --- a/tests/unit/test-qga.c +++ b/tests/unit/test-qga.c @@ -729,7 +729,7 @@ static void test_qga_config(gconstpointer data) g_assert_true(g_key_file_get_boolean(kf, "general", "verbose", &error)); g_assert_no_error(error); - strv = g_key_file_get_string_list(kf, "general", "blacklist", &n, &error); + strv = g_key_file_get_string_list(kf, "general", "block-rpcs", &n, &error); g_assert_cmpint(n, ==, 2); g_assert_true(g_strv_contains((const char * const *)strv, "guest-ping")); From 0e4ef702e82baf1797ea02e40f39acabe46923aa Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 27 Jul 2022 11:21:34 +0200 Subject: [PATCH 0500/1020] qga: Replace 'blacklist' and 'whitelist' in the guest agent sources MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's use better, more inclusive wording here. Message-Id: <20220727092135.302915-3-thuth@redhat.com> Reviewed-by: Daniel P. BerrangĂ© Reviewed-by: Konstantin Kostiuk Signed-off-by: Thomas Huth --- qga/commands-posix.c | 16 ++++++------ qga/commands-win32.c | 10 +++---- qga/guest-agent-core.h | 2 +- qga/main.c | 59 +++++++++++++++++++++--------------------- qga/qapi-schema.json | 4 +-- 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 954efed01b..eea819cff0 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -3356,8 +3356,8 @@ qmp_guest_fstrim(bool has_minimum, int64_t minimum, Error **errp) } #endif -/* add unsupported commands to the blacklist */ -GList *ga_command_blacklist_init(GList *blacklist) +/* add unsupported commands to the list of blocked RPCs */ +GList *ga_command_init_blockedrpcs(GList *blockedrpcs) { #if !defined(__linux__) { @@ -3370,13 +3370,13 @@ GList *ga_command_blacklist_init(GList *blacklist) char **p = (char **)list; while (*p) { - blacklist = g_list_append(blacklist, g_strdup(*p++)); + blockedrpcs = g_list_append(blockedrpcs, g_strdup(*p++)); } } #endif #if !defined(HAVE_GETIFADDRS) - blacklist = g_list_append(blacklist, + blockedrpcs = g_list_append(blockedrpcs, g_strdup("guest-network-get-interfaces")); #endif @@ -3390,18 +3390,18 @@ GList *ga_command_blacklist_init(GList *blacklist) char **p = (char **)list; while (*p) { - blacklist = g_list_append(blacklist, g_strdup(*p++)); + blockedrpcs = g_list_append(blockedrpcs, g_strdup(*p++)); } } #endif #if !defined(CONFIG_FSTRIM) - blacklist = g_list_append(blacklist, g_strdup("guest-fstrim")); + blockedrpcs = g_list_append(blockedrpcs, g_strdup("guest-fstrim")); #endif - blacklist = g_list_append(blacklist, g_strdup("guest-get-devices")); + blockedrpcs = g_list_append(blockedrpcs, g_strdup("guest-get-devices")); - return blacklist; + return blockedrpcs; } /* register init/cleanup routines for stateful command groups */ diff --git a/qga/commands-win32.c b/qga/commands-win32.c index 7ed7664715..ec9f55b453 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -2005,8 +2005,8 @@ GuestMemoryBlockInfo *qmp_guest_get_memory_block_info(Error **errp) return NULL; } -/* add unsupported commands to the blacklist */ -GList *ga_command_blacklist_init(GList *blacklist) +/* add unsupported commands to the list of blocked RPCs */ +GList *ga_command_init_blockedrpcs(GList *blockedrpcs) { const char *list_unsupported[] = { "guest-suspend-hybrid", @@ -2017,7 +2017,7 @@ GList *ga_command_blacklist_init(GList *blacklist) char **p = (char **)list_unsupported; while (*p) { - blacklist = g_list_append(blacklist, g_strdup(*p++)); + blockedrpcs = g_list_append(blockedrpcs, g_strdup(*p++)); } if (!vss_init(true)) { @@ -2028,11 +2028,11 @@ GList *ga_command_blacklist_init(GList *blacklist) p = (char **)list; while (*p) { - blacklist = g_list_append(blacklist, g_strdup(*p++)); + blockedrpcs = g_list_append(blockedrpcs, g_strdup(*p++)); } } - return blacklist; + return blockedrpcs; } /* register init/cleanup routines for stateful command groups */ diff --git a/qga/guest-agent-core.h b/qga/guest-agent-core.h index 29cd50402f..b4e7c52c61 100644 --- a/qga/guest-agent-core.h +++ b/qga/guest-agent-core.h @@ -24,7 +24,7 @@ typedef struct GACommandState GACommandState; extern GAState *ga_state; extern QmpCommandList ga_commands; -GList *ga_command_blacklist_init(GList *blacklist); +GList *ga_command_init_blockedrpcs(GList *blockedrpcs); void ga_command_state_init(GAState *s, GACommandState *cs); void ga_command_state_add(GACommandState *cs, void (*init)(void), diff --git a/qga/main.c b/qga/main.c index 74e5c9b10c..5a9d8252e0 100644 --- a/qga/main.c +++ b/qga/main.c @@ -87,7 +87,7 @@ struct GAState { #endif bool delimit_response; bool frozen; - GList *blacklist; + GList *blockedrpcs; char *state_filepath_isfrozen; struct { const char *log_filepath; @@ -107,7 +107,7 @@ struct GAState *ga_state; QmpCommandList ga_commands; /* commands that are safe to issue while filesystems are frozen */ -static const char *ga_freeze_whitelist[] = { +static const char *ga_freeze_allowlist[] = { "guest-ping", "guest-info", "guest-sync", @@ -363,31 +363,31 @@ static gint ga_strcmp(gconstpointer str1, gconstpointer str2) } /* disable commands that aren't safe for fsfreeze */ -static void ga_disable_non_whitelisted(const QmpCommand *cmd, void *opaque) +static void ga_disable_not_allowed(const QmpCommand *cmd, void *opaque) { - bool whitelisted = false; + bool allowed = false; int i = 0; const char *name = qmp_command_name(cmd); - while (ga_freeze_whitelist[i] != NULL) { - if (strcmp(name, ga_freeze_whitelist[i]) == 0) { - whitelisted = true; + while (ga_freeze_allowlist[i] != NULL) { + if (strcmp(name, ga_freeze_allowlist[i]) == 0) { + allowed = true; } i++; } - if (!whitelisted) { + if (!allowed) { g_debug("disabling command: %s", name); qmp_disable_command(&ga_commands, name, "the agent is in frozen state"); } } -/* [re-]enable all commands, except those explicitly blacklisted by user */ -static void ga_enable_non_blacklisted(const QmpCommand *cmd, void *opaque) +/* [re-]enable all commands, except those explicitly blocked by user */ +static void ga_enable_non_blocked(const QmpCommand *cmd, void *opaque) { - GList *blacklist = opaque; + GList *blockedrpcs = opaque; const char *name = qmp_command_name(cmd); - if (g_list_find_custom(blacklist, name, ga_strcmp) == NULL && + if (g_list_find_custom(blockedrpcs, name, ga_strcmp) == NULL && !qmp_command_is_enabled(cmd)) { g_debug("enabling command: %s", name); qmp_enable_command(&ga_commands, name); @@ -426,8 +426,8 @@ void ga_set_frozen(GAState *s) if (ga_is_frozen(s)) { return; } - /* disable all non-whitelisted (for frozen state) commands */ - qmp_for_each_command(&ga_commands, ga_disable_non_whitelisted, NULL); + /* disable all forbidden (for frozen state) commands */ + qmp_for_each_command(&ga_commands, ga_disable_not_allowed, NULL); g_warning("disabling logging due to filesystem freeze"); ga_disable_logging(s); s->frozen = true; @@ -465,8 +465,8 @@ void ga_unset_frozen(GAState *s) s->deferred_options.pid_filepath = NULL; } - /* enable all disabled, non-blacklisted commands */ - qmp_for_each_command(&ga_commands, ga_enable_non_blacklisted, s->blacklist); + /* enable all disabled, non-blocked commands */ + qmp_for_each_command(&ga_commands, ga_enable_non_blocked, s->blockedrpcs); s->frozen = false; if (!ga_delete_file(s->state_filepath_isfrozen)) { g_warning("unable to delete %s, fsfreeze may not function properly", @@ -896,7 +896,8 @@ int64_t ga_get_fd_handle(GAState *s, Error **errp) int64_t handle; g_assert(s->pstate_filepath); - /* we blacklist commands and avoid operations that potentially require + /* + * We block commands and avoid operations that potentially require * writing to disk when we're in a frozen state. this includes opening * new files, so we should never get here in that situation */ @@ -950,8 +951,8 @@ struct GAConfig { #ifdef _WIN32 const char *service; #endif - gchar *bliststr; /* blacklist may point to this string */ - GList *blacklist; + gchar *bliststr; /* blockedrpcs may point to this string */ + GList *blockedrpcs; int daemonize; GLogLevelFlags log_level; int dumpconf; @@ -1019,7 +1020,7 @@ static void config_load(GAConfig *config) if (g_key_file_has_key(keyfile, "general", blockrpcs_key, NULL)) { config->bliststr = g_key_file_get_string(keyfile, "general", blockrpcs_key, &gerr); - config->blacklist = g_list_concat(config->blacklist, + config->blockedrpcs = g_list_concat(config->blockedrpcs, split_list(config->bliststr, ",")); } @@ -1079,7 +1080,7 @@ static void config_dump(GAConfig *config) config->log_level == G_LOG_LEVEL_MASK); g_key_file_set_boolean(keyfile, "general", "retry-path", config->retry_path); - tmp = list_join(config->blacklist, ','); + tmp = list_join(config->blockedrpcs, ','); g_key_file_set_string(keyfile, "general", "block-rpcs", tmp); g_free(tmp); @@ -1171,8 +1172,8 @@ static void config_parse(GAConfig *config, int argc, char **argv) qmp_for_each_command(&ga_commands, ga_print_cmd, NULL); exit(EXIT_SUCCESS); } - config->blacklist = g_list_concat(config->blacklist, - split_list(optarg, ",")); + config->blockedrpcs = g_list_concat(config->blockedrpcs, + split_list(optarg, ",")); break; } #ifdef _WIN32 @@ -1226,7 +1227,7 @@ static void config_free(GAConfig *config) #ifdef CONFIG_FSFREEZE g_free(config->fsfreeze_hook); #endif - g_list_free_full(config->blacklist, g_free); + g_list_free_full(config->blockedrpcs, g_free); g_free(config); } @@ -1310,7 +1311,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) s->deferred_options.log_filepath = config->log_filepath; } ga_disable_logging(s); - qmp_for_each_command(&ga_commands, ga_disable_non_whitelisted, NULL); + qmp_for_each_command(&ga_commands, ga_disable_not_allowed, NULL); } else { if (config->daemonize) { become_daemon(config->pid_filepath); @@ -1334,10 +1335,10 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) return NULL; } - config->blacklist = ga_command_blacklist_init(config->blacklist); - if (config->blacklist) { - GList *l = config->blacklist; - s->blacklist = config->blacklist; + config->blockedrpcs = ga_command_init_blockedrpcs(config->blockedrpcs); + if (config->blockedrpcs) { + GList *l = config->blockedrpcs; + s->blockedrpcs = config->blockedrpcs; do { g_debug("disabling command: %s", (char *)l->data); qmp_disable_command(&ga_commands, l->data, NULL); diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 869399ea1a..026a56f76c 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -16,8 +16,8 @@ { 'pragma': { 'doc-required': true } } -# Whitelists to permit QAPI rule violations; think twice before you -# add to them! +# Lists with items allowed to permit QAPI rule violations; think twice +# before you add to them! { 'pragma': { # Types whose member names may use '_' 'member-name-exceptions': [ From 903f84eb88c8d43fa2e46d4c30969de30dbb5297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Fri, 15 Jul 2022 17:54:37 -0300 Subject: [PATCH 0501/1020] target/ppc: Add HASHKEYR and HASHPKEYR SPRs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the Special Purpose Registers HASHKEYR and HASHPKEYR, which were introduced by the Power ISA 3.1B. They are used by the new instructions hashchk(p) and hashst(p). The ISA states that the Operating System should generate the value for these registers when creating a process, so it's its responsability to do so. We initialize it with 0 for qemu-softmmu, and set a random 64 bits value for linux-user. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Lucas Mateus Castro Message-Id: <20220715205439.161110-2-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu.h | 2 ++ target/ppc/cpu_init.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index a4c893cfad..4551d81b5f 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1676,6 +1676,8 @@ void ppc_compat_add_property(Object *obj, const char *name, #define SPR_BOOKE_GIVOR14 (0x1BD) #define SPR_TIR (0x1BE) #define SPR_PTCR (0x1D0) +#define SPR_HASHKEYR (0x1D4) +#define SPR_HASHPKEYR (0x1D5) #define SPR_BOOKE_SPEFSCR (0x200) #define SPR_Exxx_BBEAR (0x201) #define SPR_Exxx_BBTAR (0x202) diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 899c4a586e..6e080ebda0 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -5700,6 +5700,33 @@ static void register_power9_mmu_sprs(CPUPPCState *env) #endif } +static void register_power10_hash_sprs(CPUPPCState *env) +{ + /* + * it's the OS responsability to generate a random value for the registers + * in each process' context. So, initialize it with 0 here. + */ + uint64_t hashkeyr_initial_value = 0, hashpkeyr_initial_value = 0; +#if defined(CONFIG_USER_ONLY) + /* in linux-user, setup the hash register with a random value */ + GRand *rand = g_rand_new(); + hashkeyr_initial_value = + ((uint64_t)g_rand_int(rand) << 32) | (uint64_t)g_rand_int(rand); + hashpkeyr_initial_value = + ((uint64_t)g_rand_int(rand) << 32) | (uint64_t)g_rand_int(rand); + g_rand_free(rand); +#endif + spr_register(env, SPR_HASHKEYR, "HASHKEYR", + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + hashkeyr_initial_value); + spr_register_hv(env, SPR_HASHPKEYR, "HASHPKEYR", + SPR_NOACCESS, SPR_NOACCESS, + SPR_NOACCESS, SPR_NOACCESS, + &spr_read_generic, &spr_write_generic, + hashpkeyr_initial_value); +} + /* * Initialize PMU counter overflow timers for Power8 and * newer Power chips when using TCG. @@ -6518,6 +6545,7 @@ static void init_proc_POWER10(CPUPPCState *env) register_power8_book4_sprs(env); register_power8_rpr_sprs(env); register_power9_mmu_sprs(env); + register_power10_hash_sprs(env); /* FIXME: Filter fields properly based on privilege level */ spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL, From 670f1da374d9e9a7d509ef6f03d871144284f8d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Fri, 15 Jul 2022 17:54:38 -0300 Subject: [PATCH 0502/1020] target/ppc: Implement hashst and hashchk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementation for instructions hashst and hashchk, which were added in Power ISA 3.1B. It was decided to implement the hash algorithm from ground up in this patch exactly as described in Power ISA. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Lucas Mateus Castro Message-Id: <20220715205439.161110-3-victor.colombo@eldorado.org.br> [danielhb: fix block comment in excp_helper.c] Signed-off-by: Daniel Henrique Barboza --- target/ppc/excp_helper.c | 81 ++++++++++++++++++++++ target/ppc/helper.h | 2 + target/ppc/insn32.decode | 8 +++ target/ppc/translate.c | 5 ++ target/ppc/translate/fixedpoint-impl.c.inc | 32 +++++++++ 5 files changed, 128 insertions(+) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 7550aafed6..7a16991f3d 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2173,6 +2173,87 @@ void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2, #endif #endif +static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t lane) +{ + const uint16_t c = 0xfffc; + const uint64_t z0 = 0xfa2561cdf44ac398ULL; + uint16_t z = 0, temp; + uint16_t k[32], eff_k[32], xleft[33], xright[33], fxleft[32]; + + for (int i = 3; i >= 0; i--) { + k[i] = key & 0xffff; + key >>= 16; + } + xleft[0] = x & 0xffff; + xright[0] = (x >> 16) & 0xffff; + + for (int i = 0; i < 28; i++) { + z = (z0 >> (63 - i)) & 1; + temp = ror16(k[i + 3], 3) ^ k[i + 1]; + k[i + 4] = c ^ z ^ k[i] ^ temp ^ ror16(temp, 1); + } + + for (int i = 0; i < 8; i++) { + eff_k[4 * i + 0] = k[4 * i + ((0 + lane) % 4)]; + eff_k[4 * i + 1] = k[4 * i + ((1 + lane) % 4)]; + eff_k[4 * i + 2] = k[4 * i + ((2 + lane) % 4)]; + eff_k[4 * i + 3] = k[4 * i + ((3 + lane) % 4)]; + } + + for (int i = 0; i < 32; i++) { + fxleft[i] = (rol16(xleft[i], 1) & + rol16(xleft[i], 8)) ^ rol16(xleft[i], 2); + xleft[i + 1] = xright[i] ^ fxleft[i] ^ eff_k[i]; + xright[i + 1] = xleft[i]; + } + + return (((uint32_t)xright[32]) << 16) | xleft[32]; +} + +static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key) +{ + uint64_t stage0_h = 0ULL, stage0_l = 0ULL; + uint64_t stage1_h, stage1_l; + + for (int i = 0; i < 4; i++) { + stage0_h |= ror64(rb & 0xff, 8 * (2 * i + 1)); + stage0_h |= ((ra >> 32) & 0xff) << (8 * 2 * i); + stage0_l |= ror64((rb >> 32) & 0xff, 8 * (2 * i + 1)); + stage0_l |= (ra & 0xff) << (8 * 2 * i); + rb >>= 8; + ra >>= 8; + } + + stage1_h = (uint64_t)helper_SIMON_LIKE_32_64(stage0_h >> 32, key, 0) << 32; + stage1_h |= helper_SIMON_LIKE_32_64(stage0_h, key, 1); + stage1_l = (uint64_t)helper_SIMON_LIKE_32_64(stage0_l >> 32, key, 2) << 32; + stage1_l |= helper_SIMON_LIKE_32_64(stage0_l, key, 3); + + return stage1_h ^ stage1_l; +} + +#include "qemu/guest-random.h" + +#define HELPER_HASH(op, key, store) \ +void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \ + target_ulong rb) \ +{ \ + uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash; \ + \ + if (store) { \ + cpu_stq_data_ra(env, ea, calculated_hash, GETPC()); \ + } else { \ + loaded_hash = cpu_ldq_data_ra(env, ea, GETPC()); \ + if (loaded_hash != calculated_hash) { \ + raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, \ + POWERPC_EXCP_TRAP, GETPC()); \ + } \ + } \ +} + +HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true) +HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false) + #if !defined(CONFIG_USER_ONLY) #ifdef CONFIG_TCG diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 159b352f6e..5817af632b 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -4,6 +4,8 @@ DEF_HELPER_FLAGS_4(tw, TCG_CALL_NO_WG, void, env, tl, tl, i32) #if defined(TARGET_PPC64) DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32) #endif +DEF_HELPER_4(HASHST, void, env, tl, tl, tl) +DEF_HELPER_4(HASHCHK, void, env, tl, tl, tl) #if !defined(CONFIG_USER_ONLY) DEF_HELPER_2(store_msr, void, env, tl) DEF_HELPER_1(rfi, void, env) diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode index eb41efc100..544514565c 100644 --- a/target/ppc/insn32.decode +++ b/target/ppc/insn32.decode @@ -172,6 +172,9 @@ @X_TSX ...... ..... ra:5 rb:5 .......... . &X rt=%x_rt_tsx @X_TSXP ...... ..... ra:5 rb:5 .......... . &X rt=%rt_tsxp +%x_dw 0:1 21:5 !function=dw_compose_ea +@X_DW ...... ..... ra:5 rb:5 .......... . &X rt=%x_dw + &X_frtp_vrb frtp vrb @X_frtp_vrb ...... ....0 ..... vrb:5 .......... . &X_frtp_vrb frtp=%x_frtp @@ -323,6 +326,11 @@ CNTTZDM 011111 ..... ..... ..... 1000111011 - @X PDEPD 011111 ..... ..... ..... 0010011100 - @X PEXTD 011111 ..... ..... ..... 0010111100 - @X +# Fixed-Point Hash Instructions + +HASHST 011111 ..... ..... ..... 1011010010 . @X_DW +HASHCHK 011111 ..... ..... ..... 1011110010 . @X_DW + ## BCD Assist ADDG6S 011111 ..... ..... ..... - 001001010 - @X diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 000b1e518d..29939bd923 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6473,6 +6473,11 @@ static int times_16(DisasContext *ctx, int x) return x * 16; } +static int64_t dw_compose_ea(DisasContext *ctx, int x) +{ + return deposit64(0xfffffffffffffe00, 3, 6, x); +} + /* * Helpers for trans_* functions to check for specific insns flags. * Use token pasting to ensure that we use the proper flag with the diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc index db14d3bebc..41c06de8a2 100644 --- a/target/ppc/translate/fixedpoint-impl.c.inc +++ b/target/ppc/translate/fixedpoint-impl.c.inc @@ -540,3 +540,35 @@ static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a) gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]); return true; } + +static bool do_hash(DisasContext *ctx, arg_X *a, bool priv, + void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv)) +{ + TCGv ea; + + if (!(ctx->insns_flags2 & PPC2_ISA310)) { + /* if version is before v3.1, this operation is a nop */ + return true; + } + + if (priv) { + /* if instruction is privileged but the context is in user space */ + REQUIRE_SV(ctx); + } + + if (unlikely(a->ra == 0)) { + /* if RA=0, the instruction form is invalid */ + gen_invalid(ctx); + return true; + } + + ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt)); + helper(cpu_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]); + + tcg_temp_free(ea); + + return true; +} + +TRANS(HASHST, do_hash, false, gen_helper_HASHST) +TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK) From 53ae2aeb940729d7f6f42ce734dc65d5332260c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Fri, 15 Jul 2022 17:54:39 -0300 Subject: [PATCH 0503/1020] target/ppc: Implement hashstp and hashchkp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implementation for instructions hashstp and hashchkp, the privileged versions of hashst and hashchk, which were added in Power ISA 3.1B. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Lucas Mateus Castro Message-Id: <20220715205439.161110-4-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/excp_helper.c | 2 ++ target/ppc/helper.h | 2 ++ target/ppc/insn32.decode | 2 ++ target/ppc/translate/fixedpoint-impl.c.inc | 2 ++ 4 files changed, 8 insertions(+) diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c index 7a16991f3d..214acf5ac4 100644 --- a/target/ppc/excp_helper.c +++ b/target/ppc/excp_helper.c @@ -2253,6 +2253,8 @@ void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \ HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true) HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false) +HELPER_HASH(HASHSTP, env->spr[SPR_HASHPKEYR], true) +HELPER_HASH(HASHCHKP, env->spr[SPR_HASHPKEYR], false) #if !defined(CONFIG_USER_ONLY) diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 5817af632b..122b2e9359 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -6,6 +6,8 @@ DEF_HELPER_FLAGS_4(td, TCG_CALL_NO_WG, void, env, tl, tl, i32) #endif DEF_HELPER_4(HASHST, void, env, tl, tl, tl) DEF_HELPER_4(HASHCHK, void, env, tl, tl, tl) +DEF_HELPER_4(HASHSTP, void, env, tl, tl, tl) +DEF_HELPER_4(HASHCHKP, void, env, tl, tl, tl) #if !defined(CONFIG_USER_ONLY) DEF_HELPER_2(store_msr, void, env, tl) DEF_HELPER_1(rfi, void, env) diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode index 544514565c..da08960fca 100644 --- a/target/ppc/insn32.decode +++ b/target/ppc/insn32.decode @@ -330,6 +330,8 @@ PEXTD 011111 ..... ..... ..... 0010111100 - @X HASHST 011111 ..... ..... ..... 1011010010 . @X_DW HASHCHK 011111 ..... ..... ..... 1011110010 . @X_DW +HASHSTP 011111 ..... ..... ..... 1010010010 . @X_DW +HASHCHKP 011111 ..... ..... ..... 1010110010 . @X_DW ## BCD Assist diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc index 41c06de8a2..1ba56cbed5 100644 --- a/target/ppc/translate/fixedpoint-impl.c.inc +++ b/target/ppc/translate/fixedpoint-impl.c.inc @@ -572,3 +572,5 @@ static bool do_hash(DisasContext *ctx, arg_X *a, bool priv, TRANS(HASHST, do_hash, false, gen_helper_HASHST) TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK) +TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP) +TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP) From 6a8654d6c215f410cfd5c7dd853e6cf311156b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Mon, 5 Sep 2022 09:37:44 -0300 Subject: [PATCH 0504/1020] target/ppc: Move fsqrt to decodetree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: VĂ­ctor Colombo Reviewed-by: Richard Henderson Message-Id: <20220905123746.54659-2-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/insn32.decode | 7 +++++++ target/ppc/translate/fp-impl.c.inc | 29 +++++++++++++++++------------ target/ppc/translate/fp-ops.c.inc | 1 - 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode index da08960fca..33aa27bd4f 100644 --- a/target/ppc/insn32.decode +++ b/target/ppc/insn32.decode @@ -20,6 +20,9 @@ &A frt fra frb frc rc:bool @A ...... frt:5 fra:5 frb:5 frc:5 ..... rc:1 &A +&A_tb frt frb rc:bool +@A_tb ...... frt:5 ..... frb:5 ..... ..... rc:1 &A_tb + &D rt ra si:int64_t @D ...... rt:5 ra:5 si:s16 &D @@ -363,6 +366,10 @@ STFDU 110111 ..... ...... ............... @D STFDX 011111 ..... ...... .... 1011010111 - @X STFDUX 011111 ..... ...... .... 1011110111 - @X +### Floating-Point Arithmetic Instructions + +FSQRT 111111 ..... ----- ..... ----- 10110 . @A_tb + ### Floating-Point Select Instruction FSEL 111111 ..... ..... ..... ..... 10111 . @A diff --git a/target/ppc/translate/fp-impl.c.inc b/target/ppc/translate/fp-impl.c.inc index 0e893eafa7..e8359af005 100644 --- a/target/ppc/translate/fp-impl.c.inc +++ b/target/ppc/translate/fp-impl.c.inc @@ -254,29 +254,34 @@ static bool trans_FSEL(DisasContext *ctx, arg_A *a) GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT); /* Optional: */ -/* fsqrt */ -static void gen_fsqrt(DisasContext *ctx) +static bool do_helper_fsqrt(DisasContext *ctx, arg_A_tb *a, + void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64)) { - TCGv_i64 t0; - TCGv_i64 t1; - if (unlikely(!ctx->fpu_enabled)) { - gen_exception(ctx, POWERPC_EXCP_FPU); - return; - } + TCGv_i64 t0, t1; + + REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSQRT); + REQUIRE_FPU(ctx); + t0 = tcg_temp_new_i64(); t1 = tcg_temp_new_i64(); + gen_reset_fpstatus(); - get_fpr(t0, rB(ctx->opcode)); - gen_helper_fsqrt(t1, cpu_env, t0); - set_fpr(rD(ctx->opcode), t1); + get_fpr(t0, a->frb); + helper(t1, cpu_env, t0); + set_fpr(a->frt, t1); gen_compute_fprf_float64(t1); - if (unlikely(Rc(ctx->opcode) != 0)) { + if (unlikely(a->rc != 0)) { gen_set_cr1_from_fpscr(ctx); } + tcg_temp_free_i64(t0); tcg_temp_free_i64(t1); + + return true; } +TRANS(FSQRT, do_helper_fsqrt, gen_helper_fsqrt); + static void gen_fsqrts(DisasContext *ctx) { TCGv_i64 t0; diff --git a/target/ppc/translate/fp-ops.c.inc b/target/ppc/translate/fp-ops.c.inc index 1b65f5ab73..38759f5939 100644 --- a/target/ppc/translate/fp-ops.c.inc +++ b/target/ppc/translate/fp-ops.c.inc @@ -62,7 +62,6 @@ GEN_HANDLER_E(stfdepx, 0x1F, 0x1F, 0x16, 0x00000001, PPC_NONE, PPC2_BOOKE206), GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205), GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES), -GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT), GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT), GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT), GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT), From 4896c15bc36591436f02c3bfc4c828099be2b1f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Mon, 5 Sep 2022 09:37:45 -0300 Subject: [PATCH 0505/1020] target/ppc: Move fsqrts to decodetree MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: VĂ­ctor Colombo Reviewed-by: Richard Henderson Message-Id: <20220905123746.54659-3-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/insn32.decode | 1 + target/ppc/translate/fp-impl.c.inc | 23 +---------------------- target/ppc/translate/fp-ops.c.inc | 1 - 3 files changed, 2 insertions(+), 23 deletions(-) diff --git a/target/ppc/insn32.decode b/target/ppc/insn32.decode index 33aa27bd4f..a5249ee32c 100644 --- a/target/ppc/insn32.decode +++ b/target/ppc/insn32.decode @@ -369,6 +369,7 @@ STFDUX 011111 ..... ...... .... 1011110111 - @X ### Floating-Point Arithmetic Instructions FSQRT 111111 ..... ----- ..... ----- 10110 . @A_tb +FSQRTS 111011 ..... ----- ..... ----- 10110 . @A_tb ### Floating-Point Select Instruction diff --git a/target/ppc/translate/fp-impl.c.inc b/target/ppc/translate/fp-impl.c.inc index e8359af005..7a90c0e350 100644 --- a/target/ppc/translate/fp-impl.c.inc +++ b/target/ppc/translate/fp-impl.c.inc @@ -281,28 +281,7 @@ static bool do_helper_fsqrt(DisasContext *ctx, arg_A_tb *a, } TRANS(FSQRT, do_helper_fsqrt, gen_helper_fsqrt); - -static void gen_fsqrts(DisasContext *ctx) -{ - TCGv_i64 t0; - TCGv_i64 t1; - if (unlikely(!ctx->fpu_enabled)) { - gen_exception(ctx, POWERPC_EXCP_FPU); - return; - } - t0 = tcg_temp_new_i64(); - t1 = tcg_temp_new_i64(); - gen_reset_fpstatus(); - get_fpr(t0, rB(ctx->opcode)); - gen_helper_fsqrts(t1, cpu_env, t0); - set_fpr(rD(ctx->opcode), t1); - gen_compute_fprf_float64(t1); - if (unlikely(Rc(ctx->opcode) != 0)) { - gen_set_cr1_from_fpscr(ctx); - } - tcg_temp_free_i64(t0); - tcg_temp_free_i64(t1); -} +TRANS(FSQRTS, do_helper_fsqrt, gen_helper_fsqrts); /*** Floating-Point multiply-and-add ***/ /* fmadd - fmadds */ diff --git a/target/ppc/translate/fp-ops.c.inc b/target/ppc/translate/fp-ops.c.inc index 38759f5939..d4c6c4bed1 100644 --- a/target/ppc/translate/fp-ops.c.inc +++ b/target/ppc/translate/fp-ops.c.inc @@ -62,7 +62,6 @@ GEN_HANDLER_E(stfdepx, 0x1F, 0x1F, 0x16, 0x00000001, PPC_NONE, PPC2_BOOKE206), GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205), GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES), -GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT), GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT), GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT), GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT), From 74177ec661cc3d8553cc645632a9b6fdfe1b85e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Mon, 5 Sep 2022 09:37:46 -0300 Subject: [PATCH 0506/1020] target/ppc: Merge fsqrt and fsqrts helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These two helpers are almost identical, differing only by the softfloat operation it calls. Merge them into one using a macro. Also, take this opportunity to capitalize the helper name as we moved the instruction to decodetree in a previous patch. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Richard Henderson Message-Id: <20220905123746.54659-4-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/fpu_helper.c | 35 +++++++++++------------------- target/ppc/helper.h | 4 ++-- target/ppc/translate/fp-impl.c.inc | 4 ++-- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 0f045b70f8..32995179b5 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -830,30 +830,21 @@ static void float_invalid_op_sqrt(CPUPPCState *env, int flags, } } -/* fsqrt - fsqrt. */ -float64 helper_fsqrt(CPUPPCState *env, float64 arg) -{ - float64 ret = float64_sqrt(arg, &env->fp_status); - int flags = get_float_exception_flags(&env->fp_status); - - if (unlikely(flags & float_flag_invalid)) { - float_invalid_op_sqrt(env, flags, 1, GETPC()); - } - - return ret; +#define FPU_FSQRT(name, op) \ +float64 helper_##name(CPUPPCState *env, float64 arg) \ +{ \ + float64 ret = op(arg, &env->fp_status); \ + int flags = get_float_exception_flags(&env->fp_status); \ + \ + if (unlikely(flags & float_flag_invalid)) { \ + float_invalid_op_sqrt(env, flags, 1, GETPC()); \ + } \ + \ + return ret; \ } -/* fsqrts - fsqrts. */ -float64 helper_fsqrts(CPUPPCState *env, float64 arg) -{ - float64 ret = float64r32_sqrt(arg, &env->fp_status); - int flags = get_float_exception_flags(&env->fp_status); - - if (unlikely(flags & float_flag_invalid)) { - float_invalid_op_sqrt(env, flags, 1, GETPC()); - } - return ret; -} +FPU_FSQRT(FSQRT, float64_sqrt) +FPU_FSQRT(FSQRTS, float64r32_sqrt) /* fre - fre. */ float64 helper_fre(CPUPPCState *env, float64 arg) diff --git a/target/ppc/helper.h b/target/ppc/helper.h index 122b2e9359..57eee07256 100644 --- a/target/ppc/helper.h +++ b/target/ppc/helper.h @@ -120,8 +120,8 @@ DEF_HELPER_4(fmadds, i64, env, i64, i64, i64) DEF_HELPER_4(fmsubs, i64, env, i64, i64, i64) DEF_HELPER_4(fnmadds, i64, env, i64, i64, i64) DEF_HELPER_4(fnmsubs, i64, env, i64, i64, i64) -DEF_HELPER_2(fsqrt, f64, env, f64) -DEF_HELPER_2(fsqrts, f64, env, f64) +DEF_HELPER_2(FSQRT, f64, env, f64) +DEF_HELPER_2(FSQRTS, f64, env, f64) DEF_HELPER_2(fre, i64, env, i64) DEF_HELPER_2(fres, i64, env, i64) DEF_HELPER_2(frsqrte, i64, env, i64) diff --git a/target/ppc/translate/fp-impl.c.inc b/target/ppc/translate/fp-impl.c.inc index 7a90c0e350..8d5cf0f982 100644 --- a/target/ppc/translate/fp-impl.c.inc +++ b/target/ppc/translate/fp-impl.c.inc @@ -280,8 +280,8 @@ static bool do_helper_fsqrt(DisasContext *ctx, arg_A_tb *a, return true; } -TRANS(FSQRT, do_helper_fsqrt, gen_helper_fsqrt); -TRANS(FSQRTS, do_helper_fsqrt, gen_helper_fsqrts); +TRANS(FSQRT, do_helper_fsqrt, gen_helper_FSQRT); +TRANS(FSQRTS, do_helper_fsqrt, gen_helper_FSQRTS); /*** Floating-Point multiply-and-add ***/ /* fmadd - fmadds */ From 676696f428202b8f2dcd34ec8ff84baa38a14e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Tue, 6 Sep 2022 09:55:16 -0300 Subject: [PATCH 0507/1020] target/ppc: Remove extra space from s128 field in ppc_vsr_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Very trivial rogue space removal. There are two spaces between Int128 and s128 in ppc_vsr_t struct, where it should be only one. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220906125523.38765-2-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 4551d81b5f..602ea77914 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -246,7 +246,7 @@ typedef union _ppc_vsr_t { #ifdef CONFIG_INT128 __uint128_t u128; #endif - Int128 s128; + Int128 s128; } ppc_vsr_t; typedef ppc_vsr_t ppc_avr_t; From 228ab1451d2b4a731d00d4ff42c6e367afbbabdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Tue, 6 Sep 2022 09:55:17 -0300 Subject: [PATCH 0508/1020] target/ppc: Remove unused xer_* macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The macros xer_ov, xer_ca, xer_ov32, and xer_ca32 are both unused and hiding the usage of env. Remove them. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220906125523.38765-3-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/cpu.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 602ea77914..7f73e2ac81 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1506,10 +1506,6 @@ void ppc_compat_add_property(Object *obj, const char *name, #define XER_CMP 8 #define XER_BC 0 #define xer_so (env->so) -#define xer_ov (env->ov) -#define xer_ca (env->ca) -#define xer_ov32 (env->ov) -#define xer_ca32 (env->ca) #define xer_cmp ((env->xer >> XER_CMP) & 0xFF) #define xer_bc ((env->xer >> XER_BC) & 0x7F) From 34f760bac2c9a32afae150fbcc56ceba399d61de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Tue, 6 Sep 2022 09:55:18 -0300 Subject: [PATCH 0509/1020] target/ppc: Zero second doubleword in DFP instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Starting at PowerISA v3.1, the second doubleword of the registers used to store results in DFP instructions are supposed to be zeroed. From the ISA, chapter 7.2.1.1 Floating-Point Registers: """ Chapter 4. Floating-Point Facility provides 32 64-bit FPRs. Chapter 5. Decimal Floating-Point also employs FPRs in decimal floating-point (DFP) operations. When VSX is implemented, the 32 FPRs are mapped to doubleword 0 of VSRs 0-31. (...) All instructions that operate on an FPR are redefined to operate on doubleword element 0 of the corresponding VSR. (...) and the contents of doubleword element 1 of the VSR corresponding to the target FPR or FPR pair for these instructions are set to 0. """ Before, the result stored at doubleword 1 was said to be undefined. With that, this patch changes the DFP facility to zero doubleword 1 when using set_dfp64 and set_dfp128. This fixes the behavior for ISA 3.1 while keeping the behavior correct for previous ones. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220906125523.38765-4-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/dfp_helper.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c index 5ba74b2124..be7aa5357a 100644 --- a/target/ppc/dfp_helper.c +++ b/target/ppc/dfp_helper.c @@ -42,13 +42,16 @@ static void get_dfp128(ppc_vsr_t *dst, ppc_fprp_t *dfp) static void set_dfp64(ppc_fprp_t *dfp, ppc_vsr_t *src) { - dfp->VsrD(0) = src->VsrD(1); + dfp[0].VsrD(0) = src->VsrD(1); + dfp[0].VsrD(1) = 0ULL; } static void set_dfp128(ppc_fprp_t *dfp, ppc_vsr_t *src) { dfp[0].VsrD(0) = src->VsrD(0); dfp[1].VsrD(0) = src->VsrD(1); + dfp[0].VsrD(1) = 0ULL; + dfp[1].VsrD(1) = 0ULL; } static void set_dfp128_to_avr(ppc_avr_t *dst, ppc_vsr_t *src) From 3ecec4c0429f65de1822b881ea732689cf647254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Tue, 6 Sep 2022 09:55:19 -0300 Subject: [PATCH 0510/1020] target/ppc: Set result to QNaN for DENBCD when VXCVI occurs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to the ISA, for instruction DENBCD: "If an invalid BCD digit or sign code is detected in the source operand, an invalid-operation exception (VXCVI) occurs." In the Invalid Operation Exception section, there is the situation: "When Invalid Operation Exception is disabled (VE=0) and Invalid Operation occurs (...) If the operation is an (...) or format the target FPR is set to a Quiet NaN". This was not being done in QEMU. This patch sets the result to QNaN when the instruction DENBCD causes an Invalid Operation Exception. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220906125523.38765-5-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/dfp_helper.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c index be7aa5357a..cc024316d5 100644 --- a/target/ppc/dfp_helper.c +++ b/target/ppc/dfp_helper.c @@ -1147,6 +1147,26 @@ static inline uint8_t dfp_get_bcd_digit_128(ppc_vsr_t *t, unsigned n) return t->VsrD((n & 0x10) ? 0 : 1) >> ((n << 2) & 63) & 15; } +static inline void dfp_invalid_op_vxcvi_64(struct PPC_DFP *dfp) +{ + /* TODO: fpscr is incorrectly not being saved to env */ + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE); + if ((dfp->env->fpscr & FP_VE) == 0) { + dfp->vt.VsrD(1) = 0x7c00000000000000; /* QNaN */ + } +} + + +static inline void dfp_invalid_op_vxcvi_128(struct PPC_DFP *dfp) +{ + /* TODO: fpscr is incorrectly not being saved to env */ + dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE); + if ((dfp->env->fpscr & FP_VE) == 0) { + dfp->vt.VsrD(0) = 0x7c00000000000000; /* QNaN */ + dfp->vt.VsrD(1) = 0x0; + } +} + #define DFP_HELPER_ENBCD(op, size) \ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \ uint32_t s) \ @@ -1173,7 +1193,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \ sgn = 0; \ break; \ default: \ - dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \ + dfp_invalid_op_vxcvi_##size(&dfp); \ + set_dfp##size(t, &dfp.vt); \ return; \ } \ } \ @@ -1183,7 +1204,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \ digits[(size) / 4 - n] = dfp_get_bcd_digit_##size(&dfp.vb, \ offset++); \ if (digits[(size) / 4 - n] > 10) { \ - dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \ + dfp_invalid_op_vxcvi_##size(&dfp); \ + set_dfp##size(t, &dfp.vt); \ return; \ } else { \ nonzero |= (digits[(size) / 4 - n] > 0); \ From 9f097daa5483cdb7d745740606232c931d32b796 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Tue, 6 Sep 2022 09:55:20 -0300 Subject: [PATCH 0511/1020] target/ppc: Zero second doubleword for VSX madd instructions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In 205eb5a89e we updated most VSX instructions to zero the second doubleword, as is requested by PowerISA since v3.1. However, VSX_MADD helper was left behind unchanged, while it is also affected and should be fixed as well. This patch applies the fix for MADD instructions. Fixes: 205eb5a89e ("target/ppc: Change VSX instructions behavior to fill with zeros") Signed-off-by: VĂ­ctor Colombo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220906125523.38765-6-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/fpu_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index 32995179b5..f07330ffc1 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -2167,7 +2167,7 @@ VSX_TSQRT(xvtsqrtsp, 4, float32, VsrW(i), -126, 23) void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \ ppc_vsr_t *s1, ppc_vsr_t *s2, ppc_vsr_t *s3) \ { \ - ppc_vsr_t t = *xt; \ + ppc_vsr_t t = { }; \ int i; \ \ helper_reset_fpstatus(env); \ From af721a31696a1e08d8dcdabcd14c4cb09f9a5e16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Tue, 6 Sep 2022 09:55:21 -0300 Subject: [PATCH 0512/1020] target/ppc: Set OV32 when OV is set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to PowerISA: "OV32 is set whenever OV is implicitly set, and is set to the same value that OV is defined to be set to in 32-bit mode". This patch changes helper_update_ov_legacy to set/clear ov32 when applicable. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220906125523.38765-7-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/int_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index d905f07d02..696096100b 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -37,9 +37,9 @@ static inline void helper_update_ov_legacy(CPUPPCState *env, int ov) { if (unlikely(ov)) { - env->so = env->ov = 1; + env->so = env->ov = env->ov32 = 1; } else { - env->ov = 0; + env->ov = env->ov32 = 0; } } From 4b65b6e76977895fe43eb340c54b552fd16fe1ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Tue, 6 Sep 2022 09:55:22 -0300 Subject: [PATCH 0513/1020] target/ppc: Zero second doubleword of VSR registers for FPR insns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FPR register are mapped to the first doubleword of the VSR registers. Since PowerISA v3.1, the second doubleword of the target register must be zeroed for FP instructions. This patch does it by writting 0 to the second dw everytime the first dw is being written using set_fpr. Signed-off-by: VĂ­ctor Colombo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220906125523.38765-8-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/translate.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/target/ppc/translate.c b/target/ppc/translate.c index 29939bd923..e810842925 100644 --- a/target/ppc/translate.c +++ b/target/ppc/translate.c @@ -6443,6 +6443,14 @@ static inline void get_fpr(TCGv_i64 dst, int regno) static inline void set_fpr(int regno, TCGv_i64 src) { tcg_gen_st_i64(src, cpu_env, fpr_offset(regno)); + /* + * Before PowerISA v3.1 the result of doubleword 1 of the VSR + * corresponding to the target FPR was undefined. However, + * most (if not all) real hardware were setting the result to 0. + * Starting at ISA v3.1, the result for doubleword 1 is now defined + * to be 0. + */ + tcg_gen_st_i64(tcg_constant_i64(0), cpu_env, vsr64_offset(regno, false)); } static inline void get_avr64(TCGv_i64 dst, int regno, bool high) From c3f24257e3c094122a82611db3d7c3e8b25d9153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Colombo?= Date: Tue, 6 Sep 2022 09:55:23 -0300 Subject: [PATCH 0514/1020] target/ppc: Clear fpstatus flags on helpers missing it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In ppc emulation, exception flags are not cleared at the end of an instruction. Instead, the next instruction is responsible to clear it before its emulation. However, some helpers are not doing it, causing an issue where the previously set exception flags are being used and leading to incorrect values being set in FPSCR. Fix this by clearing fp_status before doing the instruction 'real' work for the following helpers that were missing this behavior: - VSX_CVT_INT_TO_FP_VECTOR - VSX_CVT_FP_TO_FP - VSX_CVT_FP_TO_INT_VECTOR - VSX_CVT_FP_TO_INT2 - VSX_CVT_FP_TO_INT - VSX_CVT_FP_TO_FP_HP - VSX_CVT_FP_TO_FP_VECTOR - VSX_CMP - VSX_ROUND - xscvqpdp - xscvdpsp[n] Signed-off-by: VĂ­ctor Colombo Reviewed-by: Daniel Henrique Barboza Message-Id: <20220906125523.38765-9-victor.colombo@eldorado.org.br> Signed-off-by: Daniel Henrique Barboza --- target/ppc/fpu_helper.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/target/ppc/fpu_helper.c b/target/ppc/fpu_helper.c index f07330ffc1..ae25f32d6e 100644 --- a/target/ppc/fpu_helper.c +++ b/target/ppc/fpu_helper.c @@ -2628,6 +2628,8 @@ uint32_t helper_##op(CPUPPCState *env, ppc_vsr_t *xt, \ int all_true = 1; \ int all_false = 1; \ \ + helper_reset_fpstatus(env); \ + \ for (i = 0; i < nels; i++) { \ if (unlikely(tp##_is_any_nan(xa->fld) || \ tp##_is_any_nan(xb->fld))) { \ @@ -2681,6 +2683,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ ppc_vsr_t t = { }; \ int i; \ \ + helper_reset_fpstatus(env); \ + \ for (i = 0; i < nels; i++) { \ t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \ if (unlikely(stp##_is_signaling_nan(xb->sfld, \ @@ -2706,6 +2710,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ ppc_vsr_t t = { }; \ int i; \ \ + helper_reset_fpstatus(env); \ + \ for (i = 0; i < nels; i++) { \ t.VsrW(2 * i) = stp##_to_##ttp(xb->VsrD(i), &env->fp_status); \ if (unlikely(stp##_is_signaling_nan(xb->VsrD(i), \ @@ -2743,6 +2749,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \ ppc_vsr_t t = *xt; \ int i; \ \ + helper_reset_fpstatus(env); \ + \ for (i = 0; i < nels; i++) { \ t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \ if (unlikely(stp##_is_signaling_nan(xb->sfld, \ @@ -2778,6 +2786,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ ppc_vsr_t t = { }; \ int i; \ \ + helper_reset_fpstatus(env); \ + \ for (i = 0; i < nels; i++) { \ t.tfld = stp##_to_##ttp(xb->sfld, 1, &env->fp_status); \ if (unlikely(stp##_is_signaling_nan(xb->sfld, \ @@ -2825,6 +2835,8 @@ void helper_XSCVQPDP(CPUPPCState *env, uint32_t ro, ppc_vsr_t *xt, ppc_vsr_t t = { }; float_status tstat; + helper_reset_fpstatus(env); + tstat = env->fp_status; if (ro != 0) { tstat.float_rounding_mode = float_round_to_odd; @@ -2846,6 +2858,7 @@ uint64_t helper_xscvdpspn(CPUPPCState *env, uint64_t xb) { uint64_t result, sign, exp, frac; + helper_reset_fpstatus(env); float_status tstat = env->fp_status; set_float_exception_flags(0, &tstat); @@ -2901,22 +2914,20 @@ uint64_t helper_XSCVSPDPN(uint64_t xb) #define VSX_CVT_FP_TO_INT(op, nels, stp, ttp, sfld, tfld, sfi, rnan) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - int all_flags = env->fp_status.float_exception_flags, flags; \ ppc_vsr_t t = { }; \ - int i; \ + int i, flags; \ + \ + helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ - env->fp_status.float_exception_flags = 0; \ t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \ flags = env->fp_status.float_exception_flags; \ if (unlikely(flags & float_flag_invalid)) { \ t.tfld = float_invalid_cvt(env, flags, t.tfld, rnan, 0, GETPC());\ } \ - all_flags |= flags; \ } \ \ *xt = t; \ - env->fp_status.float_exception_flags = all_flags; \ do_float_check_status(env, sfi, GETPC()); \ } @@ -2968,12 +2979,12 @@ VSX_CVT_FP_TO_INT128(XSCVQPSQZ, int128, 0x8000000000000000ULL); #define VSX_CVT_FP_TO_INT2(op, nels, stp, ttp, sfi, rnan) \ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ { \ - int all_flags = env->fp_status.float_exception_flags, flags; \ ppc_vsr_t t = { }; \ - int i; \ + int i, flags; \ + \ + helper_reset_fpstatus(env); \ \ for (i = 0; i < nels; i++) { \ - env->fp_status.float_exception_flags = 0; \ t.VsrW(2 * i) = stp##_to_##ttp##_round_to_zero(xb->VsrD(i), \ &env->fp_status); \ flags = env->fp_status.float_exception_flags; \ @@ -2982,11 +2993,9 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ rnan, 0, GETPC()); \ } \ t.VsrW(2 * i + 1) = t.VsrW(2 * i); \ - all_flags |= flags; \ } \ \ *xt = t; \ - env->fp_status.float_exception_flags = all_flags; \ do_float_check_status(env, sfi, GETPC()); \ } @@ -3011,6 +3020,8 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \ ppc_vsr_t t = { }; \ int flags; \ \ + helper_reset_fpstatus(env); \ + \ t.tfld = stp##_to_##ttp##_round_to_zero(xb->sfld, &env->fp_status); \ flags = get_float_exception_flags(&env->fp_status); \ if (flags & float_flag_invalid) { \ @@ -3023,7 +3034,6 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \ VSX_CVT_FP_TO_INT_VECTOR(xscvqpsdz, float128, int64, f128, VsrD(0), \ 0x8000000000000000ULL) - VSX_CVT_FP_TO_INT_VECTOR(xscvqpswz, float128, int32, f128, VsrD(0), \ 0xffffffff80000000ULL) VSX_CVT_FP_TO_INT_VECTOR(xscvqpudz, float128, uint64, f128, VsrD(0), 0x0ULL) @@ -3046,6 +3056,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ ppc_vsr_t t = { }; \ int i; \ \ + helper_reset_fpstatus(env); \ + \ for (i = 0; i < nels; i++) { \ t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \ if (r2sp) { \ @@ -3115,6 +3127,7 @@ void helper_##op(CPUPPCState *env, uint32_t opcode, \ { \ ppc_vsr_t t = *xt; \ \ + helper_reset_fpstatus(env); \ t.tfld = stp##_to_##ttp(xb->sfld, &env->fp_status); \ helper_compute_fprf_##ttp(env, t.tfld); \ \ @@ -3148,6 +3161,8 @@ void helper_##op(CPUPPCState *env, ppc_vsr_t *xt, ppc_vsr_t *xb) \ int i; \ FloatRoundMode curr_rounding_mode; \ \ + helper_reset_fpstatus(env); \ + \ if (rmode != FLOAT_ROUND_CURRENT) { \ curr_rounding_mode = get_float_rounding_mode(&env->fp_status); \ set_float_rounding_mode(rmode, &env->fp_status); \ From 9864b7f8ac5f06d7ce610997e01c187c3d01967c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:21 +0100 Subject: [PATCH 0515/1020] gitlab: reduce targets in cross_user_build_job MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We already limit the scope of the cross system build to reduce the cross build times. With the recent addition of more targets we are also running into timeout issues for some of the cross user builds. I've selected a few of those linux-user targets which are less likely to be in common use as distros don't have pre-built rootfs for them. I've also added the same CROSS_SKIP_TARGETS variable as is occasionally used to further limit cross system builds. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-2-alex.bennee@linaro.org> --- .gitlab-ci.d/crossbuild-template.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.d/crossbuild-template.yml b/.gitlab-ci.d/crossbuild-template.yml index 28b2142ec2..5e8892fd49 100644 --- a/.gitlab-ci.d/crossbuild-template.yml +++ b/.gitlab-ci.d/crossbuild-template.yml @@ -46,5 +46,8 @@ - cd build - PKG_CONFIG_PATH=$PKG_CONFIG_PATH ../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS - --disable-system + --disable-system --target-list-exclude="aarch64_be-linux-user + alpha-linux-user cris-linux-user m68k-linux-user microblazeel-linux-user + nios2-linux-user or1k-linux-user ppc-linux-user sparc-linux-user + xtensa-linux-user $CROSS_SKIP_TARGETS" - make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS From 7fcc3f759536b9a6e07d979e73b81ccdc4751c01 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 14 Sep 2022 16:59:22 +0100 Subject: [PATCH 0516/1020] tests/avocado/boot_linux_console: Fix the test_aarch64_xlnx_versal_virt test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The assets that this test tries to download have been removed from the server. Update to a newer version to get it working again. Signed-off-by: Thomas Huth Reviewed-by: Alistair Francis Message-Id: <20220829080940.110831-1-thuth@redhat.com> Signed-off-by: Alex BennĂ©e Message-Id: <20220914155950.804707-3-alex.bennee@linaro.org> --- tests/avocado/boot_linux_console.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py index 6b1533c17c..f26e036ab5 100644 --- a/tests/avocado/boot_linux_console.py +++ b/tests/avocado/boot_linux_console.py @@ -335,13 +335,13 @@ class BootLinuxConsole(LinuxKernelTest): """ images_url = ('http://ports.ubuntu.com/ubuntu-ports/dists/' 'bionic-updates/main/installer-arm64/' - '20101020ubuntu543.15/images/') + '20101020ubuntu543.19/images/') kernel_url = images_url + 'netboot/ubuntu-installer/arm64/linux' - kernel_hash = '5bfc54cf7ed8157d93f6e5b0241e727b6dc22c50' + kernel_hash = 'e167757620640eb26de0972f578741924abb3a82' kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash) initrd_url = images_url + 'netboot/ubuntu-installer/arm64/initrd.gz' - initrd_hash = 'd385d3e88d53e2004c5d43cbe668b458a094f772' + initrd_hash = 'cab5cb3fcefca8408aa5aae57f24574bfce8bdb9' initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash) self.vm.set_console() From c7f059ac112d5efe939a9d131442a8b019677a50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:23 +0100 Subject: [PATCH 0517/1020] tests/avocado: add explicit timeout for Aarch64 TCG tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want to rely on the soon to be reduced default time. These tests are still slow for something we want to run in CI though. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-4-alex.bennee@linaro.org> --- tests/avocado/boot_linux.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py index ee584d2fdf..67a24fe51c 100644 --- a/tests/avocado/boot_linux.py +++ b/tests/avocado/boot_linux.py @@ -63,6 +63,7 @@ class BootLinuxAarch64(LinuxTest): :avocado: tags=machine:virt :avocado: tags=machine:gic-version=2 """ + timeout = 240 def add_common_args(self): self.vm.add_args('-bios', From 06a4c9cf2447578bea2e464daaf17c80c40f212b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:24 +0100 Subject: [PATCH 0518/1020] tests/avocado: add explicit timeout for s390 TCG tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want to rely on the soon to be reduced default time. These tests are still slow for something we want to run in CI though. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-5-alex.bennee@linaro.org> --- tests/avocado/boot_linux.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py index 67a24fe51c..4f07c27ac6 100644 --- a/tests/avocado/boot_linux.py +++ b/tests/avocado/boot_linux.py @@ -130,6 +130,8 @@ class BootLinuxS390X(LinuxTest): :avocado: tags=arch:s390x """ + timeout = 240 + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_s390_ccw_virtio_tcg(self): """ From b247dba067bf2808de6395ff09ff0cb220ed7c95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:25 +0100 Subject: [PATCH 0519/1020] tests/avocado: add explicit timeout for ppc64le TCG tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't want to rely on the soon to be reduced default time. These tests are still slow for something we want to run in CI though. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-6-alex.bennee@linaro.org> --- tests/avocado/boot_linux.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/avocado/boot_linux.py b/tests/avocado/boot_linux.py index 4f07c27ac6..b7522ad3a1 100644 --- a/tests/avocado/boot_linux.py +++ b/tests/avocado/boot_linux.py @@ -115,6 +115,8 @@ class BootLinuxPPC64(LinuxTest): :avocado: tags=arch:ppc64 """ + timeout = 180 + def test_pseries_tcg(self): """ :avocado: tags=machine:pseries From 92f8e8e2fe3adcbbfaa6ee93591e7e7a3a896b08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:26 +0100 Subject: [PATCH 0520/1020] tests/avocado: split the AST2x00Machine classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SDK tests take a lot longer to run and hence need a longer timeout. As they run well over the 60 second maximum for CI lets also disable them for CI as well. I suspect they also suffer from the inability to detect the login prompt due to no newlines being processed. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-7-alex.bennee@linaro.org> --- tests/avocado/machine_aspeed.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/avocado/machine_aspeed.py b/tests/avocado/machine_aspeed.py index 65d38f4efa..0f64eb636c 100644 --- a/tests/avocado/machine_aspeed.py +++ b/tests/avocado/machine_aspeed.py @@ -6,12 +6,14 @@ # later. See the COPYING file in the top-level directory. import time +import os from avocado_qemu import QemuSystemTest from avocado_qemu import wait_for_console_pattern from avocado_qemu import exec_command from avocado_qemu import exec_command_and_wait_for_pattern from avocado.utils import archive +from avocado import skipIf class AST1030Machine(QemuSystemTest): @@ -176,6 +178,20 @@ class AST2x00Machine(QemuSystemTest): self.do_test_arm_aspeed_buidroot_poweroff() +class AST2x00MachineSDK(QemuSystemTest): + + # FIXME: Although these tests boot a whole distro they are still + # slower than comparable machine models. There may be some + # optimisations which bring down the runtime. In the meantime they + # have generous timeouts and are disable for CI which aims for all + # tests to run in less than 60 seconds. + timeout = 240 + + def wait_for_console_pattern(self, success_message, vm=None): + wait_for_console_pattern(self, success_message, + failure_message='Kernel panic - not syncing', + vm=vm) + def do_test_arm_aspeed_sdk_start(self, image, cpu_id): self.vm.set_console() self.vm.add_args('-drive', 'file=' + image + ',if=mtd,format=raw', @@ -187,6 +203,7 @@ class AST2x00Machine(QemuSystemTest): self.wait_for_console_pattern('Starting kernel ...') self.wait_for_console_pattern('Booting Linux on physical CPU ' + cpu_id) + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_arm_ast2500_evb_sdk(self): """ :avocado: tags=arch:arm @@ -204,6 +221,7 @@ class AST2x00Machine(QemuSystemTest): self.workdir + '/ast2500-default/image-bmc', '0x0') self.wait_for_console_pattern('ast2500-default login:') + @skipIf(os.getenv('GITLAB_CI'), 'Running on GitLab') def test_arm_ast2600_evb_sdk(self): """ :avocado: tags=arch:arm From 8f58f0c7d9389083695237d8f477771df9c51e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:27 +0100 Subject: [PATCH 0521/1020] tests/avocado: reduce the default timeout to 120s MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should be aiming to keep our tests under 2 minutes so lets reduce the default timeout to that. Tests that we know take longer should explicitly set a longer timeout. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-8-alex.bennee@linaro.org> --- tests/avocado/avocado_qemu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/avocado/avocado_qemu/__init__.py b/tests/avocado/avocado_qemu/__init__.py index 5f1d3e551c..910f3ba1ea 100644 --- a/tests/avocado/avocado_qemu/__init__.py +++ b/tests/avocado/avocado_qemu/__init__.py @@ -229,7 +229,7 @@ def exec_command_and_wait_for_pattern(test, command, class QemuBaseTest(avocado.Test): # default timeout for all tests, can be overridden - timeout = 900 + timeout = 120 def _get_unique_tag_val(self, tag_name): """ From d9df358f53494d121f569abe2e5a0888731315c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:28 +0100 Subject: [PATCH 0522/1020] tests/docker: update and flatten debian-alpha-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile. We really don't need the rest of the stuff from the QEMU base image just to compile test images. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-9-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - tests/docker/dockerfiles/debian-alpha-cross.docker | 12 +++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 505b267542..802e332205 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -1,7 +1,6 @@ alpha-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-alpha-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 9a45e8890b..c565aa5e7b 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -88,7 +88,6 @@ DOCKER_PARTIAL_IMAGES += debian-s390x-cross DOCKER_PARTIAL_IMAGES += fedora endif -docker-image-debian-alpha-cross: docker-image-debian10 docker-image-debian-hppa-cross: docker-image-debian10 docker-image-debian-m68k-cross: docker-image-debian10 docker-image-debian-mips-cross: docker-image-debian10 diff --git a/tests/docker/dockerfiles/debian-alpha-cross.docker b/tests/docker/dockerfiles/debian-alpha-cross.docker index 10fe30df0d..4eeb43c78a 100644 --- a/tests/docker/dockerfiles/debian-alpha-cross.docker +++ b/tests/docker/dockerfiles/debian-alpha-cross.docker @@ -1,12 +1,14 @@ # # Docker cross-compiler target # -# This docker target builds on the debian Buster base image. +# This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ gcc-alpha-linux-gnu \ libc6.1-dev-alpha-cross From 8b034187607f5b9c153b4b42ed45ee0b9b4c9881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:29 +0100 Subject: [PATCH 0523/1020] tests/docker: update and flatten debian-hppa-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile. We really don't need the rest of the stuff from the QEMU base image just to compile test images. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-10-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - tests/docker/dockerfiles/debian-hppa-cross.docker | 12 +++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 802e332205..6c1d765463 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -65,7 +65,6 @@ hexagon-cross-container: hppa-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-hppa-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index c565aa5e7b..e39597d35c 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -88,7 +88,6 @@ DOCKER_PARTIAL_IMAGES += debian-s390x-cross DOCKER_PARTIAL_IMAGES += fedora endif -docker-image-debian-hppa-cross: docker-image-debian10 docker-image-debian-m68k-cross: docker-image-debian10 docker-image-debian-mips-cross: docker-image-debian10 docker-image-debian-mips64-cross: docker-image-debian10 diff --git a/tests/docker/dockerfiles/debian-hppa-cross.docker b/tests/docker/dockerfiles/debian-hppa-cross.docker index 3d6c65a3ef..af1c8403d8 100644 --- a/tests/docker/dockerfiles/debian-hppa-cross.docker +++ b/tests/docker/dockerfiles/debian-hppa-cross.docker @@ -1,12 +1,14 @@ # # Docker cross-compiler target # -# This docker target builds on the debian Buster base image. +# This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ gcc-hppa-linux-gnu \ libc6-dev-hppa-cross From 77855002369b80d7d31cb85952c2149f7f3f2624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:30 +0100 Subject: [PATCH 0524/1020] tests/docker: update and flatten debian-m68k-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile. We really don't need the rest of the stuff from the QEMU base image just to compile test images. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-11-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - tests/docker/dockerfiles/debian-m68k-cross.docker | 12 +++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 6c1d765463..15a5270f6d 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -71,7 +71,6 @@ hppa-debian-cross-container: m68k-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-m68k-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index e39597d35c..95790e974e 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -88,7 +88,6 @@ DOCKER_PARTIAL_IMAGES += debian-s390x-cross DOCKER_PARTIAL_IMAGES += fedora endif -docker-image-debian-m68k-cross: docker-image-debian10 docker-image-debian-mips-cross: docker-image-debian10 docker-image-debian-mips64-cross: docker-image-debian10 docker-image-debian-sh4-cross: docker-image-debian10 diff --git a/tests/docker/dockerfiles/debian-m68k-cross.docker b/tests/docker/dockerfiles/debian-m68k-cross.docker index fcb10e3534..dded71c5d2 100644 --- a/tests/docker/dockerfiles/debian-m68k-cross.docker +++ b/tests/docker/dockerfiles/debian-m68k-cross.docker @@ -1,12 +1,14 @@ # # Docker cross-compiler target # -# This docker target builds on the debian Buster base image. +# This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ gcc-m68k-linux-gnu \ libc6-dev-m68k-cross From 2d2a154be711162478fccf4c5450080be41f4543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:31 +0100 Subject: [PATCH 0525/1020] tests/docker: update and flatten debian-mips64-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile. We really don't need the rest of the stuff from the QEMU base image just to compile test images. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-12-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - tests/docker/dockerfiles/debian-mips64-cross.docker | 12 +++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 15a5270f6d..a3bfa483bf 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -77,7 +77,6 @@ m68k-debian-cross-container: mips64-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-mips64-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 95790e974e..6c2ee3b175 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -89,7 +89,6 @@ DOCKER_PARTIAL_IMAGES += fedora endif docker-image-debian-mips-cross: docker-image-debian10 -docker-image-debian-mips64-cross: docker-image-debian10 docker-image-debian-sh4-cross: docker-image-debian10 docker-image-debian-sparc64-cross: docker-image-debian10 diff --git a/tests/docker/dockerfiles/debian-mips64-cross.docker b/tests/docker/dockerfiles/debian-mips64-cross.docker index 09c2ba584e..afcff9726f 100644 --- a/tests/docker/dockerfiles/debian-mips64-cross.docker +++ b/tests/docker/dockerfiles/debian-mips64-cross.docker @@ -1,12 +1,14 @@ # # Docker cross-compiler target # -# This docker target builds on the debian Buster base image. +# This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ gcc-mips64-linux-gnuabi64 \ libc6-dev-mips64-cross From 376c4109af99463aab8f33fb68a298d72da2b59b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:32 +0100 Subject: [PATCH 0526/1020] tests/docker: update and flatten debian-sh4-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile. We really don't need the rest of the stuff from the QEMU base image just to compile test images. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-13-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - tests/docker/dockerfiles/debian-sh4-cross.docker | 12 +++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index a3bfa483bf..8a611fc824 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -137,7 +137,6 @@ s390x-debian-cross-container: sh4-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-sh4-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 6c2ee3b175..37c4ea913f 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -89,7 +89,6 @@ DOCKER_PARTIAL_IMAGES += fedora endif docker-image-debian-mips-cross: docker-image-debian10 -docker-image-debian-sh4-cross: docker-image-debian10 docker-image-debian-sparc64-cross: docker-image-debian10 # The native build should never use the registry diff --git a/tests/docker/dockerfiles/debian-sh4-cross.docker b/tests/docker/dockerfiles/debian-sh4-cross.docker index fd3af89575..d48ed9065f 100644 --- a/tests/docker/dockerfiles/debian-sh4-cross.docker +++ b/tests/docker/dockerfiles/debian-sh4-cross.docker @@ -1,12 +1,14 @@ # # Docker cross-compiler target # -# This docker target builds on the debian Buster base image. +# This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ gcc-sh4-linux-gnu \ libc6-dev-sh4-cross From 6ede0767bac84d0b722c3fcc37ec102d5418f09b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:33 +0100 Subject: [PATCH 0527/1020] tests/docker: update and flatten debian-sparc64-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile. We really don't need the rest of the stuff from the QEMU base image just to compile test images. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-14-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - tests/docker/dockerfiles/debian-sparc64-cross.docker | 12 +++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 8a611fc824..db0ea15d0d 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -143,7 +143,6 @@ sh4-debian-cross-container: sparc64-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-sparc64-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 37c4ea913f..8828b6b8fa 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -89,7 +89,6 @@ DOCKER_PARTIAL_IMAGES += fedora endif docker-image-debian-mips-cross: docker-image-debian10 -docker-image-debian-sparc64-cross: docker-image-debian10 # The native build should never use the registry docker-image-debian-native: DOCKER_REGISTRY= diff --git a/tests/docker/dockerfiles/debian-sparc64-cross.docker b/tests/docker/dockerfiles/debian-sparc64-cross.docker index f4bb9b561c..8d3d306bc1 100644 --- a/tests/docker/dockerfiles/debian-sparc64-cross.docker +++ b/tests/docker/dockerfiles/debian-sparc64-cross.docker @@ -1,12 +1,14 @@ # # Docker cross-compiler target # -# This docker target builds on the debian Buster base image. +# This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ gcc-sparc64-linux-gnu \ libc6-dev-sparc64-cross From 0fd8f7a2dfcb3abcccd7b20ae18c1924f5fae708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:34 +0100 Subject: [PATCH 0528/1020] tests/docker: flatten debian-powerpc-test-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flatten into a single dockerfile. We really don't need the rest of the stuff from the QEMU base image just to compile test images. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-15-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - .../dockerfiles/debian-powerpc-test-cross.docker | 12 +++++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index db0ea15d0d..67bbf19a27 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -102,7 +102,6 @@ mipsel-debian-cross-container: powerpc-test-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian11-container'] variables: NAME: debian-powerpc-test-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 8828b6b8fa..e034eca3af 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -137,7 +137,6 @@ docker-image-debian-all-test-cross: docker-image-debian10 docker-image-debian-loongarch-cross: docker-image-debian11 docker-image-debian-microblaze-cross: docker-image-debian10 docker-image-debian-nios2-cross: docker-image-debian10 -docker-image-debian-powerpc-test-cross: docker-image-debian11 docker-image-debian-riscv64-test-cross: docker-image-debian11 # These images may be good enough for building tests but not for test builds diff --git a/tests/docker/dockerfiles/debian-powerpc-test-cross.docker b/tests/docker/dockerfiles/debian-powerpc-test-cross.docker index 36b336f709..d6b2909cc4 100644 --- a/tests/docker/dockerfiles/debian-powerpc-test-cross.docker +++ b/tests/docker/dockerfiles/debian-powerpc-test-cross.docker @@ -1,13 +1,15 @@ # # Docker powerpc/ppc64/ppc64le cross-compiler target # -# This docker target builds on the debian Bullseye base image. +# This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian11 +FROM docker.io/library/debian:11-slim -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ gcc-powerpc-linux-gnu \ libc6-dev-powerpc-cross \ gcc-10-powerpc64-linux-gnu \ From 95b0af40ded2aa0b350a9d8cb4256146e3397e48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:35 +0100 Subject: [PATCH 0529/1020] tests/docker: remove tricore qemu/debian10 dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We missed removing this dependency when we flattened the build. Fixes: 39ce923732 (gitlab: enable a very minimal build with the tricore container) Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-16-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - 2 files changed, 2 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 67bbf19a27..611c6c0b39 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -148,7 +148,6 @@ sparc64-debian-cross-container: tricore-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-tricore-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index e034eca3af..5c9398bbc9 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -132,7 +132,6 @@ docker-image-debian-nios2-cross: $(DOCKER_FILES_DIR)/debian-toolchain.docker \ $(call debian-toolchain, $@) # Specialist build images, sometimes very limited tools -docker-image-debian-tricore-cross: docker-image-debian10 docker-image-debian-all-test-cross: docker-image-debian10 docker-image-debian-loongarch-cross: docker-image-debian11 docker-image-debian-microblaze-cross: docker-image-debian10 From 0068cf8bd23738c20e131cb5f89ed3947ca77bd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:36 +0100 Subject: [PATCH 0530/1020] tests/docker: remove amd64 qemu/debian10 dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We missed removing this dependency when we flattened the build. Fixes 9e19fd7d4a (tests/docker: update debian-amd64 with lcitool) Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-17-alex.bennee@linaro.org> --- tests/docker/Makefile.include | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 5c9398bbc9..c3375f89c5 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -73,7 +73,6 @@ docker-binfmt-image-debian-%: $(DOCKER_FILES_DIR)/debian-bootstrap.docker # we don't run tests on intermediate images (used as base by another image) DOCKER_PARTIAL_IMAGES := debian10 debian11 ifeq ($(HOST_ARCH),x86_64) -docker-image-debian-amd64: docker-image-debian10 DOCKER_PARTIAL_IMAGES += debian-amd64-cross else docker-image-debian-amd64-cross: docker-image-debian10 From 3c696fdc596cdf04f8a1b3fa2cecabbb82507bb4 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 14 Sep 2022 16:59:37 +0100 Subject: [PATCH 0531/1020] tests/vm: Remove obsolete Fedora VM test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's still based on Fedora 30 - which is not supported anymore by QEMU since years. Seems like nobody is using (and refreshing) this, and it's easier to test this via a container anyway, so let's remove this now. Signed-off-by: Thomas Huth Message-Id: <20220822175317.190551-1-thuth@redhat.com> Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220914155950.804707-18-alex.bennee@linaro.org> --- tests/vm/Makefile.include | 3 +- tests/vm/fedora | 190 -------------------------------------- 2 files changed, 1 insertion(+), 192 deletions(-) delete mode 100755 tests/vm/fedora diff --git a/tests/vm/Makefile.include b/tests/vm/Makefile.include index 8d2a164552..2cc2203d09 100644 --- a/tests/vm/Makefile.include +++ b/tests/vm/Makefile.include @@ -15,7 +15,7 @@ endif EFI_AARCH64 = $(wildcard $(BUILD_DIR)/pc-bios/edk2-aarch64-code.fd) -X86_IMAGES := freebsd netbsd openbsd fedora haiku.x86_64 +X86_IMAGES := freebsd netbsd openbsd haiku.x86_64 ifneq ($(GENISOIMAGE),) X86_IMAGES += centos ifneq ($(EFI_AARCH64),) @@ -45,7 +45,6 @@ vm-help vm-test: @echo " vm-build-freebsd - Build QEMU in FreeBSD VM" @echo " vm-build-netbsd - Build QEMU in NetBSD VM" @echo " vm-build-openbsd - Build QEMU in OpenBSD VM" - @echo " vm-build-fedora - Build QEMU in Fedora VM" ifneq ($(GENISOIMAGE),) @echo " vm-build-centos - Build QEMU in CentOS VM, with Docker" ifneq ($(EFI_AARCH64),) diff --git a/tests/vm/fedora b/tests/vm/fedora deleted file mode 100755 index 12eca919a0..0000000000 --- a/tests/vm/fedora +++ /dev/null @@ -1,190 +0,0 @@ -#!/usr/bin/env python3 -# -# Fedora VM image -# -# Copyright 2019 Red Hat Inc. -# -# Authors: -# Gerd Hoffmann -# -# This code is licensed under the GPL version 2 or later. See -# the COPYING file in the top-level directory. -# - -import os -import re -import sys -import time -import socket -import subprocess -import basevm - -class FedoraVM(basevm.BaseVM): - name = "fedora" - arch = "x86_64" - - base = "https://archives.fedoraproject.org/pub/archive/fedora/linux/releases/30/" - link = base + "Server/x86_64/iso/Fedora-Server-netinst-x86_64-30-1.2.iso" - repo = base + "Server/x86_64/os/" - full = base + "Everything/x86_64/os/" - csum = "5e4eac4566d8c572bfb3bcf54b7d6c82006ec3c6c882a2c9235c6d3494d7b100" - size = "20G" - pkgs = [ - # tools - 'git-core', - 'gcc', 'binutils', 'make', 'ninja-build', - - # perl - 'perl', - - # libs: usb - '"pkgconfig(libusb-1.0)"', - '"pkgconfig(libusbredirparser-0.5)"', - - # libs: crypto - '"pkgconfig(gnutls)"', - - # libs: ui - '"pkgconfig(sdl2)"', - '"pkgconfig(gtk+-3.0)"', - '"pkgconfig(ncursesw)"', - - # libs: audio - '"pkgconfig(libpulse)"', - '"pkgconfig(alsa)"', - - # libs: migration - '"pkgconfig(libzstd)"', -] - - BUILD_SCRIPT = """ - set -e; - rm -rf /home/qemu/qemu-test.* - cd $(mktemp -d /home/qemu/qemu-test.XXXXXX); - mkdir src build; cd src; - tar -xf /dev/vdb; - cd ../build - ../src/configure --python=python3 {configure_opts}; - gmake --output-sync -j{jobs} {target} {verbose}; - """ - - def build_image(self, img): - self.print_step("Downloading install iso") - cimg = self._download_with_cache(self.link, sha256sum=self.csum) - img_tmp = img + ".tmp" - iso = img + ".install.iso" - - self.print_step("Preparing iso and disk image") - subprocess.check_call(["cp", "-f", cimg, iso]) - self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size) - self.print_step("Booting installer") - self.boot(img_tmp, extra_args = [ - "-machine", "graphics=off", - "-device", "VGA", - "-cdrom", iso - ]) - self.console_init(300) - self.console_wait("installation process.") - time.sleep(0.3) - self.console_send("\t") - time.sleep(0.3) - self.console_send(" console=ttyS0") - proxy = os.environ.get("http_proxy") - if not proxy is None: - self.console_send(" proxy=%s" % proxy) - self.console_send(" inst.proxy=%s" % proxy) - self.console_send(" inst.repo=%s" % self.repo) - self.console_send("\n") - - self.console_wait_send("2) Use text mode", "2\n") - - self.console_wait_send("5) [!] Installation Dest", "5\n") - self.console_wait_send("1) [x]", "c\n") - self.console_wait_send("2) [ ] Use All Space", "2\n") - self.console_wait_send("2) [x] Use All Space", "c\n") - self.console_wait_send("1) [ ] Standard Part", "1\n") - self.console_wait_send("1) [x] Standard Part", "c\n") - - self.console_wait_send("7) [!] Root password", "7\n") - self.console_wait("Password:") - self.console_send("%s\n" % self._config["root_pass"]) - self.console_wait("Password (confirm):") - self.console_send("%s\n" % self._config["root_pass"]) - - self.console_wait_send("8) [ ] User creation", "8\n") - self.console_wait_send("1) [ ] Create user", "1\n") - self.console_wait_send("3) User name", "3\n") - self.console_wait_send("ENTER:", "%s\n" % self._config["guest_user"]) - self.console_wait_send("4) [ ] Use password", "4\n") - self.console_wait_send("5) Password", "5\n") - self.console_wait("Password:") - self.console_send("%s\n" % self._config["guest_pass"]) - self.console_wait("Password (confirm):") - self.console_send("%s\n" % self._config["guest_pass"]) - self.console_wait_send("7) Groups", "c\n") - - while True: - good = self.console_wait("3) [x] Installation", - "3) [!] Installation") - self.console_send("r\n") - if good: - break - time.sleep(10) - - while True: - good = self.console_wait("4) [x] Software", - "4) [!] Software") - self.console_send("r\n") - if good: - break - time.sleep(10) - self.console_send("r\n" % self._config["guest_pass"]) - - self.console_wait_send("'b' to begin install", "b\n") - - self.print_step("Installation started now, this will take a while") - - self.console_wait_send("Installation complete", "\n") - self.print_step("Installation finished, rebooting") - - # setup qemu user - prompt = " ~]$" - self.console_ssh_init(prompt, self._config["guest_user"], - self._config["guest_pass"]) - self.console_wait_send(prompt, "exit\n") - - # setup root user - prompt = " ~]#" - self.console_ssh_init(prompt, "root", self._config["root_pass"]) - self.console_sshd_config(prompt) - - # setup virtio-blk #1 (tarfile) - self.console_wait(prompt) - self.console_send("echo 'KERNEL==\"vdb\" MODE=\"666\"' >> %s\n" % - "/etc/udev/rules.d/99-qemu.rules") - - self.print_step("Configuration finished, rebooting") - self.console_wait_send(prompt, "reboot\n") - self.console_wait("login:") - self.wait_ssh() - - self.print_step("Installing packages") - self.ssh_root_check("rm -vf /etc/yum.repos.d/fedora*.repo\n") - self.ssh_root_check("echo '[fedora]' >> /etc/yum.repos.d/qemu.repo\n") - self.ssh_root_check("echo 'baseurl=%s' >> /etc/yum.repos.d/qemu.repo\n" % self.full) - self.ssh_root_check("echo 'gpgcheck=0' >> /etc/yum.repos.d/qemu.repo\n") - self.ssh_root_check("dnf install -y %s\n" % " ".join(self.pkgs)) - - # shutdown - self.ssh_root(self.poweroff) - self.console_wait("sleep state S5") - self.wait() - - if os.path.exists(img): - os.remove(img) - os.rename(img_tmp, img) - os.remove(iso) - self.print_step("All done") - -if __name__ == "__main__": - sys.exit(basevm.main(FedoraVM)) From cb5b5ab9a516ce5ecddfc50971bf6f690300fd74 Mon Sep 17 00:00:00 2001 From: Xuzhou Cheng Date: Tue, 20 Sep 2022 18:31:47 +0800 Subject: [PATCH 0532/1020] hw/ppc: spapr: Use qemu_vfree() to free spapr->htab MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit spapr->htab is allocated by qemu_memalign(), hence we should use qemu_vfree() to free it. Fixes: c5f54f3e31bf ("pseries: Move hash page table allocation to reset time") Fixes: b4db54132ffe ("target/ppc: Implement H_REGISTER_PROCESS_TABLE H_CALL"") Signed-off-by: Xuzhou Cheng Signed-off-by: Bin Meng Reviewed-by: Daniel Henrique Barboza Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220920103159.1865256-28-bmeng.cn@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/ppc/spapr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index fb790b61e4..cc1adc23fa 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1522,7 +1522,7 @@ int spapr_hpt_shift_for_ramsize(uint64_t ramsize) void spapr_free_hpt(SpaprMachineState *spapr) { - g_free(spapr->htab); + qemu_vfree(spapr->htab); spapr->htab = NULL; spapr->htab_shift = 0; close_htab_fd(spapr); From 90865af7d901a2aa5eeadfb488f3a9d4aaf70605 Mon Sep 17 00:00:00 2001 From: Xuzhou Cheng Date: Tue, 20 Sep 2022 18:31:48 +0800 Subject: [PATCH 0533/1020] hw/pci-host: pnv_phb{3, 4}: Fix heap out-of-bound access failure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pnv_phb3_root_bus_info and pnv_phb4_root_bus_info are missing the instance_size initialization. This results in accessing out-of-bound memory when setting 'chip-id' and 'phb-id', and eventually crashes glib's malloc functionality with the following message: "qemu-system-ppc64: GLib: ../glib-2.72.3/glib/gmem.c:131: failed to allocate 3232 bytes" This issue was noticed only when running qtests with QEMU Windows 32-bit executable. Windows 64-bit, Linux 32/64-bit do not expose this bug though. Fixes: 9ae1329ee2fe ("ppc/pnv: Add models for POWER8 PHB3 PCIe Host bridge") Fixes: 4f9924c4d4cf ("ppc/pnv: Add models for POWER9 PHB4 PCIe Host bridge") Reviewed-by: CĂ©dric Le Goater Signed-off-by: Xuzhou Cheng Signed-off-by: Bin Meng Message-Id: <20220920103159.1865256-29-bmeng.cn@gmail.com> Signed-off-by: Daniel Henrique Barboza --- hw/pci-host/pnv_phb3.c | 1 + hw/pci-host/pnv_phb4.c | 1 + 2 files changed, 2 insertions(+) diff --git a/hw/pci-host/pnv_phb3.c b/hw/pci-host/pnv_phb3.c index af8575c007..9054c393a2 100644 --- a/hw/pci-host/pnv_phb3.c +++ b/hw/pci-host/pnv_phb3.c @@ -1169,6 +1169,7 @@ static void pnv_phb3_root_bus_class_init(ObjectClass *klass, void *data) static const TypeInfo pnv_phb3_root_bus_info = { .name = TYPE_PNV_PHB3_ROOT_BUS, .parent = TYPE_PCIE_BUS, + .instance_size = sizeof(PnvPHB3RootBus), .class_init = pnv_phb3_root_bus_class_init, }; diff --git a/hw/pci-host/pnv_phb4.c b/hw/pci-host/pnv_phb4.c index 824e1a73fb..ccbde841fc 100644 --- a/hw/pci-host/pnv_phb4.c +++ b/hw/pci-host/pnv_phb4.c @@ -1773,6 +1773,7 @@ static void pnv_phb4_root_bus_class_init(ObjectClass *klass, void *data) static const TypeInfo pnv_phb4_root_bus_info = { .name = TYPE_PNV_PHB4_ROOT_BUS, .parent = TYPE_PCIE_BUS, + .instance_size = sizeof(PnvPHB4RootBus), .class_init = pnv_phb4_root_bus_class_init, }; From 6b5cf264ee76d24b357a60b69b0635a533c1f647 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Tue, 20 Sep 2022 01:17:15 +0200 Subject: [PATCH 0534/1020] hw/ppc/spapr: Fix code style problems reported by checkpatch Reviewed-by: Daniel Henrique Barboza Signed-off-by: Bernhard Beschow Message-Id: <20220919231720.163121-5-shentey@gmail.com> Signed-off-by: Daniel Henrique Barboza --- include/hw/ppc/spapr.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 530d739b1d..04a95669ab 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -848,7 +848,8 @@ static inline uint64_t ppc64_phys_to_real(uint64_t addr) static inline uint32_t rtas_ld(target_ulong phys, int n) { - return ldl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n)); + return ldl_be_phys(&address_space_memory, + ppc64_phys_to_real(phys + 4 * n)); } static inline uint64_t rtas_ldq(target_ulong phys, int n) @@ -858,7 +859,7 @@ static inline uint64_t rtas_ldq(target_ulong phys, int n) static inline void rtas_st(target_ulong phys, int n, uint32_t val) { - stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val); + stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4 * n), val); } typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, SpaprMachineState *sm, From abafb64b6dcbdb0ca0943cd04373bd84353ce7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:38 +0100 Subject: [PATCH 0535/1020] configure: explicitly set cflags for --disable-pie MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is working around current limitation of Meson's handling of --disable-pie. Signed-off-by: Alex BennĂ©e Cc: Paolo Bonzini Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-19-alex.bennee@linaro.org> --- configure | 3 +++ 1 file changed, 3 insertions(+) diff --git a/configure b/configure index 575dde1c1f..0bbf9d28af 100755 --- a/configure +++ b/configure @@ -1382,6 +1382,9 @@ elif test "$pie" = "no"; then if compile_prog "-Werror -fno-pie" "-no-pie"; then CONFIGURE_CFLAGS="-fno-pie $CONFIGURE_CFLAGS" CONFIGURE_LDFLAGS="-no-pie $CONFIGURE_LDFLAGS" + # Meson currently only handles pie as a boolean for now so if we have + # explicitly disabled PIE we need to extend our cflags because it wont. + QEMU_CFLAGS="-fno-pie -no-pie $QEMU_CFLAGS" fi elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS" From 45e1b746943eefe4c0fb35e29878cd038ac62fd7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 14 Sep 2022 16:59:39 +0100 Subject: [PATCH 0536/1020] gitlab-ci/custom-runners: Disable -static-pie for ubuntu-20.04-aarch64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The project has reached the magic size at which we see /usr/aarch64-linux-gnu/lib/libc.a(init-first.o): in function `__libc_init_first': (.text+0x10): relocation truncated to fit: R_AARCH64_LD64_GOTPAGE_LO15 against \ symbol `__environ' defined in .bss section in /usr/aarch64-linux-gnu/lib/libc.a(environ.o) /usr/bin/ld: (.text+0x10): warning: too many GOT entries for -fpic, please recompile with -fPIC The bug has been reported upstream, but in the meantime there is nothing we can do except build a non-pie executable. Signed-off-by: Richard Henderson Signed-off-by: Alex BennĂ©e Message-Id: <20220823210329.1969895-1-richard.henderson@linaro.org> Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-20-alex.bennee@linaro.org> --- .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml index 3d878914e7..3f4dee4f86 100644 --- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml +++ b/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml @@ -16,7 +16,9 @@ ubuntu-20.04-aarch64-all-linux-static: # --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages - mkdir build - cd build - - ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh + # Disable -static-pie due to build error with system libc: + # https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1987438 + - ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh --disable-pie || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 From 66dca267489e7b150546297e7c33a04430a15eb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:40 +0100 Subject: [PATCH 0537/1020] gitlab-ci: update aarch32/aarch64 custom runner jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The custom runner is now using 22.04 so we can drop our hacks to deal with broken libssh and glusterfs. The provisioning scripts will be updated in a separate commit. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-21-alex.bennee@linaro.org> --- .gitlab-ci.d/custom-runners.yml | 4 +-- ...4-aarch32.yml => ubuntu-22.04-aarch32.yml} | 6 ++-- ...4-aarch64.yml => ubuntu-22.04-aarch64.yml} | 36 +++++++++---------- MAINTAINERS | 3 +- 4 files changed, 24 insertions(+), 25 deletions(-) rename .gitlab-ci.d/custom-runners/{ubuntu-20.04-aarch32.yml => ubuntu-22.04-aarch32.yml} (86%) rename .gitlab-ci.d/custom-runners/{ubuntu-20.04-aarch64.yml => ubuntu-22.04-aarch64.yml} (82%) diff --git a/.gitlab-ci.d/custom-runners.yml b/.gitlab-ci.d/custom-runners.yml index 15aaccc481..97f99e29c2 100644 --- a/.gitlab-ci.d/custom-runners.yml +++ b/.gitlab-ci.d/custom-runners.yml @@ -15,6 +15,6 @@ variables: include: - local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-s390x.yml' - - local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml' - - local: '/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml' + - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml' + - local: '/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml' - local: '/.gitlab-ci.d/custom-runners/centos-stream-8-x86_64.yml' diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml b/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml similarity index 86% rename from .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml rename to .gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml index cbfa9cc164..1a2f9b8dbe 100644 --- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch32.yml +++ b/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml @@ -1,12 +1,12 @@ -# All ubuntu-20.04 jobs should run successfully in an environment +# All ubuntu-22.04 jobs should run successfully in an environment # setup by the scripts/ci/setup/qemu/build-environment.yml task # "Install basic packages to build QEMU on Ubuntu 20.04" -ubuntu-20.04-aarch32-all: +ubuntu-22.04-aarch32-all: needs: [] stage: build tags: - - ubuntu_20.04 + - ubuntu_22.04 - aarch32 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' diff --git a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml b/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml similarity index 82% rename from .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml rename to .gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml index 3f4dee4f86..ce0b18af6f 100644 --- a/.gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml +++ b/.gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml @@ -2,23 +2,21 @@ # setup by the scripts/ci/setup/qemu/build-environment.yml task # "Install basic packages to build QEMU on Ubuntu 20.04" -ubuntu-20.04-aarch64-all-linux-static: +ubuntu-22.04-aarch64-all-linux-static: needs: [] stage: build tags: - - ubuntu_20.04 + - ubuntu_22.04 - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' - if: "$AARCH64_RUNNER_AVAILABLE" script: - # --disable-libssh is needed because of https://bugs.launchpad.net/qemu/+bug/1838763 - # --disable-glusterfs is needed because there's no static version of those libs in distro supplied packages - mkdir build - cd build # Disable -static-pie due to build error with system libc: # https://bugs.launchpad.net/ubuntu/+source/glibc/+bug/1987438 - - ../configure --enable-debug --static --disable-system --disable-glusterfs --disable-libssh --disable-pie + - ../configure --enable-debug --static --disable-system --disable-pie || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 @@ -26,11 +24,11 @@ ubuntu-20.04-aarch64-all-linux-static: - make --output-sync -j`nproc --ignore=40` check-tcg V=1 || { cat meson-logs/testlog.txt; exit 1; } ; -ubuntu-20.04-aarch64-all: +ubuntu-22.04-aarch64-all: needs: [] stage: build tags: - - ubuntu_20.04 + - ubuntu_22.04 - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' @@ -42,17 +40,17 @@ ubuntu-20.04-aarch64-all: script: - mkdir build - cd build - - ../configure --disable-libssh + - ../configure || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 || { cat meson-logs/testlog.txt; exit 1; } ; -ubuntu-20.04-aarch64-alldbg: +ubuntu-22.04-aarch64-alldbg: needs: [] stage: build tags: - - ubuntu_20.04 + - ubuntu_22.04 - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' @@ -60,18 +58,18 @@ ubuntu-20.04-aarch64-alldbg: script: - mkdir build - cd build - - ../configure --enable-debug --disable-libssh + - ../configure --enable-debug || { cat config.log meson-logs/meson-log.txt; exit 1; } - make clean - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 || { cat meson-logs/testlog.txt; exit 1; } ; -ubuntu-20.04-aarch64-clang: +ubuntu-22.04-aarch64-clang: needs: [] stage: build tags: - - ubuntu_20.04 + - ubuntu_22.04 - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' @@ -89,11 +87,11 @@ ubuntu-20.04-aarch64-clang: - make --output-sync -j`nproc --ignore=40` check V=1 || { cat meson-logs/testlog.txt; exit 1; } ; -ubuntu-20.04-aarch64-tci: +ubuntu-22.04-aarch64-tci: needs: [] stage: build tags: - - ubuntu_20.04 + - ubuntu_22.04 - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' @@ -105,15 +103,15 @@ ubuntu-20.04-aarch64-tci: script: - mkdir build - cd build - - ../configure --disable-libssh --enable-tcg-interpreter + - ../configure --enable-tcg-interpreter || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` -ubuntu-20.04-aarch64-notcg: +ubuntu-22.04-aarch64-notcg: needs: [] stage: build tags: - - ubuntu_20.04 + - ubuntu_22.04 - aarch64 rules: - if: '$CI_PROJECT_NAMESPACE == "qemu-project" && $CI_COMMIT_BRANCH =~ /^staging/' @@ -125,7 +123,7 @@ ubuntu-20.04-aarch64-notcg: script: - mkdir build - cd build - - ../configure --disable-libssh --disable-tcg + - ../configure --disable-tcg || { cat config.log meson-logs/meson-log.txt; exit 1; } - make --output-sync -j`nproc --ignore=40` - make --output-sync -j`nproc --ignore=40` check V=1 diff --git a/MAINTAINERS b/MAINTAINERS index 1729c0901c..738c4eb647 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3724,7 +3724,8 @@ GitLab custom runner (Works On Arm Sponsored) M: Alex BennĂ©e M: Philippe Mathieu-DaudĂ© S: Maintained -F: .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml +F: .gitlab-ci.d/custom-runners/ubuntu-22.04-aarch64.yml +F: .gitlab-ci.d/custom-runners/ubuntu-22.04-aarch32.yml Documentation ------------- From 54ab3c3feef6e5a6c6cf97c4532ebed642ec2705 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:41 +0100 Subject: [PATCH 0538/1020] Deprecate 32 bit big-endian MIPS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's becoming harder to maintain a cross-compiler to test this host architecture as the old stable Debian 10 ("Buster") moved into LTS which supports fewer architectures. For now: - mark it's deprecation in the docs - downgrade the containers to build TCG tests only - drop the cross builds from our CI Users with an appropriate toolchain and user-space can still take their chances building it. Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Reviewed-by: Huacai Chen Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-22-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - .gitlab-ci.d/crossbuilds.yml | 14 -------- docs/about/build-platforms.rst | 2 +- docs/about/deprecated.rst | 13 +++++++ tests/docker/Makefile.include | 5 ++- .../dockerfiles/debian-mips-cross.docker | 36 +++++-------------- 6 files changed, 25 insertions(+), 46 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 611c6c0b39..95d57e1c5d 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -89,7 +89,6 @@ mips64el-debian-cross-container: mips-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-mips-cross diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml index 4a5fb6ea2a..c4cd96433d 100644 --- a/.gitlab-ci.d/crossbuilds.yml +++ b/.gitlab-ci.d/crossbuilds.yml @@ -70,20 +70,6 @@ cross-i386-tci: EXTRA_CONFIGURE_OPTS: --target-list=i386-softmmu,i386-linux-user,aarch64-softmmu,aarch64-linux-user,ppc-softmmu,ppc-linux-user MAKE_CHECK_ARGS: check check-tcg -cross-mips-system: - extends: .cross_system_build_job - needs: - job: mips-debian-cross-container - variables: - IMAGE: debian-mips-cross - -cross-mips-user: - extends: .cross_user_build_job - needs: - job: mips-debian-cross-container - variables: - IMAGE: debian-mips-cross - cross-mipsel-system: extends: .cross_system_build_job needs: diff --git a/docs/about/build-platforms.rst b/docs/about/build-platforms.rst index a2fee53248..1c1e7b9e11 100644 --- a/docs/about/build-platforms.rst +++ b/docs/about/build-platforms.rst @@ -41,7 +41,7 @@ Those hosts are officially supported, with various accelerators: - Accelerators * - Arm - kvm (64 bit only), tcg, xen - * - MIPS + * - MIPS (little endian only) - kvm, tcg * - PPC - kvm, tcg diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index c75a25daad..0d1fd4469b 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -213,6 +213,19 @@ MIPS ``Trap-and-Emul`` KVM support (since 6.0) The MIPS ``Trap-and-Emul`` KVM host and guest support has been removed from Linux upstream kernel, declare it deprecated. +Host Architectures +------------------ + +BE MIPS (since 7.2) +''''''''''''''''''' + +As Debian 10 ("Buster") moved into LTS the big endian 32 bit version of +MIPS moved out of support making it hard to maintain our +cross-compilation CI tests of the architecture. As we no longer have +CI coverage support may bitrot away before the deprecation process +completes. The little endian variants of MIPS (both 32 and 64 bit) are +still a supported host architecture. + QEMU API (QAPI) events ---------------------- diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index c3375f89c5..b1bf56434f 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -81,14 +81,12 @@ endif # For non-x86 hosts not all cross-compilers have been packaged ifneq ($(HOST_ARCH),x86_64) -DOCKER_PARTIAL_IMAGES += debian-mips-cross debian-mipsel-cross debian-mips64el-cross +DOCKER_PARTIAL_IMAGES += debian-mipsel-cross debian-mips64el-cross DOCKER_PARTIAL_IMAGES += debian-ppc64el-cross DOCKER_PARTIAL_IMAGES += debian-s390x-cross DOCKER_PARTIAL_IMAGES += fedora endif -docker-image-debian-mips-cross: docker-image-debian10 - # The native build should never use the registry docker-image-debian-native: DOCKER_REGISTRY= @@ -144,6 +142,7 @@ DOCKER_PARTIAL_IMAGES += debian-hppa-cross DOCKER_PARTIAL_IMAGES += debian-loongarch-cross DOCKER_PARTIAL_IMAGES += debian-m68k-cross debian-mips64-cross DOCKER_PARTIAL_IMAGES += debian-microblaze-cross +DOCKER_PARTIAL_IMAGES += debian-mips-cross DOCKER_PARTIAL_IMAGES += debian-nios2-cross DOCKER_PARTIAL_IMAGES += debian-riscv64-test-cross DOCKER_PARTIAL_IMAGES += debian-sh4-cross debian-sparc64-cross diff --git a/tests/docker/dockerfiles/debian-mips-cross.docker b/tests/docker/dockerfiles/debian-mips-cross.docker index 26c154014d..7b55f0f3b2 100644 --- a/tests/docker/dockerfiles/debian-mips-cross.docker +++ b/tests/docker/dockerfiles/debian-mips-cross.docker @@ -1,32 +1,14 @@ # # Docker mips cross-compiler target # -# This docker target builds on the debian Buster base image. +# This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim -MAINTAINER Philippe Mathieu-DaudĂ© - -# Add the foreign architecture we want and install dependencies -RUN dpkg --add-architecture mips -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ - gcc-mips-linux-gnu - -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt build-dep -yy -a mips --arch-only qemu - -# Specify the cross prefix for this image (see tests/docker/common.rc) -ENV QEMU_CONFIGURE_OPTS --cross-prefix=mips-linux-gnu- -ENV DEF_TARGET_LIST mips-softmmu,mipsel-linux-user - -# Install extra libraries to increase code coverage -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ - libbz2-dev:mips \ - liblzo2-dev:mips \ - librdmacm-dev:mips \ - libsnappy-dev:mips +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ + gcc-mips-linux-gnu \ + libc6-dev-mips-cross From fab08026a2627625a1c4e856285ab8f350b1b3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:42 +0100 Subject: [PATCH 0539/1020] tests/docker: flatten debian-riscv64-test-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Flatten into a single dockerfile and update to match the rest of the test cross compile dockerfiles. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-23-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - .../dockerfiles/debian-riscv64-test-cross.docker | 10 ++++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 95d57e1c5d..3a8bd75473 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -122,7 +122,6 @@ riscv64-debian-cross-container: riscv64-debian-test-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian11-container'] variables: NAME: debian-riscv64-test-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index b1bf56434f..24cd44e667 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -133,7 +133,6 @@ docker-image-debian-all-test-cross: docker-image-debian10 docker-image-debian-loongarch-cross: docker-image-debian11 docker-image-debian-microblaze-cross: docker-image-debian10 docker-image-debian-nios2-cross: docker-image-debian10 -docker-image-debian-riscv64-test-cross: docker-image-debian11 # These images may be good enough for building tests but not for test builds DOCKER_PARTIAL_IMAGES += debian-alpha-cross diff --git a/tests/docker/dockerfiles/debian-riscv64-test-cross.docker b/tests/docker/dockerfiles/debian-riscv64-test-cross.docker index 1d90901298..e5f83a5aeb 100644 --- a/tests/docker/dockerfiles/debian-riscv64-test-cross.docker +++ b/tests/docker/dockerfiles/debian-riscv64-test-cross.docker @@ -3,10 +3,12 @@ # # This docker target builds on the Debian Bullseye base image. # -FROM qemu/debian11 +FROM docker.io/library/debian:11-slim -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ gcc-riscv64-linux-gnu \ libc6-dev-riscv64-cross From b6fafe5b3e5eb555cf13f51cd5d08400c86dac96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:43 +0100 Subject: [PATCH 0540/1020] tests/docker: update and flatten debian-all-test-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile. We also need to ensure we install clang as it is used for those builds as well. It would be nice to port this to lcitool but for now this will do. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-24-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - .../dockerfiles/debian-all-test-cross.docker | 18 +++++++++++++----- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 3a8bd75473..091c0d8fcb 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -14,7 +14,6 @@ amd64-debian-cross-container: amd64-debian-user-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-all-test-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 24cd44e667..ddcc502049 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -129,7 +129,6 @@ docker-image-debian-nios2-cross: $(DOCKER_FILES_DIR)/debian-toolchain.docker \ $(call debian-toolchain, $@) # Specialist build images, sometimes very limited tools -docker-image-debian-all-test-cross: docker-image-debian10 docker-image-debian-loongarch-cross: docker-image-debian11 docker-image-debian-microblaze-cross: docker-image-debian10 docker-image-debian-nios2-cross: docker-image-debian10 diff --git a/tests/docker/dockerfiles/debian-all-test-cross.docker b/tests/docker/dockerfiles/debian-all-test-cross.docker index dedcea58b4..2beb077fb4 100644 --- a/tests/docker/dockerfiles/debian-all-test-cross.docker +++ b/tests/docker/dockerfiles/debian-all-test-cross.docker @@ -6,16 +6,24 @@ # basic compilers for as many targets as possible. We shall use this # to build and run linux-user tests on GitLab # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim -# What we need to build QEMU itself -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ +# Duplicate deb line as deb-src +RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list + +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ apt build-dep -yy qemu -# Add the foreign architecture we want and install dependencies +# Add extra build tools and as many cross compilers as we can for testing RUN DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ + ccache \ + clang \ + git \ + ninja-build \ gcc-aarch64-linux-gnu \ libc6-dev-arm64-cross \ gcc-alpha-linux-gnu \ From 8bb499955e26466b2b64f0736d77037a56fcddcb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:44 +0100 Subject: [PATCH 0541/1020] tests/lcitool: bump to latest version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need this to be able to cleanly build the x86 cross images. There are a few minor updates triggered by lcitool-refresh including adding "libslirp" to the freebsd vars and opensuse-leap which will help when we finally drop the slirp submodule from QEMU. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-25-alex.bennee@linaro.org> --- .gitlab-ci.d/cirrus/freebsd-12.vars | 2 +- .gitlab-ci.d/cirrus/freebsd-13.vars | 2 +- tests/docker/dockerfiles/opensuse-leap.docker | 3 ++- tests/docker/dockerfiles/ubuntu2004.docker | 2 +- tests/lcitool/libvirt-ci | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.d/cirrus/freebsd-12.vars b/.gitlab-ci.d/cirrus/freebsd-12.vars index 8fa5a320e9..1a5959810f 100644 --- a/.gitlab-ci.d/cirrus/freebsd-12.vars +++ b/.gitlab-ci.d/cirrus/freebsd-12.vars @@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' PYPI_PKGS='' PYTHON='/usr/local/bin/python3' diff --git a/.gitlab-ci.d/cirrus/freebsd-13.vars b/.gitlab-ci.d/cirrus/freebsd-13.vars index 8ed7e33a77..5e5aafd7e5 100644 --- a/.gitlab-ci.d/cirrus/freebsd-13.vars +++ b/.gitlab-ci.d/cirrus/freebsd-13.vars @@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' PYPI_PKGS='' PYTHON='/usr/local/bin/python3' diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker index 047a435ab5..041cf9c1ff 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -66,6 +66,7 @@ RUN zypper update -y && \ librbd-devel \ libseccomp-devel \ libselinux-devel \ + libslirp-devel \ libspice-server-devel \ libssh-devel \ libtasn1-devel \ @@ -127,7 +128,7 @@ RUN zypper update -y && \ ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \ ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc -RUN pip3 install meson==0.56.0 +RUN /usr/bin/pip3 install meson==0.56.0 ENV LANG "en_US.UTF-8" ENV MAKE "/usr/bin/make" diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker index 99803b343b..e1f4ed7c80 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -137,7 +137,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \ ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc -RUN pip3 install meson==0.56.0 +RUN /usr/bin/pip3 install meson==0.56.0 ENV LANG "en_US.UTF-8" ENV MAKE "/usr/bin/make" diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci index 324355cf62..e3712b7912 160000 --- a/tests/lcitool/libvirt-ci +++ b/tests/lcitool/libvirt-ci @@ -1 +1 @@ -Subproject commit 324355cf62e86fb551408575afb123bac989ac37 +Subproject commit e3712b79122180fdb3b7a7ea8cbee47ece253f97 From cd150e19e83833d164d69fd159ee95ff3a203e17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:45 +0100 Subject: [PATCH 0542/1020] tests/docker: update and flatten debian-amd64-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now lcitool has support for building a x86_64 cross image we can use it for this. Signed-off-by: Alex BennĂ©e Acked-by: Thomas Huth Message-Id: <20220914155950.804707-26-alex.bennee@linaro.org> --- .gitlab-ci.d/container-cross.yml | 1 - tests/docker/Makefile.include | 1 - .../dockerfiles/debian-amd64-cross.docker | 178 ++++++++++++++++-- tests/lcitool/refresh | 7 + 4 files changed, 169 insertions(+), 18 deletions(-) diff --git a/.gitlab-ci.d/container-cross.yml b/.gitlab-ci.d/container-cross.yml index 091c0d8fcb..2d560e9764 100644 --- a/.gitlab-ci.d/container-cross.yml +++ b/.gitlab-ci.d/container-cross.yml @@ -7,7 +7,6 @@ alpha-debian-cross-container: amd64-debian-cross-container: extends: .container_job_template stage: containers - needs: ['amd64-debian10-container'] variables: NAME: debian-amd64-cross diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index ddcc502049..a0f5109628 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -75,7 +75,6 @@ DOCKER_PARTIAL_IMAGES := debian10 debian11 ifeq ($(HOST_ARCH),x86_64) DOCKER_PARTIAL_IMAGES += debian-amd64-cross else -docker-image-debian-amd64-cross: docker-image-debian10 DOCKER_PARTIAL_IMAGES += debian-amd64 endif diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker index 870109ef6a..7d2feb7bf7 100644 --- a/tests/docker/dockerfiles/debian-amd64-cross.docker +++ b/tests/docker/dockerfiles/debian-amd64-cross.docker @@ -1,22 +1,168 @@ +# THIS FILE WAS AUTO-GENERATED # -# Docker x86_64 cross target +# $ lcitool dockerfile --layers all --cross x86_64 debian-11 qemu # -# This docker target is used on non-x86_64 machines which need the -# x86_64 cross compilers installed. -# -FROM qemu/debian10 -MAINTAINER Alex BennĂ©e +# https://gitlab.com/libvirt/libvirt-ci -# Add the foreign architecture we want and install dependencies -RUN dpkg --add-architecture amd64 -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ - crossbuild-essential-amd64 -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt build-dep -yy -a amd64 --arch-only qemu +FROM docker.io/library/debian:11-slim -# Specify the cross prefix for this image (see tests/docker/common.rc) +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get install -y eatmydata && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y \ + bash \ + bc \ + bsdextrautils \ + bzip2 \ + ca-certificates \ + ccache \ + dbus \ + debianutils \ + diffutils \ + exuberant-ctags \ + findutils \ + gcovr \ + genisoimage \ + gettext \ + git \ + hostname \ + libpcre2-dev \ + libspice-protocol-dev \ + llvm \ + locales \ + make \ + meson \ + ncat \ + ninja-build \ + openssh-client \ + perl-base \ + pkgconf \ + python3 \ + python3-numpy \ + python3-opencv \ + python3-pillow \ + python3-pip \ + python3-sphinx \ + python3-sphinx-rtd-theme \ + python3-venv \ + python3-yaml \ + rpm2cpio \ + sed \ + sparse \ + tar \ + tesseract-ocr \ + tesseract-ocr-eng \ + texinfo && \ + eatmydata apt-get autoremove -y && \ + eatmydata apt-get autoclean -y && \ + sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \ + dpkg-reconfigure locales + +ENV LANG "en_US.UTF-8" +ENV MAKE "/usr/bin/make" +ENV NINJA "/usr/bin/ninja" +ENV PYTHON "/usr/bin/python3" +ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers" + +RUN export DEBIAN_FRONTEND=noninteractive && \ + dpkg --add-architecture amd64 && \ + eatmydata apt-get update && \ + eatmydata apt-get dist-upgrade -y && \ + eatmydata apt-get install --no-install-recommends -y dpkg-dev && \ + eatmydata apt-get install --no-install-recommends -y \ + g++-x86-64-linux-gnu \ + gcc-x86-64-linux-gnu \ + libaio-dev:amd64 \ + libasan5:amd64 \ + libasound2-dev:amd64 \ + libattr1-dev:amd64 \ + libbpf-dev:amd64 \ + libbrlapi-dev:amd64 \ + libbz2-dev:amd64 \ + libc6-dev:amd64 \ + libcacard-dev:amd64 \ + libcap-ng-dev:amd64 \ + libcapstone-dev:amd64 \ + libcmocka-dev:amd64 \ + libcurl4-gnutls-dev:amd64 \ + libdaxctl-dev:amd64 \ + libdrm-dev:amd64 \ + libepoxy-dev:amd64 \ + libfdt-dev:amd64 \ + libffi-dev:amd64 \ + libfuse3-dev:amd64 \ + libgbm-dev:amd64 \ + libgcrypt20-dev:amd64 \ + libglib2.0-dev:amd64 \ + libglusterfs-dev:amd64 \ + libgnutls28-dev:amd64 \ + libgtk-3-dev:amd64 \ + libibumad-dev:amd64 \ + libibverbs-dev:amd64 \ + libiscsi-dev:amd64 \ + libjemalloc-dev:amd64 \ + libjpeg62-turbo-dev:amd64 \ + libjson-c-dev:amd64 \ + liblttng-ust-dev:amd64 \ + liblzo2-dev:amd64 \ + libncursesw5-dev:amd64 \ + libnfs-dev:amd64 \ + libnuma-dev:amd64 \ + libpam0g-dev:amd64 \ + libpixman-1-dev:amd64 \ + libpmem-dev:amd64 \ + libpng-dev:amd64 \ + libpulse-dev:amd64 \ + librbd-dev:amd64 \ + librdmacm-dev:amd64 \ + libsasl2-dev:amd64 \ + libsdl2-dev:amd64 \ + libsdl2-image-dev:amd64 \ + libseccomp-dev:amd64 \ + libselinux1-dev:amd64 \ + libslirp-dev:amd64 \ + libsnappy-dev:amd64 \ + libspice-server-dev:amd64 \ + libssh-gcrypt-dev:amd64 \ + libsystemd-dev:amd64 \ + libtasn1-6-dev:amd64 \ + libubsan1:amd64 \ + libudev-dev:amd64 \ + liburing-dev:amd64 \ + libusb-1.0-0-dev:amd64 \ + libusbredirhost-dev:amd64 \ + libvdeplug-dev:amd64 \ + libvirglrenderer-dev:amd64 \ + libvte-2.91-dev:amd64 \ + libxen-dev:amd64 \ + libzstd-dev:amd64 \ + nettle-dev:amd64 \ + systemtap-sdt-dev:amd64 \ + xfslibs-dev:amd64 \ + zlib1g-dev:amd64 && \ + eatmydata apt-get autoremove -y && \ + eatmydata apt-get autoclean -y && \ + mkdir -p /usr/local/share/meson/cross && \ + echo "[binaries]\n\ +c = '/usr/bin/x86_64-linux-gnu-gcc'\n\ +ar = '/usr/bin/x86_64-linux-gnu-gcc-ar'\n\ +strip = '/usr/bin/x86_64-linux-gnu-strip'\n\ +pkgconfig = '/usr/bin/x86_64-linux-gnu-pkg-config'\n\ +\n\ +[host_machine]\n\ +system = 'linux'\n\ +cpu_family = 'x86_64'\n\ +cpu = 'x86_64'\n\ +endian = 'little'" > /usr/local/share/meson/cross/x86_64-linux-gnu && \ + dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \ + mkdir -p /usr/libexec/ccache-wrappers && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/x86_64-linux-gnu-c++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/x86_64-linux-gnu-cc && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/x86_64-linux-gnu-g++ && \ + ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/x86_64-linux-gnu-gcc + +ENV ABI "x86_64-linux-gnu" +ENV MESON_OPTS "--cross-file=x86_64-linux-gnu" ENV QEMU_CONFIGURE_OPTS --cross-prefix=x86_64-linux-gnu- ENV DEF_TARGET_LIST x86_64-softmmu,x86_64-linux-user,i386-softmmu,i386-linux-user diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index 2a59150322..fc604d8a21 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -119,6 +119,13 @@ try: # # Cross compiling builds # + generate_dockerfile("debian-amd64-cross", "debian-11", + cross="x86_64", + trailer=debian_cross_build("x86_64-linux-gnu-", + "x86_64-softmmu," + "x86_64-linux-user," + "i386-softmmu,i386-linux-user")) + generate_dockerfile("debian-arm64-cross", "debian-11", cross="aarch64", trailer=debian_cross_build("aarch64-linux-gnu-", From 35782a1b9a2ee71fb037bf1ec6379d5720abf817 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:46 +0100 Subject: [PATCH 0543/1020] tests/docker: update and flatten debian-loongarch-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile. We really don't need the rest of the stuff from the QEMU base image just to compile test images. In this case it is a binary distribution of the toolchain anyway. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220914155950.804707-27-alex.bennee@linaro.org> --- tests/docker/Makefile.include | 1 - tests/docker/dockerfiles/debian-loongarch-cross.docker | 8 +++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index a0f5109628..1d5a6f1fb4 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -128,7 +128,6 @@ docker-image-debian-nios2-cross: $(DOCKER_FILES_DIR)/debian-toolchain.docker \ $(call debian-toolchain, $@) # Specialist build images, sometimes very limited tools -docker-image-debian-loongarch-cross: docker-image-debian11 docker-image-debian-microblaze-cross: docker-image-debian10 docker-image-debian-nios2-cross: docker-image-debian10 diff --git a/tests/docker/dockerfiles/debian-loongarch-cross.docker b/tests/docker/dockerfiles/debian-loongarch-cross.docker index ca2469d2a8..a8e8e98909 100644 --- a/tests/docker/dockerfiles/debian-loongarch-cross.docker +++ b/tests/docker/dockerfiles/debian-loongarch-cross.docker @@ -1,11 +1,13 @@ # # Docker cross-compiler target # -# This docker target builds on the debian11 base image, -# using a prebuilt toolchains for LoongArch64 from: +# This docker target uses prebuilt toolchains for LoongArch64 from: # https://github.com/loongson/build-tools/releases # -FROM qemu/debian11 +FROM docker.io/library/debian:11-slim + +# Duplicate deb line as deb-src +RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list RUN apt-get update && \ DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \ From 581cd47fe5a708ebd999bd426a111984074c9ea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:47 +0100 Subject: [PATCH 0544/1020] tests/docker: update and flatten debian-hexagon-cross MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile as we do not some of the extraneous packages from the base image to build the toolchain. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-28-alex.bennee@linaro.org> --- .../dockerfiles/debian-hexagon-cross.docker | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/docker/dockerfiles/debian-hexagon-cross.docker b/tests/docker/dockerfiles/debian-hexagon-cross.docker index d5dc299dc1..8d219bb81d 100644 --- a/tests/docker/dockerfiles/debian-hexagon-cross.docker +++ b/tests/docker/dockerfiles/debian-hexagon-cross.docker @@ -2,12 +2,10 @@ # Docker Hexagon cross-compiler target # # This docker target is used for building hexagon tests. As it also -# needs to be able to build QEMU itself in CI we include it's -# build-deps. It is also a "stand-alone" image so as not to be -# triggered by re-builds on other base images given it takes a long -# time to build. +# needs to be able to build QEMU itself in CI we include its +# build-deps. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim # Install common build utilities RUN apt update && \ @@ -15,11 +13,18 @@ RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ bison \ + ca-certificates \ + clang \ cmake \ flex \ + gcc \ lld \ + make \ + ninja-build \ + python3 \ rsync \ - wget + wget \ + xz-utils ENV TOOLCHAIN_INSTALL /usr/local ENV ROOTFS /usr/local @@ -32,7 +37,7 @@ ADD build-toolchain.sh /root/hexagon-toolchain/build-toolchain.sh RUN cd /root/hexagon-toolchain && ./build-toolchain.sh -FROM debian:buster-slim +FROM docker.io/library/debian:11-slim # Duplicate deb line as deb-src RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list # Install QEMU build deps for use in CI From 4239162add71101feddeaba216d576c581128975 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:48 +0100 Subject: [PATCH 0545/1020] tests/docker: update and flatten debian-toolchain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to the latest stable Debian. While we are at it flatten into a single dockerfile as we do not need anything from the base image to build the toolchain. This is used to build both the nios and microblaze toolchains. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-29-alex.bennee@linaro.org> --- tests/docker/Makefile.include | 4 ---- tests/docker/dockerfiles/debian-toolchain.docker | 5 +++-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 1d5a6f1fb4..a3174346da 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -127,10 +127,6 @@ docker-image-debian-nios2-cross: $(DOCKER_FILES_DIR)/debian-toolchain.docker \ $(DOCKER_FILES_DIR)/debian-nios2-cross.d/build-toolchain.sh $(call debian-toolchain, $@) -# Specialist build images, sometimes very limited tools -docker-image-debian-microblaze-cross: docker-image-debian10 -docker-image-debian-nios2-cross: docker-image-debian10 - # These images may be good enough for building tests but not for test builds DOCKER_PARTIAL_IMAGES += debian-alpha-cross DOCKER_PARTIAL_IMAGES += debian-powerpc-test-cross diff --git a/tests/docker/dockerfiles/debian-toolchain.docker b/tests/docker/dockerfiles/debian-toolchain.docker index 738d808aa6..d3d4d3344e 100644 --- a/tests/docker/dockerfiles/debian-toolchain.docker +++ b/tests/docker/dockerfiles/debian-toolchain.docker @@ -4,7 +4,7 @@ # This dockerfile is used for building a cross-compiler toolchain. # The script for building the toolchain is supplied via extra-files. # -FROM qemu/debian10 +FROM docker.io/library/debian:11-slim # Install build utilities for building gcc and glibc. # ??? The build-dep isn't working, missing a number of @@ -15,6 +15,7 @@ RUN apt update && \ DEBIAN_FRONTEND=noninteractive eatmydata \ apt install -y --no-install-recommends \ bison \ + ca-certificates \ flex \ gawk \ libmpc-dev \ @@ -32,5 +33,5 @@ RUN cd /root && ./build-toolchain.sh # Throw away the extra toolchain build deps, the downloaded source, # and the build trees by restoring the original debian10 image, # then copying the built toolchain from stage 0. -FROM qemu/debian10 +FROM docker.io/library/debian:bullseye-slim COPY --from=0 /usr/local /usr/local From 07056db1b504acf12a0a39647846030956445fea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:49 +0100 Subject: [PATCH 0546/1020] tests/docker: remove FROM qemu/ support from docker.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to migrate from docker.py to building our images directly with docker/podman. Before we get there we need to make sure we don't re-introduce our layered builds so bug out if we see FROM qemu/ in a Dockerfile. Signed-off-by: Alex BennĂ©e Acked-by: Thomas Huth Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-30-alex.bennee@linaro.org> --- tests/docker/docker.py | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-) diff --git a/tests/docker/docker.py b/tests/docker/docker.py index d0af2861b8..3a1ed7cb18 100755 --- a/tests/docker/docker.py +++ b/tests/docker/docker.py @@ -205,22 +205,17 @@ def _read_qemu_dockerfile(img_name): return _read_dockerfile(df) -def _dockerfile_preprocess(df): - out = "" +def _dockerfile_verify_flat(df): + "Verify we do not include other qemu/ layers" for l in df.splitlines(): if len(l.strip()) == 0 or l.startswith("#"): continue from_pref = "FROM qemu/" if l.startswith(from_pref): - # TODO: Alternatively we could replace this line with "FROM $ID" - # where $ID is the image's hex id obtained with - # $ docker images $IMAGE --format="{{.Id}}" - # but unfortunately that's not supported by RHEL 7. - inlining = _read_qemu_dockerfile(l[len(from_pref):]) - out += _dockerfile_preprocess(inlining) - continue - out += l + "\n" - return out + print("We no longer support multiple QEMU layers.") + print("Dockerfiles should be flat, ideally created by lcitool") + return False + return True class Docker(object): @@ -309,23 +304,10 @@ class Docker(object): if argv is None: argv = [] - # pre-calculate the docker checksum before any - # substitutions we make for caching - checksum = _text_checksum(_dockerfile_preprocess(dockerfile)) + if not _dockerfile_verify_flat(dockerfile): + return -1 - if registry is not None: - sources = re.findall("FROM qemu\/(.*)", dockerfile) - # Fetch any cache layers we can, may fail - for s in sources: - pull_args = ["pull", "%s/qemu/%s" % (registry, s)] - if self._do(pull_args, quiet=quiet) != 0: - registry = None - break - # Make substitutions - if registry is not None: - dockerfile = dockerfile.replace("FROM qemu/", - "FROM %s/qemu/" % - (registry)) + checksum = _text_checksum(dockerfile) tmp_df = tempfile.NamedTemporaryFile(mode="w+t", encoding='utf-8', @@ -371,7 +353,7 @@ class Docker(object): checksum = self.get_image_dockerfile_checksum(tag) except Exception: return False - return checksum == _text_checksum(_dockerfile_preprocess(dockerfile)) + return checksum == _text_checksum(dockerfile) def run(self, cmd, keep, quiet, as_user=False): label = uuid.uuid4().hex From d996f0aeb2fe8f5c5f30ac8a2f633e3196457d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Wed, 14 Sep 2022 16:59:50 +0100 Subject: [PATCH 0547/1020] tests/docker: remove the Debian base images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We no longer use these in any of our images. Clean-up the remaining comments and documentation that reference them and remove from the build. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Reviewed-by: Richard Henderson Message-Id: <20220914155950.804707-31-alex.bennee@linaro.org> --- .gitlab-ci.d/container-core.yml | 5 ---- .gitlab-ci.d/containers.yml | 5 ---- docs/devel/testing.rst | 2 +- tests/docker/Makefile.include | 8 +---- tests/docker/dockerfiles/debian10.docker | 38 ------------------------ tests/docker/dockerfiles/debian11.docker | 18 ----------- 6 files changed, 2 insertions(+), 74 deletions(-) delete mode 100644 tests/docker/dockerfiles/debian10.docker delete mode 100644 tests/docker/dockerfiles/debian11.docker diff --git a/.gitlab-ci.d/container-core.yml b/.gitlab-ci.d/container-core.yml index e8dd1f476a..08f8450fa1 100644 --- a/.gitlab-ci.d/container-core.yml +++ b/.gitlab-ci.d/container-core.yml @@ -10,8 +10,3 @@ amd64-fedora-container: extends: .container_job_template variables: NAME: fedora - -amd64-debian10-container: - extends: .container_job_template - variables: - NAME: debian10 diff --git a/.gitlab-ci.d/containers.yml b/.gitlab-ci.d/containers.yml index be34cbc7ba..96d2a3b58b 100644 --- a/.gitlab-ci.d/containers.yml +++ b/.gitlab-ci.d/containers.yml @@ -7,11 +7,6 @@ amd64-alpine-container: variables: NAME: alpine -amd64-debian11-container: - extends: .container_job_template - variables: - NAME: debian11 - amd64-debian-container: extends: .container_job_template stage: containers diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index f35f117d95..aea5b42356 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -375,7 +375,7 @@ locally by using the ``NOCACHE`` build option: .. code:: - make docker-image-debian10 NOCACHE=1 + make docker-image-debian-arm64-cross NOCACHE=1 Images ~~~~~~ diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index a3174346da..270e99786e 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -69,9 +69,7 @@ docker-binfmt-image-debian-%: $(DOCKER_FILES_DIR)/debian-bootstrap.docker { echo "You will need to build $(EXECUTABLE)"; exit 1;},\ "CHECK", "debian-$* exists")) -# Enforce dependencies for composite images -# we don't run tests on intermediate images (used as base by another image) -DOCKER_PARTIAL_IMAGES := debian10 debian11 +# Special case cross-compiling x86_64 on non-x86_64 systems. ifeq ($(HOST_ARCH),x86_64) DOCKER_PARTIAL_IMAGES += debian-amd64-cross else @@ -89,10 +87,6 @@ endif # The native build should never use the registry docker-image-debian-native: DOCKER_REGISTRY= -# base images should not add a local user -docker-image-debian10: NOUSER=1 -docker-image-debian11: NOUSER=1 - # alpine has no adduser docker-image-alpine: NOUSER=1 diff --git a/tests/docker/dockerfiles/debian10.docker b/tests/docker/dockerfiles/debian10.docker deleted file mode 100644 index 03be923066..0000000000 --- a/tests/docker/dockerfiles/debian10.docker +++ /dev/null @@ -1,38 +0,0 @@ -# -# Docker multiarch cross-compiler target -# -# This docker target is builds on Debian cross compiler targets to build distro -# with a selection of cross compilers for building test binaries. -# -# On its own you can't build much but the docker-foo-cross targets -# build on top of the base debian image. -# -FROM docker.io/library/debian:buster-slim - -# Duplicate deb line as deb-src -RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list - -# Install common build utilities -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata && \ - DEBIAN_FRONTEND=noninteractive eatmydata \ - apt install -y --no-install-recommends \ - bc \ - build-essential \ - ca-certificates \ - ccache \ - clang \ - dbus \ - gdb-multiarch \ - gettext \ - git \ - libffi-dev \ - libncurses5-dev \ - ninja-build \ - pkg-config \ - psmisc \ - python3 \ - python3-sphinx \ - python3-sphinx-rtd-theme \ - python3-venv \ - $(apt-get -s build-dep --arch-only qemu | egrep ^Inst | fgrep '[all]' | cut -d\ -f2) diff --git a/tests/docker/dockerfiles/debian11.docker b/tests/docker/dockerfiles/debian11.docker deleted file mode 100644 index febf884f8f..0000000000 --- a/tests/docker/dockerfiles/debian11.docker +++ /dev/null @@ -1,18 +0,0 @@ -# -# Docker multiarch cross-compiler target -# -# This docker target uses the current development version of Debian as -# a base for cross compilers for building test binaries. We won't -# attempt to build QEMU on it yet given it is still in development. -# -# On its own you can't build much but the docker-foo-cross targets -# build on top of the base debian image. -# -FROM docker.io/library/debian:bullseye-slim - -# Duplicate deb line as deb-src -RUN cat /etc/apt/sources.list | sed "s/^deb\ /deb-src /" >> /etc/apt/sources.list - -# Install common build utilities -RUN apt update && \ - DEBIAN_FRONTEND=noninteractive apt install -yy eatmydata From 5934dae7a747f0aed24e8d20936ca5e117d95ad9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 22:17:46 -0700 Subject: [PATCH 0548/1020] target/m68k: Implement atomic test-and-set This is slightly more complicated than cas, because tas is allowed on data registers. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220829051746.227094-1-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- target/m68k/translate.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 5098f7e570..ffcc761d60 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -2825,19 +2825,39 @@ DISAS_INSN(illegal) gen_exception(s, s->base.pc_next, EXCP_ILLEGAL); } -/* ??? This should be atomic. */ DISAS_INSN(tas) { - TCGv dest; - TCGv src1; - TCGv addr; + int mode = extract32(insn, 3, 3); + int reg0 = REG(insn, 0); - dest = tcg_temp_new(); - SRC_EA(env, src1, OS_BYTE, 1, &addr); - gen_logic_cc(s, src1, OS_BYTE); - tcg_gen_ori_i32(dest, src1, 0x80); - DEST_EA(env, insn, OS_BYTE, dest, &addr); - tcg_temp_free(dest); + if (mode == 0) { + /* data register direct */ + TCGv dest = cpu_dregs[reg0]; + gen_logic_cc(s, dest, OS_BYTE); + tcg_gen_ori_tl(dest, dest, 0x80); + } else { + TCGv src1, addr; + + addr = gen_lea_mode(env, s, mode, reg0, OS_BYTE); + if (IS_NULL_QREG(addr)) { + gen_addr_fault(s); + return; + } + src1 = tcg_temp_new(); + tcg_gen_atomic_fetch_or_tl(src1, addr, tcg_constant_tl(0x80), + IS_USER(s), MO_SB); + gen_logic_cc(s, src1, OS_BYTE); + tcg_temp_free(src1); + + switch (mode) { + case 3: /* Indirect postincrement. */ + tcg_gen_addi_i32(AREG(insn, 0), addr, 1); + break; + case 4: /* Indirect predecrememnt. */ + tcg_gen_mov_i32(AREG(insn, 0), addr); + break; + } + } } DISAS_INSN(mull) From 24ec52f91dfb6d26d7035093adca60d18f02074e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 13 Sep 2022 15:28:17 +0100 Subject: [PATCH 0549/1020] target/m68k: Fix MACSR to CCR First, we were writing to the entire SR register, instead of only the flags portion. Second, we were not clearing C as per the documentation (X was cleared via the 0xf mask). Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220913142818.7802-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- target/m68k/translate.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index ffcc761d60..c9bb053803 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -5912,8 +5912,10 @@ DISAS_INSN(from_mext) DISAS_INSN(macsr_to_ccr) { TCGv tmp = tcg_temp_new(); - tcg_gen_andi_i32(tmp, QREG_MACSR, 0xf); - gen_helper_set_sr(cpu_env, tmp); + + /* Note that X and C are always cleared. */ + tcg_gen_andi_i32(tmp, QREG_MACSR, CCF_N | CCF_Z | CCF_V); + gen_helper_set_ccr(cpu_env, tmp); tcg_temp_free(tmp); set_cc_op(s, CC_OP_FLAGS); } From 214c6002d0263bce2225e23983e58d36740a6e1d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 13 Sep 2022 15:28:18 +0100 Subject: [PATCH 0550/1020] target/m68k: Perform writback before modifying SR Writes to SR may change security state, which may involve a swap of %ssp with %usp as reflected in %a7. Finish the writeback of %sp@+ before swapping stack pointers. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1206 Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Reviewed-by: Mark Cave-Ayland Message-Id: <20220913142818.7802-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- target/m68k/translate.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index c9bb053803..4640eadf78 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -2285,9 +2285,9 @@ static void gen_set_sr_im(DisasContext *s, uint16_t val, int ccr_only) tcg_gen_movi_i32(QREG_CC_N, val & CCF_N ? -1 : 0); tcg_gen_movi_i32(QREG_CC_X, val & CCF_X ? 1 : 0); } else { - TCGv sr = tcg_const_i32(val); - gen_helper_set_sr(cpu_env, sr); - tcg_temp_free(sr); + /* Must writeback before changing security state. */ + do_writebacks(s); + gen_helper_set_sr(cpu_env, tcg_constant_i32(val)); } set_cc_op(s, CC_OP_FLAGS); } @@ -2297,6 +2297,8 @@ static void gen_set_sr(DisasContext *s, TCGv val, int ccr_only) if (ccr_only) { gen_helper_set_ccr(cpu_env, val); } else { + /* Must writeback before changing security state. */ + do_writebacks(s); gen_helper_set_sr(cpu_env, val); } set_cc_op(s, CC_OP_FLAGS); From aece90d85df4c33e413af6ba75964acb304945f5 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 17 Sep 2022 12:25:12 +0100 Subject: [PATCH 0551/1020] target/m68k: rename M68K_FEATURE_M68000 to M68K_FEATURE_M68K MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The M68K_FEATURE_M68000 feature is misleading in that its name suggests the feature is defined just for Motorola 68000 CPUs, whilst in fact it is defined for all Motorola 680X0 CPUs. In order to avoid confusion with the other M68K_FEATURE_M680X0 constants which define the features available for specific Motorola CPU models, rename M68K_FEATURE_M68000 to M68K_FEATURE_M68K and add comments to clarify its usage. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220917112515.83905-2-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier --- target/m68k/cpu.c | 2 +- target/m68k/cpu.h | 5 +- target/m68k/helper.c | 2 +- target/m68k/op_helper.c | 2 +- target/m68k/translate.c | 138 ++++++++++++++++++++-------------------- 5 files changed, 75 insertions(+), 74 deletions(-) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 5bbefda575..f681be3a2a 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -110,7 +110,7 @@ static void m68000_cpu_initfn(Object *obj) M68kCPU *cpu = M68K_CPU(obj); CPUM68KState *env = &cpu->env; - m68k_set_feature(env, M68K_FEATURE_M68000); + m68k_set_feature(env, M68K_FEATURE_M68K); m68k_set_feature(env, M68K_FEATURE_USP); m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); m68k_set_feature(env, M68K_FEATURE_MOVEP); diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index 4d8f48e8c7..67b6c12c28 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -480,8 +480,9 @@ void do_m68k_semihosting(CPUM68KState *env, int nr); */ enum m68k_features { - /* Base m68k instruction set */ - M68K_FEATURE_M68000, + /* Base Motorola CPU set (not set for Coldfire CPUs) */ + M68K_FEATURE_M68K, + /* Motorola CPU feature sets */ M68K_FEATURE_M68010, M68K_FEATURE_M68020, M68K_FEATURE_M68030, diff --git a/target/m68k/helper.c b/target/m68k/helper.c index 5728e48585..4621cf2402 100644 --- a/target/m68k/helper.c +++ b/target/m68k/helper.c @@ -460,7 +460,7 @@ void m68k_switch_sp(CPUM68KState *env) int new_sp; env->sp[env->current_sp] = env->aregs[7]; - if (m68k_feature(env, M68K_FEATURE_M68000)) { + if (m68k_feature(env, M68K_FEATURE_M68K)) { if (env->sr & SR_S) { /* SR:Master-Mode bit unimplemented then ISP is not available */ if (!m68k_feature(env, M68K_FEATURE_MSP) || env->sr & SR_M) { diff --git a/target/m68k/op_helper.c b/target/m68k/op_helper.c index a96a034050..5da176d642 100644 --- a/target/m68k/op_helper.c +++ b/target/m68k/op_helper.c @@ -432,7 +432,7 @@ static void m68k_interrupt_all(CPUM68KState *env, int is_hw) static void do_interrupt_all(CPUM68KState *env, int is_hw) { - if (m68k_feature(env, M68K_FEATURE_M68000)) { + if (m68k_feature(env, M68K_FEATURE_M68K)) { m68k_interrupt_all(env, is_hw); return; } diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 4640eadf78..0b618e8eb2 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -471,7 +471,7 @@ static TCGv gen_lea_indexed(CPUM68KState *env, DisasContext *s, TCGv base) if ((ext & 0x800) == 0 && !m68k_feature(s->env, M68K_FEATURE_WORD_INDEX)) return NULL_QREG; - if (m68k_feature(s->env, M68K_FEATURE_M68000) && + if (m68k_feature(s->env, M68K_FEATURE_M68K) && !m68k_feature(s->env, M68K_FEATURE_SCALED_INDEX)) { ext &= ~(3 << 9); } @@ -804,7 +804,7 @@ static TCGv gen_lea_mode(CPUM68KState *env, DisasContext *s, reg = get_areg(s, reg0); tmp = mark_to_release(s, tcg_temp_new()); if (reg0 == 7 && opsize == OS_BYTE && - m68k_feature(s->env, M68K_FEATURE_M68000)) { + m68k_feature(s->env, M68K_FEATURE_M68K)) { tcg_gen_subi_i32(tmp, reg, 2); } else { tcg_gen_subi_i32(tmp, reg, opsize_bytes(opsize)); @@ -888,7 +888,7 @@ static TCGv gen_ea_mode(CPUM68KState *env, DisasContext *s, int mode, int reg0, if (what == EA_STORE || !addrp) { TCGv tmp = tcg_temp_new(); if (reg0 == 7 && opsize == OS_BYTE && - m68k_feature(s->env, M68K_FEATURE_M68000)) { + m68k_feature(s->env, M68K_FEATURE_M68K)) { tcg_gen_addi_i32(tmp, reg, 2); } else { tcg_gen_addi_i32(tmp, reg, opsize_bytes(opsize)); @@ -2210,7 +2210,7 @@ DISAS_INSN(bitop_im) op = (insn >> 6) & 3; bitnum = read_im16(env, s); - if (m68k_feature(s->env, M68K_FEATURE_M68000)) { + if (m68k_feature(s->env, M68K_FEATURE_M68K)) { if (bitnum & 0xfe00) { disas_undef(env, s, insn); return; @@ -2897,7 +2897,7 @@ DISAS_INSN(mull) return; } SRC_EA(env, src1, OS_LONG, 0, NULL); - if (m68k_feature(s->env, M68K_FEATURE_M68000)) { + if (m68k_feature(s->env, M68K_FEATURE_M68K)) { tcg_gen_movi_i32(QREG_CC_C, 0); if (sign) { tcg_gen_muls2_i32(QREG_CC_N, QREG_CC_V, src1, DREG(ext, 12)); @@ -3492,7 +3492,7 @@ static inline void shift_im(DisasContext *s, uint16_t insn, int opsize) * while M68000 sets if the most significant bit is changed at * any time during the shift operation. */ - if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) { + if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) { /* if shift count >= bits, V is (reg != 0) */ if (count >= bits) { tcg_gen_setcond_i32(TCG_COND_NE, QREG_CC_V, reg, QREG_CC_V); @@ -3576,7 +3576,7 @@ static inline void shift_reg(DisasContext *s, uint16_t insn, int opsize) * int64_t t = (int64_t)(intN_t)reg << count; * V = ((s ^ t) & (-1 << (bits - 1))) != 0 */ - if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) { + if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) { TCGv_i64 tt = tcg_const_i64(32); /* if shift is greater than 32, use 32 */ tcg_gen_movcond_i64(TCG_COND_GT, s64, s64, tt, tt, s64); @@ -3669,7 +3669,7 @@ DISAS_INSN(shift_mem) * while M68000 sets if the most significant bit is changed at * any time during the shift operation */ - if (!logical && m68k_feature(s->env, M68K_FEATURE_M68000)) { + if (!logical && m68k_feature(s->env, M68K_FEATURE_M68K)) { src = gen_extend(s, src, OS_WORD, 1); tcg_gen_xor_i32(QREG_CC_V, QREG_CC_N, src); } @@ -4620,7 +4620,7 @@ DISAS_INSN(move_from_sr) { TCGv sr; - if (IS_USER(s) && !m68k_feature(env, M68K_FEATURE_M68000)) { + if (IS_USER(s) && !m68k_feature(env, M68K_FEATURE_M68K)) { gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); return; } @@ -6035,7 +6035,7 @@ void register_m68k_insns (CPUM68KState *env) } while(0) BASE(undef, 0000, 0000); INSN(arith_im, 0080, fff8, CF_ISA_A); - INSN(arith_im, 0000, ff00, M68000); + INSN(arith_im, 0000, ff00, M68K); INSN(chk2, 00c0, f9c0, CHK2); INSN(bitrev, 00c0, fff8, CF_ISA_APLUSC); BASE(bitop_reg, 0100, f1c0); @@ -6044,26 +6044,26 @@ void register_m68k_insns (CPUM68KState *env) BASE(bitop_reg, 01c0, f1c0); INSN(movep, 0108, f138, MOVEP); INSN(arith_im, 0280, fff8, CF_ISA_A); - INSN(arith_im, 0200, ff00, M68000); - INSN(undef, 02c0, ffc0, M68000); + INSN(arith_im, 0200, ff00, M68K); + INSN(undef, 02c0, ffc0, M68K); INSN(byterev, 02c0, fff8, CF_ISA_APLUSC); INSN(arith_im, 0480, fff8, CF_ISA_A); - INSN(arith_im, 0400, ff00, M68000); - INSN(undef, 04c0, ffc0, M68000); - INSN(arith_im, 0600, ff00, M68000); - INSN(undef, 06c0, ffc0, M68000); + INSN(arith_im, 0400, ff00, M68K); + INSN(undef, 04c0, ffc0, M68K); + INSN(arith_im, 0600, ff00, M68K); + INSN(undef, 06c0, ffc0, M68K); INSN(ff1, 04c0, fff8, CF_ISA_APLUSC); INSN(arith_im, 0680, fff8, CF_ISA_A); INSN(arith_im, 0c00, ff38, CF_ISA_A); - INSN(arith_im, 0c00, ff00, M68000); + INSN(arith_im, 0c00, ff00, M68K); BASE(bitop_im, 0800, ffc0); BASE(bitop_im, 0840, ffc0); BASE(bitop_im, 0880, ffc0); BASE(bitop_im, 08c0, ffc0); INSN(arith_im, 0a80, fff8, CF_ISA_A); - INSN(arith_im, 0a00, ff00, M68000); + INSN(arith_im, 0a00, ff00, M68K); #if defined(CONFIG_SOFTMMU) - INSN(moves, 0e00, ff00, M68000); + INSN(moves, 0e00, ff00, M68K); #endif INSN(cas, 0ac0, ffc0, CAS); INSN(cas, 0cc0, ffc0, CAS); @@ -6073,44 +6073,44 @@ void register_m68k_insns (CPUM68KState *env) BASE(move, 1000, f000); BASE(move, 2000, f000); BASE(move, 3000, f000); - INSN(chk, 4000, f040, M68000); + INSN(chk, 4000, f040, M68K); INSN(strldsr, 40e7, ffff, CF_ISA_APLUSC); INSN(negx, 4080, fff8, CF_ISA_A); - INSN(negx, 4000, ff00, M68000); - INSN(undef, 40c0, ffc0, M68000); + INSN(negx, 4000, ff00, M68K); + INSN(undef, 40c0, ffc0, M68K); INSN(move_from_sr, 40c0, fff8, CF_ISA_A); - INSN(move_from_sr, 40c0, ffc0, M68000); + INSN(move_from_sr, 40c0, ffc0, M68K); BASE(lea, 41c0, f1c0); BASE(clr, 4200, ff00); BASE(undef, 42c0, ffc0); INSN(move_from_ccr, 42c0, fff8, CF_ISA_A); - INSN(move_from_ccr, 42c0, ffc0, M68000); + INSN(move_from_ccr, 42c0, ffc0, M68K); INSN(neg, 4480, fff8, CF_ISA_A); - INSN(neg, 4400, ff00, M68000); - INSN(undef, 44c0, ffc0, M68000); + INSN(neg, 4400, ff00, M68K); + INSN(undef, 44c0, ffc0, M68K); BASE(move_to_ccr, 44c0, ffc0); INSN(not, 4680, fff8, CF_ISA_A); - INSN(not, 4600, ff00, M68000); + INSN(not, 4600, ff00, M68K); #if defined(CONFIG_SOFTMMU) BASE(move_to_sr, 46c0, ffc0); #endif - INSN(nbcd, 4800, ffc0, M68000); - INSN(linkl, 4808, fff8, M68000); + INSN(nbcd, 4800, ffc0, M68K); + INSN(linkl, 4808, fff8, M68K); BASE(pea, 4840, ffc0); BASE(swap, 4840, fff8); INSN(bkpt, 4848, fff8, BKPT); INSN(movem, 48d0, fbf8, CF_ISA_A); INSN(movem, 48e8, fbf8, CF_ISA_A); - INSN(movem, 4880, fb80, M68000); + INSN(movem, 4880, fb80, M68K); BASE(ext, 4880, fff8); BASE(ext, 48c0, fff8); BASE(ext, 49c0, fff8); BASE(tst, 4a00, ff00); INSN(tas, 4ac0, ffc0, CF_ISA_B); - INSN(tas, 4ac0, ffc0, M68000); + INSN(tas, 4ac0, ffc0, M68K); #if defined(CONFIG_SOFTMMU) INSN(halt, 4ac8, ffff, CF_ISA_A); - INSN(halt, 4ac8, ffff, M68060); + INSN(halt, 4ac8, ffff, M68K); #endif INSN(pulse, 4acc, ffff, CF_ISA_A); BASE(illegal, 4afc, ffff); @@ -6125,7 +6125,7 @@ void register_m68k_insns (CPUM68KState *env) #if defined(CONFIG_SOFTMMU) INSN(move_to_usp, 4e60, fff8, USP); INSN(move_from_usp, 4e68, fff8, USP); - INSN(reset, 4e70, ffff, M68000); + INSN(reset, 4e70, ffff, M68K); BASE(stop, 4e72, ffff); BASE(rte, 4e73, ffff); INSN(cf_movec, 4e7b, ffff, CF_ISA_A); @@ -6134,15 +6134,15 @@ void register_m68k_insns (CPUM68KState *env) BASE(nop, 4e71, ffff); INSN(rtd, 4e74, ffff, RTD); BASE(rts, 4e75, ffff); - INSN(trapv, 4e76, ffff, M68000); - INSN(rtr, 4e77, ffff, M68000); + INSN(trapv, 4e76, ffff, M68K); + INSN(rtr, 4e77, ffff, M68K); BASE(jump, 4e80, ffc0); BASE(jump, 4ec0, ffc0); - INSN(addsubq, 5000, f080, M68000); + INSN(addsubq, 5000, f080, M68K); BASE(addsubq, 5080, f0c0); INSN(scc, 50c0, f0f8, CF_ISA_A); /* Scc.B Dx */ - INSN(scc, 50c0, f0c0, M68000); /* Scc.B */ - INSN(dbcc, 50c8, f0f8, M68000); + INSN(scc, 50c0, f0c0, M68K); /* Scc.B */ + INSN(dbcc, 50c8, f0f8, M68K); INSN(trapcc, 50fa, f0fe, TRAPCC); /* opmode 010, 011 */ INSN(trapcc, 50fc, f0ff, TRAPCC); /* opmode 100 */ INSN(trapcc, 51fa, fffe, CF_ISA_A); /* TPF (trapf) opmode 010, 011 */ @@ -6161,15 +6161,15 @@ void register_m68k_insns (CPUM68KState *env) INSN(mvzs, 7100, f100, CF_ISA_B); BASE(or, 8000, f000); BASE(divw, 80c0, f0c0); - INSN(sbcd_reg, 8100, f1f8, M68000); - INSN(sbcd_mem, 8108, f1f8, M68000); + INSN(sbcd_reg, 8100, f1f8, M68K); + INSN(sbcd_mem, 8108, f1f8, M68K); BASE(addsub, 9000, f000); INSN(undef, 90c0, f0c0, CF_ISA_A); INSN(subx_reg, 9180, f1f8, CF_ISA_A); - INSN(subx_reg, 9100, f138, M68000); - INSN(subx_mem, 9108, f138, M68000); + INSN(subx_reg, 9100, f138, M68K); + INSN(subx_mem, 9108, f138, M68K); INSN(suba, 91c0, f1c0, CF_ISA_A); - INSN(suba, 90c0, f0c0, M68000); + INSN(suba, 90c0, f0c0, M68K); BASE(undef_mac, a000, f000); INSN(mac, a000, f100, CF_EMAC); @@ -6190,41 +6190,41 @@ void register_m68k_insns (CPUM68KState *env) INSN(cmpa, b0c0, f1c0, CF_ISA_B); /* cmpa.w */ INSN(cmp, b080, f1c0, CF_ISA_A); INSN(cmpa, b1c0, f1c0, CF_ISA_A); - INSN(cmp, b000, f100, M68000); - INSN(eor, b100, f100, M68000); - INSN(cmpm, b108, f138, M68000); - INSN(cmpa, b0c0, f0c0, M68000); + INSN(cmp, b000, f100, M68K); + INSN(eor, b100, f100, M68K); + INSN(cmpm, b108, f138, M68K); + INSN(cmpa, b0c0, f0c0, M68K); INSN(eor, b180, f1c0, CF_ISA_A); BASE(and, c000, f000); - INSN(exg_dd, c140, f1f8, M68000); - INSN(exg_aa, c148, f1f8, M68000); - INSN(exg_da, c188, f1f8, M68000); + INSN(exg_dd, c140, f1f8, M68K); + INSN(exg_aa, c148, f1f8, M68K); + INSN(exg_da, c188, f1f8, M68K); BASE(mulw, c0c0, f0c0); - INSN(abcd_reg, c100, f1f8, M68000); - INSN(abcd_mem, c108, f1f8, M68000); + INSN(abcd_reg, c100, f1f8, M68K); + INSN(abcd_mem, c108, f1f8, M68K); BASE(addsub, d000, f000); INSN(undef, d0c0, f0c0, CF_ISA_A); INSN(addx_reg, d180, f1f8, CF_ISA_A); - INSN(addx_reg, d100, f138, M68000); - INSN(addx_mem, d108, f138, M68000); + INSN(addx_reg, d100, f138, M68K); + INSN(addx_mem, d108, f138, M68K); INSN(adda, d1c0, f1c0, CF_ISA_A); - INSN(adda, d0c0, f0c0, M68000); + INSN(adda, d0c0, f0c0, M68K); INSN(shift_im, e080, f0f0, CF_ISA_A); INSN(shift_reg, e0a0, f0f0, CF_ISA_A); - INSN(shift8_im, e000, f0f0, M68000); - INSN(shift16_im, e040, f0f0, M68000); - INSN(shift_im, e080, f0f0, M68000); - INSN(shift8_reg, e020, f0f0, M68000); - INSN(shift16_reg, e060, f0f0, M68000); - INSN(shift_reg, e0a0, f0f0, M68000); - INSN(shift_mem, e0c0, fcc0, M68000); - INSN(rotate_im, e090, f0f0, M68000); - INSN(rotate8_im, e010, f0f0, M68000); - INSN(rotate16_im, e050, f0f0, M68000); - INSN(rotate_reg, e0b0, f0f0, M68000); - INSN(rotate8_reg, e030, f0f0, M68000); - INSN(rotate16_reg, e070, f0f0, M68000); - INSN(rotate_mem, e4c0, fcc0, M68000); + INSN(shift8_im, e000, f0f0, M68K); + INSN(shift16_im, e040, f0f0, M68K); + INSN(shift_im, e080, f0f0, M68K); + INSN(shift8_reg, e020, f0f0, M68K); + INSN(shift16_reg, e060, f0f0, M68K); + INSN(shift_reg, e0a0, f0f0, M68K); + INSN(shift_mem, e0c0, fcc0, M68K); + INSN(rotate_im, e090, f0f0, M68K); + INSN(rotate8_im, e010, f0f0, M68K); + INSN(rotate16_im, e050, f0f0, M68K); + INSN(rotate_reg, e0b0, f0f0, M68K); + INSN(rotate8_reg, e030, f0f0, M68K); + INSN(rotate16_reg, e070, f0f0, M68K); + INSN(rotate_mem, e4c0, fcc0, M68K); INSN(bfext_mem, e9c0, fdc0, BITFIELD); /* bfextu & bfexts */ INSN(bfext_reg, e9c0, fdf8, BITFIELD); INSN(bfins_mem, efc0, ffc0, BITFIELD); From c7546abfaa1b1c2729eaddd41c6268a73cdae14f Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sat, 17 Sep 2022 12:25:15 +0100 Subject: [PATCH 0552/1020] target/m68k: always call gen_exit_tb() after writes to SR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Any write to SR can change the security state so always call gen_exit_tb() when this occurs. In particular MacOS makes use of andiw/oriw in a few places to handle the switch between user and supervisor mode. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220917112515.83905-5-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier --- target/m68k/translate.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 0b618e8eb2..233b9d8e57 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -2375,6 +2375,7 @@ DISAS_INSN(arith_im) tcg_gen_or_i32(dest, src1, im); if (with_SR) { gen_set_sr(s, dest, opsize == OS_BYTE); + gen_exit_tb(s); } else { DEST_EA(env, insn, opsize, dest, &addr); gen_logic_cc(s, dest, opsize); @@ -2384,6 +2385,7 @@ DISAS_INSN(arith_im) tcg_gen_and_i32(dest, src1, im); if (with_SR) { gen_set_sr(s, dest, opsize == OS_BYTE); + gen_exit_tb(s); } else { DEST_EA(env, insn, opsize, dest, &addr); gen_logic_cc(s, dest, opsize); @@ -2407,6 +2409,7 @@ DISAS_INSN(arith_im) tcg_gen_xor_i32(dest, src1, im); if (with_SR) { gen_set_sr(s, dest, opsize == OS_BYTE); + gen_exit_tb(s); } else { DEST_EA(env, insn, opsize, dest, &addr); gen_logic_cc(s, dest, opsize); @@ -4614,6 +4617,7 @@ DISAS_INSN(strldsr) } gen_push(s, gen_get_sr(s)); gen_set_sr_im(s, ext, 0); + gen_exit_tb(s); } DISAS_INSN(move_from_sr) From b91b6b5a2cd83a096116929dfc8e016091080adc Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 8 Sep 2022 11:40:30 +0200 Subject: [PATCH 0553/1020] hw/microblaze: pass random seed to fdt If the FDT contains /chosen/rng-seed, then the Linux RNG will use it to initialize early. Set this using the usual guest random number generation function. This FDT node is part of the DT specification. Reviewed-by: Edgar E. Iglesias Signed-off-by: Jason A. Donenfeld Signed-off-by: Edgar E. Iglesias --- hw/microblaze/boot.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c index 8b92a9801a..25ad54754e 100644 --- a/hw/microblaze/boot.c +++ b/hw/microblaze/boot.c @@ -30,6 +30,7 @@ #include "qemu/option.h" #include "qemu/config-file.h" #include "qemu/error-report.h" +#include "qemu/guest-random.h" #include "sysemu/device_tree.h" #include "sysemu/reset.h" #include "hw/boards.h" @@ -75,6 +76,7 @@ static int microblaze_load_dtb(hwaddr addr, int fdt_size; void *fdt = NULL; int r; + uint8_t rng_seed[32]; if (dtb_filename) { fdt = load_device_tree(dtb_filename, &fdt_size); @@ -83,6 +85,9 @@ static int microblaze_load_dtb(hwaddr addr, return 0; } + qemu_guest_getrandom_nofail(rng_seed, sizeof(rng_seed)); + qemu_fdt_setprop(fdt, "/chosen", "rng-seed", rng_seed, sizeof(rng_seed)); + if (kernel_cmdline) { r = qemu_fdt_setprop_string(fdt, "/chosen", "bootargs", kernel_cmdline); From fb96d131eec66ecb2993c544058a8cb2c9c3521f Mon Sep 17 00:00:00 2001 From: Anton Kochkov Date: Wed, 17 Aug 2022 14:22:03 +0000 Subject: [PATCH 0554/1020] hw/net/can: fix Xilinx ZynqMP CAN RX FIFO logic For consistency, function "update_rx_fifo()" should use the RX FIFO register field names, not the TX FIFO ones, even if they refer to the same bit positions in the register. Signed-off-by: Anton Kochkov Reviewed-by: Francisco Iglesias Message-id: 20220817141754.2105981-1-anton.kochkov@proton.me Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1123 [PMM: tweaked commit message] Signed-off-by: Peter Maydell --- hw/net/can/xlnx-zynqmp-can.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c index 82ac48cee2..e93e6c5e19 100644 --- a/hw/net/can/xlnx-zynqmp-can.c +++ b/hw/net/can/xlnx-zynqmp-can.c @@ -696,30 +696,30 @@ static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame) timestamp)); /* First 32 bit of the data. */ - fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT, - R_TXFIFO_DATA1_DB3_LENGTH, + fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DATA1_DB3_SHIFT, + R_RXFIFO_DATA1_DB3_LENGTH, frame->data[0]) | - deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT, - R_TXFIFO_DATA1_DB2_LENGTH, + deposit32(0, R_RXFIFO_DATA1_DB2_SHIFT, + R_RXFIFO_DATA1_DB2_LENGTH, frame->data[1]) | - deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT, - R_TXFIFO_DATA1_DB1_LENGTH, + deposit32(0, R_RXFIFO_DATA1_DB1_SHIFT, + R_RXFIFO_DATA1_DB1_LENGTH, frame->data[2]) | - deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT, - R_TXFIFO_DATA1_DB0_LENGTH, + deposit32(0, R_RXFIFO_DATA1_DB0_SHIFT, + R_RXFIFO_DATA1_DB0_LENGTH, frame->data[3])); /* Last 32 bit of the data. */ - fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT, - R_TXFIFO_DATA2_DB7_LENGTH, + fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DATA2_DB7_SHIFT, + R_RXFIFO_DATA2_DB7_LENGTH, frame->data[4]) | - deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT, - R_TXFIFO_DATA2_DB6_LENGTH, + deposit32(0, R_RXFIFO_DATA2_DB6_SHIFT, + R_RXFIFO_DATA2_DB6_LENGTH, frame->data[5]) | - deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT, - R_TXFIFO_DATA2_DB5_LENGTH, + deposit32(0, R_RXFIFO_DATA2_DB5_SHIFT, + R_RXFIFO_DATA2_DB5_LENGTH, frame->data[6]) | - deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT, - R_TXFIFO_DATA2_DB4_LENGTH, + deposit32(0, R_RXFIFO_DATA2_DB4_SHIFT, + R_RXFIFO_DATA2_DB4_LENGTH, frame->data[7])); ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1); From 3a661024cc680104ce2cd21f8f5466dacba6f405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= Date: Wed, 14 Sep 2022 12:50:59 +0200 Subject: [PATCH 0555/1020] target/arm: Fix alignment for VLD4.32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When requested, the alignment for VLD4.32 is 8 and not 16. See ARM documentation about VLD4 encoding: ebytes = 1 << UInt(size); if size == '10' then alignment = if a == '0' then 1 else 8; else alignment = if a == '0' then 1 else 4*ebytes; Signed-off-by: ClĂ©ment Chigot Reviewed-by: Richard Henderson Message-id: 20220914105058.2787404-1-chigot@adacore.com Signed-off-by: Peter Maydell --- target/arm/translate-neon.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c index 321c17e2c7..4016339d46 100644 --- a/target/arm/translate-neon.c +++ b/target/arm/translate-neon.c @@ -584,7 +584,11 @@ static bool trans_VLD_all_lanes(DisasContext *s, arg_VLD_all_lanes *a) case 3: return false; case 4: - align = pow2_align(size + 2); + if (size == 2) { + align = pow2_align(3); + } else { + align = pow2_align(size + 2); + } break; default: g_assert_not_reached(); From de05a709ec2b3ddf7a739d85ef8cdd9d5a02b6e1 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:36 -0700 Subject: [PATCH 0556/1020] target/arm: Create GetPhysAddrResult Combine 5 output pointer arguments from get_phys_addr into a single struct. Adjust all callers. Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-2-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/helper.c | 27 ++++----- target/arm/internals.h | 13 ++++- target/arm/m_helper.c | 52 ++++++----------- target/arm/ptw.c | 120 +++++++++++++++++++++------------------- target/arm/tlb_helper.c | 22 +++----- 5 files changed, 109 insertions(+), 125 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 1a57d2e1d6..b5dac651e7 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3190,24 +3190,19 @@ static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri, static uint64_t do_ats_write(CPUARMState *env, uint64_t value, MMUAccessType access_type, ARMMMUIdx mmu_idx) { - hwaddr phys_addr; - target_ulong page_size; - int prot; bool ret; uint64_t par64; bool format64 = false; - MemTxAttrs attrs = {}; ARMMMUFaultInfo fi = {}; - ARMCacheAttrs cacheattrs = {}; + GetPhysAddrResult res = {}; - ret = get_phys_addr(env, value, access_type, mmu_idx, &phys_addr, &attrs, - &prot, &page_size, &fi, &cacheattrs); + ret = get_phys_addr(env, value, access_type, mmu_idx, &res, &fi); /* * ATS operations only do S1 or S1+S2 translations, so we never * have to deal with the ARMCacheAttrs format for S2 only. */ - assert(!cacheattrs.is_s2_format); + assert(!res.cacheattrs.is_s2_format); if (ret) { /* @@ -3313,12 +3308,12 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, /* Create a 64-bit PAR */ par64 = (1 << 11); /* LPAE bit always set */ if (!ret) { - par64 |= phys_addr & ~0xfffULL; - if (!attrs.secure) { + par64 |= res.phys & ~0xfffULL; + if (!res.attrs.secure) { par64 |= (1 << 9); /* NS */ } - par64 |= (uint64_t)cacheattrs.attrs << 56; /* ATTR */ - par64 |= cacheattrs.shareability << 7; /* SH */ + par64 |= (uint64_t)res.cacheattrs.attrs << 56; /* ATTR */ + par64 |= res.cacheattrs.shareability << 7; /* SH */ } else { uint32_t fsr = arm_fi_to_lfsc(&fi); @@ -3338,13 +3333,13 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, */ if (!ret) { /* We do not set any attribute bits in the PAR */ - if (page_size == (1 << 24) + if (res.page_size == (1 << 24) && arm_feature(env, ARM_FEATURE_V7)) { - par64 = (phys_addr & 0xff000000) | (1 << 1); + par64 = (res.phys & 0xff000000) | (1 << 1); } else { - par64 = phys_addr & 0xfffff000; + par64 = res.phys & 0xfffff000; } - if (!attrs.secure) { + if (!res.attrs.secure) { par64 |= (1 << 9); /* NS */ } } else { diff --git a/target/arm/internals.h b/target/arm/internals.h index bf60cd5f84..e9743d3e22 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1142,11 +1142,18 @@ typedef struct ARMCacheAttrs { bool is_s2_format:1; } ARMCacheAttrs; +/* Fields that are valid upon success. */ +typedef struct GetPhysAddrResult { + hwaddr phys; + target_ulong page_size; + int prot; + MemTxAttrs attrs; + ARMCacheAttrs cacheattrs; +} GetPhysAddrResult; + bool get_phys_addr(CPUARMState *env, target_ulong address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot, - target_ulong *page_size, - ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) __attribute__((nonnull)); void arm_log_exception(CPUState *cs); diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 308610f6b4..84c6796b8d 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -183,19 +183,14 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value, { CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; - MemTxAttrs attrs = {}; MemTxResult txres; - target_ulong page_size; - hwaddr physaddr; - int prot; + GetPhysAddrResult res = {}; ARMMMUFaultInfo fi = {}; - ARMCacheAttrs cacheattrs = {}; bool secure = mmu_idx & ARM_MMU_IDX_M_S; int exc; bool exc_secure; - if (get_phys_addr(env, addr, MMU_DATA_STORE, mmu_idx, &physaddr, - &attrs, &prot, &page_size, &fi, &cacheattrs)) { + if (get_phys_addr(env, addr, MMU_DATA_STORE, mmu_idx, &res, &fi)) { /* MPU/SAU lookup failed */ if (fi.type == ARMFault_QEMU_SFault) { if (mode == STACK_LAZYFP) { @@ -228,8 +223,8 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value, } goto pend_fault; } - address_space_stl_le(arm_addressspace(cs, attrs), physaddr, value, - attrs, &txres); + address_space_stl_le(arm_addressspace(cs, res.attrs), res.phys, value, + res.attrs, &txres); if (txres != MEMTX_OK) { /* BusFault trying to write the data */ if (mode == STACK_LAZYFP) { @@ -276,20 +271,15 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr, { CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; - MemTxAttrs attrs = {}; MemTxResult txres; - target_ulong page_size; - hwaddr physaddr; - int prot; + GetPhysAddrResult res = {}; ARMMMUFaultInfo fi = {}; - ARMCacheAttrs cacheattrs = {}; bool secure = mmu_idx & ARM_MMU_IDX_M_S; int exc; bool exc_secure; uint32_t value; - if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr, - &attrs, &prot, &page_size, &fi, &cacheattrs)) { + if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &res, &fi)) { /* MPU/SAU lookup failed */ if (fi.type == ARMFault_QEMU_SFault) { qemu_log_mask(CPU_LOG_INT, @@ -308,8 +298,8 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr, goto pend_fault; } - value = address_space_ldl(arm_addressspace(cs, attrs), physaddr, - attrs, &txres); + value = address_space_ldl(arm_addressspace(cs, res.attrs), res.phys, + res.attrs, &txres); if (txres != MEMTX_OK) { /* BusFault trying to read the data */ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.UNSTKERR\n"); @@ -2008,13 +1998,9 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; V8M_SAttributes sattrs = {}; - MemTxAttrs attrs = {}; + GetPhysAddrResult res = {}; ARMMMUFaultInfo fi = {}; - ARMCacheAttrs cacheattrs = {}; MemTxResult txres; - target_ulong page_size; - hwaddr physaddr; - int prot; v8m_security_lookup(env, addr, MMU_INST_FETCH, mmu_idx, &sattrs); if (!sattrs.nsc || sattrs.ns) { @@ -2028,16 +2014,15 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, "...really SecureFault with SFSR.INVEP\n"); return false; } - if (get_phys_addr(env, addr, MMU_INST_FETCH, mmu_idx, &physaddr, - &attrs, &prot, &page_size, &fi, &cacheattrs)) { + if (get_phys_addr(env, addr, MMU_INST_FETCH, mmu_idx, &res, &fi)) { /* the MPU lookup failed */ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_IACCVIOL_MASK; armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, env->v7m.secure); qemu_log_mask(CPU_LOG_INT, "...really MemManage with CFSR.IACCVIOL\n"); return false; } - *insn = address_space_lduw_le(arm_addressspace(cs, attrs), physaddr, - attrs, &txres); + *insn = address_space_lduw_le(arm_addressspace(cs, res.attrs), res.phys, + res.attrs, &txres); if (txres != MEMTX_OK) { env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_IBUSERR_MASK; armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false); @@ -2060,17 +2045,12 @@ static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx, */ CPUState *cs = CPU(cpu); CPUARMState *env = &cpu->env; - MemTxAttrs attrs = {}; MemTxResult txres; - target_ulong page_size; - hwaddr physaddr; - int prot; + GetPhysAddrResult res = {}; ARMMMUFaultInfo fi = {}; - ARMCacheAttrs cacheattrs = {}; uint32_t value; - if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr, - &attrs, &prot, &page_size, &fi, &cacheattrs)) { + if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &res, &fi)) { /* MPU/SAU lookup failed */ if (fi.type == ARMFault_QEMU_SFault) { qemu_log_mask(CPU_LOG_INT, @@ -2088,8 +2068,8 @@ static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx, } return false; } - value = address_space_ldl(arm_addressspace(cs, attrs), physaddr, - attrs, &txres); + value = address_space_ldl(arm_addressspace(cs, res.attrs), res.phys, + res.attrs, &txres); if (txres != MEMTX_OK) { /* BusFault trying to read the data */ qemu_log_mask(CPU_LOG_INT, diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 3261039d93..8db2abac01 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2300,18 +2300,12 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env, * @address: virtual address to get physical address for * @access_type: 0 for read, 1 for write, 2 for execute * @mmu_idx: MMU index indicating required translation regime - * @phys_ptr: set to the physical address corresponding to the virtual address - * @attrs: set to the memory transaction attributes to use - * @prot: set to the permissions for the page containing phys_ptr - * @page_size: set to the size of the page containing phys_ptr + * @result: set on translation success. * @fi: set to fault info if the translation fails - * @cacheattrs: (if non-NULL) set to the cacheability/shareability attributes */ bool get_phys_addr(CPUARMState *env, target_ulong address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot, - target_ulong *page_size, - ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx); @@ -2322,43 +2316,54 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, */ if (arm_feature(env, ARM_FEATURE_EL2)) { hwaddr ipa; - int s2_prot; + int s1_prot; int ret; bool ipa_secure; - ARMCacheAttrs cacheattrs2 = {}; + ARMCacheAttrs cacheattrs1; ARMMMUIdx s2_mmu_idx; bool is_el0; - ret = get_phys_addr(env, address, access_type, s1_mmu_idx, &ipa, - attrs, prot, page_size, fi, cacheattrs); + ret = get_phys_addr(env, address, access_type, s1_mmu_idx, + result, fi); /* If S1 fails or S2 is disabled, return early. */ if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2)) { - *phys_ptr = ipa; return ret; } - ipa_secure = attrs->secure; + ipa = result->phys; + ipa_secure = result->attrs.secure; if (arm_is_secure_below_el3(env)) { if (ipa_secure) { - attrs->secure = !(env->cp15.vstcr_el2 & VSTCR_SW); + result->attrs.secure = !(env->cp15.vstcr_el2 & VSTCR_SW); } else { - attrs->secure = !(env->cp15.vtcr_el2 & VTCR_NSW); + result->attrs.secure = !(env->cp15.vtcr_el2 & VTCR_NSW); } } else { assert(!ipa_secure); } - s2_mmu_idx = attrs->secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2; + s2_mmu_idx = (result->attrs.secure + ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2); is_el0 = mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_SE10_0; - /* S1 is done. Now do S2 translation. */ + /* + * S1 is done, now do S2 translation. + * Save the stage1 results so that we may merge + * prot and cacheattrs later. + */ + s1_prot = result->prot; + cacheattrs1 = result->cacheattrs; + memset(result, 0, sizeof(*result)); + ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx, is_el0, - phys_ptr, attrs, &s2_prot, - page_size, fi, &cacheattrs2); + &result->phys, &result->attrs, + &result->prot, &result->page_size, + fi, &result->cacheattrs); fi->s2addr = ipa; + /* Combine the S1 and S2 perms. */ - *prot &= s2_prot; + result->prot &= s1_prot; /* If S2 fails, return early. */ if (ret) { @@ -2374,20 +2379,21 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, * Outer Write-Back Read-Allocate Write-Allocate. * Do not overwrite Tagged within attrs. */ - if (cacheattrs->attrs != 0xf0) { - cacheattrs->attrs = 0xff; + if (cacheattrs1.attrs != 0xf0) { + cacheattrs1.attrs = 0xff; } - cacheattrs->shareability = 0; + cacheattrs1.shareability = 0; } - *cacheattrs = combine_cacheattrs(env, *cacheattrs, cacheattrs2); + result->cacheattrs = combine_cacheattrs(env, cacheattrs1, + result->cacheattrs); /* Check if IPA translates to secure or non-secure PA space. */ if (arm_is_secure_below_el3(env)) { if (ipa_secure) { - attrs->secure = + result->attrs.secure = !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)); } else { - attrs->secure = + result->attrs.secure = !((env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW)) || (env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW))); } @@ -2406,8 +2412,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, * cannot upgrade an non-secure translation regime's attributes * to secure. */ - attrs->secure = regime_is_secure(env, mmu_idx); - attrs->user = regime_is_user(env, mmu_idx); + result->attrs.secure = regime_is_secure(env, mmu_idx); + result->attrs.user = regime_is_user(env, mmu_idx); /* * Fast Context Switch Extension. This doesn't exist at all in v8. @@ -2424,20 +2430,22 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, if (arm_feature(env, ARM_FEATURE_PMSA)) { bool ret; - *page_size = TARGET_PAGE_SIZE; + result->page_size = TARGET_PAGE_SIZE; if (arm_feature(env, ARM_FEATURE_V8)) { /* PMSAv8 */ ret = get_phys_addr_pmsav8(env, address, access_type, mmu_idx, - phys_ptr, attrs, prot, page_size, fi); + &result->phys, &result->attrs, + &result->prot, &result->page_size, fi); } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx, - phys_ptr, prot, page_size, fi); + &result->phys, &result->prot, + &result->page_size, fi); } else { /* Pre-v7 MPU */ ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx, - phys_ptr, prot, fi); + &result->phys, &result->prot, fi); } qemu_log_mask(CPU_LOG_MMU, "PMSA MPU lookup for %s at 0x%08" PRIx32 " mmu_idx %u -> %s (prot %c%c%c)\n", @@ -2445,9 +2453,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, (access_type == MMU_DATA_STORE ? "writing" : "execute"), (uint32_t)address, mmu_idx, ret ? "Miss" : "Hit", - *prot & PAGE_READ ? 'r' : '-', - *prot & PAGE_WRITE ? 'w' : '-', - *prot & PAGE_EXEC ? 'x' : '-'); + result->prot & PAGE_READ ? 'r' : '-', + result->prot & PAGE_WRITE ? 'w' : '-', + result->prot & PAGE_EXEC ? 'x' : '-'); return ret; } @@ -2492,14 +2500,14 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, address = extract64(address, 0, 52); } } - *phys_ptr = address; - *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - *page_size = TARGET_PAGE_SIZE; + result->phys = address; + result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + result->page_size = TARGET_PAGE_SIZE; /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */ hcr = arm_hcr_el2_eff(env); - cacheattrs->shareability = 0; - cacheattrs->is_s2_format = false; + result->cacheattrs.shareability = 0; + result->cacheattrs.is_s2_format = false; if (hcr & HCR_DC) { if (hcr & HCR_DCT) { memattr = 0xf0; /* Tagged, Normal, WB, RWA */ @@ -2512,24 +2520,27 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, } else { memattr = 0x44; /* Normal, NC, No */ } - cacheattrs->shareability = 2; /* outer sharable */ + result->cacheattrs.shareability = 2; /* outer sharable */ } else { memattr = 0x00; /* Device, nGnRnE */ } - cacheattrs->attrs = memattr; + result->cacheattrs.attrs = memattr; return 0; } if (regime_using_lpae_format(env, mmu_idx)) { return get_phys_addr_lpae(env, address, access_type, mmu_idx, false, - phys_ptr, attrs, prot, page_size, - fi, cacheattrs); + &result->phys, &result->attrs, + &result->prot, &result->page_size, + fi, &result->cacheattrs); } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { return get_phys_addr_v6(env, address, access_type, mmu_idx, - phys_ptr, attrs, prot, page_size, fi); + &result->phys, &result->attrs, + &result->prot, &result->page_size, fi); } else { return get_phys_addr_v5(env, address, access_type, mmu_idx, - phys_ptr, prot, page_size, fi); + &result->phys, &result->prot, + &result->page_size, fi); } } @@ -2538,21 +2549,16 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, { ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; - hwaddr phys_addr; - target_ulong page_size; - int prot; - bool ret; + GetPhysAddrResult res = {}; ARMMMUFaultInfo fi = {}; ARMMMUIdx mmu_idx = arm_mmu_idx(env); - ARMCacheAttrs cacheattrs = {}; + bool ret; - *attrs = (MemTxAttrs) {}; - - ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &phys_addr, - attrs, &prot, &page_size, &fi, &cacheattrs); + ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &res, &fi); + *attrs = res.attrs; if (ret) { return -1; } - return phys_addr; + return res.phys; } diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c index 5a709eab56..ad225b1cb2 100644 --- a/target/arm/tlb_helper.c +++ b/target/arm/tlb_helper.c @@ -209,11 +209,8 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, { ARMCPU *cpu = ARM_CPU(cs); ARMMMUFaultInfo fi = {}; - hwaddr phys_addr; - target_ulong page_size; - int prot, ret; - MemTxAttrs attrs = {}; - ARMCacheAttrs cacheattrs = {}; + GetPhysAddrResult res = {}; + int ret; /* * Walk the page table and (if the mapping exists) add the page @@ -223,25 +220,24 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, */ ret = get_phys_addr(&cpu->env, address, access_type, core_to_arm_mmu_idx(&cpu->env, mmu_idx), - &phys_addr, &attrs, &prot, &page_size, - &fi, &cacheattrs); + &res, &fi); if (likely(!ret)) { /* * Map a single [sub]page. Regions smaller than our declared * target page size are handled specially, so for those we * pass in the exact addresses. */ - if (page_size >= TARGET_PAGE_SIZE) { - phys_addr &= TARGET_PAGE_MASK; + if (res.page_size >= TARGET_PAGE_SIZE) { + res.phys &= TARGET_PAGE_MASK; address &= TARGET_PAGE_MASK; } /* Notice and record tagged memory. */ - if (cpu_isar_feature(aa64_mte, cpu) && cacheattrs.attrs == 0xf0) { - arm_tlb_mte_tagged(&attrs) = true; + if (cpu_isar_feature(aa64_mte, cpu) && res.cacheattrs.attrs == 0xf0) { + arm_tlb_mte_tagged(&res.attrs) = true; } - tlb_set_page_with_attrs(cs, address, phys_addr, attrs, - prot, mmu_idx, page_size); + tlb_set_page_with_attrs(cs, address, res.phys, res.attrs, + res.prot, mmu_idx, res.page_size); return true; } else if (probe) { return false; From 03ee9bbe702a471a03c9a0f5c9b924e257d1001b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:38 -0700 Subject: [PATCH 0557/1020] target/arm: Use GetPhysAddrResult in get_phys_addr_lpae MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-4-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 69 ++++++++++++++++++------------------------------ 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 8db2abac01..e8d3f88628 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -16,10 +16,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - bool s1_is_el0, hwaddr *phys_ptr, - MemTxAttrs *txattrs, int *prot, - target_ulong *page_size_ptr, - ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) + bool s1_is_el0, GetPhysAddrResult *result, + ARMMMUFaultInfo *fi) __attribute__((nonnull)); /* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */ @@ -204,18 +202,13 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, { if (arm_mmu_idx_is_stage1_of_2(mmu_idx) && !regime_translation_disabled(env, ARMMMUIdx_Stage2)) { - target_ulong s2size; - hwaddr s2pa; - int s2prot; - int ret; ARMMMUIdx s2_mmu_idx = *is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2; - ARMCacheAttrs cacheattrs = {}; - MemTxAttrs txattrs = {}; + GetPhysAddrResult s2 = {}; + int ret; ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx, false, - &s2pa, &txattrs, &s2prot, &s2size, fi, - &cacheattrs); + &s2, fi); if (ret) { assert(fi->type != ARMFault_None); fi->s2addr = addr; @@ -225,7 +218,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, return ~0; } if ((arm_hcr_el2_eff(env) & HCR_PTW) && - ptw_attrs_are_device(env, cacheattrs)) { + ptw_attrs_are_device(env, s2.cacheattrs)) { /* * PTW set and S1 walk touched S2 Device memory: * generate Permission fault. @@ -249,7 +242,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, assert(!*is_secure); } - addr = s2pa; + addr = s2.phys; } return addr; } @@ -972,19 +965,13 @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, * table walk), must be true if this is stage 2 of a stage 1+2 * walk for an EL0 access. If @mmu_idx is anything else, * @s1_is_el0 is ignored. - * @phys_ptr: set to the physical address corresponding to the virtual address - * @attrs: set to the memory transaction attributes to use - * @prot: set to the permissions for the page containing phys_ptr - * @page_size_ptr: set to the size of the page containing phys_ptr + * @result: set on translation success, * @fi: set to fault info if the translation fails - * @cacheattrs: (if non-NULL) set to the cacheability/shareability attributes */ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - bool s1_is_el0, hwaddr *phys_ptr, - MemTxAttrs *txattrs, int *prot, - target_ulong *page_size_ptr, - ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs) + bool s1_is_el0, GetPhysAddrResult *result, + ARMMMUFaultInfo *fi) { ARMCPU *cpu = env_archcpu(env); /* Read an LPAE long-descriptor translation table. */ @@ -1302,16 +1289,16 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) { ns = mmu_idx == ARMMMUIdx_Stage2; xn = extract32(attrs, 11, 2); - *prot = get_S2prot(env, ap, xn, s1_is_el0); + result->prot = get_S2prot(env, ap, xn, s1_is_el0); } else { ns = extract32(attrs, 3, 1); xn = extract32(attrs, 12, 1); pxn = extract32(attrs, 11, 1); - *prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn); + result->prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn); } fault_type = ARMFault_Permission; - if (!(*prot & (1 << access_type))) { + if (!(result->prot & (1 << access_type))) { goto do_fault; } @@ -1321,23 +1308,23 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, * the CPU doesn't support TZ or this is a non-secure translation * regime, because the attribute will already be non-secure. */ - txattrs->secure = false; + result->attrs.secure = false; } /* When in aarch64 mode, and BTI is enabled, remember GP in the IOTLB. */ if (aarch64 && guarded && cpu_isar_feature(aa64_bti, cpu)) { - arm_tlb_bti_gp(txattrs) = true; + arm_tlb_bti_gp(&result->attrs) = true; } if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) { - cacheattrs->is_s2_format = true; - cacheattrs->attrs = extract32(attrs, 0, 4); + result->cacheattrs.is_s2_format = true; + result->cacheattrs.attrs = extract32(attrs, 0, 4); } else { /* Index into MAIR registers for cache attributes */ uint8_t attrindx = extract32(attrs, 0, 3); uint64_t mair = env->cp15.mair_el[regime_el(env, mmu_idx)]; assert(attrindx <= 7); - cacheattrs->is_s2_format = false; - cacheattrs->attrs = extract64(mair, attrindx * 8, 8); + result->cacheattrs.is_s2_format = false; + result->cacheattrs.attrs = extract64(mair, attrindx * 8, 8); } /* @@ -1346,13 +1333,13 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, * that case comes from TCR_ELx, which we extracted earlier. */ if (param.ds) { - cacheattrs->shareability = param.sh; + result->cacheattrs.shareability = param.sh; } else { - cacheattrs->shareability = extract32(attrs, 6, 2); + result->cacheattrs.shareability = extract32(attrs, 6, 2); } - *phys_ptr = descaddr; - *page_size_ptr = page_size; + result->phys = descaddr; + result->page_size = page_size; return false; do_fault: @@ -2356,10 +2343,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, cacheattrs1 = result->cacheattrs; memset(result, 0, sizeof(*result)); - ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx, is_el0, - &result->phys, &result->attrs, - &result->prot, &result->page_size, - fi, &result->cacheattrs); + ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx, + is_el0, result, fi); fi->s2addr = ipa; /* Combine the S1 and S2 perms. */ @@ -2530,9 +2515,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, if (regime_using_lpae_format(env, mmu_idx)) { return get_phys_addr_lpae(env, address, access_type, mmu_idx, false, - &result->phys, &result->attrs, - &result->prot, &result->page_size, - fi, &result->cacheattrs); + result, fi); } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { return get_phys_addr_v6(env, address, access_type, mmu_idx, &result->phys, &result->attrs, From 60a6a180b1694ee7452266d05f71c8feb8ea8383 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:39 -0700 Subject: [PATCH 0558/1020] target/arm: Use GetPhysAddrResult in get_phys_addr_v6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-5-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index e8d3f88628..600d9e6650 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -536,8 +536,7 @@ do_fault: static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, MemTxAttrs *attrs, int *prot, - target_ulong *page_size, ARMMMUFaultInfo *fi) + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { ARMCPU *cpu = env_archcpu(env); int level = 1; @@ -597,11 +596,11 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, phys_addr = (desc & 0xff000000) | (address & 0x00ffffff); phys_addr |= (uint64_t)extract32(desc, 20, 4) << 32; phys_addr |= (uint64_t)extract32(desc, 5, 4) << 36; - *page_size = 0x1000000; + result->page_size = 0x1000000; } else { /* Section. */ phys_addr = (desc & 0xfff00000) | (address & 0x000fffff); - *page_size = 0x100000; + result->page_size = 0x100000; } ap = ((desc >> 10) & 3) | ((desc >> 13) & 4); xn = desc & (1 << 4); @@ -627,12 +626,12 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, case 1: /* 64k page. */ phys_addr = (desc & 0xffff0000) | (address & 0xffff); xn = desc & (1 << 15); - *page_size = 0x10000; + result->page_size = 0x10000; break; case 2: case 3: /* 4k page. */ phys_addr = (desc & 0xfffff000) | (address & 0xfff); xn = desc & 1; - *page_size = 0x1000; + result->page_size = 0x1000; break; default: /* Never happens, but compiler isn't smart enough to tell. */ @@ -640,7 +639,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, } } if (domain_prot == 3) { - *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; } else { if (pxn && !regime_is_user(env, mmu_idx)) { xn = 1; @@ -658,14 +657,14 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, fi->type = ARMFault_AccessFlag; goto do_fault; } - *prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1); + result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1); } else { - *prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); + result->prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); } - if (*prot && !xn) { - *prot |= PAGE_EXEC; + if (result->prot && !xn) { + result->prot |= PAGE_EXEC; } - if (!(*prot & (1 << access_type))) { + if (!(result->prot & (1 << access_type))) { /* Access permission fault. */ fi->type = ARMFault_Permission; goto do_fault; @@ -676,9 +675,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, * the CPU doesn't support TZ or this is a non-secure translation * regime, because the attribute will already be non-secure. */ - attrs->secure = false; + result->attrs.secure = false; } - *phys_ptr = phys_addr; + result->phys = phys_addr; return false; do_fault: fi->domain = domain; @@ -2518,8 +2517,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, result, fi); } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { return get_phys_addr_v6(env, address, access_type, mmu_idx, - &result->phys, &result->attrs, - &result->prot, &result->page_size, fi); + result, fi); } else { return get_phys_addr_v5(env, address, access_type, mmu_idx, &result->phys, &result->prot, From 51d98ce2cbfcea8fc14d5b05736f782ecae499d3 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:40 -0700 Subject: [PATCH 0559/1020] target/arm: Use GetPhysAddrResult in get_phys_addr_v5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-6-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 600d9e6650..4e2476278e 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -414,9 +414,7 @@ static int simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap) static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, int *prot, - target_ulong *page_size, - ARMMMUFaultInfo *fi) + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { int level = 1; uint32_t table; @@ -464,7 +462,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, /* 1Mb section. */ phys_addr = (desc & 0xfff00000) | (address & 0x000fffff); ap = (desc >> 10) & 3; - *page_size = 1024 * 1024; + result->page_size = 1024 * 1024; } else { /* Lookup l2 entry. */ if (type == 1) { @@ -486,12 +484,12 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, case 1: /* 64k page. */ phys_addr = (desc & 0xffff0000) | (address & 0xffff); ap = (desc >> (4 + ((address >> 13) & 6))) & 3; - *page_size = 0x10000; + result->page_size = 0x10000; break; case 2: /* 4k page. */ phys_addr = (desc & 0xfffff000) | (address & 0xfff); ap = (desc >> (4 + ((address >> 9) & 6))) & 3; - *page_size = 0x1000; + result->page_size = 0x1000; break; case 3: /* 1k page, or ARMv6/XScale "extended small (4k) page" */ if (type == 1) { @@ -499,7 +497,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, if (arm_feature(env, ARM_FEATURE_XSCALE) || arm_feature(env, ARM_FEATURE_V6)) { phys_addr = (desc & 0xfffff000) | (address & 0xfff); - *page_size = 0x1000; + result->page_size = 0x1000; } else { /* * UNPREDICTABLE in ARMv5; we choose to take a @@ -510,7 +508,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, } } else { phys_addr = (desc & 0xfffffc00) | (address & 0x3ff); - *page_size = 0x400; + result->page_size = 0x400; } ap = (desc >> 4) & 3; break; @@ -519,14 +517,14 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, g_assert_not_reached(); } } - *prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); - *prot |= *prot ? PAGE_EXEC : 0; - if (!(*prot & (1 << access_type))) { + result->prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); + result->prot |= result->prot ? PAGE_EXEC : 0; + if (!(result->prot & (1 << access_type))) { /* Access permission fault. */ fi->type = ARMFault_Permission; goto do_fault; } - *phys_ptr = phys_addr; + result->phys = phys_addr; return false; do_fault: fi->domain = domain; @@ -2520,8 +2518,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, result, fi); } else { return get_phys_addr_v5(env, address, access_type, mmu_idx, - &result->phys, &result->prot, - &result->page_size, fi); + result, fi); } } From b7b9b579cf616e3a933e833462e50ad5b4e36d75 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:41 -0700 Subject: [PATCH 0560/1020] target/arm: Use GetPhysAddrResult in get_phys_addr_pmsav5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-7-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 4e2476278e..70abcce81f 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1351,7 +1351,7 @@ do_fault: static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, int *prot, + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { int n; @@ -1361,12 +1361,12 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled. */ - *phys_ptr = address; - *prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + result->phys = address; + result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return false; } - *phys_ptr = address; + result->phys = address; for (n = 7; n >= 0; n--) { base = env->cp15.c6_region[n]; if ((base & 1) == 0) { @@ -1402,16 +1402,16 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, fi->level = 1; return true; } - *prot = PAGE_READ | PAGE_WRITE; + result->prot = PAGE_READ | PAGE_WRITE; break; case 2: - *prot = PAGE_READ; + result->prot = PAGE_READ; if (!is_user) { - *prot |= PAGE_WRITE; + result->prot |= PAGE_WRITE; } break; case 3: - *prot = PAGE_READ | PAGE_WRITE; + result->prot = PAGE_READ | PAGE_WRITE; break; case 5: if (is_user) { @@ -1419,10 +1419,10 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, fi->level = 1; return true; } - *prot = PAGE_READ; + result->prot = PAGE_READ; break; case 6: - *prot = PAGE_READ; + result->prot = PAGE_READ; break; default: /* Bad permission. */ @@ -1430,7 +1430,7 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, fi->level = 1; return true; } - *prot |= PAGE_EXEC; + result->prot |= PAGE_EXEC; return false; } @@ -2427,7 +2427,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, } else { /* Pre-v7 MPU */ ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx, - &result->phys, &result->prot, fi); + result, fi); } qemu_log_mask(CPU_LOG_MMU, "PMSA MPU lookup for %s at 0x%08" PRIx32 " mmu_idx %u -> %s (prot %c%c%c)\n", From e59367e2ef998a4e0cb1f123861a56fc288d5620 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:42 -0700 Subject: [PATCH 0561/1020] target/arm: Use GetPhysAddrResult in get_phys_addr_pmsav7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-8-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 70abcce81f..36b108907f 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1513,17 +1513,16 @@ static bool pmsav7_use_background_region(ARMCPU *cpu, ARMMMUIdx mmu_idx, static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, int *prot, - target_ulong *page_size, + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { ARMCPU *cpu = env_archcpu(env); int n; bool is_user = regime_is_user(env, mmu_idx); - *phys_ptr = address; - *page_size = TARGET_PAGE_SIZE; - *prot = 0; + result->phys = address; + result->page_size = TARGET_PAGE_SIZE; + result->prot = 0; if (regime_translation_disabled(env, mmu_idx) || m_is_ppb_region(env, address)) { @@ -1535,7 +1534,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, * which always does a direct read using address_space_ldl(), rather * than going via this function, so we don't need to check that here. */ - get_phys_addr_pmsav7_default(env, mmu_idx, address, prot); + get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot); } else { /* MPU enabled */ for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) { /* region search */ @@ -1577,7 +1576,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, if (ranges_overlap(base, rmask, address & TARGET_PAGE_MASK, TARGET_PAGE_SIZE)) { - *page_size = 1; + result->page_size = 1; } continue; } @@ -1615,7 +1614,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, continue; } if (rsize < TARGET_PAGE_BITS) { - *page_size = 1 << rsize; + result->page_size = 1 << rsize; } break; } @@ -1626,7 +1625,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, fi->type = ARMFault_Background; return true; } - get_phys_addr_pmsav7_default(env, mmu_idx, address, prot); + get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot); } else { /* a MPU hit! */ uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3); uint32_t xn = extract32(env->pmsav7.dracr[n], 12, 1); @@ -1643,16 +1642,16 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, case 5: break; /* no access */ case 3: - *prot |= PAGE_WRITE; + result->prot |= PAGE_WRITE; /* fall through */ case 2: case 6: - *prot |= PAGE_READ | PAGE_EXEC; + result->prot |= PAGE_READ | PAGE_EXEC; break; case 7: /* for v7M, same as 6; for R profile a reserved value */ if (arm_feature(env, ARM_FEATURE_M)) { - *prot |= PAGE_READ | PAGE_EXEC; + result->prot |= PAGE_READ | PAGE_EXEC; break; } /* fall through */ @@ -1668,16 +1667,16 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, case 1: case 2: case 3: - *prot |= PAGE_WRITE; + result->prot |= PAGE_WRITE; /* fall through */ case 5: case 6: - *prot |= PAGE_READ | PAGE_EXEC; + result->prot |= PAGE_READ | PAGE_EXEC; break; case 7: /* for v7M, same as 6; for R profile a reserved value */ if (arm_feature(env, ARM_FEATURE_M)) { - *prot |= PAGE_READ | PAGE_EXEC; + result->prot |= PAGE_READ | PAGE_EXEC; break; } /* fall through */ @@ -1690,14 +1689,14 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, /* execute never */ if (xn) { - *prot &= ~PAGE_EXEC; + result->prot &= ~PAGE_EXEC; } } } fi->type = ARMFault_Permission; fi->level = 1; - return !(*prot & (1 << access_type)); + return !(result->prot & (1 << access_type)); } bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, @@ -2422,8 +2421,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx, - &result->phys, &result->prot, - &result->page_size, fi); + result, fi); } else { /* Pre-v7 MPU */ ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx, From 5272b23e2e525d50ab5a507632b26cc67f1f6daf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:43 -0700 Subject: [PATCH 0562/1020] target/arm: Use GetPhysAddrResult in get_phys_addr_pmsav8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-9-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 36b108907f..2286f6e12d 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1967,8 +1967,7 @@ void v8m_security_lookup(CPUARMState *env, uint32_t address, static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, MemTxAttrs *txattrs, - int *prot, target_ulong *page_size, + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { uint32_t secure = regime_is_secure(env, mmu_idx); @@ -2003,9 +2002,9 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, } else { fi->type = ARMFault_QEMU_SFault; } - *page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE; - *phys_ptr = address; - *prot = 0; + result->page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE; + result->phys = address; + result->prot = 0; return true; } } else { @@ -2015,7 +2014,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, * might downgrade a secure access to nonsecure. */ if (sattrs.ns) { - txattrs->secure = false; + result->attrs.secure = false; } else if (!secure) { /* * NS access to S memory must fault. @@ -2028,17 +2027,19 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, * for M_FAKE_FSR_SFAULT in arm_v7m_cpu_do_interrupt(). */ fi->type = ARMFault_QEMU_SFault; - *page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE; - *phys_ptr = address; - *prot = 0; + result->page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE; + result->phys = address; + result->prot = 0; return true; } } } - ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, phys_ptr, - txattrs, prot, &mpu_is_subpage, fi, NULL); - *page_size = sattrs.subpage || mpu_is_subpage ? 1 : TARGET_PAGE_SIZE; + ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, + &result->phys, &result->attrs, &result->prot, + &mpu_is_subpage, fi, NULL); + result->page_size = + sattrs.subpage || mpu_is_subpage ? 1 : TARGET_PAGE_SIZE; return ret; } @@ -2416,8 +2417,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, if (arm_feature(env, ARM_FEATURE_V8)) { /* PMSAv8 */ ret = get_phys_addr_pmsav8(env, address, access_type, mmu_idx, - &result->phys, &result->attrs, - &result->prot, &result->page_size, fi); + result, fi); } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx, From d2c92e585619516d7d29d38de3acba206806e64c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:44 -0700 Subject: [PATCH 0563/1020] target/arm: Use GetPhysAddrResult in pmsav8_mpu_lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-10-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/internals.h | 11 +++++------ target/arm/m_helper.c | 16 +++++++--------- target/arm/ptw.c | 20 +++++++++----------- 3 files changed, 21 insertions(+), 26 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index e9743d3e22..103ae743a7 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1125,12 +1125,6 @@ void v8m_security_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, V8M_SAttributes *sattrs); -bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, - MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, MemTxAttrs *txattrs, - int *prot, bool *is_subpage, - ARMMMUFaultInfo *fi, uint32_t *mregion); - /* Cacheability and shareability attributes for a memory access */ typedef struct ARMCacheAttrs { /* @@ -1156,6 +1150,11 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) __attribute__((nonnull)); +bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, + MMUAccessType access_type, ARMMMUIdx mmu_idx, + GetPhysAddrResult *result, bool *is_subpage, + ARMMMUFaultInfo *fi, uint32_t *mregion); + void arm_log_exception(CPUState *cs); #endif /* !CONFIG_USER_ONLY */ diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 84c6796b8d..69d4a63fa6 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -2770,15 +2770,10 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) V8M_SAttributes sattrs = {}; uint32_t tt_resp; bool r, rw, nsr, nsrw, mrvalid; - int prot; - ARMMMUFaultInfo fi = {}; - MemTxAttrs attrs = {}; - hwaddr phys_addr; ARMMMUIdx mmu_idx; uint32_t mregion; bool targetpriv; bool targetsec = env->v7m.secure; - bool is_subpage; /* * Work out what the security state and privilege level we're @@ -2809,18 +2804,21 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) * inspecting the other MPU state. */ if (arm_current_el(env) != 0 || alt) { + GetPhysAddrResult res = {}; + ARMMMUFaultInfo fi = {}; + bool is_subpage; + /* We can ignore the return value as prot is always set */ pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, - &phys_addr, &attrs, &prot, &is_subpage, - &fi, &mregion); + &res, &is_subpage, &fi, &mregion); if (mregion == -1) { mrvalid = false; mregion = 0; } else { mrvalid = true; } - r = prot & PAGE_READ; - rw = prot & PAGE_WRITE; + r = res.prot & PAGE_READ; + rw = res.prot & PAGE_WRITE; } else { r = false; rw = false; diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 2286f6e12d..d6890048f1 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1701,8 +1701,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - hwaddr *phys_ptr, MemTxAttrs *txattrs, - int *prot, bool *is_subpage, + GetPhysAddrResult *result, bool *is_subpage, ARMMMUFaultInfo *fi, uint32_t *mregion) { /* @@ -1724,8 +1723,8 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1); *is_subpage = false; - *phys_ptr = address; - *prot = 0; + result->phys = address; + result->prot = 0; if (mregion) { *mregion = -1; } @@ -1807,7 +1806,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, if (matchregion == -1) { /* hit using the background region */ - get_phys_addr_pmsav7_default(env, mmu_idx, address, prot); + get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot); } else { uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2); uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1); @@ -1822,9 +1821,9 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, xn = 1; } - *prot = simple_ap_to_rw_prot(env, mmu_idx, ap); - if (*prot && !xn && !(pxn && !is_user)) { - *prot |= PAGE_EXEC; + result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap); + if (result->prot && !xn && !(pxn && !is_user)) { + result->prot |= PAGE_EXEC; } /* * We don't need to look the attribute up in the MAIR0/MAIR1 @@ -1837,7 +1836,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, fi->type = ARMFault_Permission; fi->level = 1; - return !(*prot & (1 << access_type)); + return !(result->prot & (1 << access_type)); } static bool v8m_is_sau_exempt(CPUARMState *env, @@ -2036,8 +2035,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, } ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, - &result->phys, &result->attrs, &result->prot, - &mpu_is_subpage, fi, NULL); + result, &mpu_is_subpage, fi, NULL); result->page_size = sattrs.subpage || mpu_is_subpage ? 1 : TARGET_PAGE_SIZE; return ret; From 652c750ee5c57ba3bbaf32e5ebb77fbbc8f68385 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:45 -0700 Subject: [PATCH 0564/1020] target/arm: Remove is_subpage argument to pmsav8_mpu_lookup This can be made redundant with result->page_size, by moving the basic set of page_size from get_phys_addr_pmsav8. We still need to overwrite page_size when v8m_security_lookup signals a subpage. Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-11-richard.henderson@linaro.org [PMM: Update a comment that used to refer to is_subpage] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/internals.h | 4 ++-- target/arm/m_helper.c | 3 +-- target/arm/ptw.c | 23 ++++++++++++----------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index 103ae743a7..f8b22d3ab0 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1152,8 +1152,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, bool *is_subpage, - ARMMMUFaultInfo *fi, uint32_t *mregion); + GetPhysAddrResult *result, ARMMMUFaultInfo *fi, + uint32_t *mregion); void arm_log_exception(CPUState *cs); diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 69d4a63fa6..01263990dc 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -2806,11 +2806,10 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) if (arm_current_el(env) != 0 || alt) { GetPhysAddrResult res = {}; ARMMMUFaultInfo fi = {}; - bool is_subpage; /* We can ignore the return value as prot is always set */ pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, - &res, &is_subpage, &fi, &mregion); + &res, &fi, &mregion); if (mregion == -1) { mrvalid = false; mregion = 0; diff --git a/target/arm/ptw.c b/target/arm/ptw.c index d6890048f1..bb3c709f8f 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1701,8 +1701,8 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, bool *is_subpage, - ARMMMUFaultInfo *fi, uint32_t *mregion) + GetPhysAddrResult *result, ARMMMUFaultInfo *fi, + uint32_t *mregion) { /* * Perform a PMSAv8 MPU lookup (without also doing the SAU check @@ -1710,8 +1710,9 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, * mregion is (if not NULL) set to the region number which matched, * or -1 if no region number is returned (MPU off, address did not * hit a region, address hit in multiple regions). - * We set is_subpage to true if the region hit doesn't cover the - * entire TARGET_PAGE the address is within. + * If the region hit doesn't cover the entire TARGET_PAGE the address + * is within, then we set the result page_size to 1 to force the + * memory system to use a subpage. */ ARMCPU *cpu = env_archcpu(env); bool is_user = regime_is_user(env, mmu_idx); @@ -1722,7 +1723,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, uint32_t addr_page_base = address & TARGET_PAGE_MASK; uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1); - *is_subpage = false; + result->page_size = TARGET_PAGE_SIZE; result->phys = address; result->prot = 0; if (mregion) { @@ -1774,13 +1775,13 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, ranges_overlap(base, limit - base + 1, addr_page_base, TARGET_PAGE_SIZE)) { - *is_subpage = true; + result->page_size = 1; } continue; } if (base > addr_page_base || limit < addr_page_limit) { - *is_subpage = true; + result->page_size = 1; } if (matchregion != -1) { @@ -1972,7 +1973,6 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, uint32_t secure = regime_is_secure(env, mmu_idx); V8M_SAttributes sattrs = {}; bool ret; - bool mpu_is_subpage; if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { v8m_security_lookup(env, address, access_type, mmu_idx, &sattrs); @@ -2035,9 +2035,10 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, } ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, - result, &mpu_is_subpage, fi, NULL); - result->page_size = - sattrs.subpage || mpu_is_subpage ? 1 : TARGET_PAGE_SIZE; + result, fi, NULL); + if (sattrs.subpage) { + result->page_size = 1; + } return ret; } From dbf2a71ad62b99286adf6cdc6d6c12cdb26306a9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:46 -0700 Subject: [PATCH 0565/1020] target/arm: Add is_secure parameter to v8m_security_lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from v8m_security_lookup, passing the new parameter to the lookup instead. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-12-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/internals.h | 2 +- target/arm/m_helper.c | 9 ++++++--- target/arm/ptw.c | 9 +++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index f8b22d3ab0..e97f5c3d47 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1123,7 +1123,7 @@ typedef struct V8M_SAttributes { void v8m_security_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - V8M_SAttributes *sattrs); + bool secure, V8M_SAttributes *sattrs); /* Cacheability and shareability attributes for a memory access */ typedef struct ARMCacheAttrs { diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 01263990dc..45fbf19559 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -689,7 +689,8 @@ static bool arm_v7m_load_vector(ARMCPU *cpu, int exc, bool targets_secure, if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { V8M_SAttributes sattrs = {}; - v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, &sattrs); + v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, + targets_secure, &sattrs); if (sattrs.ns) { attrs.secure = false; } else if (!targets_secure) { @@ -2002,7 +2003,8 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, ARMMMUFaultInfo fi = {}; MemTxResult txres; - v8m_security_lookup(env, addr, MMU_INST_FETCH, mmu_idx, &sattrs); + v8m_security_lookup(env, addr, MMU_INST_FETCH, mmu_idx, + regime_is_secure(env, mmu_idx), &sattrs); if (!sattrs.nsc || sattrs.ns) { /* * This must be the second half of the insn, and it straddles a @@ -2826,7 +2828,8 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) } if (env->v7m.secure) { - v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, &sattrs); + v8m_security_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, + targetsec, &sattrs); nsr = sattrs.ns && r; nsrw = sattrs.ns && rw; } else { diff --git a/target/arm/ptw.c b/target/arm/ptw.c index bb3c709f8f..74d2f63359 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1857,8 +1857,8 @@ static bool v8m_is_sau_exempt(CPUARMState *env, } void v8m_security_lookup(CPUARMState *env, uint32_t address, - MMUAccessType access_type, ARMMMUIdx mmu_idx, - V8M_SAttributes *sattrs) + MMUAccessType access_type, ARMMMUIdx mmu_idx, + bool is_secure, V8M_SAttributes *sattrs) { /* * Look up the security attributes for this address. Compare the @@ -1886,7 +1886,7 @@ void v8m_security_lookup(CPUARMState *env, uint32_t address, } if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) { - sattrs->ns = !regime_is_secure(env, mmu_idx); + sattrs->ns = !is_secure; return; } @@ -1975,7 +1975,8 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, bool ret; if (arm_feature(env, ARM_FEATURE_M_SECURITY)) { - v8m_security_lookup(env, address, access_type, mmu_idx, &sattrs); + v8m_security_lookup(env, address, access_type, mmu_idx, + secure, &sattrs); if (access_type == MMU_INST_FETCH) { /* * Instruction fetches always use the MMU bank and the From e9fb709041d7866fca33de0848a3d43092e42512 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:47 -0700 Subject: [PATCH 0566/1020] target/arm: Add secure parameter to pmsav8_mpu_lookup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from pmsav8_mpu_lookup, passing the new parameter to the lookup instead. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-13-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/internals.h | 4 ++-- target/arm/m_helper.c | 2 +- target/arm/ptw.c | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index e97f5c3d47..307a596505 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1152,8 +1152,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, ARMMMUFaultInfo *fi, - uint32_t *mregion); + bool is_secure, GetPhysAddrResult *result, + ARMMMUFaultInfo *fi, uint32_t *mregion); void arm_log_exception(CPUState *cs); diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 45fbf19559..5ee4ee15b3 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -2810,7 +2810,7 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) ARMMMUFaultInfo fi = {}; /* We can ignore the return value as prot is always set */ - pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, + pmsav8_mpu_lookup(env, addr, MMU_DATA_LOAD, mmu_idx, targetsec, &res, &fi, &mregion); if (mregion == -1) { mrvalid = false; diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 74d2f63359..308a9cc3ac 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1701,8 +1701,8 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, ARMMMUFaultInfo *fi, - uint32_t *mregion) + bool secure, GetPhysAddrResult *result, + ARMMMUFaultInfo *fi, uint32_t *mregion) { /* * Perform a PMSAv8 MPU lookup (without also doing the SAU check @@ -1716,7 +1716,6 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, */ ARMCPU *cpu = env_archcpu(env); bool is_user = regime_is_user(env, mmu_idx); - uint32_t secure = regime_is_secure(env, mmu_idx); int n; int matchregion = -1; bool hit = false; @@ -2035,7 +2034,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, } } - ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, + ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, secure, result, fi, NULL); if (sattrs.subpage) { result->page_size = 1; From b29c85d50c7069ddf53187860e18f9dce824f590 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:48 -0700 Subject: [PATCH 0567/1020] target/arm: Add is_secure parameter to get_phys_addr_v5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from get_phys_addr_v5, passing the new parameter to the lookup instead. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson [PMM: Folded in definition of local is_secure in get_phys_addr(), since I dropped the earlier patch that would have provided it] Message-id: 20220822152741.1617527-14-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 308a9cc3ac..96639da504 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -414,7 +414,8 @@ static int simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx mmu_idx, int ap) static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, ARMMMUFaultInfo *fi) + bool is_secure, GetPhysAddrResult *result, + ARMMMUFaultInfo *fi) { int level = 1; uint32_t table; @@ -433,8 +434,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, fi->type = ARMFault_Translation; goto do_fault; } - desc = arm_ldl_ptw(env, table, regime_is_secure(env, mmu_idx), - mmu_idx, fi); + desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi); if (fi->type != ARMFault_None) { goto do_fault; } @@ -472,8 +472,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, /* Fine pagetable. */ table = (desc & 0xfffff000) | ((address >> 8) & 0xffc); } - desc = arm_ldl_ptw(env, table, regime_is_secure(env, mmu_idx), - mmu_idx, fi); + desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi); if (fi->type != ARMFault_None) { goto do_fault; } @@ -2291,6 +2290,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx); + bool is_secure = regime_is_secure(env, mmu_idx); if (mmu_idx != s1_mmu_idx) { /* @@ -2393,7 +2393,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, * cannot upgrade an non-secure translation regime's attributes * to secure. */ - result->attrs.secure = regime_is_secure(env, mmu_idx); + result->attrs.secure = is_secure; result->attrs.user = regime_is_user(env, mmu_idx); /* @@ -2515,7 +2515,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, result, fi); } else { return get_phys_addr_v5(env, address, access_type, mmu_idx, - result, fi); + is_secure, result, fi); } } From 71e73beb5101f0999f1a1440a3c544b24cb71430 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:49 -0700 Subject: [PATCH 0568/1020] target/arm: Add is_secure parameter to get_phys_addr_v6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from get_phys_addr_v6, passing the new parameter to the lookup instead. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-15-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 96639da504..8f0810a196 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -533,7 +533,8 @@ do_fault: static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, ARMMMUFaultInfo *fi) + bool is_secure, GetPhysAddrResult *result, + ARMMMUFaultInfo *fi) { ARMCPU *cpu = env_archcpu(env); int level = 1; @@ -556,8 +557,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, fi->type = ARMFault_Translation; goto do_fault; } - desc = arm_ldl_ptw(env, table, regime_is_secure(env, mmu_idx), - mmu_idx, fi); + desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi); if (fi->type != ARMFault_None) { goto do_fault; } @@ -610,8 +610,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, ns = extract32(desc, 3, 1); /* Lookup l2 entry. */ table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc); - desc = arm_ldl_ptw(env, table, regime_is_secure(env, mmu_idx), - mmu_idx, fi); + desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi); if (fi->type != ARMFault_None) { goto do_fault; } @@ -2512,7 +2511,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, result, fi); } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { return get_phys_addr_v6(env, address, access_type, mmu_idx, - result, fi); + is_secure, result, fi); } else { return get_phys_addr_v5(env, address, access_type, mmu_idx, is_secure, result, fi); From be0ca9485d6aeb3a9d9cae36f5e5b8fe1de9440b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:50 -0700 Subject: [PATCH 0569/1020] target/arm: Add secure parameter to get_phys_addr_pmsav8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from get_phys_addr_pmsav8. Since we already had a local variable named secure, use that. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-16-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 8f0810a196..6a73f16e09 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1964,10 +1964,9 @@ void v8m_security_lookup(CPUARMState *env, uint32_t address, static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, + bool secure, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { - uint32_t secure = regime_is_secure(env, mmu_idx); V8M_SAttributes sattrs = {}; bool ret; @@ -2415,7 +2414,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, if (arm_feature(env, ARM_FEATURE_V8)) { /* PMSAv8 */ ret = get_phys_addr_pmsav8(env, address, access_type, mmu_idx, - result, fi); + is_secure, result, fi); } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx, From 1a469cf78d45a711fb5fce3cbbb325917d17895a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:51 -0700 Subject: [PATCH 0570/1020] target/arm: Add is_secure parameter to pmsav7_use_background_region MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from pmsav7_use_background_region, using the new parameter instead. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-17-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 6a73f16e09..9e1f60d10b 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1489,7 +1489,7 @@ static bool m_is_system_region(CPUARMState *env, uint32_t address) } static bool pmsav7_use_background_region(ARMCPU *cpu, ARMMMUIdx mmu_idx, - bool is_user) + bool is_secure, bool is_user) { /* * Return true if we should use the default memory map as a @@ -1502,8 +1502,7 @@ static bool pmsav7_use_background_region(ARMCPU *cpu, ARMMMUIdx mmu_idx, } if (arm_feature(env, ARM_FEATURE_M)) { - return env->v7m.mpu_ctrl[regime_is_secure(env, mmu_idx)] - & R_V7M_MPU_CTRL_PRIVDEFENA_MASK; + return env->v7m.mpu_ctrl[is_secure] & R_V7M_MPU_CTRL_PRIVDEFENA_MASK; } else { return regime_sctlr(env, mmu_idx) & SCTLR_BR; } @@ -1516,6 +1515,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, { ARMCPU *cpu = env_archcpu(env); int n; + bool secure = regime_is_secure(env, mmu_idx); bool is_user = regime_is_user(env, mmu_idx); result->phys = address; @@ -1618,7 +1618,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, } if (n == -1) { /* no hits */ - if (!pmsav7_use_background_region(cpu, mmu_idx, is_user)) { + if (!pmsav7_use_background_region(cpu, mmu_idx, secure, is_user)) { /* background fault */ fi->type = ARMFault_Background; return true; @@ -1739,7 +1739,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, } else if (m_is_ppb_region(env, address)) { hit = true; } else { - if (pmsav7_use_background_region(cpu, mmu_idx, is_user)) { + if (pmsav7_use_background_region(cpu, mmu_idx, secure, is_user)) { hit = true; } From 957a0bb751e9b87c85118a2f55871d981df78d20 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:53 -0700 Subject: [PATCH 0571/1020] target/arm: Add secure parameter to get_phys_addr_pmsav7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from get_phys_addr_pmsav7, using the new parameter instead. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-19-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 9e1f60d10b..1e81eefa47 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1510,12 +1510,11 @@ static bool pmsav7_use_background_region(ARMCPU *cpu, ARMMMUIdx mmu_idx, static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, + bool secure, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { ARMCPU *cpu = env_archcpu(env); int n; - bool secure = regime_is_secure(env, mmu_idx); bool is_user = regime_is_user(env, mmu_idx); result->phys = address; @@ -2418,7 +2417,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, } else if (arm_feature(env, ARM_FEATURE_V7)) { /* PMSAv7 */ ret = get_phys_addr_pmsav7(env, address, access_type, mmu_idx, - result, fi); + is_secure, result, fi); } else { /* Pre-v7 MPU */ ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx, From a5b5092f66fc93c49e24c043d5e0589150a6c352 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 08:26:55 -0700 Subject: [PATCH 0572/1020] target/arm: Add is_secure parameter to get_phys_addr_pmsav5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from get_phys_addr_pmsav5. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-id: 20220822152741.1617527-21-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 1e81eefa47..2ddfc028ab 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1349,7 +1349,7 @@ do_fault: static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, + bool is_secure, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { int n; @@ -2421,7 +2421,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, } else { /* Pre-v7 MPU */ ret = get_phys_addr_pmsav5(env, address, access_type, mmu_idx, - result, fi); + is_secure, result, fi); } qemu_log_mask(CPU_LOG_MMU, "PMSA MPU lookup for %s at 0x%08" PRIx32 " mmu_idx %u -> %s (prot %c%c%c)\n", From d4424bebceaa8ffbc23060ce45e52a9bb817e3c9 Mon Sep 17 00:00:00 2001 From: Keqian Zhu Date: Tue, 16 Aug 2022 17:49:57 +0800 Subject: [PATCH 0573/1020] hw/acpi: Add ospm_status hook implementation for acpi-ged Setup an ARM virtual machine of machine virt and execute qmp "query-acpi-ospm-status" causes segmentation fault with following dumpstack: #1 0x0000aaaaab64235c in qmp_query_acpi_ospm_status (errp=errp@entry=0xfffffffff030) at ../monitor/qmp-cmds.c:312 #2 0x0000aaaaabfc4e20 in qmp_marshal_query_acpi_ospm_status (args=, ret=0xffffea4ffe90, errp=0xffffea4ffe88) at qapi/qapi-commands-acpi.c:63 #3 0x0000aaaaabff8ba0 in do_qmp_dispatch_bh (opaque=0xffffea4ffe98) at ../qapi/qmp-dispatch.c:128 #4 0x0000aaaaac02e594 in aio_bh_call (bh=0xffffe0004d80) at ../util/async.c:150 #5 aio_bh_poll (ctx=ctx@entry=0xaaaaad0f6040) at ../util/async.c:178 #6 0x0000aaaaac00bd40 in aio_dispatch (ctx=ctx@entry=0xaaaaad0f6040) at ../util/aio-posix.c:421 #7 0x0000aaaaac02e010 in aio_ctx_dispatch (source=0xaaaaad0f6040, callback=, user_data=) at ../util/async.c:320 #8 0x0000fffff76f6884 in g_main_context_dispatch () at /usr/lib64/libglib-2.0.so.0 #9 0x0000aaaaac0452d4 in glib_pollfds_poll () at ../util/main-loop.c:297 #10 os_host_main_loop_wait (timeout=0) at ../util/main-loop.c:320 #11 main_loop_wait (nonblocking=nonblocking@entry=0) at ../util/main-loop.c:596 #12 0x0000aaaaab5c9e50 in qemu_main_loop () at ../softmmu/runstate.c:734 #13 0x0000aaaaab185370 in qemu_main (argc=argc@entry=47, argv=argv@entry=0xfffffffff518, envp=envp@entry=0x0) at ../softmmu/main.c:38 #14 0x0000aaaaab16f99c in main (argc=47, argv=0xfffffffff518) at ../softmmu/main.c:47 Fixes: ebb62075021a ("hw/acpi: Add ACPI Generic Event Device Support") Signed-off-by: Keqian Zhu Reviewed-by: Igor Mammedov Message-id: 20220816094957.31700-1-zhukeqian1@huawei.com Signed-off-by: Peter Maydell --- hw/acpi/generic_event_device.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c index e28457a7d1..a3d31631fe 100644 --- a/hw/acpi/generic_event_device.c +++ b/hw/acpi/generic_event_device.c @@ -267,6 +267,13 @@ static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev, } } +static void acpi_ged_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list) +{ + AcpiGedState *s = ACPI_GED(adev); + + acpi_memory_ospm_status(&s->memhp_state, list); +} + static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev) { AcpiGedState *s = ACPI_GED(adev); @@ -409,6 +416,7 @@ static void acpi_ged_class_init(ObjectClass *class, void *data) hc->unplug_request = acpi_ged_unplug_request_cb; hc->unplug = acpi_ged_unplug_cb; + adevc->ospm_status = acpi_ged_ospm_status; adevc->send_event = acpi_ged_send_event; } From 895a803ce91704f28c9b49621a4f589273289f1e Mon Sep 17 00:00:00 2001 From: Lucas Dietrich Date: Mon, 29 Aug 2022 22:00:46 +0200 Subject: [PATCH 0574/1020] hw/net/lan9118: Signal TSFL_INT flag when TX FIFO reaches specified level The LAN9118 allows the guest to specify a level for both the TX and RX FIFOs at which an interrupt will be generated. We implement the RSFL_INT interrupt for the RX FIFO but are missing the handling of the equivalent TSFL_INT for the TX FIFO. Add the missing test to set the interrupt if the TX FIFO has exceeded the guest-specified level. This flag is required for Micrium lan911x ethernet driver to work. Signed-off-by: Lucas Dietrich [PMM: Tweaked commit message and comment] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/net/lan9118.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c index 456ae38107..f1cba55967 100644 --- a/hw/net/lan9118.c +++ b/hw/net/lan9118.c @@ -696,6 +696,14 @@ static void do_tx_packet(lan9118_state *s) n = (s->tx_status_fifo_head + s->tx_status_fifo_used) & 511; s->tx_status_fifo[n] = status; s->tx_status_fifo_used++; + + /* + * Generate TSFL interrupt if TX FIFO level exceeds the level + * specified in the FIFO_INT TX Status Level field. + */ + if (s->tx_status_fifo_used > ((s->fifo_int >> 16) & 0xff)) { + s->int_sts |= TSFL_INT; + } if (s->tx_status_fifo_used == 512) { s->int_sts |= TSFF_INT; /* TODO: Stop transmission. */ From f63a6e381c48b796c3964accaa88c0d0e229b17f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:21 +0100 Subject: [PATCH 0575/1020] chardev/baum: Replace magic values by X_MAX / Y_MAX definitions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace '84' magic value by the X_MAX definition, and '1' by Y_MAX. Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Samuel Thibault Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-2-peter.maydell@linaro.org --- chardev/baum.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/chardev/baum.c b/chardev/baum.c index 79d618e350..6d538808a0 100644 --- a/chardev/baum.c +++ b/chardev/baum.c @@ -87,6 +87,9 @@ #define BUF_SIZE 256 +#define X_MAX 84 +#define Y_MAX 1 + struct BaumChardev { Chardev parent; @@ -244,11 +247,11 @@ static int baum_deferred_init(BaumChardev *baum) brlapi_perror("baum: brlapi__getDisplaySize"); return 0; } - if (baum->y > 1) { - baum->y = 1; + if (baum->y > Y_MAX) { + baum->y = Y_MAX; } - if (baum->x > 84) { - baum->x = 84; + if (baum->x > X_MAX) { + baum->x = X_MAX; } con = qemu_console_lookup_by_index(0); From 1e3acd33576c695262a09262c9319d44a01b11e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:22 +0100 Subject: [PATCH 0576/1020] chardev/baum: Use definitions to avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We know 'x * y' will be at most 'X_MAX * Y_MAX' (which is not a big value, it is actually 84). Instead of having the compiler use variable-length array, declare an array able to hold the maximum 'x * y'. Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Samuel Thibault Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-3-peter.maydell@linaro.org --- chardev/baum.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/chardev/baum.c b/chardev/baum.c index 6d538808a0..6a210ffd81 100644 --- a/chardev/baum.c +++ b/chardev/baum.c @@ -383,9 +383,9 @@ static int baum_eat_packet(BaumChardev *baum, const uint8_t *buf, int len) switch (req) { case BAUM_REQ_DisplayData: { - uint8_t cells[baum->x * baum->y], c; - uint8_t text[baum->x * baum->y]; - uint8_t zero[baum->x * baum->y]; + uint8_t cells[X_MAX * Y_MAX], c; + uint8_t text[X_MAX * Y_MAX]; + uint8_t zero[X_MAX * Y_MAX]; int cursor = BRLAPI_CURSOR_OFF; int i; @@ -408,7 +408,7 @@ static int baum_eat_packet(BaumChardev *baum, const uint8_t *buf, int len) } timer_del(baum->cellCount_timer); - memset(zero, 0, sizeof(zero)); + memset(zero, 0, baum->x * baum->y); brlapi_writeArguments_t wa = { .displayNumber = BRLAPI_DISPLAY_DEFAULT, From d34977d682e382fb2af83e6e6508e3b06d1a3cf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:23 +0100 Subject: [PATCH 0577/1020] chardev/baum: Avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use autofree heap allocation instead of variable-length array on the stack. Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Samuel Thibault Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-4-peter.maydell@linaro.org --- chardev/baum.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chardev/baum.c b/chardev/baum.c index 6a210ffd81..0a0d12661a 100644 --- a/chardev/baum.c +++ b/chardev/baum.c @@ -299,7 +299,8 @@ static void baum_chr_accept_input(struct Chardev *chr) static void baum_write_packet(BaumChardev *baum, const uint8_t *buf, int len) { Chardev *chr = CHARDEV(baum); - uint8_t io_buf[1 + 2 * len], *cur = io_buf; + g_autofree uint8_t *io_buf = g_malloc(1 + 2 * len); + uint8_t *cur = io_buf; int room; *cur++ = ESC; while (len--) From 5e689840a10e01dc2ab87defc5347337db8103da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:24 +0100 Subject: [PATCH 0578/1020] io/channel-websock: Replace strlen(const_str) by sizeof(const_str) - 1 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The combined_key[... QIO_CHANNEL_WEBSOCK_GUID_LEN ...] array in qio_channel_websock_handshake_send_res_ok() expands to a call to strlen(QIO_CHANNEL_WEBSOCK_GUID), and the compiler doesn't realize the string is const, so consider combined_key[] being a variable-length array. To remove the variable-length array, we provide it a hint to the compiler by using sizeof() - 1 instead of strlen(). Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Daniel P. BerrangĂ© Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-5-peter.maydell@linaro.org --- io/channel-websock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/io/channel-websock.c b/io/channel-websock.c index 9619906ac3..fb4932ade7 100644 --- a/io/channel-websock.c +++ b/io/channel-websock.c @@ -32,7 +32,7 @@ #define QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN 24 #define QIO_CHANNEL_WEBSOCK_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" -#define QIO_CHANNEL_WEBSOCK_GUID_LEN strlen(QIO_CHANNEL_WEBSOCK_GUID) +#define QIO_CHANNEL_WEBSOCK_GUID_LEN (sizeof(QIO_CHANNEL_WEBSOCK_GUID) - 1) #define QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL "sec-websocket-protocol" #define QIO_CHANNEL_WEBSOCK_HEADER_VERSION "sec-websocket-version" From c140a69055bad798a335ea3c83aebceaca82bde0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:25 +0100 Subject: [PATCH 0579/1020] hw/net/e1000e_core: Use definition to avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compiler isn't clever enough to figure 'min_buf_size' is a constant, so help it by using a definitions instead. Signed-off-by: Philippe Mathieu-DaudĂ© Acked-by: Jason Wang Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-6-peter.maydell@linaro.org --- hw/net/e1000e_core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 208e3e0d79..82aa61fedc 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -1622,15 +1622,16 @@ e1000e_rx_fix_l4_csum(E1000ECore *core, struct NetRxPkt *pkt) } } +/* Min. octets in an ethernet frame sans FCS */ +#define MIN_BUF_SIZE 60 + ssize_t e1000e_receive_iov(E1000ECore *core, const struct iovec *iov, int iovcnt) { static const int maximum_ethernet_hdr_len = (14 + 4); - /* Min. octets in an ethernet frame sans FCS */ - static const int min_buf_size = 60; uint32_t n = 0; - uint8_t min_buf[min_buf_size]; + uint8_t min_buf[MIN_BUF_SIZE]; struct iovec min_iov; uint8_t *filter_buf; size_t size, orig_size; From a580fdcd609e1db77ef5a1cbcbfd2af5ca05c939 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:26 +0100 Subject: [PATCH 0580/1020] hw/ppc/pnv: Avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use autofree heap allocation instead of variable-length array on the stack. Signed-off-by: Philippe Mathieu-DaudĂ© Acked-by: David Gibson Signed-off-by: Peter Maydell Reviewed-by: Peter Maydell Reviewed-by: Daniel Henrique Barboza Message-id: 20220819153931.3147384-7-peter.maydell@linaro.org --- hw/ppc/pnv.c | 4 ++-- hw/ppc/spapr.c | 8 ++++---- hw/ppc/spapr_pci_nvlink2.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 354aa289d1..78e00afb9b 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -138,7 +138,7 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) int smt_threads = CPU_CORE(pc)->nr_threads; CPUPPCState *env = &cpu->env; PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); - uint32_t servers_prop[smt_threads]; + g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads); int i; uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40), 0xffffffff, 0xffffffff}; @@ -241,7 +241,7 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt) servers_prop[i] = cpu_to_be32(pc->pir + i); } _FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", - servers_prop, sizeof(servers_prop)))); + servers_prop, sizeof(*servers_prop) * smt_threads))); } static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir, diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index cc1adc23fa..8bbaf4f8a4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -177,8 +177,8 @@ static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, int smt_threads) { int i, ret = 0; - uint32_t servers_prop[smt_threads]; - uint32_t gservers_prop[smt_threads * 2]; + g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads); + g_autofree uint32_t *gservers_prop = g_new(uint32_t, smt_threads * 2); int index = spapr_get_vcpu_id(cpu); if (cpu->compat_pvr) { @@ -196,12 +196,12 @@ static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, gservers_prop[i*2 + 1] = 0; } ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s", - servers_prop, sizeof(servers_prop)); + servers_prop, sizeof(*servers_prop) * smt_threads); if (ret < 0) { return ret; } ret = fdt_setprop(fdt, offset, "ibm,ppc-interrupt-gserver#s", - gservers_prop, sizeof(gservers_prop)); + gservers_prop, sizeof(*gservers_prop) * smt_threads * 2); return ret; } diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c index 63b476c8f7..2a8a11be1d 100644 --- a/hw/ppc/spapr_pci_nvlink2.c +++ b/hw/ppc/spapr_pci_nvlink2.c @@ -397,7 +397,7 @@ void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt, int offset, continue; } if (dev == nvslot->gpdev) { - uint32_t npus[nvslot->linknum]; + g_autofree uint32_t *npus = g_new(uint32_t, nvslot->linknum); for (j = 0; j < nvslot->linknum; ++j) { PCIDevice *npdev = nvslot->links[j].npdev; From 7650c8fe520c67c3b36f6962c4ad990f56ad40b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:27 +0100 Subject: [PATCH 0581/1020] hw/intc/xics: Avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use autofree heap allocation instead of variable-length array on the stack. Signed-off-by: Philippe Mathieu-DaudĂ© Acked-by: David Gibson Reviewed-by: Greg Kurz Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-8-peter.maydell@linaro.org --- hw/intc/xics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/intc/xics.c b/hw/intc/xics.c index 5b0b4d9624..dcd021af66 100644 --- a/hw/intc/xics.c +++ b/hw/intc/xics.c @@ -567,8 +567,8 @@ static void ics_reset_irq(ICSIRQState *irq) static void ics_reset(DeviceState *dev) { ICSState *ics = ICS(dev); + g_autofree uint8_t *flags = g_malloc(ics->nr_irqs); int i; - uint8_t flags[ics->nr_irqs]; for (i = 0; i < ics->nr_irqs; i++) { flags[i] = ics->irqs[i].flags; From fa87341dabebe79d2e5577432a98b83c9eddf968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:28 +0100 Subject: [PATCH 0582/1020] hw/i386/multiboot: Avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use autofree heap allocation instead of variable-length array on the stack. Replace the snprintf() call by g_strdup_printf(). Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-9-peter.maydell@linaro.org --- hw/i386/multiboot.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c index 0a10089f14..963e29362e 100644 --- a/hw/i386/multiboot.c +++ b/hw/i386/multiboot.c @@ -163,6 +163,7 @@ int load_multiboot(X86MachineState *x86ms, uint8_t *mb_bootinfo_data; uint32_t cmdline_len; GList *mods = NULL; + g_autofree char *kcmdline = NULL; /* Ok, let's see if it is a multiboot image. The header is 12x32bit long, so the latest entry may be 8192 - 48. */ @@ -362,9 +363,7 @@ int load_multiboot(X86MachineState *x86ms, } /* Commandline support */ - char kcmdline[strlen(kernel_filename) + strlen(kernel_cmdline) + 2]; - snprintf(kcmdline, sizeof(kcmdline), "%s %s", - kernel_filename, kernel_cmdline); + kcmdline = g_strdup_printf("%s %s", kernel_filename, kernel_cmdline); stl_p(bootinfo + MBI_CMDLINE, mb_add_cmdline(&mbs, kcmdline)); stl_p(bootinfo + MBI_BOOTLOADER, mb_add_bootloader(&mbs, bootloader_name)); From 29d81e429d16fe8f0f1cd99e63507ca53ca1945c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:29 +0100 Subject: [PATCH 0583/1020] hw/usb/hcd-ohci: Use definition to avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compiler isn't clever enough to figure 'width' is a constant, so help it by using a definitions instead. Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-10-peter.maydell@linaro.org --- hw/usb/hcd-ohci.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 895b29fb86..5585fd32cc 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -805,13 +805,14 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed) return 1; } +#define HEX_CHAR_PER_LINE 16 + static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len) { bool print16; bool printall; - const int width = 16; int i; - char tmp[3 * width + 1]; + char tmp[3 * HEX_CHAR_PER_LINE + 1]; char *p = tmp; print16 = !!trace_event_get_state_backends(TRACE_USB_OHCI_TD_PKT_SHORT); @@ -822,7 +823,7 @@ static void ohci_td_pkt(const char *msg, const uint8_t *buf, size_t len) } for (i = 0; ; i++) { - if (i && (!(i % width) || (i == len))) { + if (i && (!(i % HEX_CHAR_PER_LINE) || (i == len))) { if (!printall) { trace_usb_ohci_td_pkt_short(msg, tmp); break; From 2d5f4a713d27f2b218b0c5abfa9833953da108d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:30 +0100 Subject: [PATCH 0584/1020] ui/curses: Avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use autofree heap allocation instead of variable-length array on the stack. Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-11-peter.maydell@linaro.org --- ui/curses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/curses.c b/ui/curses.c index 861d63244c..de962faa7c 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -69,7 +69,7 @@ static void curses_update(DisplayChangeListener *dcl, int x, int y, int w, int h) { console_ch_t *line; - cchar_t curses_line[width]; + g_autofree cchar_t *curses_line = g_new(cchar_t, width); wchar_t wch[CCHARW_MAX]; attr_t attrs; short colors; From 972d325a8dc855aa3817d0df9e09fd556a0449f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Fri, 19 Aug 2022 16:39:31 +0100 Subject: [PATCH 0585/1020] tests/unit/test-vmstate: Avoid dynamic stack allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use autofree heap allocation instead of variable-length array on the stack. Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20220819153931.3147384-12-peter.maydell@linaro.org --- tests/unit/test-vmstate.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/unit/test-vmstate.c b/tests/unit/test-vmstate.c index 72077b5780..541bb4f63e 100644 --- a/tests/unit/test-vmstate.c +++ b/tests/unit/test-vmstate.c @@ -87,17 +87,16 @@ static void save_buffer(const uint8_t *buf, size_t buf_size) static void compare_vmstate(const uint8_t *wire, size_t size) { QEMUFile *f = open_test_file(false); - uint8_t result[size]; + g_autofree uint8_t *result = g_malloc(size); /* read back as binary */ - g_assert_cmpint(qemu_get_buffer(f, result, sizeof(result)), ==, - sizeof(result)); + g_assert_cmpint(qemu_get_buffer(f, result, size), ==, size); g_assert(!qemu_file_get_error(f)); /* Compare that what is on the file is the same that what we expected to be there */ - SUCCESS(memcmp(result, wire, sizeof(result))); + SUCCESS(memcmp(result, wire, size)); /* Must reach EOF */ qemu_get_byte(f); From 342cf3041394916c9e6d6f23c27f62093a97a834 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Aug 2022 16:06:57 +0100 Subject: [PATCH 0586/1020] configure: Remove unused python_version variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shellcheck correctly reports that we set python_version and never use it. This is a leftover from commit f9332757898a7: we used to use python_version purely to as part of the summary information printed at the end of a configure run, and that commit changed to printing the information from meson (which looks up the python version itself). Remove the unused variable. Signed-off-by: Peter Maydell Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Philippe Mathieu-DaudĂ© Message-id: 20220825150703.4074125-2-peter.maydell@linaro.org --- configure | 3 --- 1 file changed, 3 deletions(-) diff --git a/configure b/configure index 0bbf9d28af..b5ace4cb49 100755 --- a/configure +++ b/configure @@ -1112,9 +1112,6 @@ if ! $python -c 'import sys; sys.exit(sys.version_info < (3,6))'; then "Use --python=/path/to/python to specify a supported Python." fi -# Preserve python version since some functionality is dependent on it -python_version=$($python -c 'import sys; print("%d.%d.%d" % (sys.version_info[0], sys.version_info[1], sys.version_info[2]))' 2>/dev/null) - # Suppress writing compiled files python="$python -B" From cbbc44d8efc57f4a07fada20740dfa9ef55b4fbc Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Aug 2022 16:06:58 +0100 Subject: [PATCH 0587/1020] configure: Remove unused meson_args variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The meson_args variable was added in commit 3b4da13293482134b, but was not used in that commit and isn't used today. Delete the unnecessary assignment. Signed-off-by: Peter Maydell Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Philippe Mathieu-DaudĂ© Message-id: 20220825150703.4074125-3-peter.maydell@linaro.org --- configure | 1 - 1 file changed, 1 deletion(-) diff --git a/configure b/configure index b5ace4cb49..e42d43d6a5 100755 --- a/configure +++ b/configure @@ -311,7 +311,6 @@ pie="" coroutine="" plugins="$default_feature" meson="" -meson_args="" ninja="" bindir="bin" skip_meson=no From 64708615e7c4748a6487f3c078dfac71061be01f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Aug 2022 16:06:59 +0100 Subject: [PATCH 0588/1020] configure: Add missing quoting for some easy cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds quotes in some places which: * are spotted by shellcheck * are obviously incorrect * are easy to fix just by adding the quotes It doesn't attempt fix all of the places shellcheck finds errors, or even all the ones which are easy to fix. It's just a random sampling which is hopefully easy to review and which cuts down the size of the problem for next time somebody wants to try to look at shellcheck errors. Signed-off-by: Peter Maydell Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Philippe Mathieu-DaudĂ© Message-id: 20220825150703.4074125-4-peter.maydell@linaro.org --- configure | 64 +++++++++++++++++++++++++++---------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/configure b/configure index e42d43d6a5..86cc625918 100755 --- a/configure +++ b/configure @@ -57,7 +57,7 @@ GNUmakefile: ; EOF cd build - exec $source_path/configure "$@" + exec "$source_path/configure" "$@" fi # Temporary directory used for files created while @@ -691,7 +691,7 @@ meson_option_build_array() { printf ']\n' } -. $source_path/scripts/meson-buildoptions.sh +. "$source_path/scripts/meson-buildoptions.sh" meson_options= meson_option_add() { @@ -711,7 +711,7 @@ for opt do case "$opt" in --help|-h) show_help=yes ;; - --version|-V) exec cat $source_path/VERSION + --version|-V) exec cat "$source_path/VERSION" ;; --prefix=*) prefix="$optarg" ;; @@ -985,7 +985,7 @@ default_target_list="" mak_wilds="" if [ "$linux_user" != no ]; then - if [ "$targetos" = linux ] && [ -d $source_path/linux-user/include/host/$cpu ]; then + if [ "$targetos" = linux ] && [ -d "$source_path/linux-user/include/host/$cpu" ]; then linux_user=yes elif [ "$linux_user" = yes ]; then error_exit "linux-user not supported on this architecture" @@ -995,7 +995,7 @@ if [ "$bsd_user" != no ]; then if [ "$bsd_user" = "" ]; then test $targetos = freebsd && bsd_user=yes fi - if [ "$bsd_user" = yes ] && ! [ -d $source_path/bsd-user/$targetos ]; then + if [ "$bsd_user" = yes ] && ! [ -d "$source_path/bsd-user/$targetos" ]; then error_exit "bsd-user not supported on this host OS" fi fi @@ -1117,7 +1117,7 @@ python="$python -B" if test -z "$meson"; then if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.59.3; then meson=meson - elif test $git_submodules_action != 'ignore' ; then + elif test "$git_submodules_action" != 'ignore' ; then meson=git elif test -e "${source_path}/meson/meson.py" ; then meson=internal @@ -1834,7 +1834,7 @@ esac container="no" if test $use_containers = "yes"; then if has "docker" || has "podman"; then - container=$($python $source_path/tests/docker/docker.py probe) + container=$($python "$source_path"/tests/docker/docker.py probe) fi fi @@ -2284,7 +2284,7 @@ if test "$QEMU_GA_DISTRO" = ""; then QEMU_GA_DISTRO=Linux fi if test "$QEMU_GA_VERSION" = ""; then - QEMU_GA_VERSION=$(cat $source_path/VERSION) + QEMU_GA_VERSION=$(cat "$source_path"/VERSION) fi @@ -2533,7 +2533,7 @@ fi for target in $target_list; do target_dir="$target" target_name=$(echo $target | cut -d '-' -f 1)$EXESUF - mkdir -p $target_dir + mkdir -p "$target_dir" case $target in *-user) symlink "../qemu-$target_name" "$target_dir/qemu-$target_name" ;; *) symlink "../qemu-system-$target_name" "$target_dir/qemu-system-$target_name" ;; @@ -2568,14 +2568,14 @@ for target in $target_list; do config_target_mak=tests/tcg/config-$target.mak echo "# Automatically generated by configure - do not modify" > $config_target_mak - echo "TARGET_NAME=$arch" >> $config_target_mak + echo "TARGET_NAME=$arch" >> "$config_target_mak" case $target in xtensa*-linux-user) # the toolchain is not complete with headers, only build softmmu tests continue ;; *-softmmu) - test -f $source_path/tests/tcg/$arch/Makefile.softmmu-target || continue + test -f "$source_path/tests/tcg/$arch/Makefile.softmmu-target" || continue qemu="qemu-system-$arch" ;; *-linux-user|*-bsd-user) @@ -2590,73 +2590,73 @@ for target in $target_list; do # compilers is a requirememt for adding a new test that needs a # compiler feature. - echo "BUILD_STATIC=$build_static" >> $config_target_mak - write_target_makefile >> $config_target_mak + echo "BUILD_STATIC=$build_static" >> "$config_target_mak" + write_target_makefile >> "$config_target_mak" case $target in aarch64-*) if do_compiler "$target_cc" $target_cflags \ -march=armv8.1-a+sve -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_SVE=y" >> $config_target_mak + echo "CROSS_CC_HAS_SVE=y" >> "$config_target_mak" fi if do_compiler "$target_cc" $target_cflags \ -march=armv8.1-a+sve2 -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_SVE2=y" >> $config_target_mak + echo "CROSS_CC_HAS_SVE2=y" >> "$config_target_mak" fi if do_compiler "$target_cc" $target_cflags \ -march=armv8.3-a -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak + echo "CROSS_CC_HAS_ARMV8_3=y" >> "$config_target_mak" fi if do_compiler "$target_cc" $target_cflags \ -mbranch-protection=standard -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak + echo "CROSS_CC_HAS_ARMV8_BTI=y" >> "$config_target_mak" fi if do_compiler "$target_cc" $target_cflags \ -march=armv8.5-a+memtag -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_ARMV8_MTE=y" >> $config_target_mak + echo "CROSS_CC_HAS_ARMV8_MTE=y" >> "$config_target_mak" fi ;; ppc*) if do_compiler "$target_cc" $target_cflags \ -mpower8-vector -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_POWER8_VECTOR=y" >> $config_target_mak + echo "CROSS_CC_HAS_POWER8_VECTOR=y" >> "$config_target_mak" fi if do_compiler "$target_cc" $target_cflags \ -mpower10 -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_POWER10=y" >> $config_target_mak + echo "CROSS_CC_HAS_POWER10=y" >> "$config_target_mak" fi ;; i386-linux-user) if do_compiler "$target_cc" $target_cflags \ -Werror -fno-pie -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_I386_NOPIE=y" >> $config_target_mak + echo "CROSS_CC_HAS_I386_NOPIE=y" >> "$config_target_mak" fi ;; esac elif test -n "$container_image"; then echo "build-tcg-tests-$target: docker-image-$container_image" >> $makefile - echo "BUILD_STATIC=y" >> $config_target_mak - write_container_target_makefile >> $config_target_mak + echo "BUILD_STATIC=y" >> "$config_target_mak" + write_container_target_makefile >> "$config_target_mak" case $target in aarch64-*) - echo "CROSS_CC_HAS_SVE=y" >> $config_target_mak - echo "CROSS_CC_HAS_SVE2=y" >> $config_target_mak - echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak - echo "CROSS_CC_HAS_ARMV8_BTI=y" >> $config_target_mak - echo "CROSS_CC_HAS_ARMV8_MTE=y" >> $config_target_mak + echo "CROSS_CC_HAS_SVE=y" >> "$config_target_mak" + echo "CROSS_CC_HAS_SVE2=y" >> "$config_target_mak" + echo "CROSS_CC_HAS_ARMV8_3=y" >> "$config_target_mak" + echo "CROSS_CC_HAS_ARMV8_BTI=y" >> "$config_target_mak" + echo "CROSS_CC_HAS_ARMV8_MTE=y" >> "$config_target_mak" ;; ppc*) - echo "CROSS_CC_HAS_POWER8_VECTOR=y" >> $config_target_mak - echo "CROSS_CC_HAS_POWER10=y" >> $config_target_mak + echo "CROSS_CC_HAS_POWER8_VECTOR=y" >> "$config_target_mak" + echo "CROSS_CC_HAS_POWER10=y" >> "$config_target_mak" ;; i386-linux-user) - echo "CROSS_CC_HAS_I386_NOPIE=y" >> $config_target_mak + echo "CROSS_CC_HAS_I386_NOPIE=y" >> "$config_target_mak" ;; esac got_cross_cc=yes fi if test $got_cross_cc = yes; then mkdir -p tests/tcg/$target - echo "QEMU=$PWD/$qemu" >> $config_target_mak + echo "QEMU=$PWD/$qemu" >> "$config_target_mak" echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> $makefile tcg_tests_targets="$tcg_tests_targets $target" fi From 002d8c13df9f28bd3112edc1c1159b6d762d130f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Aug 2022 16:07:00 +0100 Subject: [PATCH 0589/1020] configure: Add './' on front of glob of */config-devices.mak.d MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shellcheck warns that in rm -f */config-devices.mak.d the glob might expand to something with a '-' in it, which would then be misinterpreted as an option to rm. Fix this by adding './'. Signed-off-by: Peter Maydell Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Philippe Mathieu-DaudĂ© Message-id: 20220825150703.4074125-5-peter.maydell@linaro.org --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 86cc625918..482497e974 100755 --- a/configure +++ b/configure @@ -1093,7 +1093,7 @@ exit 0 fi # Remove old dependency files to make sure that they get properly regenerated -rm -f */config-devices.mak.d +rm -f ./*/config-devices.mak.d if test -z "$python" then From cc3c71e89f0b1b18024030976fda650d27806c9f Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Aug 2022 16:07:01 +0100 Subject: [PATCH 0590/1020] configure: Remove use of backtick `...` syntax MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's only one place in configure where we use `...` to execute a command and capture the result. Switch to $() to match the rest of the script. This silences a shellcheck warning. Signed-off-by: Peter Maydell Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Philippe Mathieu-DaudĂ© Message-id: 20220825150703.4074125-6-peter.maydell@linaro.org --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 482497e974..8b48e72a13 100755 --- a/configure +++ b/configure @@ -2311,7 +2311,7 @@ LINKS="$LINKS python" LINKS="$LINKS contrib/plugins/Makefile " for f in $LINKS ; do if [ -e "$source_path/$f" ]; then - mkdir -p `dirname ./$f` + mkdir -p "$(dirname ./"$f")" symlink "$source_path/$f" "$f" fi done From 563661c05677ad7c4b3f956507f3529df42afbf7 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Aug 2022 16:07:02 +0100 Subject: [PATCH 0591/1020] configure: Check mkdir result directly, not via $? MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shellcheck warns that we have one place where we run a command and then check if it failed using $?; this is better written to simply check the command in the 'if' statement directly. Signed-off-by: Peter Maydell Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Philippe Mathieu-DaudĂ© Message-id: 20220825150703.4074125-7-peter.maydell@linaro.org --- configure | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure b/configure index 8b48e72a13..b39561b2ed 100755 --- a/configure +++ b/configure @@ -67,8 +67,7 @@ fi # it when configure exits.) TMPDIR1="config-temp" rm -rf "${TMPDIR1}" -mkdir -p "${TMPDIR1}" -if [ $? -ne 0 ]; then +if ! mkdir -p "${TMPDIR1}"; then echo "ERROR: failed to create temporary directory" exit 1 fi From b3b5472db0ab7a53499441c1fe1dedec05b1e285 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 25 Aug 2022 16:07:03 +0100 Subject: [PATCH 0592/1020] configure: Avoid use of 'local' as it is non-POSIX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use the non-POSIX 'local' keyword in just two places in configure; rewrite to avoid it. In do_compiler(), just drop the 'local' keyword. The variable 'compiler' is only used elsewhere in the do_compiler_werror() function, which already uses the variable as a normal non-local one. In probe_target_compiler(), $try and $t are both local; make them normal variables and use a more obviously distinct variable name for $t. Signed-off-by: Peter Maydell Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Philippe Mathieu-DaudĂ© Message-id: 20220825150703.4074125-8-peter.maydell@linaro.org --- configure | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/configure b/configure index b39561b2ed..cc4ecd6008 100755 --- a/configure +++ b/configure @@ -110,7 +110,7 @@ error_exit() { do_compiler() { # Run the compiler, capturing its output to the log. First argument # is compiler binary to execute. - local compiler="$1" + compiler="$1" shift if test -n "$BASH_VERSION"; then eval ' echo >>config.log " @@ -2065,7 +2065,6 @@ probe_target_compiler() { : ${container_cross_strip:=${container_cross_prefix}strip} done - local t try try=cross case "$target_arch:$cpu" in aarch64_be:aarch64 | \ @@ -2078,8 +2077,8 @@ probe_target_compiler() { try='native cross' ;; esac eval "target_cflags=\${cross_cc_cflags_$target_arch}" - for t in $try; do - case $t in + for thistry in $try; do + case $thistry in native) target_cc=$cc target_ccas=$ccas From f16d15c9276bd8f501f861c39cbd4adc812d0c1d Mon Sep 17 00:00:00 2001 From: Yusuke Okada Date: Thu, 18 Aug 2022 14:46:19 -0400 Subject: [PATCH 0593/1020] virtiofsd: use g_date_time_get_microsecond to get subsecond The "%f" specifier in g_date_time_format() is only available in glib 2.65.2 or later. If combined with older glib, the function returns null and the timestamp displayed as "(null)". For backward compatibility, g_date_time_get_microsecond should be used to retrieve subsecond. In this patch the g_date_time_format() leaves subsecond field as "%06d" and let next snprintf to format with g_date_time_get_microsecond. Signed-off-by: Yusuke Okada Reviewed-by: Dr. David Alan Gilbert Message-id: 20220818184618.2205172-1-yokada.996@gmail.com Signed-off-by: Stefan Hajnoczi --- tools/virtiofsd/passthrough_ll.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/virtiofsd/passthrough_ll.c b/tools/virtiofsd/passthrough_ll.c index 371a7bead6..20f0f41f99 100644 --- a/tools/virtiofsd/passthrough_ll.c +++ b/tools/virtiofsd/passthrough_ll.c @@ -4185,6 +4185,7 @@ static void setup_nofile_rlimit(unsigned long rlimit_nofile) static void log_func(enum fuse_log_level level, const char *fmt, va_list ap) { g_autofree char *localfmt = NULL; + char buf[64]; if (current_log_level < level) { return; @@ -4197,9 +4198,11 @@ static void log_func(enum fuse_log_level level, const char *fmt, va_list ap) fmt); } else { g_autoptr(GDateTime) now = g_date_time_new_now_utc(); - g_autofree char *nowstr = g_date_time_format(now, "%Y-%m-%d %H:%M:%S.%f%z"); + g_autofree char *nowstr = g_date_time_format(now, + "%Y-%m-%d %H:%M:%S.%%06d%z"); + snprintf(buf, 64, nowstr, g_date_time_get_microsecond(now)); localfmt = g_strdup_printf("[%s] [ID: %08ld] %s", - nowstr, syscall(__NR_gettid), fmt); + buf, syscall(__NR_gettid), fmt); } fmt = localfmt; } From 131aafa7eff4aa4d747cb7113726b27394a38866 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Wed, 14 Sep 2022 12:57:50 +0200 Subject: [PATCH 0594/1020] s390x/tcg: Fix opcode for lzrf Fix the opcode for Load and Zero Rightmost Byte (32). Fixes: c2a5c1d718ea ("target/s390x: Implement load-and-zero-rightmost-byte insns") Reported-by: Nathan Chancellor Signed-off-by: Christian Borntraeger Tested-by: Nathan Chancellor Reviewed-by: Cornelia Huck Reviewed-by: David Hildenbrand Cc: qemu-stable@nongnu.org Message-Id: <20220914105750.767697-1-borntraeger@linux.ibm.com> Signed-off-by: Thomas Huth --- target/s390x/tcg/insn-data.def | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.def index 6d2cfe5fa2..6382ceabfc 100644 --- a/target/s390x/tcg/insn-data.def +++ b/target/s390x/tcg/insn-data.def @@ -466,7 +466,7 @@ C(0xe39f, LAT, RXY_a, LAT, 0, m2_32u, r1, 0, lat, 0) C(0xe385, LGAT, RXY_a, LAT, 0, a2, r1, 0, lgat, 0) /* LOAD AND ZERO RIGHTMOST BYTE */ - C(0xe3eb, LZRF, RXY_a, LZRB, 0, m2_32u, new, r1_32, lzrb, 0) + C(0xe33b, LZRF, RXY_a, LZRB, 0, m2_32u, new, r1_32, lzrb, 0) C(0xe32a, LZRG, RXY_a, LZRB, 0, m2_64, r1, 0, lzrb, 0) /* LOAD LOGICAL AND ZERO RIGHTMOST BYTE */ C(0xe33a, LLZRGF, RXY_a, LZRB, 0, m2_32u, r1, 0, lzrb, 0) From df6322a8973b5e69bdc8931ff79d3bfe3901cab5 Mon Sep 17 00:00:00 2001 From: Cal Peake Date: Thu, 11 Aug 2022 18:01:38 -0400 Subject: [PATCH 0595/1020] ui/console: Get tab completion working again in the SDL monitor vc Define a QEMU special key constant for the tab key and add an entry for it in the qcode_to_keysym table. This allows tab completion to work again in the SDL monitor virtual console, which has been broken ever since the migration from SDL1 to SDL2. Signed-off-by: Cal Peake Message-Id: <7054816e-99c-7e2-6737-7cf98cc56e2@absolutedigital.net> Signed-off-by: Gerd Hoffmann --- include/ui/console.h | 1 + ui/console.c | 1 + 2 files changed, 2 insertions(+) diff --git a/include/ui/console.h b/include/ui/console.h index c0520c694c..e400ee9fa7 100644 --- a/include/ui/console.h +++ b/include/ui/console.h @@ -70,6 +70,7 @@ void hmp_mouse_set(Monitor *mon, const QDict *qdict); /* keysym is a unicode code except for special keys (see QEMU_KEY_xxx constants) */ #define QEMU_KEY_ESC1(c) ((c) | 0xe100) +#define QEMU_KEY_TAB 0x0009 #define QEMU_KEY_BACKSPACE 0x007f #define QEMU_KEY_UP QEMU_KEY_ESC1('A') #define QEMU_KEY_DOWN QEMU_KEY_ESC1('B') diff --git a/ui/console.c b/ui/console.c index 765892f84f..243f2f6e64 100644 --- a/ui/console.c +++ b/ui/console.c @@ -1368,6 +1368,7 @@ static const int qcode_to_keysym[Q_KEY_CODE__MAX] = { [Q_KEY_CODE_PGUP] = QEMU_KEY_PAGEUP, [Q_KEY_CODE_PGDN] = QEMU_KEY_PAGEDOWN, [Q_KEY_CODE_DELETE] = QEMU_KEY_DELETE, + [Q_KEY_CODE_TAB] = QEMU_KEY_TAB, [Q_KEY_CODE_BACKSPACE] = QEMU_KEY_BACKSPACE, }; From d135f781405f7c78153aa65e0327b05a4aa72e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Fri, 23 Sep 2022 12:04:13 +0100 Subject: [PATCH 0596/1020] linux-user: use 'max' instead of 'qemu32' / 'qemu64' by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'qemu64' CPU model implements the least featureful x86_64 CPU that's possible. Historically this hasn't been an issue since it was rare for OS distros to build with a higher mandatory CPU baseline. With RHEL-9, however, the entire distro is built for the x86_64-v2 ABI baseline: https://developers.redhat.com/blog/2021/01/05/building-red-hat-enterprise-linux-9-for-the-x86-64-v2-microarchitecture-level It is likely that other distros may take similar steps in the not too distant future. For example, it has been suggested for Fedora on a number of occasions. This new baseline is not compatible with the qemu64 CPU model though. While it is possible to pass a '-cpu xxx' flag to qemu-x86_64, the usage of QEMU doesn't always allow for this. For example, the args are typically controlled via binfmt rules that the user has no ability to change. This impacts users who are trying to use podman on aarch64 platforms, to run containers with x86_64 content. There's no arg to podman that can be used to change the qemu-x86_64 args, and a non-root user of podman can not change binfmt rules without elevating privileges: https://github.com/containers/podman/issues/15456#issuecomment-1228210973 Changing to the 'max' CPU model gives 'qemu-x86_64' maximum compatibility with binaries it is likely to encounter in the wild, and not likely to have a significant downside for existing usage. Most other architectures already use an 'any' CPU model, which is often mapped to 'max' (or similar) already, rather than the oldest possible CPU model. For the sake of consistency the 'i386' architecture is also changed from using 'qemu32' to 'max'. Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Daniel P. BerrangĂ© Message-Id: <20220923110413.70593-1-berrange@redhat.com> Signed-off-by: Laurent Vivier --- linux-user/i386/target_elf.h | 2 +- linux-user/x86_64/target_elf.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/i386/target_elf.h b/linux-user/i386/target_elf.h index 1c6142e7da..238a9aba73 100644 --- a/linux-user/i386/target_elf.h +++ b/linux-user/i386/target_elf.h @@ -9,6 +9,6 @@ #define I386_TARGET_ELF_H static inline const char *cpu_get_model(uint32_t eflags) { - return "qemu32"; + return "max"; } #endif diff --git a/linux-user/x86_64/target_elf.h b/linux-user/x86_64/target_elf.h index 7b76a90de8..3f628f8d66 100644 --- a/linux-user/x86_64/target_elf.h +++ b/linux-user/x86_64/target_elf.h @@ -9,6 +9,6 @@ #define X86_64_TARGET_ELF_H static inline const char *cpu_get_model(uint32_t eflags) { - return "qemu64"; + return "max"; } #endif From bab6a301c58286229ca8fbc36728d1469f243260 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Fri, 19 Aug 2022 22:27:54 +0900 Subject: [PATCH 0597/1020] ui/cocoa: Run qemu_init in the main thread This work is based on: https://patchew.org/QEMU/20220317125534.38706-1-philippe.mathieu.daude@gmail.com/ Simplify the initialization dance by running qemu_init() in the main thread before the Cocoa event loop starts. The secondary thread only runs only qemu_main_loop() and qemu_cleanup(). This fixes a case where addRemovableDevicesMenuItems() calls qmp_query_block() while expecting the main thread to still hold the BQL. Overriding the code after calling qemu_init() is done by dynamically replacing a function pointer variable, qemu_main when initializing ui/cocoa, which unifies the static implementation of main() for builds with ui/cocoa and ones without ui/cocoa. Signed-off-by: Akihiko Odaki Message-Id: <20220819132756.74641-2-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann --- docs/devel/fuzzing.rst | 4 +- include/qemu-main.h | 3 +- include/sysemu/sysemu.h | 2 +- softmmu/main.c | 10 +-- softmmu/vl.c | 2 +- tests/qtest/fuzz/fuzz.c | 2 +- ui/cocoa.m | 144 ++++++++++++++-------------------------- 7 files changed, 62 insertions(+), 105 deletions(-) diff --git a/docs/devel/fuzzing.rst b/docs/devel/fuzzing.rst index 784ecb99e6..715330c856 100644 --- a/docs/devel/fuzzing.rst +++ b/docs/devel/fuzzing.rst @@ -287,8 +287,8 @@ select the fuzz target. Then, the qtest client is initialized. If the target requires qos, qgraph is set up and the QOM/LIBQOS modules are initialized. Then the QGraph is walked and the QEMU cmd_line is determined and saved. -After this, the ``vl.c:qemu_main`` is called to set up the guest. There are -target-specific hooks that can be called before and after qemu_main, for +After this, the ``vl.c:main`` is called to set up the guest. There are +target-specific hooks that can be called before and after main, for additional setup(e.g. PCI setup, or VM snapshotting). ``LLVMFuzzerTestOneInput``: Uses qtest/qos functions to act based on the fuzz diff --git a/include/qemu-main.h b/include/qemu-main.h index 6a3e90d0ad..940960a7db 100644 --- a/include/qemu-main.h +++ b/include/qemu-main.h @@ -5,6 +5,7 @@ #ifndef QEMU_MAIN_H #define QEMU_MAIN_H -int qemu_main(int argc, char **argv, char **envp); +int qemu_default_main(void); +extern int (*qemu_main)(void); #endif /* QEMU_MAIN_H */ diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h index 31aa45160b..6a7a31e64d 100644 --- a/include/sysemu/sysemu.h +++ b/include/sysemu/sysemu.h @@ -102,7 +102,7 @@ void qemu_boot_set(const char *boot_order, Error **errp); bool defaults_enabled(void); -void qemu_init(int argc, char **argv, char **envp); +void qemu_init(int argc, char **argv); int qemu_main_loop(void); void qemu_cleanup(void); diff --git a/softmmu/main.c b/softmmu/main.c index 1b675a8c03..694388bd7f 100644 --- a/softmmu/main.c +++ b/softmmu/main.c @@ -30,20 +30,20 @@ #include #endif -int qemu_main(int argc, char **argv, char **envp) +int qemu_default_main(void) { int status; - qemu_init(argc, argv, envp); status = qemu_main_loop(); qemu_cleanup(); return status; } -#ifndef CONFIG_COCOA +int (*qemu_main)(void) = qemu_default_main; + int main(int argc, char **argv) { - return qemu_main(argc, argv, NULL); + qemu_init(argc, argv); + return qemu_main(); } -#endif diff --git a/softmmu/vl.c b/softmmu/vl.c index e62b9cc35d..9abadcc150 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -2605,7 +2605,7 @@ void qmp_x_exit_preconfig(Error **errp) } } -void qemu_init(int argc, char **argv, char **envp) +void qemu_init(int argc, char **argv) { QemuOpts *opts; QemuOpts *icount_opts = NULL, *accel_opts = NULL; diff --git a/tests/qtest/fuzz/fuzz.c b/tests/qtest/fuzz/fuzz.c index 2b3bc1fb9d..eb7520544b 100644 --- a/tests/qtest/fuzz/fuzz.c +++ b/tests/qtest/fuzz/fuzz.c @@ -218,7 +218,7 @@ int LLVMFuzzerInitialize(int *argc, char ***argv, char ***envp) g_free(pretty_cmd_line); } - qemu_init(result.we_wordc, result.we_wordv, NULL); + qemu_init(result.we_wordc, result.we_wordv); /* re-enable the rcu atfork, which was previously disabled in qemu_init */ rcu_enable_atfork(); diff --git a/ui/cocoa.m b/ui/cocoa.m index 5a8bd5dd84..660d3e0935 100644 --- a/ui/cocoa.m +++ b/ui/cocoa.m @@ -100,13 +100,9 @@ static int cursor_hide = 1; static int left_command_key_enabled = 1; static bool swap_opt_cmd; -static int gArgc; -static char **gArgv; static bool stretch_video; static NSTextField *pauseLabel; -static QemuSemaphore display_init_sem; -static QemuSemaphore app_started_sem; static bool allow_events; static NSInteger cbchangecount = -1; @@ -597,7 +593,7 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven /* * Don't try to tell QEMU about UI information in the application * startup phase -- we haven't yet registered dcl with the QEMU UI - * layer, and also trying to take the iothread lock would deadlock. + * layer. * When cocoa_display_init() does register the dcl, the UI layer * will call cocoa_switch(), which will call updateUIInfo, so * we don't lose any information here. @@ -790,16 +786,6 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven - (bool) handleEvent:(NSEvent *)event { - if(!allow_events) { - /* - * Just let OSX have all events that arrive before - * applicationDidFinishLaunching. - * This avoids a deadlock on the iothread lock, which cocoa_display_init() - * will not drop until after the app_started_sem is posted. (In theory - * there should not be any such events, but OSX Catalina now emits some.) - */ - return false; - } return bool_with_iothread_lock(^{ return [self handleEventLocked:event]; }); @@ -1287,8 +1273,6 @@ static CGEventRef handleTapEvent(CGEventTapProxy proxy, CGEventType type, CGEven { COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching\n"); allow_events = true; - /* Tell cocoa_display_init to proceed */ - qemu_sem_post(&app_started_sem); } - (void)applicationWillTerminate:(NSNotification *)aNotification @@ -1919,92 +1903,45 @@ static void cocoa_clipboard_request(QemuClipboardInfo *info, /* * The startup process for the OSX/Cocoa UI is complicated, because * OSX insists that the UI runs on the initial main thread, and so we - * need to start a second thread which runs the vl.c qemu_main(): - * - * Initial thread: 2nd thread: + * need to start a second thread which runs the qemu_default_main(): * in main(): - * create qemu-main thread - * wait on display_init semaphore - * call qemu_main() - * ... - * in cocoa_display_init(): - * post the display_init semaphore - * wait on app_started semaphore - * create application, menus, etc - * enter OSX run loop - * in applicationDidFinishLaunching: - * post app_started semaphore - * tell main thread to fullscreen if needed - * [...] - * run qemu main-loop - * - * We do this in two stages so that we don't do the creation of the - * GUI application menus and so on for command line options like --help - * where we want to just print text to stdout and exit immediately. + * in cocoa_display_init(): + * assign cocoa_main to qemu_main + * create application, menus, etc + * in cocoa_main(): + * create qemu-main thread + * enter OSX run loop */ static void *call_qemu_main(void *opaque) { int status; - COCOA_DEBUG("Second thread: calling qemu_main()\n"); - status = qemu_main(gArgc, gArgv, *_NSGetEnviron()); - COCOA_DEBUG("Second thread: qemu_main() returned, exiting\n"); + COCOA_DEBUG("Second thread: calling qemu_default_main()\n"); + qemu_mutex_lock_iothread(); + status = qemu_default_main(); + qemu_mutex_unlock_iothread(); + COCOA_DEBUG("Second thread: qemu_default_main() returned, exiting\n"); [cbowner release]; exit(status); } -int main (int argc, char **argv) { +static int cocoa_main() +{ QemuThread thread; - COCOA_DEBUG("Entered main()\n"); - gArgc = argc; - gArgv = argv; - - qemu_sem_init(&display_init_sem, 0); - qemu_sem_init(&app_started_sem, 0); + COCOA_DEBUG("Entered %s()\n", __func__); + qemu_mutex_unlock_iothread(); qemu_thread_create(&thread, "qemu_main", call_qemu_main, NULL, QEMU_THREAD_DETACHED); - COCOA_DEBUG("Main thread: waiting for display_init_sem\n"); - qemu_sem_wait(&display_init_sem); - COCOA_DEBUG("Main thread: initializing app\n"); - - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - - // Pull this console process up to being a fully-fledged graphical - // app with a menubar and Dock icon - ProcessSerialNumber psn = { 0, kCurrentProcess }; - TransformProcessType(&psn, kProcessTransformToForegroundApplication); - - [QemuApplication sharedApplication]; - - create_initial_menus(); - - /* - * Create the menu entries which depend on QEMU state (for consoles - * and removeable devices). These make calls back into QEMU functions, - * which is OK because at this point we know that the second thread - * holds the iothread lock and is synchronously waiting for us to - * finish. - */ - add_console_menu_entries(); - addRemovableDevicesMenuItems(); - - // Create an Application controller - QemuCocoaAppController *appController = [[QemuCocoaAppController alloc] init]; - [NSApp setDelegate:appController]; - // Start the main event loop COCOA_DEBUG("Main thread: entering OSX run loop\n"); [NSApp run]; - COCOA_DEBUG("Main thread: left OSX run loop, exiting\n"); + COCOA_DEBUG("Main thread: left OSX run loop, which should never happen\n"); - [appController release]; - [pool release]; - - return 0; + abort(); } @@ -2083,25 +2020,42 @@ static void cocoa_refresh(DisplayChangeListener *dcl) static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n"); - /* Tell main thread to go ahead and create the app and enter the run loop */ - qemu_sem_post(&display_init_sem); - qemu_sem_wait(&app_started_sem); - COCOA_DEBUG("cocoa_display_init: app start completed\n"); + qemu_main = cocoa_main; + + // Pull this console process up to being a fully-fledged graphical + // app with a menubar and Dock icon + ProcessSerialNumber psn = { 0, kCurrentProcess }; + TransformProcessType(&psn, kProcessTransformToForegroundApplication); + + [QemuApplication sharedApplication]; + + create_initial_menus(); + + /* + * Create the menu entries which depend on QEMU state (for consoles + * and removeable devices). These make calls back into QEMU functions, + * which is OK because at this point we know that the second thread + * holds the iothread lock and is synchronously waiting for us to + * finish. + */ + add_console_menu_entries(); + addRemovableDevicesMenuItems(); + + // Create an Application controller + QemuCocoaAppController *controller = [[QemuCocoaAppController alloc] init]; + [NSApp setDelegate:controller]; - QemuCocoaAppController *controller = (QemuCocoaAppController *)[[NSApplication sharedApplication] delegate]; /* if fullscreen mode is to be used */ if (opts->has_full_screen && opts->full_screen) { - dispatch_async(dispatch_get_main_queue(), ^{ - [NSApp activateIgnoringOtherApps: YES]; - [controller toggleFullScreen: nil]; - }); + [NSApp activateIgnoringOtherApps: YES]; + [controller toggleFullScreen: nil]; } if (opts->u.cocoa.has_full_grab && opts->u.cocoa.full_grab) { - dispatch_async(dispatch_get_main_queue(), ^{ - [controller setFullGrab: nil]; - }); + [controller setFullGrab: nil]; } if (opts->has_show_cursor && opts->show_cursor) { @@ -2121,6 +2075,8 @@ static void cocoa_display_init(DisplayState *ds, DisplayOptions *opts) qemu_event_init(&cbevent, false); cbowner = [[QemuCocoaPasteboardTypeOwner alloc] init]; qemu_clipboard_peer_register(&cbpeer); + + [pool release]; } static QemuDisplay qemu_display_cocoa = { From 2dc7f90a835a4cd2362ace5e2388687afd296b85 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Fri, 19 Aug 2022 22:27:55 +0900 Subject: [PATCH 0598/1020] Revert "main-loop: Disable block backend global state assertion on Cocoa" This reverts commit 47281859f66bdab1974fb122cab2cbb4a1c9af7f. Signed-off-by: Akihiko Odaki Reviewed-by: Emanuele Giuseppe Esposito Reviewed-by: Peter Maydell Reviewed-by: Paolo Bonzini Message-Id: <20220819132756.74641-3-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann --- include/qemu/main-loop.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index c50d1b7e3a..aac707d073 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -284,23 +284,10 @@ bool qemu_in_main_thread(void); * Please refer to include/block/block-global-state.h for more * information about GS API. */ -#ifdef CONFIG_COCOA -/* - * When using the Cocoa UI, addRemovableDevicesMenuItems() is called from - * a thread different from the QEMU main thread and can not take the BQL, - * triggering this assertions in the block layer (commit 0439c5a462). - * As the Cocoa fix is not trivial, disable this assertion for the v7.0.0 - * release (when using Cocoa); we will restore it immediately after the - * release. - * This issue is tracked as https://gitlab.com/qemu-project/qemu/-/issues/926 - */ -#define GLOBAL_STATE_CODE() -#else #define GLOBAL_STATE_CODE() \ do { \ assert(qemu_in_main_thread()); \ } while (0) -#endif /* CONFIG_COCOA */ /* * Mark and check that the function is part of the I/O API. From 64d3fec76c913bf94f9b87f7482669302af9bbf9 Mon Sep 17 00:00:00 2001 From: Akihiko Odaki Date: Fri, 19 Aug 2022 22:27:56 +0900 Subject: [PATCH 0599/1020] meson: Allow to enable gtk and sdl while cocoa is enabled As ui/cocoa does no longer override main(), ui/gtk and ui/sdl can be enabled even ui/cocoa is enabled. Signed-off-by: Akihiko Odaki Reviewed-by: Peter Maydell Reviewed-by: Paolo Bonzini Message-Id: <20220819132756.74641-4-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann --- meson.build | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index 3885fc1076..d9ac91ff36 100644 --- a/meson.build +++ b/meson.build @@ -589,12 +589,6 @@ endif cocoa = dependency('appleframeworks', modules: ['Cocoa', 'CoreVideo'], required: get_option('cocoa')) -if cocoa.found() and get_option('sdl').enabled() - error('Cocoa and SDL cannot be enabled at the same time') -endif -if cocoa.found() and get_option('gtk').enabled() - error('Cocoa and GTK+ cannot be enabled at the same time') -endif vmnet = dependency('appleframeworks', modules: 'vmnet', required: get_option('vmnet')) if vmnet.found() and not cc.has_header_symbol('vmnet/vmnet.h', @@ -921,7 +915,7 @@ if not get_option('brlapi').auto() or have_system endif sdl = not_found -if not get_option('sdl').auto() or (have_system and not cocoa.found()) +if not get_option('sdl').auto() or have_system sdl = dependency('sdl2', required: get_option('sdl'), kwargs: static_kwargs) sdl_image = not_found endif @@ -1187,7 +1181,7 @@ endif gtk = not_found gtkx11 = not_found vte = not_found -if not get_option('gtk').auto() or (have_system and not cocoa.found()) +if not get_option('gtk').auto() or have_system gtk = dependency('gtk+-3.0', version: '>=3.22.0', method: 'pkg-config', required: get_option('gtk'), From 410840cdb1342751f58a3521f48d5a9faf694c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 12 Sep 2022 14:24:51 +0400 Subject: [PATCH 0600/1020] ui: add some vdagent related traces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps debugging clipboard serial sync issues. Signed-off-by: Marc-AndrĂ© Lureau Message-Id: <20220912102455.111765-2-marcandre.lureau@redhat.com> [ kraxel: code style fix ] Signed-off-by: Gerd Hoffmann --- ui/clipboard.c | 11 +++++++++-- ui/trace-events | 5 +++++ ui/vdagent.c | 4 ++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/ui/clipboard.c b/ui/clipboard.c index 9079ef829b..cd5382fcb0 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -1,5 +1,6 @@ #include "qemu/osdep.h" #include "ui/clipboard.h" +#include "trace.h" static NotifierList clipboard_notifiers = NOTIFIER_LIST_INITIALIZER(clipboard_notifiers); @@ -43,17 +44,23 @@ void qemu_clipboard_peer_release(QemuClipboardPeer *peer, bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client) { + bool ok; + if (!info->has_serial || !cbinfo[info->selection] || !cbinfo[info->selection]->has_serial) { + trace_clipboard_check_serial(-1, -1, true); return true; } if (client) { - return cbinfo[info->selection]->serial >= info->serial; + ok = cbinfo[info->selection]->serial >= info->serial; } else { - return cbinfo[info->selection]->serial > info->serial; + ok = cbinfo[info->selection]->serial > info->serial; } + + trace_clipboard_check_serial(cbinfo[info->selection]->serial, info->serial, ok); + return ok; } void qemu_clipboard_update(QemuClipboardInfo *info) diff --git a/ui/trace-events b/ui/trace-events index a922f00e10..977577fbba 100644 --- a/ui/trace-events +++ b/ui/trace-events @@ -127,15 +127,20 @@ xkeymap_vendor(const char *name) "vendor '%s'" xkeymap_keycodes(const char *name) "keycodes '%s'" xkeymap_keymap(const char *name) "keymap '%s'" +# clipboard.c +clipboard_check_serial(int cur, int recv, bool ok) "cur:%d recv:%d %d" + # vdagent.c vdagent_open(void) "" vdagent_close(void) "" +vdagent_disconnect(void) "" vdagent_send(const char *name) "msg %s" vdagent_send_empty_clipboard(void) "" vdagent_recv_chunk(uint32_t size) "size %d" vdagent_recv_msg(const char *name, uint32_t size) "msg %s, size %d" vdagent_peer_cap(const char *name) "cap %s" vdagent_cb_grab_selection(const char *name) "selection %s" +vdagent_cb_grab_discard(const char *name, int cur, int recv) "selection %s, cur:%d recv:%d" vdagent_cb_grab_type(const char *name) "type %s" vdagent_cb_serial_discard(uint32_t current, uint32_t received) "current=%u, received=%u" diff --git a/ui/vdagent.c b/ui/vdagent.c index a899eed195..58ce7507fd 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -533,6 +533,8 @@ static void vdagent_clipboard_recv_grab(VDAgentChardev *vd, uint8_t s, uint32_t info->has_serial = true; info->serial = *(uint32_t *)data; if (info->serial < vd->last_serial[s]) { + trace_vdagent_cb_grab_discard(GET_NAME(sel_name, s), + vd->last_serial[s], info->serial); /* discard lower-ordering guest grab */ return; } @@ -853,6 +855,8 @@ static void vdagent_chr_accept_input(Chardev *chr) static void vdagent_disconnect(VDAgentChardev *vd) { + trace_vdagent_disconnect(); + buffer_reset(&vd->outbuf); vdagent_reset_bufs(vd); vd->caps = 0; From 0e23ae9c657d65049e5ef3a06451b22830964f35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 12 Sep 2022 14:24:52 +0400 Subject: [PATCH 0601/1020] ui/clipboard: fix serial priority MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The incoming grab event should have a higher serial. See also "vdagent: introduce VD_AGENT_CAP_CLIPBOARD_GRAB_SERIAL": https://gitlab.freedesktop.org/spice/spice-protocol/-/commit/045a6978d6dbbf7046affc5c321fa8177c8cce56 This is only a relevant fix for the -display dbus, only user of that function. Signed-off-by: Marc-AndrĂ© Lureau Message-Id: <20220912102455.111765-3-marcandre.lureau@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/clipboard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/clipboard.c b/ui/clipboard.c index cd5382fcb0..3e2d02d549 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -54,9 +54,9 @@ bool qemu_clipboard_check_serial(QemuClipboardInfo *info, bool client) } if (client) { - ok = cbinfo[info->selection]->serial >= info->serial; + ok = info->serial >= cbinfo[info->selection]->serial; } else { - ok = cbinfo[info->selection]->serial > info->serial; + ok = info->serial > cbinfo[info->selection]->serial; } trace_clipboard_check_serial(cbinfo[info->selection]->serial, info->serial, ok); From e46d4d684224872b8b5999a51c688ee8fffb4a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 12 Sep 2022 14:24:53 +0400 Subject: [PATCH 0602/1020] ui/vdagent: always reset the clipboard serial on caps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The guest agent doesn't know what is the current serial state. Reset the serial value whenever a new agent connection is established. Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2124446 Signed-off-by: Marc-AndrĂ© Lureau Message-Id: <20220912102455.111765-4-marcandre.lureau@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/vdagent.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index 58ce7507fd..819e0dc143 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -719,8 +719,10 @@ static void vdagent_chr_recv_caps(VDAgentChardev *vd, VDAgentMessage *msg) if (have_mouse(vd) && vd->mouse_hs) { qemu_input_handler_activate(vd->mouse_hs); } + + memset(vd->last_serial, 0, sizeof(vd->last_serial)); + if (have_clipboard(vd) && vd->cbpeer.notifier.notify == NULL) { - memset(vd->last_serial, 0, sizeof(vd->last_serial)); vd->cbpeer.name = "vdagent"; vd->cbpeer.notifier.notify = vdagent_clipboard_notify; vd->cbpeer.request = vdagent_clipboard_request; From 72ce36f77ca6fe8cf9aae5ed28d7c3c865ef887d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 12 Sep 2022 14:24:54 +0400 Subject: [PATCH 0603/1020] ui/clipboard: reset the serial state on reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not only we have to reset the vdagent clipboards serial state, but also the current QEMU clipboards info serial (the value is currently used by qemu_clipboard_check_serial, only used by -display dbus). Signed-off-by: Marc-AndrĂ© Lureau Message-Id: <20220912102455.111765-5-marcandre.lureau@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/clipboard.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ui/clipboard.c b/ui/clipboard.c index 3e2d02d549..3d14bffaf8 100644 --- a/ui/clipboard.c +++ b/ui/clipboard.c @@ -139,7 +139,14 @@ void qemu_clipboard_request(QemuClipboardInfo *info, void qemu_clipboard_reset_serial(void) { QemuClipboardNotify notify = { .type = QEMU_CLIPBOARD_RESET_SERIAL }; + int i; + for (i = 0; i < QEMU_CLIPBOARD_SELECTION__COUNT; i++) { + QemuClipboardInfo *info = qemu_clipboard_info(i); + if (info) { + info->serial = 0; + } + } notifier_list_notify(&clipboard_notifiers, ¬ify); } From d18431547f388db1e43c0cbc8a423ea9cc0df3d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 12 Sep 2022 14:24:55 +0400 Subject: [PATCH 0604/1020] ui/vdagent: fix serial reset of guest agent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to reset the guest agent, we send CLOSED & OPENED events. They are correctly received by the guest kernel. However, they might not be noticed by the guest agent process, as the IO task (poll() for example) might be wake up after both CLOSED & OPENED have been processed. Wait until the guest agent is disconnected to re-open our side. Signed-off-by: Marc-AndrĂ© Lureau Message-Id: <20220912102455.111765-6-marcandre.lureau@redhat.com> Signed-off-by: Gerd Hoffmann --- ui/vdagent.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui/vdagent.c b/ui/vdagent.c index 819e0dc143..4bf50f0c4d 100644 --- a/ui/vdagent.c +++ b/ui/vdagent.c @@ -471,7 +471,7 @@ static void vdagent_clipboard_reset_serial(VDAgentChardev *vd) /* reopen the agent connection to reset the serial state */ qemu_chr_be_event(chr, CHR_EVENT_CLOSED); - qemu_chr_be_event(chr, CHR_EVENT_OPENED); + /* OPENED again after the guest disconnected, see set_fe_open */ } static void vdagent_clipboard_notify(Notifier *notifier, void *data) @@ -875,6 +875,9 @@ static void vdagent_chr_set_fe_open(struct Chardev *chr, int fe_open) { if (!fe_open) { trace_vdagent_close(); + /* To reset_serial, we CLOSED our side. Make sure the other end knows we + * are ready again. */ + qemu_chr_be_event(chr, CHR_EVENT_OPENED); return; } From 17b55372b509a253abed9d7d4a81772f6067220f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Mon, 19 Sep 2022 08:19:56 +0200 Subject: [PATCH 0605/1020] ui/console: fix three double frees in png_save() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The png_destroy_write_struct() function frees all memory used by libpng. Don't use the glib auto cleanup mechanism to free the memory allocated by libpng again. For the pixman image, use only the auto cleanup mechanism and remove the qemu_pixman_image_unref() function call to prevent another double free. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1210 Fixes: 9a0a119a38 ("Added parameter to take screenshot with screendump as PNG") Tested-by: Philippe Mathieu-DaudĂ© Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Volker RĂ¼melin Message-Id: <20220919061956.30929-1-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann --- ui/console.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/ui/console.c b/ui/console.c index 243f2f6e64..49da6a91df 100644 --- a/ui/console.c +++ b/ui/console.c @@ -304,8 +304,8 @@ static bool png_save(int fd, pixman_image_t *image, Error **errp) { int width = pixman_image_get_width(image); int height = pixman_image_get_height(image); - g_autofree png_struct *png_ptr = NULL; - g_autofree png_info *info_ptr = NULL; + png_struct *png_ptr; + png_info *info_ptr; g_autoptr(pixman_image_t) linebuf = qemu_pixman_linebuf_create(PIXMAN_a8r8g8b8, width); uint8_t *buf = (uint8_t *)pixman_image_get_data(linebuf); @@ -346,7 +346,6 @@ static bool png_save(int fd, pixman_image_t *image, Error **errp) qemu_pixman_linebuf_fill(linebuf, image, width, 0, y); png_write_row(png_ptr, buf); } - qemu_pixman_image_unref(linebuf); png_write_end(png_ptr, NULL); From 0b33bb394d0d02918679064caa11ef59e5ff3924 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Wed, 17 Aug 2022 18:00:16 +0200 Subject: [PATCH 0606/1020] hw/usb/hcd-xhci: Check whether DMA accesses fail If a guest sets up bad descriptors, it could force QEMU to access non-existing memory regions. Thus we should check the return value of dma_memory_read/write() to make sure that these errors don't go unnoticed. Signed-off-by: Thomas Huth Message-Id: <20220817160016.49752-1-thuth@redhat.com> Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 64 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 3c48b58dde..acd60b1a49 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -463,6 +463,12 @@ static void xhci_mfwrap_timer(void *opaque) xhci_mfwrap_update(xhci); } +static void xhci_die(XHCIState *xhci) +{ + xhci->usbsts |= USBSTS_HCE; + DPRINTF("xhci: asserted controller error\n"); +} + static inline dma_addr_t xhci_addr64(uint32_t low, uint32_t high) { if (sizeof(dma_addr_t) == 4) { @@ -488,7 +494,14 @@ static inline void xhci_dma_read_u32s(XHCIState *xhci, dma_addr_t addr, assert((len % sizeof(uint32_t)) == 0); - dma_memory_read(xhci->as, addr, buf, len, MEMTXATTRS_UNSPECIFIED); + if (dma_memory_read(xhci->as, addr, buf, len, + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n", + __func__); + memset(buf, 0xff, len); + xhci_die(xhci); + return; + } for (i = 0; i < (len / sizeof(uint32_t)); i++) { buf[i] = le32_to_cpu(buf[i]); @@ -496,7 +509,7 @@ static inline void xhci_dma_read_u32s(XHCIState *xhci, dma_addr_t addr, } static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr, - uint32_t *buf, size_t len) + const uint32_t *buf, size_t len) { int i; uint32_t tmp[5]; @@ -508,7 +521,13 @@ static inline void xhci_dma_write_u32s(XHCIState *xhci, dma_addr_t addr, for (i = 0; i < n; i++) { tmp[i] = cpu_to_le32(buf[i]); } - dma_memory_write(xhci->as, addr, tmp, len, MEMTXATTRS_UNSPECIFIED); + if (dma_memory_write(xhci->as, addr, tmp, len, + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n", + __func__); + xhci_die(xhci); + return; + } } static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport) @@ -593,12 +612,6 @@ static inline int xhci_running(XHCIState *xhci) return !(xhci->usbsts & USBSTS_HCH); } -static void xhci_die(XHCIState *xhci) -{ - xhci->usbsts |= USBSTS_HCE; - DPRINTF("xhci: asserted controller error\n"); -} - static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v) { XHCIInterrupter *intr = &xhci->intr[v]; @@ -619,7 +632,12 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v) ev_trb.status, ev_trb.control); addr = intr->er_start + TRB_SIZE*intr->er_ep_idx; - dma_memory_write(xhci->as, addr, &ev_trb, TRB_SIZE, MEMTXATTRS_UNSPECIFIED); + if (dma_memory_write(xhci->as, addr, &ev_trb, TRB_SIZE, + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n", + __func__); + xhci_die(xhci); + } intr->er_ep_idx++; if (intr->er_ep_idx >= intr->er_size) { @@ -680,8 +698,12 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb, while (1) { TRBType type; - dma_memory_read(xhci->as, ring->dequeue, trb, TRB_SIZE, - MEMTXATTRS_UNSPECIFIED); + if (dma_memory_read(xhci->as, ring->dequeue, trb, TRB_SIZE, + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n", + __func__); + return 0; + } trb->addr = ring->dequeue; trb->ccs = ring->ccs; le64_to_cpus(&trb->parameter); @@ -798,8 +820,14 @@ static void xhci_er_reset(XHCIState *xhci, int v) xhci_die(xhci); return; } - dma_memory_read(xhci->as, erstba, &seg, sizeof(seg), - MEMTXATTRS_UNSPECIFIED); + if (dma_memory_read(xhci->as, erstba, &seg, sizeof(seg), + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory access failed!\n", + __func__); + xhci_die(xhci); + return; + } + le32_to_cpus(&seg.addr_low); le32_to_cpus(&seg.addr_high); le32_to_cpus(&seg.size); @@ -2415,8 +2443,12 @@ static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx) /* TODO: actually implement real values here */ bw_ctx[0] = 0; memset(&bw_ctx[1], 80, xhci->numports); /* 80% */ - dma_memory_write(xhci->as, ctx, bw_ctx, sizeof(bw_ctx), - MEMTXATTRS_UNSPECIFIED); + if (dma_memory_write(xhci->as, ctx, bw_ctx, sizeof(bw_ctx), + MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: DMA memory write failed!\n", + __func__); + return CC_TRB_ERROR; + } return CC_SUCCESS; } From d8c2e6f2f6d29ccb766197181eb1c65c1d46b3a4 Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Fri, 26 Aug 2022 13:15:56 +0800 Subject: [PATCH 0607/1020] hcd-ohci: Drop ohci_service_iso_td() if ed->head & OHCI_DPTR_MASK is zero An abort happens in ohci_frame_boundary() when ohci->done is 0 [1]. ``` c static void ohci_frame_boundary(void *opaque) { // ... if (ohci->done_count == 0 && !(ohci->intr_status & OHCI_INTR_WD)) { if (!ohci->done) abort(); <----------------------------------------- [1] ``` This was reported in https://bugs.launchpad.net/qemu/+bug/1911216/, https://lists.gnu.org/archive/html/qemu-devel/2021-06/msg03613.html, and https://gitlab.com/qemu-project/qemu/-/issues/545. I can still reproduce it with the latest QEMU. This happends due to crafted ED with putting ISO_TD at physical address 0. Suppose ed->head & OHCI_DPTR_MASK is 0 [2], and we memset 0 to the phyiscal memory from 0 to sizeof(ohci_iso_td). Then, starting_frame [3] and frame_count [4] are both 0. As we can control the value of ohci->frame_number (0 to 0x1f, suppose 1), we then control the value of relative_frame_number to be 1 [6]. The control flow goes to [7] where ohci->done is 0. Have returned from ohci_service_iso_td(), ohci_frame_boundary() will abort() [1]. ``` c static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed) { // ... addr = ed->head & OHCI_DPTR_MASK; // <--------------------- [2] if (ohci_read_iso_td(ohci, addr, &iso_td)) { // <-------- [3] // ... starting_frame = OHCI_BM(iso_td.flags, TD_SF); // <-------- [4] frame_count = OHCI_BM(iso_td.flags, TD_FC); // <-------- [5] relative_frame_number = USUB(ohci->frame_number, starting_frame); // <-------- [6] if (relative_frame_number < 0) { return 1; } else if (relative_frame_number > frame_count) { // ... ohci->done = addr; // <-------- [7] // ... } ``` As only (afaik) a guest root user can manipulate ED, TD and the physical memory, this assertion failure is not a security bug. The idea to fix this issue is to drop ohci_service_iso_td() if ed->head & OHCI_DPTR_MASK is 0, which is similar to the drop operation for ohci_service_ed_list() when head is 0. Probably, a similar issue is in ohci_service_td(). I drop ohci_service_td() if ed->head & OHCI_DPTR_MASK is 0. Fixes: 7bfe577702 ("OHCI USB isochronous transfers support (Arnon Gilboa)") Reported-by: Gaoning Pan Reported-by: Alexander Bulekov Reported-by: Qiang Liu Resolves: https://gitlab.com/qemu-project/qemu/-/issues/545 Buglink: https://lists.gnu.org/archive/html/qemu-devel/2021-06/msg03613.html Buglink: https://bugs.launchpad.net/qemu/+bug/1911216 Signed-off-by: Qiang Liu Message-Id: <20220826051557.119570-1-cyruscyliu@gmail.com> Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-ohci.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c index 895b29fb86..72bdde9261 100644 --- a/hw/usb/hcd-ohci.c +++ b/hw/usb/hcd-ohci.c @@ -571,6 +571,11 @@ static int ohci_service_iso_td(OHCIState *ohci, struct ohci_ed *ed) addr = ed->head & OHCI_DPTR_MASK; + if (addr == 0) { + ohci_die(ohci); + return 1; + } + if (ohci_read_iso_td(ohci, addr, &iso_td)) { trace_usb_ohci_iso_td_read_failed(addr); ohci_die(ohci); @@ -858,6 +863,11 @@ static int ohci_service_td(OHCIState *ohci, struct ohci_ed *ed) int completion; addr = ed->head & OHCI_DPTR_MASK; + if (addr == 0) { + ohci_die(ohci); + return 1; + } + /* See if this TD has already been submitted to the device. */ completion = (addr == ohci->async_td); if (completion && !ohci->async_complete) { From ab9ccfa8502435502c74fc55cec8ae6eda879919 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 20 Sep 2022 13:39:07 +0200 Subject: [PATCH 0608/1020] linux-user/host/s390: Add vector instructions to host_signal_write() The new noexec test fails on s390x with "unexpected SEGV". This test overwrites code using libc's memcpy(), which uses VSTL instruction. host_signal_write() does not recognize it, which causes SEGV to be incorrectly forwarded to the test. Add all vector instructions that write to memory to host_signal_write(). Fixes: ab12c95d3f19 ("target/s390x: Make translator stop before the end of a page") Reported-by: Thomas Huth Signed-off-by: Ilya Leoshkevich Message-Id: <20220920113907.334144-1-iii@linux.ibm.com> Tested-by: Thomas Huth Signed-off-by: Thomas Huth --- linux-user/include/host/s390/host-signal.h | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/linux-user/include/host/s390/host-signal.h b/linux-user/include/host/s390/host-signal.h index 25fefa00bd..e6d3ec26dc 100644 --- a/linux-user/include/host/s390/host-signal.h +++ b/linux-user/include/host/s390/host-signal.h @@ -87,6 +87,31 @@ static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc) return true; } break; + case 0xe6: + switch (pinsn[2] & 0xff) { + case 0x09: /* VSTEBRH */ + case 0x0a: /* VSTEBRG */ + case 0x0b: /* VSTEBRF */ + case 0x0e: /* VSTBR */ + case 0x0f: /* VSTER */ + case 0x3f: /* VSTRLR */ + return true; + } + break; + case 0xe7: + switch (pinsn[2] & 0xff) { + case 0x08: /* VSTEB */ + case 0x09: /* VSTEH */ + case 0x0a: /* VSTEG */ + case 0x0b: /* VSTEF */ + case 0x0e: /* VST */ + case 0x1a: /* VSCEG */ + case 0x1b: /* VSCEF */ + case 0x3e: /* VSTM */ + case 0x3f: /* VSTL */ + return true; + } + break; case 0xeb: /* RSY format insns */ switch (pinsn[2] & 0xff) { case 0x14: /* CSY */ From 9f17bfdab422887807cbd5260ed6b0b6e54ddb33 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 22 Sep 2022 17:38:20 +0200 Subject: [PATCH 0609/1020] target/s390x: support SHA-512 extensions In order to fully support MSA_EXT_5, we have to support the SHA-512 special instructions. So implement those. The implementation began as something TweetNacl-like, and then was adjusted to be useful here. It's not very beautiful, but it is quite short and compact, which is what we're going for. Signed-off-by: Jason A. Donenfeld [ restructure, add missing exception, add comments, fixup CPU model ] Signed-off-by: David Hildenbrand Message-Id: <20220922153820.221811-1-david@redhat.com> Signed-off-by: Thomas Huth --- hw/s390x/s390-virtio-ccw.c | 3 + target/s390x/gen-features.c | 9 +- target/s390x/tcg/crypto_helper.c | 229 +++++++++++++++++++++++++++++++ 3 files changed, 240 insertions(+), 1 deletion(-) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 9a2467c889..e18b816aba 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -803,8 +803,11 @@ DEFINE_CCW_MACHINE(7_2, "7.2", true); static void ccw_machine_7_1_instance_options(MachineState *machine) { + static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V7_1 }; + ccw_machine_7_2_instance_options(machine); s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAIE); + s390_set_qemu_cpu_model(0x8561, 15, 1, qemu_cpu_feat); } static void ccw_machine_7_1_class_options(MachineClass *mc) diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index 1558c52626..baadbf4517 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -744,13 +744,19 @@ static uint16_t qemu_V7_0[] = { S390_FEAT_MISC_INSTRUCTION_EXT3, }; +static uint16_t qemu_V7_1[] = { + S390_FEAT_VECTOR_ENH2, +}; + /* * Features for the "qemu" CPU model of the latest QEMU machine and the "max" * CPU model under TCG. Don't include features that are not part of the full * feature set of the current "max" CPU model generation. */ static uint16_t qemu_MAX[] = { - S390_FEAT_VECTOR_ENH2, + S390_FEAT_MSA_EXT_5, + S390_FEAT_KIMD_SHA_512, + S390_FEAT_KLMD_SHA_512, }; /****** END FEATURE DEFS ******/ @@ -873,6 +879,7 @@ static FeatGroupDefSpec QemuFeatDef[] = { QEMU_FEAT_INITIALIZER(V6_0), QEMU_FEAT_INITIALIZER(V6_2), QEMU_FEAT_INITIALIZER(V7_0), + QEMU_FEAT_INITIALIZER(V7_1), QEMU_FEAT_INITIALIZER(MAX), }; diff --git a/target/s390x/tcg/crypto_helper.c b/target/s390x/tcg/crypto_helper.c index 138d9e7ad9..106c89fd2d 100644 --- a/target/s390x/tcg/crypto_helper.c +++ b/target/s390x/tcg/crypto_helper.c @@ -1,10 +1,12 @@ /* * s390x crypto helpers * + * Copyright (C) 2022 Jason A. Donenfeld . All Rights Reserved. * Copyright (c) 2017 Red Hat Inc * * Authors: * David Hildenbrand + * Jason A. Donenfeld * * This work is licensed under the terms of the GNU GPL, version 2 or later. * See the COPYING file in the top-level directory. @@ -18,6 +20,230 @@ #include "exec/exec-all.h" #include "exec/cpu_ldst.h" +static uint64_t R(uint64_t x, int c) +{ + return (x >> c) | (x << (64 - c)); +} +static uint64_t Ch(uint64_t x, uint64_t y, uint64_t z) +{ + return (x & y) ^ (~x & z); +} +static uint64_t Maj(uint64_t x, uint64_t y, uint64_t z) +{ + return (x & y) ^ (x & z) ^ (y & z); +} +static uint64_t Sigma0(uint64_t x) +{ + return R(x, 28) ^ R(x, 34) ^ R(x, 39); +} +static uint64_t Sigma1(uint64_t x) +{ + return R(x, 14) ^ R(x, 18) ^ R(x, 41); +} +static uint64_t sigma0(uint64_t x) +{ + return R(x, 1) ^ R(x, 8) ^ (x >> 7); +} +static uint64_t sigma1(uint64_t x) +{ + return R(x, 19) ^ R(x, 61) ^ (x >> 6); +} + +static const uint64_t K[80] = { + 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, + 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, + 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL, 0xd807aa98a3030242ULL, + 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL, + 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, + 0xc19bf174cf692694ULL, 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, + 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL, 0x2de92c6f592b0275ULL, + 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL, + 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, + 0xbf597fc7beef0ee4ULL, 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, + 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL, 0x27b70a8546d22ffcULL, + 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL, + 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, + 0x92722c851482353bULL, 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, + 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL, 0xd192e819d6ef5218ULL, + 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL, + 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, + 0x34b0bcb5e19b48a8ULL, 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, + 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL, 0x748f82ee5defb2fcULL, + 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL, + 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, + 0xc67178f2e372532bULL, 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, + 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL, 0x06f067aa72176fbaULL, + 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL, + 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, + 0x431d67c49c100d4cULL, 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, + 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL +}; + +/* a is icv/ocv, w is a single message block. w will get reused internally. */ +static void sha512_bda(uint64_t a[8], uint64_t w[16]) +{ + uint64_t t, z[8], b[8]; + int i, j; + + memcpy(z, a, sizeof(z)); + for (i = 0; i < 80; i++) { + memcpy(b, a, sizeof(b)); + + t = a[7] + Sigma1(a[4]) + Ch(a[4], a[5], a[6]) + K[i] + w[i % 16]; + b[7] = t + Sigma0(a[0]) + Maj(a[0], a[1], a[2]); + b[3] += t; + for (j = 0; j < 8; ++j) { + a[(j + 1) % 8] = b[j]; + } + if (i % 16 == 15) { + for (j = 0; j < 16; ++j) { + w[j] += w[(j + 9) % 16] + sigma0(w[(j + 1) % 16]) + + sigma1(w[(j + 14) % 16]); + } + } + } + + for (i = 0; i < 8; i++) { + a[i] += z[i]; + } +} + +/* a is icv/ocv, w is a single message block that needs be64 conversion. */ +static void sha512_bda_be64(uint64_t a[8], uint64_t w[16]) +{ + uint64_t t[16]; + int i; + + for (i = 0; i < 16; i++) { + t[i] = be64_to_cpu(w[i]); + } + sha512_bda(a, t); +} + +static void sha512_read_icv(CPUS390XState *env, uint64_t addr, + uint64_t a[8], uintptr_t ra) +{ + int i; + + for (i = 0; i < 8; i++, addr += 8) { + addr = wrap_address(env, addr); + a[i] = cpu_ldq_be_data_ra(env, addr, ra); + } +} + +static void sha512_write_ocv(CPUS390XState *env, uint64_t addr, + uint64_t a[8], uintptr_t ra) +{ + int i; + + for (i = 0; i < 8; i++, addr += 8) { + addr = wrap_address(env, addr); + cpu_stq_be_data_ra(env, addr, a[i], ra); + } +} + +static void sha512_read_block(CPUS390XState *env, uint64_t addr, + uint64_t a[16], uintptr_t ra) +{ + int i; + + for (i = 0; i < 16; i++, addr += 8) { + addr = wrap_address(env, addr); + a[i] = cpu_ldq_be_data_ra(env, addr, ra); + } +} + +static void sha512_read_mbl_be64(CPUS390XState *env, uint64_t addr, + uint8_t a[16], uintptr_t ra) +{ + int i; + + for (i = 0; i < 16; i++, addr += 1) { + addr = wrap_address(env, addr); + a[i] = cpu_ldub_data_ra(env, addr, ra); + } +} + +static int cpacf_sha512(CPUS390XState *env, uintptr_t ra, uint64_t param_addr, + uint64_t *message_reg, uint64_t *len_reg, uint32_t type) +{ + enum { MAX_BLOCKS_PER_RUN = 64 }; /* Arbitrary: keep interactivity. */ + uint64_t len = *len_reg, a[8], processed = 0; + int i, message_reg_len = 64; + + g_assert(type == S390_FEAT_TYPE_KIMD || type == S390_FEAT_TYPE_KLMD); + + if (!(env->psw.mask & PSW_MASK_64)) { + len = (uint32_t)len; + message_reg_len = (env->psw.mask & PSW_MASK_32) ? 32 : 24; + } + + /* KIMD: length has to be properly aligned. */ + if (type == S390_FEAT_TYPE_KIMD && !QEMU_IS_ALIGNED(len, 128)) { + tcg_s390_program_interrupt(env, PGM_SPECIFICATION, ra); + } + + sha512_read_icv(env, param_addr, a, ra); + + /* Process full blocks first. */ + for (; len >= 128; len -= 128, processed += 128) { + uint64_t w[16]; + + if (processed >= MAX_BLOCKS_PER_RUN * 128) { + break; + } + + sha512_read_block(env, *message_reg + processed, w, ra); + sha512_bda(a, w); + } + + /* KLMD: Process partial/empty block last. */ + if (type == S390_FEAT_TYPE_KLMD && len < 128) { + uint8_t x[128]; + + /* Read the remainder of the message byte-per-byte. */ + for (i = 0; i < len; i++) { + uint64_t addr = wrap_address(env, *message_reg + processed + i); + + x[i] = cpu_ldub_data_ra(env, addr, ra); + } + /* Pad the remainder with zero and set the top bit. */ + memset(x + len, 0, 128 - len); + x[len] = 128; + + /* + * Place the MBL either into this block (if there is space left), + * or use an additional one. + */ + if (len < 112) { + sha512_read_mbl_be64(env, param_addr + 64, x + 112, ra); + } + sha512_bda_be64(a, (uint64_t *)x); + + if (len >= 112) { + memset(x, 0, 112); + sha512_read_mbl_be64(env, param_addr + 64, x + 112, ra); + sha512_bda_be64(a, (uint64_t *)x); + } + + processed += len; + len = 0; + } + + /* + * Modify memory after we read all inputs and modify registers only after + * writing memory succeeded. + * + * TODO: if writing fails halfway through (e.g., when crossing page + * boundaries), we're in trouble. We'd need something like access_prepare(). + */ + sha512_write_ocv(env, param_addr, a, ra); + *message_reg = deposit64(*message_reg, 0, message_reg_len, + *message_reg + processed); + *len_reg -= processed; + return !len ? 0 : 3; +} + uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, uint32_t type) { @@ -52,6 +278,9 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, cpu_stb_data_ra(env, param_addr, subfunc[i], ra); } break; + case 3: /* CPACF_*_SHA_512 */ + return cpacf_sha512(env, ra, env->regs[1], &env->regs[r2], + &env->regs[r2 + 1], type); default: /* we don't implement any other subfunction yet */ g_assert_not_reached(); From 65d4830dac7d88059ba77f1d31ec0c2f8f65ae28 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Mon, 8 Aug 2022 15:07:27 -0400 Subject: [PATCH 0610/1020] linux-user: fix readlinkat handling with magic exe symlink Exactly the same as f17f4989fa193fa8279474c5462289a3cfe69aea before was for readlink. I suppose this was simply missed at the time. Signed-off-by: Jameson Nash Reviewed-by: Laurent Vivier Message-Id: <20220808190727.875155-1-vtjnash@gmail.com> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f409121202..abf82bab2a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -9912,11 +9912,22 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); if (!p || !p2) { ret = -TARGET_EFAULT; + } else if (!arg4) { + /* Short circuit this for the magic exe check. */ + ret = -TARGET_EINVAL; } else if (is_proc_myself((const char *)p, "exe")) { char real[PATH_MAX], *temp; temp = realpath(exec_path, real); - ret = temp == NULL ? get_errno(-1) : strlen(real) ; - snprintf((char *)p2, arg4, "%s", real); + /* Return value is # of bytes that we wrote to the buffer. */ + if (temp == NULL) { + ret = get_errno(-1); + } else { + /* Don't worry about sign mismatch as earlier mapping + * logic would have thrown a bad address error. */ + ret = MIN(strlen(real), arg4); + /* We cannot NUL terminate the string. */ + memcpy(p2, real, ret); + } } else { ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); } From 3dbc5fdacb5af08dffa408ac7315eae53c4d5497 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 21 Sep 2022 12:07:29 +0200 Subject: [PATCH 0611/1020] target/s390x: support PRNO_TRNG instruction In order for hosts running inside of TCG to initialize the kernel's random number generator, we should support the PRNO_TRNG instruction, backed in the usual way with the qemu_guest_getrandom helper. This is confirmed working on Linux 5.19. Signed-off-by: Jason A. Donenfeld Message-Id: <20220921100729.2942008-2-Jason@zx2c4.com> Reviewed-by: David Hildenbrand [thuth: turn prno-trng off in avocado test to avoid breaking it] Signed-off-by: Thomas Huth --- target/s390x/gen-features.c | 1 + target/s390x/tcg/crypto_helper.c | 30 ++++++++++++++++++++++++ tests/avocado/machine_s390_ccw_virtio.py | 1 + 3 files changed, 32 insertions(+) diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c index baadbf4517..1e3b7c0dc9 100644 --- a/target/s390x/gen-features.c +++ b/target/s390x/gen-features.c @@ -757,6 +757,7 @@ static uint16_t qemu_MAX[] = { S390_FEAT_MSA_EXT_5, S390_FEAT_KIMD_SHA_512, S390_FEAT_KLMD_SHA_512, + S390_FEAT_PRNO_TRNG, }; /****** END FEATURE DEFS ******/ diff --git a/target/s390x/tcg/crypto_helper.c b/target/s390x/tcg/crypto_helper.c index 106c89fd2d..762b277884 100644 --- a/target/s390x/tcg/crypto_helper.c +++ b/target/s390x/tcg/crypto_helper.c @@ -14,6 +14,7 @@ #include "qemu/osdep.h" #include "qemu/main-loop.h" +#include "qemu/guest-random.h" #include "s390x-internal.h" #include "tcg_s390x.h" #include "exec/helper-proto.h" @@ -244,6 +245,31 @@ static int cpacf_sha512(CPUS390XState *env, uintptr_t ra, uint64_t param_addr, return !len ? 0 : 3; } +static void fill_buf_random(CPUS390XState *env, uintptr_t ra, + uint64_t *buf_reg, uint64_t *len_reg) +{ + uint8_t tmp[256]; + uint64_t len = *len_reg; + int buf_reg_len = 64; + + if (!(env->psw.mask & PSW_MASK_64)) { + len = (uint32_t)len; + buf_reg_len = (env->psw.mask & PSW_MASK_32) ? 32 : 24; + } + + while (len) { + size_t block = MIN(len, sizeof(tmp)); + + qemu_guest_getrandom_nofail(tmp, block); + for (size_t i = 0; i < block; ++i) { + cpu_stb_data_ra(env, wrap_address(env, *buf_reg), tmp[i], ra); + *buf_reg = deposit64(*buf_reg, 0, buf_reg_len, *buf_reg + 1); + --*len_reg; + } + len -= block; + } +} + uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, uint32_t type) { @@ -281,6 +307,10 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, case 3: /* CPACF_*_SHA_512 */ return cpacf_sha512(env, ra, env->regs[1], &env->regs[r2], &env->regs[r2 + 1], type); + case 114: /* CPACF_PRNO_TRNG */ + fill_buf_random(env, ra, &env->regs[r1], &env->regs[r1 + 1]); + fill_buf_random(env, ra, &env->regs[r2], &env->regs[r2 + 1]); + break; default: /* we don't implement any other subfunction yet */ g_assert_not_reached(); diff --git a/tests/avocado/machine_s390_ccw_virtio.py b/tests/avocado/machine_s390_ccw_virtio.py index 438a6f4321..78152f2ad1 100644 --- a/tests/avocado/machine_s390_ccw_virtio.py +++ b/tests/avocado/machine_s390_ccw_virtio.py @@ -66,6 +66,7 @@ class S390CCWVirtioMachine(QemuSystemTest): '-kernel', kernel_path, '-initrd', initrd_path, '-append', kernel_command_line, + '-cpu', 'max,prno-trng=off', '-device', 'virtio-net-ccw,devno=fe.1.1111', '-device', 'virtio-rng-ccw,devno=fe.2.0000,max_revision=0,id=rn1', From 28d01b1d69e947a50b9ab9b45113fda1c4f96ac9 Mon Sep 17 00:00:00 2001 From: Chenyi Qiang Date: Thu, 15 Sep 2022 17:10:34 +0800 Subject: [PATCH 0612/1020] configure: Add -Wno-gnu-variable-sized-type-not-at-end MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A Linux headers update to v6.0-rc switches some definitions from GNU 'zero-length-array' extension to the C-standard-defined flexible array member. e.g. struct kvm_msrs { __u32 nmsrs; /* number of msrs in entries */ __u32 pad; - struct kvm_msr_entry entries[0]; + struct kvm_msr_entry entries[]; }; Those (unlike the GNU zero-length-array) have some extra restrictions like 'this must be put at the end of a struct', which clang build would complain about. e.g. the current code struct { struct kvm_msrs info; struct kvm_msr_entry entries[1]; } msr_data = { } generates the warning like: target/i386/kvm/kvm.c:2868:25: error: field 'info' with variable sized type 'struct kvm_msrs' not at the end of a struct or class is a GNU extension [-Werror,-Wgnu-variable-sized-type-not-at-end] struct kvm_msrs info; ^ In fact, the variable length 'entries[]' field in 'info' is zero-sized in GNU defined semantics, which can give predictable offset for 'entries[1]' in local msr_data. The local defined struct is just there to force a stack allocation large enough for 1 kvm_msr_entry, a clever trick but requires to turn off this clang warning. Suggested-by: Daniel P. BerrangĂ© Signed-off-by: Chenyi Qiang Reviewed-by: Richard Henderson Reviewed-by: Cornelia Huck Message-Id: <20220915091035.3897-2-chenyi.qiang@intel.com> Signed-off-by: Thomas Huth --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index 0bbf9d28af..78e0ab8db4 100755 --- a/configure +++ b/configure @@ -1258,6 +1258,7 @@ add_to nowarn_flags -Wno-string-plus-int add_to nowarn_flags -Wno-typedef-redefinition add_to nowarn_flags -Wno-tautological-type-limit-compare add_to nowarn_flags -Wno-psabi +add_to nowarn_flags -Wno-gnu-variable-sized-type-not-at-end gcc_flags="$warn_flags $nowarn_flags" From d525f73f9186a5bc641b8caf0b2c9bb94e5aa963 Mon Sep 17 00:00:00 2001 From: Chenyi Qiang Date: Thu, 15 Sep 2022 17:10:35 +0800 Subject: [PATCH 0613/1020] Update linux headers to v6.0-rc4 commit 7e18e42e4b280c85b76967a9106a13ca61c16179 Signed-off-by: Chenyi Qiang Reviewed-by: Cornelia Huck Message-Id: <20220915091035.3897-3-chenyi.qiang@intel.com> Signed-off-by: Thomas Huth --- include/standard-headers/asm-x86/bootparam.h | 7 +- include/standard-headers/drm/drm_fourcc.h | 73 +++++++- include/standard-headers/linux/ethtool.h | 29 +-- include/standard-headers/linux/input.h | 12 +- include/standard-headers/linux/pci_regs.h | 30 ++- include/standard-headers/linux/vhost_types.h | 17 +- include/standard-headers/linux/virtio_9p.h | 2 +- .../standard-headers/linux/virtio_config.h | 7 +- include/standard-headers/linux/virtio_ids.h | 14 +- include/standard-headers/linux/virtio_net.h | 34 +++- include/standard-headers/linux/virtio_pci.h | 2 + include/standard-headers/linux/virtio_ring.h | 16 +- linux-headers/asm-arm64/kvm.h | 33 +++- linux-headers/asm-generic/unistd.h | 4 +- linux-headers/asm-riscv/kvm.h | 22 +++ linux-headers/asm-riscv/unistd.h | 3 +- linux-headers/asm-s390/kvm.h | 1 + linux-headers/asm-x86/kvm.h | 33 ++-- linux-headers/asm-x86/mman.h | 14 -- linux-headers/linux/kvm.h | 172 +++++++++++++++++- linux-headers/linux/userfaultfd.h | 10 +- linux-headers/linux/vduse.h | 47 +++++ linux-headers/linux/vfio.h | 4 +- linux-headers/linux/vfio_zdev.h | 7 + linux-headers/linux/vhost.h | 35 +++- 25 files changed, 538 insertions(+), 90 deletions(-) diff --git a/include/standard-headers/asm-x86/bootparam.h b/include/standard-headers/asm-x86/bootparam.h index b2aaad10e5..0b06d2bff1 100644 --- a/include/standard-headers/asm-x86/bootparam.h +++ b/include/standard-headers/asm-x86/bootparam.h @@ -10,12 +10,13 @@ #define SETUP_EFI 4 #define SETUP_APPLE_PROPERTIES 5 #define SETUP_JAILHOUSE 6 +#define SETUP_CC_BLOB 7 +#define SETUP_IMA 8 #define SETUP_RNG_SEED 9 +#define SETUP_ENUM_MAX SETUP_RNG_SEED #define SETUP_INDIRECT (1<<31) - -/* SETUP_INDIRECT | max(SETUP_*) */ -#define SETUP_TYPE_MAX (SETUP_INDIRECT | SETUP_JAILHOUSE) +#define SETUP_TYPE_MAX (SETUP_ENUM_MAX | SETUP_INDIRECT) /* ram_size flags */ #define RAMDISK_IMAGE_START_MASK 0x07FF diff --git a/include/standard-headers/drm/drm_fourcc.h b/include/standard-headers/drm/drm_fourcc.h index 4888f85f69..48b620cbef 100644 --- a/include/standard-headers/drm/drm_fourcc.h +++ b/include/standard-headers/drm/drm_fourcc.h @@ -558,7 +558,7 @@ extern "C" { * * The main surface is Y-tiled and is at plane index 0 whereas CCS is linear * and at index 1. The clear color is stored at index 2, and the pitch should - * be ignored. The clear color structure is 256 bits. The first 128 bits + * be 64 bytes aligned. The clear color structure is 256 bits. The first 128 bits * represents Raw Clear Color Red, Green, Blue and Alpha color each represented * by 32 bits. The raw clear color is consumed by the 3d engine and generates * the converted clear color of size 64 bits. The first 32 bits store the Lower @@ -571,6 +571,53 @@ extern "C" { */ #define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC fourcc_mod_code(INTEL, 8) +/* + * Intel Tile 4 layout + * + * This is a tiled layout using 4KB tiles in a row-major layout. It has the same + * shape as Tile Y at two granularities: 4KB (128B x 32) and 64B (16B x 4). It + * only differs from Tile Y at the 256B granularity in between. At this + * granularity, Tile Y has a shape of 16B x 32 rows, but this tiling has a shape + * of 64B x 8 rows. + */ +#define I915_FORMAT_MOD_4_TILED fourcc_mod_code(INTEL, 9) + +/* + * Intel color control surfaces (CCS) for DG2 render compression. + * + * The main surface is Tile 4 and at plane index 0. The CCS data is stored + * outside of the GEM object in a reserved memory area dedicated for the + * storage of the CCS data for all RC/RC_CC/MC compressible GEM objects. The + * main surface pitch is required to be a multiple of four Tile 4 widths. + */ +#define I915_FORMAT_MOD_4_TILED_DG2_RC_CCS fourcc_mod_code(INTEL, 10) + +/* + * Intel color control surfaces (CCS) for DG2 media compression. + * + * The main surface is Tile 4 and at plane index 0. For semi-planar formats + * like NV12, the Y and UV planes are Tile 4 and are located at plane indices + * 0 and 1, respectively. The CCS for all planes are stored outside of the + * GEM object in a reserved memory area dedicated for the storage of the + * CCS data for all RC/RC_CC/MC compressible GEM objects. The main surface + * pitch is required to be a multiple of four Tile 4 widths. + */ +#define I915_FORMAT_MOD_4_TILED_DG2_MC_CCS fourcc_mod_code(INTEL, 11) + +/* + * Intel Color Control Surface with Clear Color (CCS) for DG2 render compression. + * + * The main surface is Tile 4 and at plane index 0. The CCS data is stored + * outside of the GEM object in a reserved memory area dedicated for the + * storage of the CCS data for all RC/RC_CC/MC compressible GEM objects. The + * main surface pitch is required to be a multiple of four Tile 4 widths. The + * clear color is stored at plane index 1 and the pitch should be 64 bytes + * aligned. The format of the 256 bits of clear color data matches the one used + * for the I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC modifier, see its description + * for details. + */ +#define I915_FORMAT_MOD_4_TILED_DG2_RC_CCS_CC fourcc_mod_code(INTEL, 12) + /* * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks * @@ -608,6 +655,28 @@ extern "C" { */ #define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1) +/* + * Qualcomm Tiled Format + * + * Similar to DRM_FORMAT_MOD_QCOM_COMPRESSED but not compressed. + * Implementation may be platform and base-format specific. + * + * Each macrotile consists of m x n (mostly 4 x 4) tiles. + * Pixel data pitch/stride is aligned with macrotile width. + * Pixel data height is aligned with macrotile height. + * Entire pixel data buffer is aligned with 4k(bytes). + */ +#define DRM_FORMAT_MOD_QCOM_TILED3 fourcc_mod_code(QCOM, 3) + +/* + * Qualcomm Alternate Tiled Format + * + * Alternate tiled format typically only used within GMEM. + * Implementation may be platform and base-format specific. + */ +#define DRM_FORMAT_MOD_QCOM_TILED2 fourcc_mod_code(QCOM, 2) + + /* Vivante framebuffer modifiers */ /* @@ -1293,6 +1362,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(uint64_t modifier) #define AMD_FMT_MOD_TILE_VER_GFX9 1 #define AMD_FMT_MOD_TILE_VER_GFX10 2 #define AMD_FMT_MOD_TILE_VER_GFX10_RBPLUS 3 +#define AMD_FMT_MOD_TILE_VER_GFX11 4 /* * 64K_S is the same for GFX9/GFX10/GFX10_RBPLUS and hence has GFX9 as canonical @@ -1308,6 +1378,7 @@ drm_fourcc_canonicalize_nvidia_format_mod(uint64_t modifier) #define AMD_FMT_MOD_TILE_GFX9_64K_S_X 25 #define AMD_FMT_MOD_TILE_GFX9_64K_D_X 26 #define AMD_FMT_MOD_TILE_GFX9_64K_R_X 27 +#define AMD_FMT_MOD_TILE_GFX11_256K_R_X 31 #define AMD_FMT_MOD_DCC_BLOCK_64B 0 #define AMD_FMT_MOD_DCC_BLOCK_128B 1 diff --git a/include/standard-headers/linux/ethtool.h b/include/standard-headers/linux/ethtool.h index 38d5a4cd6e..4537da20cc 100644 --- a/include/standard-headers/linux/ethtool.h +++ b/include/standard-headers/linux/ethtool.h @@ -257,7 +257,7 @@ struct ethtool_tunable { uint32_t id; uint32_t type_id; uint32_t len; - void *data[0]; + void *data[]; }; #define DOWNSHIFT_DEV_DEFAULT_COUNT 0xff @@ -322,7 +322,7 @@ struct ethtool_regs { uint32_t cmd; uint32_t version; uint32_t len; - uint8_t data[0]; + uint8_t data[]; }; /** @@ -348,7 +348,7 @@ struct ethtool_eeprom { uint32_t magic; uint32_t offset; uint32_t len; - uint8_t data[0]; + uint8_t data[]; }; /** @@ -752,7 +752,7 @@ struct ethtool_gstrings { uint32_t cmd; uint32_t string_set; uint32_t len; - uint8_t data[0]; + uint8_t data[]; }; /** @@ -777,7 +777,7 @@ struct ethtool_sset_info { uint32_t cmd; uint32_t reserved; uint64_t sset_mask; - uint32_t data[0]; + uint32_t data[]; }; /** @@ -817,7 +817,7 @@ struct ethtool_test { uint32_t flags; uint32_t reserved; uint32_t len; - uint64_t data[0]; + uint64_t data[]; }; /** @@ -834,7 +834,7 @@ struct ethtool_test { struct ethtool_stats { uint32_t cmd; uint32_t n_stats; - uint64_t data[0]; + uint64_t data[]; }; /** @@ -851,7 +851,7 @@ struct ethtool_stats { struct ethtool_perm_addr { uint32_t cmd; uint32_t size; - uint8_t data[0]; + uint8_t data[]; }; /* boolean flags controlling per-interface behavior characteristics. @@ -1160,7 +1160,7 @@ struct ethtool_rxnfc { struct ethtool_rxfh_indir { uint32_t cmd; uint32_t size; - uint32_t ring_index[0]; + uint32_t ring_index[]; }; /** @@ -1201,7 +1201,7 @@ struct ethtool_rxfh { uint8_t hfunc; uint8_t rsvd8[3]; uint32_t rsvd32; - uint32_t rss_config[0]; + uint32_t rss_config[]; }; #define ETH_RXFH_CONTEXT_ALLOC 0xffffffff #define ETH_RXFH_INDIR_NO_CHANGE 0xffffffff @@ -1286,7 +1286,7 @@ struct ethtool_dump { uint32_t version; uint32_t flag; uint32_t len; - uint8_t data[0]; + uint8_t data[]; }; #define ETH_FW_DUMP_DISABLE 0 @@ -1318,7 +1318,7 @@ struct ethtool_get_features_block { struct ethtool_gfeatures { uint32_t cmd; uint32_t size; - struct ethtool_get_features_block features[0]; + struct ethtool_get_features_block features[]; }; /** @@ -1340,7 +1340,7 @@ struct ethtool_set_features_block { struct ethtool_sfeatures { uint32_t cmd; uint32_t size; - struct ethtool_set_features_block features[0]; + struct ethtool_set_features_block features[]; }; /** @@ -1691,6 +1691,7 @@ enum ethtool_link_mode_bit_indices { ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT = 89, ETHTOOL_LINK_MODE_100baseFX_Half_BIT = 90, ETHTOOL_LINK_MODE_100baseFX_Full_BIT = 91, + ETHTOOL_LINK_MODE_10baseT1L_Full_BIT = 92, /* must be last entry */ __ETHTOOL_LINK_MODE_MASK_NBITS }; @@ -2086,7 +2087,7 @@ struct ethtool_link_settings { uint8_t master_slave_state; uint8_t reserved1[1]; uint32_t reserved[7]; - uint32_t link_mode_masks[0]; + uint32_t link_mode_masks[]; /* layout of link_mode_masks fields: * uint32_t map_supported[link_mode_masks_nwords]; * uint32_t map_advertising[link_mode_masks_nwords]; diff --git a/include/standard-headers/linux/input.h b/include/standard-headers/linux/input.h index 7822c24178..942ea6aaa9 100644 --- a/include/standard-headers/linux/input.h +++ b/include/standard-headers/linux/input.h @@ -75,10 +75,13 @@ struct input_id { * Note that input core does not clamp reported values to the * [minimum, maximum] limits, such task is left to userspace. * - * The default resolution for main axes (ABS_X, ABS_Y, ABS_Z) - * is reported in units per millimeter (units/mm), resolution - * for rotational axes (ABS_RX, ABS_RY, ABS_RZ) is reported - * in units per radian. + * The default resolution for main axes (ABS_X, ABS_Y, ABS_Z, + * ABS_MT_POSITION_X, ABS_MT_POSITION_Y) is reported in units + * per millimeter (units/mm), resolution for rotational axes + * (ABS_RX, ABS_RY, ABS_RZ) is reported in units per radian. + * The resolution for the size axes (ABS_MT_TOUCH_MAJOR, + * ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MAJOR, ABS_MT_WIDTH_MINOR) + * is reported in units per millimeter (units/mm). * When INPUT_PROP_ACCELEROMETER is set the resolution changes. * The main axes (ABS_X, ABS_Y, ABS_Z) are then reported in * units per g (units/g) and in units per degree per second @@ -268,6 +271,7 @@ struct input_mask { #define BUS_RMI 0x1D #define BUS_CEC 0x1E #define BUS_INTEL_ISHTP 0x1F +#define BUS_AMD_SFH 0x20 /* * MT_TOOL types diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h index bee1a9ed6e..57b8e2ffb1 100644 --- a/include/standard-headers/linux/pci_regs.h +++ b/include/standard-headers/linux/pci_regs.h @@ -616,6 +616,7 @@ #define PCI_EXP_SLTCTL_PWR_OFF 0x0400 /* Power Off */ #define PCI_EXP_SLTCTL_EIC 0x0800 /* Electromechanical Interlock Control */ #define PCI_EXP_SLTCTL_DLLSCE 0x1000 /* Data Link Layer State Changed Enable */ +#define PCI_EXP_SLTCTL_ASPL_DISABLE 0x2000 /* Auto Slot Power Limit Disable */ #define PCI_EXP_SLTCTL_IBPD_DISABLE 0x4000 /* In-band PD disable */ #define PCI_EXP_SLTSTA 0x1a /* Slot Status */ #define PCI_EXP_SLTSTA_ABP 0x0001 /* Attention Button Pressed */ @@ -736,7 +737,8 @@ #define PCI_EXT_CAP_ID_DVSEC 0x23 /* Designated Vendor-Specific */ #define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */ #define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */ -#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PL_16GT +#define PCI_EXT_CAP_ID_DOE 0x2E /* Data Object Exchange */ +#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_DOE #define PCI_EXT_CAP_DSN_SIZEOF 12 #define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40 @@ -1102,4 +1104,30 @@ #define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK 0x000000F0 #define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT 4 +/* Data Object Exchange */ +#define PCI_DOE_CAP 0x04 /* DOE Capabilities Register */ +#define PCI_DOE_CAP_INT_SUP 0x00000001 /* Interrupt Support */ +#define PCI_DOE_CAP_INT_MSG_NUM 0x00000ffe /* Interrupt Message Number */ +#define PCI_DOE_CTRL 0x08 /* DOE Control Register */ +#define PCI_DOE_CTRL_ABORT 0x00000001 /* DOE Abort */ +#define PCI_DOE_CTRL_INT_EN 0x00000002 /* DOE Interrupt Enable */ +#define PCI_DOE_CTRL_GO 0x80000000 /* DOE Go */ +#define PCI_DOE_STATUS 0x0c /* DOE Status Register */ +#define PCI_DOE_STATUS_BUSY 0x00000001 /* DOE Busy */ +#define PCI_DOE_STATUS_INT_STATUS 0x00000002 /* DOE Interrupt Status */ +#define PCI_DOE_STATUS_ERROR 0x00000004 /* DOE Error */ +#define PCI_DOE_STATUS_DATA_OBJECT_READY 0x80000000 /* Data Object Ready */ +#define PCI_DOE_WRITE 0x10 /* DOE Write Data Mailbox Register */ +#define PCI_DOE_READ 0x14 /* DOE Read Data Mailbox Register */ + +/* DOE Data Object - note not actually registers */ +#define PCI_DOE_DATA_OBJECT_HEADER_1_VID 0x0000ffff +#define PCI_DOE_DATA_OBJECT_HEADER_1_TYPE 0x00ff0000 +#define PCI_DOE_DATA_OBJECT_HEADER_2_LENGTH 0x0003ffff + +#define PCI_DOE_DATA_OBJECT_DISC_REQ_3_INDEX 0x000000ff +#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_VID 0x0000ffff +#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_PROTOCOL 0x00ff0000 +#define PCI_DOE_DATA_OBJECT_DISC_RSP_3_NEXT_INDEX 0xff000000 + #endif /* LINUX_PCI_REGS_H */ diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h index 0bd2684a2a..c41a73fe36 100644 --- a/include/standard-headers/linux/vhost_types.h +++ b/include/standard-headers/linux/vhost_types.h @@ -87,7 +87,7 @@ struct vhost_msg { struct vhost_msg_v2 { uint32_t type; - uint32_t reserved; + uint32_t asid; union { struct vhost_iotlb_msg iotlb; uint8_t padding[64]; @@ -107,7 +107,7 @@ struct vhost_memory_region { struct vhost_memory { uint32_t nregions; uint32_t padding; - struct vhost_memory_region regions[0]; + struct vhost_memory_region regions[]; }; /* VHOST_SCSI specific definitions */ @@ -135,7 +135,7 @@ struct vhost_scsi_target { struct vhost_vdpa_config { uint32_t off; uint32_t len; - uint8_t buf[0]; + uint8_t buf[]; }; /* vhost vdpa IOVA range @@ -153,4 +153,15 @@ struct vhost_vdpa_iova_range { /* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */ #define VHOST_NET_F_VIRTIO_NET_HDR 27 +/* Use message type V2 */ +#define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1 +/* IOTLB can accept batching hints */ +#define VHOST_BACKEND_F_IOTLB_BATCH 0x2 +/* IOTLB can accept address space identifier through V2 type of IOTLB + * message + */ +#define VHOST_BACKEND_F_IOTLB_ASID 0x3 +/* Device can be suspended */ +#define VHOST_BACKEND_F_SUSPEND 0x4 + #endif diff --git a/include/standard-headers/linux/virtio_9p.h b/include/standard-headers/linux/virtio_9p.h index f5604fc5fb..da61dee98c 100644 --- a/include/standard-headers/linux/virtio_9p.h +++ b/include/standard-headers/linux/virtio_9p.h @@ -38,7 +38,7 @@ struct virtio_9p_config { /* length of the tag name */ __virtio16 tag_len; /* non-NULL terminated tag name */ - uint8_t tag[0]; + uint8_t tag[]; } QEMU_PACKED; #endif /* _LINUX_VIRTIO_9P_H */ diff --git a/include/standard-headers/linux/virtio_config.h b/include/standard-headers/linux/virtio_config.h index 7acd8d4abc..965ee6ae23 100644 --- a/include/standard-headers/linux/virtio_config.h +++ b/include/standard-headers/linux/virtio_config.h @@ -52,7 +52,7 @@ * rest are per-device feature bits. */ #define VIRTIO_TRANSPORT_F_START 28 -#define VIRTIO_TRANSPORT_F_END 38 +#define VIRTIO_TRANSPORT_F_END 41 #ifndef VIRTIO_CONFIG_NO_LEGACY /* Do we get callbacks when the ring is completely used, even if we've @@ -96,4 +96,9 @@ * Does the device support Single Root I/O Virtualization? */ #define VIRTIO_F_SR_IOV 37 + +/* + * This feature indicates that the driver can reset a queue individually. + */ +#define VIRTIO_F_RING_RESET 40 #endif /* _LINUX_VIRTIO_CONFIG_H */ diff --git a/include/standard-headers/linux/virtio_ids.h b/include/standard-headers/linux/virtio_ids.h index 80d76b75bc..7aa2eb7662 100644 --- a/include/standard-headers/linux/virtio_ids.h +++ b/include/standard-headers/linux/virtio_ids.h @@ -73,12 +73,12 @@ * Virtio Transitional IDs */ -#define VIRTIO_TRANS_ID_NET 1000 /* transitional virtio net */ -#define VIRTIO_TRANS_ID_BLOCK 1001 /* transitional virtio block */ -#define VIRTIO_TRANS_ID_BALLOON 1002 /* transitional virtio balloon */ -#define VIRTIO_TRANS_ID_CONSOLE 1003 /* transitional virtio console */ -#define VIRTIO_TRANS_ID_SCSI 1004 /* transitional virtio SCSI */ -#define VIRTIO_TRANS_ID_RNG 1005 /* transitional virtio rng */ -#define VIRTIO_TRANS_ID_9P 1009 /* transitional virtio 9p console */ +#define VIRTIO_TRANS_ID_NET 0x1000 /* transitional virtio net */ +#define VIRTIO_TRANS_ID_BLOCK 0x1001 /* transitional virtio block */ +#define VIRTIO_TRANS_ID_BALLOON 0x1002 /* transitional virtio balloon */ +#define VIRTIO_TRANS_ID_CONSOLE 0x1003 /* transitional virtio console */ +#define VIRTIO_TRANS_ID_SCSI 0x1004 /* transitional virtio SCSI */ +#define VIRTIO_TRANS_ID_RNG 0x1005 /* transitional virtio rng */ +#define VIRTIO_TRANS_ID_9P 0x1009 /* transitional virtio 9p console */ #endif /* _LINUX_VIRTIO_IDS_H */ diff --git a/include/standard-headers/linux/virtio_net.h b/include/standard-headers/linux/virtio_net.h index e0a070518f..42c68caf71 100644 --- a/include/standard-headers/linux/virtio_net.h +++ b/include/standard-headers/linux/virtio_net.h @@ -56,7 +56,7 @@ #define VIRTIO_NET_F_MQ 22 /* Device supports Receive Flow * Steering */ #define VIRTIO_NET_F_CTRL_MAC_ADDR 23 /* Set MAC address */ - +#define VIRTIO_NET_F_NOTF_COAL 53 /* Device supports notifications coalescing */ #define VIRTIO_NET_F_HASH_REPORT 57 /* Supports hash report */ #define VIRTIO_NET_F_RSS 60 /* Supports RSS RX steering */ #define VIRTIO_NET_F_RSC_EXT 61 /* extended coalescing info */ @@ -355,4 +355,36 @@ struct virtio_net_hash_config { #define VIRTIO_NET_CTRL_GUEST_OFFLOADS 5 #define VIRTIO_NET_CTRL_GUEST_OFFLOADS_SET 0 +/* + * Control notifications coalescing. + * + * Request the device to change the notifications coalescing parameters. + * + * Available with the VIRTIO_NET_F_NOTF_COAL feature bit. + */ +#define VIRTIO_NET_CTRL_NOTF_COAL 6 +/* + * Set the tx-usecs/tx-max-packets parameters. + */ +struct virtio_net_ctrl_coal_tx { + /* Maximum number of packets to send before a TX notification */ + uint32_t tx_max_packets; + /* Maximum number of usecs to delay a TX notification */ + uint32_t tx_usecs; +}; + +#define VIRTIO_NET_CTRL_NOTF_COAL_TX_SET 0 + +/* + * Set the rx-usecs/rx-max-packets parameters. + */ +struct virtio_net_ctrl_coal_rx { + /* Maximum number of packets to receive before a RX notification */ + uint32_t rx_max_packets; + /* Maximum number of usecs to delay a RX notification */ + uint32_t rx_usecs; +}; + +#define VIRTIO_NET_CTRL_NOTF_COAL_RX_SET 1 + #endif /* _LINUX_VIRTIO_NET_H */ diff --git a/include/standard-headers/linux/virtio_pci.h b/include/standard-headers/linux/virtio_pci.h index db7a8e2fcb..be912cfc95 100644 --- a/include/standard-headers/linux/virtio_pci.h +++ b/include/standard-headers/linux/virtio_pci.h @@ -202,6 +202,8 @@ struct virtio_pci_cfg_cap { #define VIRTIO_PCI_COMMON_Q_AVAILHI 44 #define VIRTIO_PCI_COMMON_Q_USEDLO 48 #define VIRTIO_PCI_COMMON_Q_USEDHI 52 +#define VIRTIO_PCI_COMMON_Q_NDATA 56 +#define VIRTIO_PCI_COMMON_Q_RESET 58 #endif /* VIRTIO_PCI_NO_MODERN */ diff --git a/include/standard-headers/linux/virtio_ring.h b/include/standard-headers/linux/virtio_ring.h index 0fa0e1067f..22f6eb8ca7 100644 --- a/include/standard-headers/linux/virtio_ring.h +++ b/include/standard-headers/linux/virtio_ring.h @@ -91,15 +91,21 @@ #define VRING_USED_ALIGN_SIZE 4 #define VRING_DESC_ALIGN_SIZE 16 -/* Virtio ring descriptors: 16 bytes. These can chain together via "next". */ +/** + * struct vring_desc - Virtio ring descriptors, + * 16 bytes long. These can chain together via @next. + * + * @addr: buffer address (guest-physical) + * @len: buffer length + * @flags: descriptor flags + * @next: index of the next descriptor in the chain, + * if the VRING_DESC_F_NEXT flag is set. We chain unused + * descriptors via this, too. + */ struct vring_desc { - /* Address (guest-physical). */ __virtio64 addr; - /* Length. */ __virtio32 len; - /* The flags as indicated above. */ __virtio16 flags; - /* We chain unused descriptors via this, too */ __virtio16 next; }; diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index 5c28a9737a..4bf2d7246e 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -75,9 +75,11 @@ struct kvm_regs { /* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */ #define KVM_ARM_DEVICE_TYPE_SHIFT 0 -#define KVM_ARM_DEVICE_TYPE_MASK (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT) +#define KVM_ARM_DEVICE_TYPE_MASK GENMASK(KVM_ARM_DEVICE_TYPE_SHIFT + 15, \ + KVM_ARM_DEVICE_TYPE_SHIFT) #define KVM_ARM_DEVICE_ID_SHIFT 16 -#define KVM_ARM_DEVICE_ID_MASK (0xffff << KVM_ARM_DEVICE_ID_SHIFT) +#define KVM_ARM_DEVICE_ID_MASK GENMASK(KVM_ARM_DEVICE_ID_SHIFT + 15, \ + KVM_ARM_DEVICE_ID_SHIFT) /* Supported device IDs */ #define KVM_ARM_DEVICE_VGIC_V2 0 @@ -139,8 +141,10 @@ struct kvm_guest_debug_arch { __u64 dbg_wvr[KVM_ARM_MAX_DBG_REGS]; }; +#define KVM_DEBUG_ARCH_HSR_HIGH_VALID (1 << 0) struct kvm_debug_exit_arch { __u32 hsr; + __u32 hsr_high; /* ESR_EL2[61:32] */ __u64 far; /* used for watchpoints */ }; @@ -332,6 +336,31 @@ struct kvm_arm_copy_mte_tags { #define KVM_ARM64_SVE_VLS_WORDS \ ((KVM_ARM64_SVE_VQ_MAX - KVM_ARM64_SVE_VQ_MIN) / 64 + 1) +/* Bitmap feature firmware registers */ +#define KVM_REG_ARM_FW_FEAT_BMAP (0x0016 << KVM_REG_ARM_COPROC_SHIFT) +#define KVM_REG_ARM_FW_FEAT_BMAP_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \ + KVM_REG_ARM_FW_FEAT_BMAP | \ + ((r) & 0xffff)) + +#define KVM_REG_ARM_STD_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(0) + +enum { + KVM_REG_ARM_STD_BIT_TRNG_V1_0 = 0, +}; + +#define KVM_REG_ARM_STD_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(1) + +enum { + KVM_REG_ARM_STD_HYP_BIT_PV_TIME = 0, +}; + +#define KVM_REG_ARM_VENDOR_HYP_BMAP KVM_REG_ARM_FW_FEAT_BMAP_REG(2) + +enum { + KVM_REG_ARM_VENDOR_HYP_BIT_FUNC_FEAT = 0, + KVM_REG_ARM_VENDOR_HYP_BIT_PTP = 1, +}; + /* Device Control API: ARM VGIC */ #define KVM_DEV_ARM_VGIC_GRP_ADDR 0 #define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1 diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h index 1c48b0ae3b..45fa180cc5 100644 --- a/linux-headers/asm-generic/unistd.h +++ b/linux-headers/asm-generic/unistd.h @@ -383,7 +383,7 @@ __SYSCALL(__NR_syslog, sys_syslog) /* kernel/ptrace.c */ #define __NR_ptrace 117 -__SYSCALL(__NR_ptrace, sys_ptrace) +__SC_COMP(__NR_ptrace, sys_ptrace, compat_sys_ptrace) /* kernel/sched/core.c */ #define __NR_sched_setparam 118 @@ -779,7 +779,7 @@ __SYSCALL(__NR_rseq, sys_rseq) #define __NR_kexec_file_load 294 __SYSCALL(__NR_kexec_file_load, sys_kexec_file_load) /* 295 through 402 are unassigned to sync up with generic numbers, don't use */ -#if __BITS_PER_LONG == 32 +#if defined(__SYSCALL_COMPAT) || __BITS_PER_LONG == 32 #define __NR_clock_gettime64 403 __SYSCALL(__NR_clock_gettime64, sys_clock_gettime) #define __NR_clock_settime64 404 diff --git a/linux-headers/asm-riscv/kvm.h b/linux-headers/asm-riscv/kvm.h index f808ad1ce5..7351417afd 100644 --- a/linux-headers/asm-riscv/kvm.h +++ b/linux-headers/asm-riscv/kvm.h @@ -82,6 +82,25 @@ struct kvm_riscv_timer { __u64 state; }; +/* + * ISA extension IDs specific to KVM. This is not the same as the host ISA + * extension IDs as that is internal to the host and should not be exposed + * to the guest. This should always be contiguous to keep the mapping simple + * in KVM implementation. + */ +enum KVM_RISCV_ISA_EXT_ID { + KVM_RISCV_ISA_EXT_A = 0, + KVM_RISCV_ISA_EXT_C, + KVM_RISCV_ISA_EXT_D, + KVM_RISCV_ISA_EXT_F, + KVM_RISCV_ISA_EXT_H, + KVM_RISCV_ISA_EXT_I, + KVM_RISCV_ISA_EXT_M, + KVM_RISCV_ISA_EXT_SVPBMT, + KVM_RISCV_ISA_EXT_SSTC, + KVM_RISCV_ISA_EXT_MAX, +}; + /* Possible states for kvm_riscv_timer */ #define KVM_RISCV_TIMER_STATE_OFF 0 #define KVM_RISCV_TIMER_STATE_ON 1 @@ -123,6 +142,9 @@ struct kvm_riscv_timer { #define KVM_REG_RISCV_FP_D_REG(name) \ (offsetof(struct __riscv_d_ext_state, name) / sizeof(__u64)) +/* ISA Extension registers are mapped as type 7 */ +#define KVM_REG_RISCV_ISA_EXT (0x07 << KVM_REG_RISCV_TYPE_SHIFT) + #endif #endif /* __LINUX_KVM_RISCV_H */ diff --git a/linux-headers/asm-riscv/unistd.h b/linux-headers/asm-riscv/unistd.h index 8062996c2d..73d7cdd2ec 100644 --- a/linux-headers/asm-riscv/unistd.h +++ b/linux-headers/asm-riscv/unistd.h @@ -15,12 +15,13 @@ * along with this program. If not, see . */ -#ifdef __LP64__ +#if defined(__LP64__) && !defined(__SYSCALL_COMPAT) #define __ARCH_WANT_NEW_STAT #define __ARCH_WANT_SET_GET_RLIMIT #endif /* __LP64__ */ #define __ARCH_WANT_SYS_CLONE3 +#define __ARCH_WANT_MEMFD_SECRET #include diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h index f053b8304a..e2afd95420 100644 --- a/linux-headers/asm-s390/kvm.h +++ b/linux-headers/asm-s390/kvm.h @@ -74,6 +74,7 @@ struct kvm_s390_io_adapter_req { #define KVM_S390_VM_CRYPTO 2 #define KVM_S390_VM_CPU_MODEL 3 #define KVM_S390_VM_MIGRATION 4 +#define KVM_S390_VM_CPU_TOPOLOGY 5 /* kvm attributes for mem_ctrl */ #define KVM_S390_VM_MEM_ENABLE_CMMA 0 diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h index bf6e96011d..46de10a809 100644 --- a/linux-headers/asm-x86/kvm.h +++ b/linux-headers/asm-x86/kvm.h @@ -198,13 +198,13 @@ struct kvm_msrs { __u32 nmsrs; /* number of msrs in entries */ __u32 pad; - struct kvm_msr_entry entries[0]; + struct kvm_msr_entry entries[]; }; /* for KVM_GET_MSR_INDEX_LIST */ struct kvm_msr_list { __u32 nmsrs; /* number of msrs in entries */ - __u32 indices[0]; + __u32 indices[]; }; /* Maximum size of any access bitmap in bytes */ @@ -241,7 +241,7 @@ struct kvm_cpuid_entry { struct kvm_cpuid { __u32 nent; __u32 padding; - struct kvm_cpuid_entry entries[0]; + struct kvm_cpuid_entry entries[]; }; struct kvm_cpuid_entry2 { @@ -263,7 +263,7 @@ struct kvm_cpuid_entry2 { struct kvm_cpuid2 { __u32 nent; __u32 padding; - struct kvm_cpuid_entry2 entries[0]; + struct kvm_cpuid_entry2 entries[]; }; /* for KVM_GET_PIT and KVM_SET_PIT */ @@ -306,7 +306,8 @@ struct kvm_pit_state { struct kvm_pit_channel_state channels[3]; }; -#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001 +#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001 +#define KVM_PIT_FLAGS_SPEAKER_DATA_ON 0x00000002 struct kvm_pit_state2 { struct kvm_pit_channel_state channels[3]; @@ -325,6 +326,7 @@ struct kvm_reinject_control { #define KVM_VCPUEVENT_VALID_SHADOW 0x00000004 #define KVM_VCPUEVENT_VALID_SMM 0x00000008 #define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010 +#define KVM_VCPUEVENT_VALID_TRIPLE_FAULT 0x00000020 /* Interrupt shadow states */ #define KVM_X86_SHADOW_INT_MOV_SS 0x01 @@ -359,7 +361,10 @@ struct kvm_vcpu_events { __u8 smm_inside_nmi; __u8 latched_init; } smi; - __u8 reserved[27]; + struct { + __u8 pending; + } triple_fault; + __u8 reserved[26]; __u8 exception_has_payload; __u64 exception_payload; }; @@ -389,7 +394,7 @@ struct kvm_xsave { * the contents of CPUID leaf 0xD on the host. */ __u32 region[1024]; - __u32 extra[0]; + __u32 extra[]; }; #define KVM_MAX_XCRS 16 @@ -428,11 +433,13 @@ struct kvm_sync_regs { struct kvm_vcpu_events events; }; -#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) -#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) -#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) -#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) -#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4) +#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) +#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) +#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) +#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) +#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4) +#define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5) +#define KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS (1 << 6) #define KVM_STATE_NESTED_FORMAT_VMX 0 #define KVM_STATE_NESTED_FORMAT_SVM 1 @@ -515,7 +522,7 @@ struct kvm_pmu_event_filter { __u32 fixed_counter_bitmap; __u32 flags; __u32 pad[4]; - __u64 events[0]; + __u64 events[]; }; #define KVM_PMU_EVENT_ALLOW 0 diff --git a/linux-headers/asm-x86/mman.h b/linux-headers/asm-x86/mman.h index d4a8d0424b..775dbd3aff 100644 --- a/linux-headers/asm-x86/mman.h +++ b/linux-headers/asm-x86/mman.h @@ -5,20 +5,6 @@ #define MAP_32BIT 0x40 /* only give out 32bit addresses */ #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS -/* - * Take the 4 protection key bits out of the vma->vm_flags - * value and turn them in to the bits that we can put in - * to a pte. - * - * Only override these if Protection Keys are available - * (which is only on 64-bit). - */ -#define arch_vm_get_page_prot(vm_flags) __pgprot( \ - ((vm_flags) & VM_PKEY_BIT0 ? _PAGE_PKEY_BIT0 : 0) | \ - ((vm_flags) & VM_PKEY_BIT1 ? _PAGE_PKEY_BIT1 : 0) | \ - ((vm_flags) & VM_PKEY_BIT2 ? _PAGE_PKEY_BIT2 : 0) | \ - ((vm_flags) & VM_PKEY_BIT3 ? _PAGE_PKEY_BIT3 : 0)) - #define arch_calc_vm_prot_bits(prot, key) ( \ ((key) & 0x1 ? VM_PKEY_BIT0 : 0) | \ ((key) & 0x2 ? VM_PKEY_BIT1 : 0) | \ diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index f089349149..ebdafa576d 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -270,6 +270,8 @@ struct kvm_xen_exit { #define KVM_EXIT_X86_BUS_LOCK 33 #define KVM_EXIT_XEN 34 #define KVM_EXIT_RISCV_SBI 35 +#define KVM_EXIT_RISCV_CSR 36 +#define KVM_EXIT_NOTIFY 37 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -444,6 +446,9 @@ struct kvm_run { #define KVM_SYSTEM_EVENT_SHUTDOWN 1 #define KVM_SYSTEM_EVENT_RESET 2 #define KVM_SYSTEM_EVENT_CRASH 3 +#define KVM_SYSTEM_EVENT_WAKEUP 4 +#define KVM_SYSTEM_EVENT_SUSPEND 5 +#define KVM_SYSTEM_EVENT_SEV_TERM 6 __u32 type; __u32 ndata; union { @@ -491,6 +496,18 @@ struct kvm_run { unsigned long args[6]; unsigned long ret[2]; } riscv_sbi; + /* KVM_EXIT_RISCV_CSR */ + struct { + unsigned long csr_num; + unsigned long new_value; + unsigned long write_mask; + unsigned long ret_value; + } riscv_csr; + /* KVM_EXIT_NOTIFY */ + struct { +#define KVM_NOTIFY_CONTEXT_INVALID (1 << 0) + __u32 flags; + } notify; /* Fix the size of the union. */ char padding[256]; }; @@ -537,7 +554,7 @@ struct kvm_coalesced_mmio { struct kvm_coalesced_mmio_ring { __u32 first, last; - struct kvm_coalesced_mmio coalesced_mmio[0]; + struct kvm_coalesced_mmio coalesced_mmio[]; }; #define KVM_COALESCED_MMIO_MAX \ @@ -616,7 +633,7 @@ struct kvm_clear_dirty_log { /* for KVM_SET_SIGNAL_MASK */ struct kvm_signal_mask { __u32 len; - __u8 sigset[0]; + __u8 sigset[]; }; /* for KVM_TPR_ACCESS_REPORTING */ @@ -644,6 +661,7 @@ struct kvm_vapic_addr { #define KVM_MP_STATE_OPERATING 7 #define KVM_MP_STATE_LOAD 8 #define KVM_MP_STATE_AP_RESET_HOLD 9 +#define KVM_MP_STATE_SUSPENDED 10 struct kvm_mp_state { __u32 mp_state; @@ -1148,8 +1166,15 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_S390_MEM_OP_EXTENSION 211 #define KVM_CAP_PMU_CAPABILITY 212 #define KVM_CAP_DISABLE_QUIRKS2 213 -/* #define KVM_CAP_VM_TSC_CONTROL 214 */ +#define KVM_CAP_VM_TSC_CONTROL 214 #define KVM_CAP_SYSTEM_EVENT_DATA 215 +#define KVM_CAP_ARM_SYSTEM_SUSPEND 216 +#define KVM_CAP_S390_PROTECTED_DUMP 217 +#define KVM_CAP_X86_TRIPLE_FAULT_EVENT 218 +#define KVM_CAP_X86_NOTIFY_VMEXIT 219 +#define KVM_CAP_VM_DISABLE_NX_HUGE_PAGES 220 +#define KVM_CAP_S390_ZPCI_OP 221 +#define KVM_CAP_S390_CPU_TOPOLOGY 222 #ifdef KVM_CAP_IRQ_ROUTING @@ -1214,7 +1239,7 @@ struct kvm_irq_routing_entry { struct kvm_irq_routing { __u32 nr; __u32 flags; - struct kvm_irq_routing_entry entries[0]; + struct kvm_irq_routing_entry entries[]; }; #endif @@ -1238,6 +1263,7 @@ struct kvm_x86_mce { #define KVM_XEN_HVM_CONFIG_SHARED_INFO (1 << 2) #define KVM_XEN_HVM_CONFIG_RUNSTATE (1 << 3) #define KVM_XEN_HVM_CONFIG_EVTCHN_2LEVEL (1 << 4) +#define KVM_XEN_HVM_CONFIG_EVTCHN_SEND (1 << 5) struct kvm_xen_hvm_config { __u32 flags; @@ -1333,7 +1359,7 @@ struct kvm_dirty_tlb { struct kvm_reg_list { __u64 n; /* number of regs */ - __u64 reg[0]; + __u64 reg[]; }; struct kvm_one_reg { @@ -1476,7 +1502,8 @@ struct kvm_s390_ucas_mapping { #define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2) /* Available with KVM_CAP_PPC_GET_PVINFO */ #define KVM_PPC_GET_PVINFO _IOW(KVMIO, 0xa1, struct kvm_ppc_pvinfo) -/* Available with KVM_CAP_TSC_CONTROL */ +/* Available with KVM_CAP_TSC_CONTROL for a vCPU, or with +* KVM_CAP_VM_TSC_CONTROL to set defaults for a VM */ #define KVM_SET_TSC_KHZ _IO(KVMIO, 0xa2) #define KVM_GET_TSC_KHZ _IO(KVMIO, 0xa3) /* Available with KVM_CAP_PCI_2_3 */ @@ -1651,6 +1678,55 @@ struct kvm_s390_pv_unp { __u64 tweak; }; +enum pv_cmd_dmp_id { + KVM_PV_DUMP_INIT, + KVM_PV_DUMP_CONFIG_STOR_STATE, + KVM_PV_DUMP_COMPLETE, + KVM_PV_DUMP_CPU, +}; + +struct kvm_s390_pv_dmp { + __u64 subcmd; + __u64 buff_addr; + __u64 buff_len; + __u64 gaddr; /* For dump storage state */ + __u64 reserved[4]; +}; + +enum pv_cmd_info_id { + KVM_PV_INFO_VM, + KVM_PV_INFO_DUMP, +}; + +struct kvm_s390_pv_info_dump { + __u64 dump_cpu_buffer_len; + __u64 dump_config_mem_buffer_per_1m; + __u64 dump_config_finalize_len; +}; + +struct kvm_s390_pv_info_vm { + __u64 inst_calls_list[4]; + __u64 max_cpus; + __u64 max_guests; + __u64 max_guest_addr; + __u64 feature_indication; +}; + +struct kvm_s390_pv_info_header { + __u32 id; + __u32 len_max; + __u32 len_written; + __u32 reserved; +}; + +struct kvm_s390_pv_info { + struct kvm_s390_pv_info_header header; + union { + struct kvm_s390_pv_info_dump dump; + struct kvm_s390_pv_info_vm vm; + }; +}; + enum pv_cmd_id { KVM_PV_ENABLE, KVM_PV_DISABLE, @@ -1659,6 +1735,8 @@ enum pv_cmd_id { KVM_PV_VERIFY, KVM_PV_PREP_RESET, KVM_PV_UNSHARE_ALL, + KVM_PV_INFO, + KVM_PV_DUMP, }; struct kvm_pv_cmd { @@ -1692,6 +1770,32 @@ struct kvm_xen_hvm_attr { struct { __u64 gfn; } shared_info; + struct { + __u32 send_port; + __u32 type; /* EVTCHNSTAT_ipi / EVTCHNSTAT_interdomain */ + __u32 flags; +#define KVM_XEN_EVTCHN_DEASSIGN (1 << 0) +#define KVM_XEN_EVTCHN_UPDATE (1 << 1) +#define KVM_XEN_EVTCHN_RESET (1 << 2) + /* + * Events sent by the guest are either looped back to + * the guest itself (potentially on a different port#) + * or signalled via an eventfd. + */ + union { + struct { + __u32 port; + __u32 vcpu; + __u32 priority; + } port; + struct { + __u32 port; /* Zero for eventfd */ + __s32 fd; + } eventfd; + __u32 padding[4]; + } deliver; + } evtchn; + __u32 xen_version; __u64 pad[8]; } u; }; @@ -1700,11 +1804,17 @@ struct kvm_xen_hvm_attr { #define KVM_XEN_ATTR_TYPE_LONG_MODE 0x0 #define KVM_XEN_ATTR_TYPE_SHARED_INFO 0x1 #define KVM_XEN_ATTR_TYPE_UPCALL_VECTOR 0x2 +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */ +#define KVM_XEN_ATTR_TYPE_EVTCHN 0x3 +#define KVM_XEN_ATTR_TYPE_XEN_VERSION 0x4 /* Per-vCPU Xen attributes */ #define KVM_XEN_VCPU_GET_ATTR _IOWR(KVMIO, 0xca, struct kvm_xen_vcpu_attr) #define KVM_XEN_VCPU_SET_ATTR _IOW(KVMIO, 0xcb, struct kvm_xen_vcpu_attr) +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */ +#define KVM_XEN_HVM_EVTCHN_SEND _IOW(KVMIO, 0xd0, struct kvm_irq_routing_xen_evtchn) + #define KVM_GET_SREGS2 _IOR(KVMIO, 0xcc, struct kvm_sregs2) #define KVM_SET_SREGS2 _IOW(KVMIO, 0xcd, struct kvm_sregs2) @@ -1722,6 +1832,13 @@ struct kvm_xen_vcpu_attr { __u64 time_blocked; __u64 time_offline; } runstate; + __u32 vcpu_id; + struct { + __u32 port; + __u32 priority; + __u64 expires_ns; + } timer; + __u8 vector; } u; }; @@ -1732,6 +1849,10 @@ struct kvm_xen_vcpu_attr { #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_CURRENT 0x3 #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_DATA 0x4 #define KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST 0x5 +/* Available with KVM_CAP_XEN_HVM / KVM_XEN_HVM_CONFIG_EVTCHN_SEND */ +#define KVM_XEN_VCPU_ATTR_TYPE_VCPU_ID 0x6 +#define KVM_XEN_VCPU_ATTR_TYPE_TIMER 0x7 +#define KVM_XEN_VCPU_ATTR_TYPE_UPCALL_VECTOR 0x8 /* Secure Encrypted Virtualization command */ enum sev_cmd_id { @@ -2032,7 +2153,7 @@ struct kvm_stats_header { #define KVM_STATS_UNIT_SECONDS (0x2 << KVM_STATS_UNIT_SHIFT) #define KVM_STATS_UNIT_CYCLES (0x3 << KVM_STATS_UNIT_SHIFT) #define KVM_STATS_UNIT_BOOLEAN (0x4 << KVM_STATS_UNIT_SHIFT) -#define KVM_STATS_UNIT_MAX KVM_STATS_UNIT_CYCLES +#define KVM_STATS_UNIT_MAX KVM_STATS_UNIT_BOOLEAN #define KVM_STATS_BASE_SHIFT 8 #define KVM_STATS_BASE_MASK (0xF << KVM_STATS_BASE_SHIFT) @@ -2067,4 +2188,41 @@ struct kvm_stats_desc { /* Available with KVM_CAP_XSAVE2 */ #define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) +/* Available with KVM_CAP_S390_PROTECTED_DUMP */ +#define KVM_S390_PV_CPU_COMMAND _IOWR(KVMIO, 0xd0, struct kvm_pv_cmd) + +/* Available with KVM_CAP_X86_NOTIFY_VMEXIT */ +#define KVM_X86_NOTIFY_VMEXIT_ENABLED (1ULL << 0) +#define KVM_X86_NOTIFY_VMEXIT_USER (1ULL << 1) + +/* Available with KVM_CAP_S390_ZPCI_OP */ +#define KVM_S390_ZPCI_OP _IOW(KVMIO, 0xd1, struct kvm_s390_zpci_op) + +struct kvm_s390_zpci_op { + /* in */ + __u32 fh; /* target device */ + __u8 op; /* operation to perform */ + __u8 pad[3]; + union { + /* for KVM_S390_ZPCIOP_REG_AEN */ + struct { + __u64 ibv; /* Guest addr of interrupt bit vector */ + __u64 sb; /* Guest addr of summary bit */ + __u32 flags; + __u32 noi; /* Number of interrupts */ + __u8 isc; /* Guest interrupt subclass */ + __u8 sbo; /* Offset of guest summary bit vector */ + __u16 pad; + } reg_aen; + __u64 reserved[8]; + } u; +}; + +/* types for kvm_s390_zpci_op->op */ +#define KVM_S390_ZPCIOP_REG_AEN 0 +#define KVM_S390_ZPCIOP_DEREG_AEN 1 + +/* flags for kvm_s390_zpci_op->u.reg_aen.flags */ +#define KVM_S390_ZPCIOP_REGAEN_HOST (1 << 0) + #endif /* __LINUX_KVM_H */ diff --git a/linux-headers/linux/userfaultfd.h b/linux-headers/linux/userfaultfd.h index 769b8379e4..a3a377cd44 100644 --- a/linux-headers/linux/userfaultfd.h +++ b/linux-headers/linux/userfaultfd.h @@ -33,7 +33,8 @@ UFFD_FEATURE_THREAD_ID | \ UFFD_FEATURE_MINOR_HUGETLBFS | \ UFFD_FEATURE_MINOR_SHMEM | \ - UFFD_FEATURE_EXACT_ADDRESS) + UFFD_FEATURE_EXACT_ADDRESS | \ + UFFD_FEATURE_WP_HUGETLBFS_SHMEM) #define UFFD_API_IOCTLS \ ((__u64)1 << _UFFDIO_REGISTER | \ (__u64)1 << _UFFDIO_UNREGISTER | \ @@ -47,7 +48,8 @@ #define UFFD_API_RANGE_IOCTLS_BASIC \ ((__u64)1 << _UFFDIO_WAKE | \ (__u64)1 << _UFFDIO_COPY | \ - (__u64)1 << _UFFDIO_CONTINUE) + (__u64)1 << _UFFDIO_CONTINUE | \ + (__u64)1 << _UFFDIO_WRITEPROTECT) /* * Valid ioctl command number range with this API is from 0x00 to @@ -194,6 +196,9 @@ struct uffdio_api { * UFFD_FEATURE_EXACT_ADDRESS indicates that the exact address of page * faults would be provided and the offset within the page would not be * masked. + * + * UFFD_FEATURE_WP_HUGETLBFS_SHMEM indicates that userfaultfd + * write-protection mode is supported on both shmem and hugetlbfs. */ #define UFFD_FEATURE_PAGEFAULT_FLAG_WP (1<<0) #define UFFD_FEATURE_EVENT_FORK (1<<1) @@ -207,6 +212,7 @@ struct uffdio_api { #define UFFD_FEATURE_MINOR_HUGETLBFS (1<<9) #define UFFD_FEATURE_MINOR_SHMEM (1<<10) #define UFFD_FEATURE_EXACT_ADDRESS (1<<11) +#define UFFD_FEATURE_WP_HUGETLBFS_SHMEM (1<<12) __u64 features; __u64 ioctls; diff --git a/linux-headers/linux/vduse.h b/linux-headers/linux/vduse.h index d47b004ce6..6d2ca064b5 100644 --- a/linux-headers/linux/vduse.h +++ b/linux-headers/linux/vduse.h @@ -210,6 +210,53 @@ struct vduse_vq_eventfd { */ #define VDUSE_VQ_INJECT_IRQ _IOW(VDUSE_BASE, 0x17, __u32) +/** + * struct vduse_iova_umem - userspace memory configuration for one IOVA region + * @uaddr: start address of userspace memory, it must be aligned to page size + * @iova: start of the IOVA region + * @size: size of the IOVA region + * @reserved: for future use, needs to be initialized to zero + * + * Structure used by VDUSE_IOTLB_REG_UMEM and VDUSE_IOTLB_DEREG_UMEM + * ioctls to register/de-register userspace memory for IOVA regions + */ +struct vduse_iova_umem { + __u64 uaddr; + __u64 iova; + __u64 size; + __u64 reserved[3]; +}; + +/* Register userspace memory for IOVA regions */ +#define VDUSE_IOTLB_REG_UMEM _IOW(VDUSE_BASE, 0x18, struct vduse_iova_umem) + +/* De-register the userspace memory. Caller should set iova and size field. */ +#define VDUSE_IOTLB_DEREG_UMEM _IOW(VDUSE_BASE, 0x19, struct vduse_iova_umem) + +/** + * struct vduse_iova_info - information of one IOVA region + * @start: start of the IOVA region + * @last: last of the IOVA region + * @capability: capability of the IOVA regsion + * @reserved: for future use, needs to be initialized to zero + * + * Structure used by VDUSE_IOTLB_GET_INFO ioctl to get information of + * one IOVA region. + */ +struct vduse_iova_info { + __u64 start; + __u64 last; +#define VDUSE_IOVA_CAP_UMEM (1 << 0) + __u64 capability; + __u64 reserved[3]; +}; + +/* + * Find the first IOVA region that overlaps with the range [start, last] + * and return some information on it. Caller should set start and last fields. + */ +#define VDUSE_IOTLB_GET_INFO _IOWR(VDUSE_BASE, 0x1a, struct vduse_iova_info) + /* The control messages definition for read(2)/write(2) on /dev/vduse/$NAME */ /** diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index e9f7795c39..ede44b5572 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -643,7 +643,7 @@ enum { }; /** - * VFIO_DEVICE_GET_PCI_HOT_RESET_INFO - _IORW(VFIO_TYPE, VFIO_BASE + 12, + * VFIO_DEVICE_GET_PCI_HOT_RESET_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 12, * struct vfio_pci_hot_reset_info) * * Return: 0 on success, -errno on failure: @@ -770,7 +770,7 @@ struct vfio_device_ioeventfd { #define VFIO_DEVICE_IOEVENTFD _IO(VFIO_TYPE, VFIO_BASE + 16) /** - * VFIO_DEVICE_FEATURE - _IORW(VFIO_TYPE, VFIO_BASE + 17, + * VFIO_DEVICE_FEATURE - _IOWR(VFIO_TYPE, VFIO_BASE + 17, * struct vfio_device_feature) * * Get, set, or probe feature data of the device. The feature is selected diff --git a/linux-headers/linux/vfio_zdev.h b/linux-headers/linux/vfio_zdev.h index b4309397b6..77f2aff1f2 100644 --- a/linux-headers/linux/vfio_zdev.h +++ b/linux-headers/linux/vfio_zdev.h @@ -29,6 +29,9 @@ struct vfio_device_info_cap_zpci_base { __u16 fmb_length; /* Measurement Block Length (in bytes) */ __u8 pft; /* PCI Function Type */ __u8 gid; /* PCI function group ID */ + /* End of version 1 */ + __u32 fh; /* PCI function handle */ + /* End of version 2 */ }; /** @@ -47,6 +50,10 @@ struct vfio_device_info_cap_zpci_group { __u16 noi; /* Maximum number of MSIs */ __u16 maxstbl; /* Maximum Store Block Length */ __u8 version; /* Supported PCI Version */ + /* End of version 1 */ + __u8 reserved; + __u16 imaxstbl; /* Maximum Interpreted Store Block Length */ + /* End of version 2 */ }; /** diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h index 5d99e7c242..f9f115a7c7 100644 --- a/linux-headers/linux/vhost.h +++ b/linux-headers/linux/vhost.h @@ -89,11 +89,6 @@ /* Set or get vhost backend capability */ -/* Use message type V2 */ -#define VHOST_BACKEND_F_IOTLB_MSG_V2 0x1 -/* IOTLB can accept batching hints */ -#define VHOST_BACKEND_F_IOTLB_BATCH 0x2 - #define VHOST_SET_BACKEND_FEATURES _IOW(VHOST_VIRTIO, 0x25, __u64) #define VHOST_GET_BACKEND_FEATURES _IOR(VHOST_VIRTIO, 0x26, __u64) @@ -150,11 +145,39 @@ /* Get the valid iova range */ #define VHOST_VDPA_GET_IOVA_RANGE _IOR(VHOST_VIRTIO, 0x78, \ struct vhost_vdpa_iova_range) - /* Get the config size */ #define VHOST_VDPA_GET_CONFIG_SIZE _IOR(VHOST_VIRTIO, 0x79, __u32) /* Get the count of all virtqueues */ #define VHOST_VDPA_GET_VQS_COUNT _IOR(VHOST_VIRTIO, 0x80, __u32) +/* Get the number of virtqueue groups. */ +#define VHOST_VDPA_GET_GROUP_NUM _IOR(VHOST_VIRTIO, 0x81, __u32) + +/* Get the number of address spaces. */ +#define VHOST_VDPA_GET_AS_NUM _IOR(VHOST_VIRTIO, 0x7A, unsigned int) + +/* Get the group for a virtqueue: read index, write group in num, + * The virtqueue index is stored in the index field of + * vhost_vring_state. The group for this specific virtqueue is + * returned via num field of vhost_vring_state. + */ +#define VHOST_VDPA_GET_VRING_GROUP _IOWR(VHOST_VIRTIO, 0x7B, \ + struct vhost_vring_state) +/* Set the ASID for a virtqueue group. The group index is stored in + * the index field of vhost_vring_state, the ASID associated with this + * group is stored at num field of vhost_vring_state. + */ +#define VHOST_VDPA_SET_GROUP_ASID _IOW(VHOST_VIRTIO, 0x7C, \ + struct vhost_vring_state) + +/* Suspend a device so it does not process virtqueue requests anymore + * + * After the return of ioctl the device must preserve all the necessary state + * (the virtqueue vring base plus the possible device specific states) that is + * required for restoring in the future. The device must not change its + * configuration after that point. + */ +#define VHOST_VDPA_SUSPEND _IO(VHOST_VIRTIO, 0x7D) + #endif From 21fa15298d88db2050a713cdf79c10cb0e09146f Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Fri, 2 Sep 2022 13:27:31 -0400 Subject: [PATCH 0614/1020] s390x/pci: add routine to get host function handle from CLP info In order to interface with the underlying host zPCI device, we need to know its function handle. Add a routine to grab this from the vfio CLP capabilities chain. Signed-off-by: Matthew Rosato Reviewed-by: Pierre Morel Message-Id: <20220902172737.170349-3-mjrosato@linux.ibm.com> [thuth: Replace free(info) with g_free(info)] Signed-off-by: Thomas Huth --- hw/s390x/s390-pci-vfio.c | 83 ++++++++++++++++++++++++++------ include/hw/s390x/s390-pci-vfio.h | 5 ++ 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index 6f80a47e29..08bcc55e85 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -124,6 +124,27 @@ static void s390_pci_read_base(S390PCIBusDevice *pbdev, pbdev->zpci_fn.pft = 0; } +static bool get_host_fh(S390PCIBusDevice *pbdev, struct vfio_device_info *info, + uint32_t *fh) +{ + struct vfio_info_cap_header *hdr; + struct vfio_device_info_cap_zpci_base *cap; + VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + + hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_BASE); + + /* Can only get the host fh with version 2 or greater */ + if (hdr == NULL || hdr->version < 2) { + trace_s390_pci_clp_cap(vpci->vbasedev.name, + VFIO_DEVICE_INFO_CAP_ZPCI_BASE); + return false; + } + cap = (void *) hdr; + + *fh = cap->fh; + return true; +} + static void s390_pci_read_group(S390PCIBusDevice *pbdev, struct vfio_device_info *info) { @@ -217,25 +238,13 @@ static void s390_pci_read_pfip(S390PCIBusDevice *pbdev, memcpy(pbdev->zpci_fn.pfip, cap->pfip, CLP_PFIP_NR_SEGMENTS); } -/* - * This function will issue the VFIO_DEVICE_GET_INFO ioctl and look for - * capabilities that contain information about CLP features provided by the - * underlying host. - * On entry, defaults have already been placed into the guest CLP response - * buffers. On exit, defaults will have been overwritten for any CLP features - * found in the capability chain; defaults will remain for any CLP features not - * found in the chain. - */ -void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) +static struct vfio_device_info *get_device_info(S390PCIBusDevice *pbdev, + uint32_t argsz) { - g_autofree struct vfio_device_info *info = NULL; + struct vfio_device_info *info = g_malloc0(argsz); VFIOPCIDevice *vfio_pci; - uint32_t argsz; int fd; - argsz = sizeof(*info); - info = g_malloc0(argsz); - vfio_pci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); fd = vfio_pci->vbasedev.fd; @@ -250,7 +259,8 @@ retry: if (ioctl(fd, VFIO_DEVICE_GET_INFO, info)) { trace_s390_pci_clp_dev_info(vfio_pci->vbasedev.name); - return; + g_free(info); + return NULL; } if (info->argsz > argsz) { @@ -259,6 +269,47 @@ retry: goto retry; } + return info; +} + +/* + * Get the host function handle from the vfio CLP capabilities chain. Returns + * true if a fh value was placed into the provided buffer. Returns false + * if a fh could not be obtained (ioctl failed or capabilitiy version does + * not include the fh) + */ +bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh) +{ + g_autofree struct vfio_device_info *info = NULL; + + assert(fh); + + info = get_device_info(pbdev, sizeof(*info)); + if (!info) { + return false; + } + + return get_host_fh(pbdev, info, fh); +} + +/* + * This function will issue the VFIO_DEVICE_GET_INFO ioctl and look for + * capabilities that contain information about CLP features provided by the + * underlying host. + * On entry, defaults have already been placed into the guest CLP response + * buffers. On exit, defaults will have been overwritten for any CLP features + * found in the capability chain; defaults will remain for any CLP features not + * found in the chain. + */ +void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) +{ + g_autofree struct vfio_device_info *info = NULL; + + info = get_device_info(pbdev, sizeof(*info)); + if (!info) { + return; + } + /* * Find the CLP features provided and fill in the guest CLP responses. * Always call s390_pci_read_base first as information from this could diff --git a/include/hw/s390x/s390-pci-vfio.h b/include/hw/s390x/s390-pci-vfio.h index ff708aef50..ae1b126ff7 100644 --- a/include/hw/s390x/s390-pci-vfio.h +++ b/include/hw/s390x/s390-pci-vfio.h @@ -20,6 +20,7 @@ bool s390_pci_update_dma_avail(int fd, unsigned int *avail); S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, S390PCIBusDevice *pbdev); void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt); +bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh); void s390_pci_get_clp_info(S390PCIBusDevice *pbdev); #else static inline bool s390_pci_update_dma_avail(int fd, unsigned int *avail) @@ -33,6 +34,10 @@ static inline S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s, } static inline void s390_pci_end_dma_count(S390pciState *s, S390PCIDMACount *cnt) { } +static inline bool s390_pci_get_host_fh(S390PCIBusDevice *pbdev, uint32_t *fh) +{ + return false; +} static inline void s390_pci_get_clp_info(S390PCIBusDevice *pbdev) { } #endif From dd1d5fd9684beeb0c14c39f497ef2aa9ac683aa7 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Fri, 2 Sep 2022 13:27:32 -0400 Subject: [PATCH 0615/1020] s390x/pci: enable for load/store interpretation If the ZPCI_OP ioctl reports that is is available and usable, then the underlying KVM host will enable load/store intepretation for any guest device without a SHM bit in the guest function handle. For a device that will be using interpretation support, ensure the guest function handle matches the host function handle; this value is re-checked every time the guest issues a SET PCI FN to enable the guest device as it is the only opportunity to reflect function handle changes. By default, unless interpret=off is specified, interpretation support will always be assumed and exploited if the necessary ioctl and features are available on the host kernel. When these are unavailable, we will silently revert to the interception model; this allows existing guest configurations to work unmodified on hosts with and without zPCI interpretation support, allowing QEMU to choose the best support model available. Signed-off-by: Matthew Rosato Acked-by: Thomas Huth Message-Id: <20220902172737.170349-4-mjrosato@linux.ibm.com> Signed-off-by: Thomas Huth --- hw/s390x/meson.build | 1 + hw/s390x/s390-pci-bus.c | 66 ++++++++++++++++++++++++++++++++- hw/s390x/s390-pci-inst.c | 16 ++++++++ hw/s390x/s390-pci-kvm.c | 22 +++++++++++ include/hw/s390x/s390-pci-bus.h | 1 + include/hw/s390x/s390-pci-kvm.h | 24 ++++++++++++ target/s390x/kvm/kvm.c | 7 ++++ target/s390x/kvm/kvm_s390x.h | 1 + 8 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 hw/s390x/s390-pci-kvm.c create mode 100644 include/hw/s390x/s390-pci-kvm.h diff --git a/hw/s390x/meson.build b/hw/s390x/meson.build index feefe0717e..f291016fee 100644 --- a/hw/s390x/meson.build +++ b/hw/s390x/meson.build @@ -23,6 +23,7 @@ s390x_ss.add(when: 'CONFIG_KVM', if_true: files( 's390-skeys-kvm.c', 's390-stattrib-kvm.c', 'pv.c', + 's390-pci-kvm.c', )) s390x_ss.add(when: 'CONFIG_TCG', if_true: files( 'tod-tcg.c', diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 4b2bdd94b3..156051e6e9 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -16,6 +16,7 @@ #include "qapi/visitor.h" #include "hw/s390x/s390-pci-bus.h" #include "hw/s390x/s390-pci-inst.h" +#include "hw/s390x/s390-pci-kvm.h" #include "hw/s390x/s390-pci-vfio.h" #include "hw/pci/pci_bus.h" #include "hw/qdev-properties.h" @@ -971,12 +972,51 @@ static void s390_pci_update_subordinate(PCIDevice *dev, uint32_t nr) } } +static int s390_pci_interp_plug(S390pciState *s, S390PCIBusDevice *pbdev) +{ + uint32_t idx, fh; + + if (!s390_pci_get_host_fh(pbdev, &fh)) { + return -EPERM; + } + + /* + * The host device is already in an enabled state, but we always present + * the initial device state to the guest as disabled (ZPCI_FS_DISABLED). + * Therefore, mask off the enable bit from the passthrough handle until + * the guest issues a CLP SET PCI FN later to enable the device. + */ + pbdev->fh = fh & ~FH_MASK_ENABLE; + + /* Next, see if the idx is already in-use */ + idx = pbdev->fh & FH_MASK_INDEX; + if (pbdev->idx != idx) { + if (s390_pci_find_dev_by_idx(s, idx)) { + return -EINVAL; + } + /* + * Update the idx entry with the passed through idx + * If the relinquished idx is lower than next_idx, use it + * to replace next_idx + */ + g_hash_table_remove(s->zpci_table, &pbdev->idx); + if (idx < s->next_idx) { + s->next_idx = idx; + } + pbdev->idx = idx; + g_hash_table_insert(s->zpci_table, &pbdev->idx, pbdev); + } + + return 0; +} + static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev); PCIDevice *pdev = NULL; S390PCIBusDevice *pbdev = NULL; + int rc; if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) { PCIBridge *pb = PCI_BRIDGE(dev); @@ -1022,12 +1062,35 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, set_pbdev_info(pbdev); if (object_dynamic_cast(OBJECT(dev), "vfio-pci")) { - pbdev->fh |= FH_SHM_VFIO; + /* + * By default, interpretation is always requested; if the available + * facilities indicate it is not available, fallback to the + * interception model. + */ + if (pbdev->interp) { + if (s390_pci_kvm_interp_allowed()) { + rc = s390_pci_interp_plug(s, pbdev); + if (rc) { + error_setg(errp, "Plug failed for zPCI device in " + "interpretation mode: %d", rc); + return; + } + } else { + DPRINTF("zPCI interpretation facilities missing.\n"); + pbdev->interp = false; + } + } pbdev->iommu->dma_limit = s390_pci_start_dma_count(s, pbdev); /* Fill in CLP information passed via the vfio region */ s390_pci_get_clp_info(pbdev); + if (!pbdev->interp) { + /* Do vfio passthrough but intercept for I/O */ + pbdev->fh |= FH_SHM_VFIO; + } } else { pbdev->fh |= FH_SHM_EMUL; + /* Always intercept emulated devices */ + pbdev->interp = false; } if (s390_pci_msix_init(pbdev)) { @@ -1360,6 +1423,7 @@ static Property s390_pci_device_properties[] = { DEFINE_PROP_UINT16("uid", S390PCIBusDevice, uid, UID_UNDEFINED), DEFINE_PROP_S390_PCI_FID("fid", S390PCIBusDevice, fid), DEFINE_PROP_STRING("target", S390PCIBusDevice, target), + DEFINE_PROP_BOOL("interpret", S390PCIBusDevice, interp, true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 6d400d4147..651ec38635 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -18,6 +18,8 @@ #include "sysemu/hw_accel.h" #include "hw/s390x/s390-pci-inst.h" #include "hw/s390x/s390-pci-bus.h" +#include "hw/s390x/s390-pci-kvm.h" +#include "hw/s390x/s390-pci-vfio.h" #include "hw/s390x/tod.h" #ifndef DEBUG_S390PCI_INST @@ -246,6 +248,20 @@ int clp_service_call(S390CPU *cpu, uint8_t r2, uintptr_t ra) goto out; } + /* + * Take this opportunity to make sure we still have an accurate + * host fh. It's possible part of the handle changed while the + * device was disabled to the guest (e.g. vfio hot reset for + * ISM during plug) + */ + if (pbdev->interp) { + /* Take this opportunity to make sure we are sync'd with host */ + if (!s390_pci_get_host_fh(pbdev, &pbdev->fh) || + !(pbdev->fh & FH_MASK_ENABLE)) { + stw_p(&ressetpci->hdr.rsp, CLP_RC_SETPCIFN_FH); + goto out; + } + } pbdev->fh |= FH_MASK_ENABLE; pbdev->state = ZPCI_FS_ENABLED; stl_p(&ressetpci->fh, pbdev->fh); diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c new file mode 100644 index 0000000000..0f16104a74 --- /dev/null +++ b/hw/s390x/s390-pci-kvm.c @@ -0,0 +1,22 @@ +/* + * s390 zPCI KVM interfaces + * + * Copyright 2022 IBM Corp. + * Author(s): Matthew Rosato + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#include "qemu/osdep.h" + +#include "kvm/kvm_s390x.h" +#include "hw/s390x/pv.h" +#include "hw/s390x/s390-pci-kvm.h" +#include "cpu_models.h" + +bool s390_pci_kvm_interp_allowed(void) +{ + return kvm_s390_get_zpci_op() && !s390_is_pv(); +} diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h index da3cde2bb4..a9843dfe97 100644 --- a/include/hw/s390x/s390-pci-bus.h +++ b/include/hw/s390x/s390-pci-bus.h @@ -350,6 +350,7 @@ struct S390PCIBusDevice { IndAddr *indicator; bool pci_unplug_request_processed; bool unplug_requested; + bool interp; QTAILQ_ENTRY(S390PCIBusDevice) link; }; diff --git a/include/hw/s390x/s390-pci-kvm.h b/include/hw/s390x/s390-pci-kvm.h new file mode 100644 index 0000000000..80a2e7d0ca --- /dev/null +++ b/include/hw/s390x/s390-pci-kvm.h @@ -0,0 +1,24 @@ +/* + * s390 PCI KVM interfaces + * + * Copyright 2022 IBM Corp. + * Author(s): Matthew Rosato + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level + * directory. + */ + +#ifndef HW_S390_PCI_KVM_H +#define HW_S390_PCI_KVM_H + +#ifdef CONFIG_KVM +bool s390_pci_kvm_interp_allowed(void); +#else +static inline bool s390_pci_kvm_interp_allowed(void) +{ + return false; +} +#endif + +#endif diff --git a/target/s390x/kvm/kvm.c b/target/s390x/kvm/kvm.c index 7bd8db0e7b..6a8dbadf7e 100644 --- a/target/s390x/kvm/kvm.c +++ b/target/s390x/kvm/kvm.c @@ -157,6 +157,7 @@ static int cap_ri; static int cap_hpage_1m; static int cap_vcpu_resets; static int cap_protected; +static int cap_zpci_op; static bool mem_op_storage_key_support; @@ -362,6 +363,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_s390_irq = kvm_check_extension(s, KVM_CAP_S390_INJECT_IRQ); cap_vcpu_resets = kvm_check_extension(s, KVM_CAP_S390_VCPU_RESETS); cap_protected = kvm_check_extension(s, KVM_CAP_S390_PROTECTED); + cap_zpci_op = kvm_check_extension(s, KVM_CAP_S390_ZPCI_OP); kvm_vm_enable_cap(s, KVM_CAP_S390_USER_SIGP, 0); kvm_vm_enable_cap(s, KVM_CAP_S390_VECTOR_REGISTERS, 0); @@ -2574,3 +2576,8 @@ bool kvm_arch_cpu_check_are_resettable(void) { return true; } + +int kvm_s390_get_zpci_op(void) +{ + return cap_zpci_op; +} diff --git a/target/s390x/kvm/kvm_s390x.h b/target/s390x/kvm/kvm_s390x.h index 05a5e1e6f4..aaae8570de 100644 --- a/target/s390x/kvm/kvm_s390x.h +++ b/target/s390x/kvm/kvm_s390x.h @@ -27,6 +27,7 @@ void kvm_s390_vcpu_interrupt_pre_save(S390CPU *cpu); int kvm_s390_vcpu_interrupt_post_load(S390CPU *cpu); int kvm_s390_get_hpage_1m(void); int kvm_s390_get_ri(void); +int kvm_s390_get_zpci_op(void); int kvm_s390_get_clock(uint8_t *tod_high, uint64_t *tod_clock); int kvm_s390_get_clock_ext(uint8_t *tod_high, uint64_t *tod_clock); int kvm_s390_set_clock(uint8_t tod_high, uint64_t tod_clock); From 15d0e7942d3b31ff71d8e0e8cec3a8203214f19b Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Fri, 2 Sep 2022 13:27:33 -0400 Subject: [PATCH 0616/1020] s390x/pci: don't fence interpreted devices without MSI-X Lack of MSI-X support is not an issue for interpreted passthrough devices, so let's let these in. This will allow, for example, ISM devices to be passed through -- but only when interpretation is available and being used. Signed-off-by: Matthew Rosato Reviewed-by: Thomas Huth Reviewed-by: Pierre Morel Message-Id: <20220902172737.170349-5-mjrosato@linux.ibm.com> Signed-off-by: Thomas Huth --- hw/s390x/s390-pci-bus.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 156051e6e9..816d17af99 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -881,6 +881,10 @@ static int s390_pci_msix_init(S390PCIBusDevice *pbdev) static void s390_pci_msix_free(S390PCIBusDevice *pbdev) { + if (pbdev->msix.entries == 0) { + return; + } + memory_region_del_subregion(&pbdev->iommu->mr, &pbdev->msix_notify_mr); object_unparent(OBJECT(&pbdev->msix_notify_mr)); } @@ -1093,7 +1097,7 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, pbdev->interp = false; } - if (s390_pci_msix_init(pbdev)) { + if (s390_pci_msix_init(pbdev) && !pbdev->interp) { error_setg(errp, "MSI-X support is mandatory " "in the S390 architecture"); return; From d0bc7091c2013ad2fa164100cf7b17962370e8ab Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Fri, 2 Sep 2022 13:27:34 -0400 Subject: [PATCH 0617/1020] s390x/pci: enable adapter event notification for interpreted devices Use the associated kvm ioctl operation to enable adapter event notification and forwarding for devices when requested. This feature will be set up with or without firmware assist based upon the 'forwarding_assist' setting. Signed-off-by: Matthew Rosato Message-Id: <20220902172737.170349-6-mjrosato@linux.ibm.com> [thuth: Rename "forwarding_assist" property to "forwarding-assist"] Signed-off-by: Thomas Huth --- hw/s390x/s390-pci-bus.c | 20 ++++++++++++++--- hw/s390x/s390-pci-inst.c | 40 +++++++++++++++++++++++++++++++-- hw/s390x/s390-pci-kvm.c | 30 +++++++++++++++++++++++++ include/hw/s390x/s390-pci-bus.h | 1 + include/hw/s390x/s390-pci-kvm.h | 14 ++++++++++++ 5 files changed, 100 insertions(+), 5 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 816d17af99..2f19973913 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -190,7 +190,10 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) rc = SCLP_RC_NO_ACTION_REQUIRED; break; default: - if (pbdev->summary_ind) { + if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) { + /* Interpreted devices were using interrupt forwarding */ + s390_pci_kvm_aif_disable(pbdev); + } else if (pbdev->summary_ind) { pci_dereg_irqs(pbdev); } if (pbdev->iommu->enabled) { @@ -1082,6 +1085,7 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, } else { DPRINTF("zPCI interpretation facilities missing.\n"); pbdev->interp = false; + pbdev->forwarding_assist = false; } } pbdev->iommu->dma_limit = s390_pci_start_dma_count(s, pbdev); @@ -1090,11 +1094,13 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, if (!pbdev->interp) { /* Do vfio passthrough but intercept for I/O */ pbdev->fh |= FH_SHM_VFIO; + pbdev->forwarding_assist = false; } } else { pbdev->fh |= FH_SHM_EMUL; /* Always intercept emulated devices */ pbdev->interp = false; + pbdev->forwarding_assist = false; } if (s390_pci_msix_init(pbdev) && !pbdev->interp) { @@ -1244,7 +1250,10 @@ static void s390_pcihost_reset(DeviceState *dev) /* Process all pending unplug requests */ QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) { if (pbdev->unplug_requested) { - if (pbdev->summary_ind) { + if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) { + /* Interpreted devices were using interrupt forwarding */ + s390_pci_kvm_aif_disable(pbdev); + } else if (pbdev->summary_ind) { pci_dereg_irqs(pbdev); } if (pbdev->iommu->enabled) { @@ -1382,7 +1391,10 @@ static void s390_pci_device_reset(DeviceState *dev) break; } - if (pbdev->summary_ind) { + if (pbdev->interp && (pbdev->fh & FH_MASK_ENABLE)) { + /* Interpreted devices were using interrupt forwarding */ + s390_pci_kvm_aif_disable(pbdev); + } else if (pbdev->summary_ind) { pci_dereg_irqs(pbdev); } if (pbdev->iommu->enabled) { @@ -1428,6 +1440,8 @@ static Property s390_pci_device_properties[] = { DEFINE_PROP_S390_PCI_FID("fid", S390PCIBusDevice, fid), DEFINE_PROP_STRING("target", S390PCIBusDevice, target), DEFINE_PROP_BOOL("interpret", S390PCIBusDevice, interp, true), + DEFINE_PROP_BOOL("forwarding-assist", S390PCIBusDevice, forwarding_assist, + true), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 651ec38635..20a9bcc7af 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -1066,6 +1066,32 @@ static void fmb_update(void *opaque) timer_mod(pbdev->fmb_timer, t + pbdev->pci_group->zpci_group.mui); } +static int mpcifc_reg_int_interp(S390PCIBusDevice *pbdev, ZpciFib *fib) +{ + int rc; + + rc = s390_pci_kvm_aif_enable(pbdev, fib, pbdev->forwarding_assist); + if (rc) { + DPRINTF("Failed to enable interrupt forwarding\n"); + return rc; + } + + return 0; +} + +static int mpcifc_dereg_int_interp(S390PCIBusDevice *pbdev, ZpciFib *fib) +{ + int rc; + + rc = s390_pci_kvm_aif_disable(pbdev); + if (rc) { + DPRINTF("Failed to disable interrupt forwarding\n"); + return rc; + } + + return 0; +} + int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, uintptr_t ra) { @@ -1120,7 +1146,12 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, switch (oc) { case ZPCI_MOD_FC_REG_INT: - if (pbdev->summary_ind) { + if (pbdev->interp) { + if (mpcifc_reg_int_interp(pbdev, &fib)) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } + } else if (pbdev->summary_ind) { cc = ZPCI_PCI_LS_ERR; s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); } else if (reg_irqs(env, pbdev, fib)) { @@ -1129,7 +1160,12 @@ int mpcifc_service_call(S390CPU *cpu, uint8_t r1, uint64_t fiba, uint8_t ar, } break; case ZPCI_MOD_FC_DEREG_INT: - if (!pbdev->summary_ind) { + if (pbdev->interp) { + if (mpcifc_dereg_int_interp(pbdev, &fib)) { + cc = ZPCI_PCI_LS_ERR; + s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); + } + } else if (!pbdev->summary_ind) { cc = ZPCI_PCI_LS_ERR; s390_set_status_code(env, r1, ZPCI_MOD_ST_SEQUENCE); } else { diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c index 0f16104a74..9134fe185f 100644 --- a/hw/s390x/s390-pci-kvm.c +++ b/hw/s390x/s390-pci-kvm.c @@ -11,12 +11,42 @@ #include "qemu/osdep.h" +#include + #include "kvm/kvm_s390x.h" #include "hw/s390x/pv.h" +#include "hw/s390x/s390-pci-bus.h" #include "hw/s390x/s390-pci-kvm.h" +#include "hw/s390x/s390-pci-inst.h" #include "cpu_models.h" bool s390_pci_kvm_interp_allowed(void) { return kvm_s390_get_zpci_op() && !s390_is_pv(); } + +int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist) +{ + struct kvm_s390_zpci_op args = { + .fh = pbdev->fh, + .op = KVM_S390_ZPCIOP_REG_AEN, + .u.reg_aen.ibv = fib->aibv, + .u.reg_aen.sb = fib->aisb, + .u.reg_aen.noi = FIB_DATA_NOI(fib->data), + .u.reg_aen.isc = FIB_DATA_ISC(fib->data), + .u.reg_aen.sbo = FIB_DATA_AISBO(fib->data), + .u.reg_aen.flags = (assist) ? 0 : KVM_S390_ZPCIOP_REGAEN_HOST + }; + + return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); +} + +int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev) +{ + struct kvm_s390_zpci_op args = { + .fh = pbdev->fh, + .op = KVM_S390_ZPCIOP_DEREG_AEN + }; + + return kvm_vm_ioctl(kvm_state, KVM_S390_ZPCI_OP, &args); +} diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h index a9843dfe97..5b09f0cf2f 100644 --- a/include/hw/s390x/s390-pci-bus.h +++ b/include/hw/s390x/s390-pci-bus.h @@ -351,6 +351,7 @@ struct S390PCIBusDevice { bool pci_unplug_request_processed; bool unplug_requested; bool interp; + bool forwarding_assist; QTAILQ_ENTRY(S390PCIBusDevice) link; }; diff --git a/include/hw/s390x/s390-pci-kvm.h b/include/hw/s390x/s390-pci-kvm.h index 80a2e7d0ca..933814a402 100644 --- a/include/hw/s390x/s390-pci-kvm.h +++ b/include/hw/s390x/s390-pci-kvm.h @@ -12,13 +12,27 @@ #ifndef HW_S390_PCI_KVM_H #define HW_S390_PCI_KVM_H +#include "hw/s390x/s390-pci-bus.h" +#include "hw/s390x/s390-pci-inst.h" + #ifdef CONFIG_KVM bool s390_pci_kvm_interp_allowed(void); +int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist); +int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev); #else static inline bool s390_pci_kvm_interp_allowed(void) { return false; } +static inline int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, + bool assist) +{ + return -EINVAL; +} +static inline int s390_pci_kvm_aif_disable(S390PCIBusDevice *pbdev) +{ + return -EINVAL; +} #endif #endif From 30dcf4f7fd23bef7d72a2454c60881710fd4c785 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Fri, 2 Sep 2022 13:27:35 -0400 Subject: [PATCH 0618/1020] s390x/pci: let intercept devices have separate PCI groups Let's use the reserved pool of simulated PCI groups to allow intercept devices to have separate groups from interpreted devices as some group values may be different. If we run out of simulated PCI groups, subsequent intercept devices just get the default group. Furthermore, if we encounter any PCI groups from hostdevs that are marked as simulated, let's just assign them to the default group to avoid conflicts between host simulated groups and our own simulated groups. Signed-off-by: Matthew Rosato Reviewed-by: Pierre Morel Message-Id: <20220902172737.170349-7-mjrosato@linux.ibm.com> Signed-off-by: Thomas Huth --- hw/s390x/s390-pci-bus.c | 19 ++++++++++++++-- hw/s390x/s390-pci-vfio.c | 40 ++++++++++++++++++++++++++++++--- include/hw/s390x/s390-pci-bus.h | 6 ++++- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c index 2f19973913..977e7daa15 100644 --- a/hw/s390x/s390-pci-bus.c +++ b/hw/s390x/s390-pci-bus.c @@ -748,13 +748,14 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn) object_unref(OBJECT(iommu)); } -S390PCIGroup *s390_group_create(int id) +S390PCIGroup *s390_group_create(int id, int host_id) { S390PCIGroup *group; S390pciState *s = s390_get_phb(); group = g_new0(S390PCIGroup, 1); group->id = id; + group->host_id = host_id; QTAILQ_INSERT_TAIL(&s->zpci_groups, group, link); return group; } @@ -772,12 +773,25 @@ S390PCIGroup *s390_group_find(int id) return NULL; } +S390PCIGroup *s390_group_find_host_sim(int host_id) +{ + S390PCIGroup *group; + S390pciState *s = s390_get_phb(); + + QTAILQ_FOREACH(group, &s->zpci_groups, link) { + if (group->id >= ZPCI_SIM_GRP_START && group->host_id == host_id) { + return group; + } + } + return NULL; +} + static void s390_pci_init_default_group(void) { S390PCIGroup *group; ClpRspQueryPciGrp *resgrp; - group = s390_group_create(ZPCI_DEFAULT_FN_GRP); + group = s390_group_create(ZPCI_DEFAULT_FN_GRP, ZPCI_DEFAULT_FN_GRP); resgrp = &group->zpci_group; resgrp->fr = 1; resgrp->dasm = 0; @@ -825,6 +839,7 @@ static void s390_pcihost_realize(DeviceState *dev, Error **errp) NULL, g_free); s->zpci_table = g_hash_table_new_full(g_int_hash, g_int_equal, NULL, NULL); s->bus_no = 0; + s->next_sim_grp = ZPCI_SIM_GRP_START; QTAILQ_INIT(&s->pending_sei); QTAILQ_INIT(&s->zpci_devs); QTAILQ_INIT(&s->zpci_dma_limit); diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index 08bcc55e85..338f436e87 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -150,13 +150,18 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev, { struct vfio_info_cap_header *hdr; struct vfio_device_info_cap_zpci_group *cap; + S390pciState *s = s390_get_phb(); ClpRspQueryPciGrp *resgrp; VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev); + uint8_t start_gid = pbdev->zpci_fn.pfgid; hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_GROUP); - /* If capability not provided, just use the default group */ - if (hdr == NULL) { + /* + * If capability not provided or the underlying hostdev is simulated, just + * use the default group. + */ + if (hdr == NULL || pbdev->zpci_fn.pfgid >= ZPCI_SIM_GRP_START) { trace_s390_pci_clp_cap(vpci->vbasedev.name, VFIO_DEVICE_INFO_CAP_ZPCI_GROUP); pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP; @@ -165,11 +170,40 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev, } cap = (void *) hdr; + /* + * For an intercept device, let's use an existing simulated group if one + * one was already created for other intercept devices in this group. + * If not, create a new simulated group if any are still available. + * If all else fails, just fall back on the default group. + */ + if (!pbdev->interp) { + pbdev->pci_group = s390_group_find_host_sim(pbdev->zpci_fn.pfgid); + if (pbdev->pci_group) { + /* Use existing simulated group */ + pbdev->zpci_fn.pfgid = pbdev->pci_group->id; + return; + } else { + if (s->next_sim_grp == ZPCI_DEFAULT_FN_GRP) { + /* All out of simulated groups, use default */ + trace_s390_pci_clp_cap(vpci->vbasedev.name, + VFIO_DEVICE_INFO_CAP_ZPCI_GROUP); + pbdev->zpci_fn.pfgid = ZPCI_DEFAULT_FN_GRP; + pbdev->pci_group = s390_group_find(ZPCI_DEFAULT_FN_GRP); + return; + } else { + /* We can assign a new simulated group */ + pbdev->zpci_fn.pfgid = s->next_sim_grp; + s->next_sim_grp++; + /* Fall through to create the new sim group using CLP info */ + } + } + } + /* See if the PCI group is already defined, create if not */ pbdev->pci_group = s390_group_find(pbdev->zpci_fn.pfgid); if (!pbdev->pci_group) { - pbdev->pci_group = s390_group_create(pbdev->zpci_fn.pfgid); + pbdev->pci_group = s390_group_create(pbdev->zpci_fn.pfgid, start_gid); resgrp = &pbdev->pci_group->zpci_group; if (cap->flags & VFIO_DEVICE_INFO_ZPCI_FLAG_REFRESH) { diff --git a/include/hw/s390x/s390-pci-bus.h b/include/hw/s390x/s390-pci-bus.h index 5b09f0cf2f..0605fcea24 100644 --- a/include/hw/s390x/s390-pci-bus.h +++ b/include/hw/s390x/s390-pci-bus.h @@ -315,13 +315,16 @@ typedef struct ZpciFmb { QEMU_BUILD_BUG_MSG(offsetof(ZpciFmb, fmt0) != 48, "padding in ZpciFmb"); #define ZPCI_DEFAULT_FN_GRP 0xFF +#define ZPCI_SIM_GRP_START 0xF0 typedef struct S390PCIGroup { ClpRspQueryPciGrp zpci_group; int id; + int host_id; QTAILQ_ENTRY(S390PCIGroup) link; } S390PCIGroup; -S390PCIGroup *s390_group_create(int id); +S390PCIGroup *s390_group_create(int id, int host_id); S390PCIGroup *s390_group_find(int id); +S390PCIGroup *s390_group_find_host_sim(int host_id); struct S390PCIBusDevice { DeviceState qdev; @@ -370,6 +373,7 @@ struct S390pciState { QTAILQ_HEAD(, S390PCIBusDevice) zpci_devs; QTAILQ_HEAD(, S390PCIDMACount) zpci_dma_limit; QTAILQ_HEAD(, S390PCIGroup) zpci_groups; + uint8_t next_sim_grp; }; S390pciState *s390_get_phb(void); From 9ee8f7e46a7d42ede69a4780200129bf1acb0d01 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Fri, 2 Sep 2022 13:27:36 -0400 Subject: [PATCH 0619/1020] s390x/pci: reflect proper maxstbl for groups of interpreted devices The maximum supported store block length might be different depending on whether the instruction is interpretively executed (firmware-reported maximum) or handled via userspace intercept (host kernel API maximum). Choose the best available value during group creation. Signed-off-by: Matthew Rosato Reviewed-by: Pierre Morel Message-Id: <20220902172737.170349-8-mjrosato@linux.ibm.com> Signed-off-by: Thomas Huth --- hw/s390x/s390-pci-vfio.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c index 338f436e87..2aefa508a0 100644 --- a/hw/s390x/s390-pci-vfio.c +++ b/hw/s390x/s390-pci-vfio.c @@ -213,7 +213,11 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev, resgrp->msia = cap->msi_addr; resgrp->mui = cap->mui; resgrp->i = cap->noi; - resgrp->maxstbl = cap->maxstbl; + if (pbdev->interp && hdr->version >= 2) { + resgrp->maxstbl = cap->imaxstbl; + } else { + resgrp->maxstbl = cap->maxstbl; + } resgrp->version = cap->version; resgrp->dtsm = ZPCI_DTSM; } From 59d1ce44396e3ad2330dc3261ff3da7ad3a16184 Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Fri, 2 Sep 2022 13:27:37 -0400 Subject: [PATCH 0620/1020] s390x/s390-virtio-ccw: add zpcii-disable machine property The zpcii-disable machine property can be used to force-disable the use of zPCI interpretation facilities for a VM. By default, this setting will be off for machine 7.2 and newer. Signed-off-by: Matthew Rosato Message-Id: <20220902172737.170349-9-mjrosato@linux.ibm.com> Reviewed-by: Thomas Huth [thuth: Fix contextual conflict in ccw_machine_7_1_instance_options()] Signed-off-by: Thomas Huth --- hw/s390x/s390-pci-kvm.c | 4 +++- hw/s390x/s390-virtio-ccw.c | 24 ++++++++++++++++++++++++ include/hw/s390x/s390-virtio-ccw.h | 1 + qemu-options.hx | 8 +++++++- util/qemu-config.c | 4 ++++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/hw/s390x/s390-pci-kvm.c b/hw/s390x/s390-pci-kvm.c index 9134fe185f..5eb7fd12e2 100644 --- a/hw/s390x/s390-pci-kvm.c +++ b/hw/s390x/s390-pci-kvm.c @@ -22,7 +22,9 @@ bool s390_pci_kvm_interp_allowed(void) { - return kvm_s390_get_zpci_op() && !s390_is_pv(); + return (kvm_s390_get_zpci_op() && !s390_is_pv() && + !object_property_get_bool(OBJECT(qdev_get_machine()), + "zpcii-disable", NULL)); } int s390_pci_kvm_aif_enable(S390PCIBusDevice *pbdev, ZpciFib *fib, bool assist) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index e18b816aba..03855c7231 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -645,6 +645,21 @@ static inline void machine_set_dea_key_wrap(Object *obj, bool value, ms->dea_key_wrap = value; } +static inline bool machine_get_zpcii_disable(Object *obj, Error **errp) +{ + S390CcwMachineState *ms = S390_CCW_MACHINE(obj); + + return ms->zpcii_disable; +} + +static inline void machine_set_zpcii_disable(Object *obj, bool value, + Error **errp) +{ + S390CcwMachineState *ms = S390_CCW_MACHINE(obj); + + ms->zpcii_disable = value; +} + static S390CcwMachineClass *current_mc; /* @@ -740,6 +755,13 @@ static inline void s390_machine_initfn(Object *obj) "Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted" " to upper case) to pass to machine loader, boot manager," " and guest kernel"); + + object_property_add_bool(obj, "zpcii-disable", + machine_get_zpcii_disable, + machine_set_zpcii_disable); + object_property_set_description(obj, "zpcii-disable", + "disable zPCI interpretation facilties"); + object_property_set_bool(obj, "zpcii-disable", false, NULL); } static const TypeInfo ccw_machine_info = { @@ -804,10 +826,12 @@ DEFINE_CCW_MACHINE(7_2, "7.2", true); static void ccw_machine_7_1_instance_options(MachineState *machine) { static const S390FeatInit qemu_cpu_feat = { S390_FEAT_LIST_QEMU_V7_1 }; + S390CcwMachineState *ms = S390_CCW_MACHINE(machine); ccw_machine_7_2_instance_options(machine); s390_cpudef_featoff_greater(16, 1, S390_FEAT_PAIE); s390_set_qemu_cpu_model(0x8561, 15, 1, qemu_cpu_feat); + ms->zpcii_disable = true; } static void ccw_machine_7_1_class_options(MachineClass *mc) diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index 3331990e02..8a0090a071 100644 --- a/include/hw/s390x/s390-virtio-ccw.h +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -27,6 +27,7 @@ struct S390CcwMachineState { bool aes_key_wrap; bool dea_key_wrap; bool pv; + bool zpcii_disable; uint8_t loadparm[8]; }; diff --git a/qemu-options.hx b/qemu-options.hx index d8b5ce5b43..7c61868b68 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -37,7 +37,8 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \ " memory-encryption=@var{} memory encryption object to use (default=none)\n" " hmat=on|off controls ACPI HMAT support (default=off)\n" " memory-backend='backend-id' specifies explicitly provided backend for main RAM (default=none)\n" - " cxl-fmw.0.targets.0=firsttarget,cxl-fmw.0.targets.1=secondtarget,cxl-fmw.0.size=size[,cxl-fmw.0.interleave-granularity=granularity]\n", + " cxl-fmw.0.targets.0=firsttarget,cxl-fmw.0.targets.1=secondtarget,cxl-fmw.0.size=size[,cxl-fmw.0.interleave-granularity=granularity]\n" + " zpcii-disable=on|off disables zPCI interpretation facilities (default=off)\n", QEMU_ARCH_ALL) SRST ``-machine [type=]name[,prop=value[,...]]`` @@ -157,6 +158,11 @@ SRST :: -machine cxl-fmw.0.targets.0=cxl.0,cxl-fmw.0.targets.1=cxl.1,cxl-fmw.0.size=128G,cxl-fmw.0.interleave-granularity=512k + + ``zpcii-disable=on|off`` + Disables zPCI interpretation facilties on s390-ccw hosts. + This feature can be used to disable hardware virtual assists + related to zPCI devices. The default is off. ERST DEF("M", HAS_ARG, QEMU_OPTION_M, diff --git a/util/qemu-config.c b/util/qemu-config.c index 433488aa56..5325f6bf80 100644 --- a/util/qemu-config.c +++ b/util/qemu-config.c @@ -236,6 +236,10 @@ static QemuOptsList machine_opts = { .help = "Up to 8 chars in set of [A-Za-z0-9. ](lower case chars" " converted to upper case) to pass to machine" " loader, boot manager, and guest kernel", + },{ + .name = "zpcii-disable", + .type = QEMU_OPT_BOOL, + .help = "disable zPCI interpretation facilities", }, { /* End of list */ } } From 5890258aeeba303704ec1adca415e46067800777 Mon Sep 17 00:00:00 2001 From: Thomas Huth Date: Fri, 8 Apr 2022 18:20:47 +0200 Subject: [PATCH 0621/1020] Remove the slirp submodule (i.e. compile only with an external libslirp) Since QEMU 7.1 we don't support Ubuntu 18.04 anymore, so the last big important Linux distro that did not have a pre-packaged libslirp has been dismissed. All other major distros seem to have a libslirp package in their distribution already - according to repology.org: Fedora 35: 4.6.1 CentOS 8 (RHEL-8): 4.4.0 Debian 11: 4.4.0 OpenSUSE Leap 15.3: 4.3.1 Ubuntu LTS 20.04: 4.1.0 FreeBSD Ports: 4.7.0 NetBSD pkgsrc: 4.7.0 Homebrew: 4.7.0 MSYS2 mingw: 4.7.0 The only one that was still missing a libslirp package is OpenBSD - but the next version (OpenBSD 7.2 which will be shipped in October) is going to include a libslirp package. Since QEMU 7.2 will be published after OpenBSD 7.2, we should be fine there, too. So there is no real urgent need for keeping the slirp submodule in the QEMU tree anymore. Thus let's drop the slirp submodule now and rely on the libslirp packages from the distributions instead. Message-Id: <20220824151122.704946-7-thuth@redhat.com> Acked-by: Samuel Thibault Signed-off-by: Thomas Huth --- .gitlab-ci.d/buildtest.yml | 20 +++--- .gitmodules | 3 - MAINTAINERS | 1 - configure | 24 ------- meson.build | 121 +++++++--------------------------- meson_options.txt | 5 +- scripts/archive-source.sh | 2 +- scripts/meson-buildoptions.sh | 4 +- slirp | 1 - 9 files changed, 34 insertions(+), 147 deletions(-) delete mode 160000 slirp diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 1931b77b49..6c05c46397 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -41,8 +41,7 @@ build-system-ubuntu: job: amd64-ubuntu2004-container variables: IMAGE: ubuntu2004 - CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-slirp=system - --enable-capstone + CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-capstone TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu microblazeel-softmmu mips64el-softmmu MAKE_CHECK_ARGS: check-build @@ -120,7 +119,7 @@ build-system-fedora: variables: IMAGE: fedora CONFIGURE_ARGS: --disable-gcrypt --enable-nettle --enable-docs - --enable-fdt=system --enable-slirp=system --enable-capstone + --enable-fdt=system --enable-slirp --enable-capstone TARGETS: tricore-softmmu microblaze-softmmu mips-softmmu xtensa-softmmu m68k-softmmu riscv32-softmmu ppc-softmmu sparc64-softmmu MAKE_CHECK_ARGS: check-build @@ -339,10 +338,8 @@ clang-user: # On gitlab runners, default value sometimes end up calling 2 lds concurrently and # triggers an Out-Of-Memory error # -# Since slirp callbacks are used in QEMU Timers, slirp needs to be compiled together -# with QEMU and linked as a static library to avoid false positives in CFI checks. -# This can be accomplished by using -enable-slirp=git, which avoids the use of -# a system-wide version of the library +# Since slirp callbacks are used in QEMU Timers, we cannot use libslirp with +# CFI builds, and thus have to disable it here. # # Split in three sets of build/check/avocado to limit the execution time of each # job @@ -355,7 +352,7 @@ build-cfi-aarch64: AR: llvm-ar IMAGE: fedora CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug - --enable-safe-stack --enable-slirp=git + --enable-safe-stack --disable-slirp TARGETS: aarch64-softmmu MAKE_CHECK_ARGS: check-build # FIXME: This job is often failing, likely due to out-of-memory problems in @@ -395,7 +392,7 @@ build-cfi-ppc64-s390x: AR: llvm-ar IMAGE: fedora CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug - --enable-safe-stack --enable-slirp=git + --enable-safe-stack --disable-slirp TARGETS: ppc64-softmmu s390x-softmmu MAKE_CHECK_ARGS: check-build # FIXME: This job is often failing, likely due to out-of-memory problems in @@ -435,7 +432,7 @@ build-cfi-x86_64: AR: llvm-ar IMAGE: fedora CONFIGURE_ARGS: --cc=clang --cxx=clang++ --enable-cfi --enable-cfi-debug - --enable-safe-stack --enable-slirp=git + --enable-safe-stack --disable-slirp TARGETS: x86_64-softmmu MAKE_CHECK_ARGS: check-build timeout: 70m @@ -469,7 +466,7 @@ tsan-build: variables: IMAGE: ubuntu2004 CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10 - --enable-trace-backends=ust --enable-fdt=system --enable-slirp=system + --enable-trace-backends=ust --enable-fdt=system --disable-slirp TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user MAKE_CHECK_ARGS: bench V=1 @@ -571,7 +568,6 @@ build-without-default-features: --disable-capstone --disable-pie --disable-qom-cast-debug - --disable-slirp --disable-strip TARGETS: avr-softmmu i386-softmmu mips64-softmmu s390x-softmmu sh4-softmmu sparc64-softmmu hexagon-linux-user i386-linux-user s390x-linux-user diff --git a/.gitmodules b/.gitmodules index aedd9a03d4..24cffa87d4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -46,9 +46,6 @@ [submodule "roms/edk2"] path = roms/edk2 url = https://gitlab.com/qemu-project/edk2.git -[submodule "slirp"] - path = slirp - url = https://gitlab.com/qemu-project/libslirp.git [submodule "roms/opensbi"] path = roms/opensbi url = https://gitlab.com/qemu-project/opensbi.git diff --git a/MAINTAINERS b/MAINTAINERS index 738c4eb647..fc0985a1d1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2978,7 +2978,6 @@ F: include/hw/registerfields.h SLIRP M: Samuel Thibault S: Maintained -F: slirp/ F: net/slirp.c F: include/net/slirp.h T: git https://people.debian.org/~sthibault/qemu.git slirp diff --git a/configure b/configure index 78e0ab8db4..2ba1a82613 100755 --- a/configure +++ b/configure @@ -321,11 +321,6 @@ vfio_user_server="disabled" # are included in the automatically generated help message) # 1. Track which submodules are needed -if test "$default_feature" = no ; then - slirp="disabled" -else - slirp="auto" -fi fdt="auto" # 2. Automatically enable/disable other options @@ -829,14 +824,6 @@ for opt do ;; --disable-tsan) tsan="no" ;; - --disable-slirp) slirp="disabled" - ;; - --enable-slirp) slirp="enabled" - ;; - --enable-slirp=git) slirp="internal" - ;; - --enable-slirp=*) slirp="$optarg" - ;; --disable-tcg) tcg="disabled" plugins="no" ;; @@ -1823,16 +1810,6 @@ EOF fi fi -########################################## -# check for slirp - -case "$slirp" in - auto | enabled | internal) - # Simpler to always update submodule, even if not needed. - git_submodules="${git_submodules} slirp" - ;; -esac - ########################################## # functions to probe cross compilers @@ -2741,7 +2718,6 @@ if test "$skip_meson" = no; then test "$fdt" != auto && meson_option_add "-Dfdt=$fdt" test -n "${LIB_FUZZING_ENGINE+xxx}" && meson_option_add "-Dfuzzing_engine=$LIB_FUZZING_ENGINE" test "$qemu_suffix" != qemu && meson_option_add "-Dqemu_suffix=$qemu_suffix" - test "$slirp" != auto && meson_option_add "-Dslirp=$slirp" test "$smbd" != '' && meson_option_add "-Dsmbd=$smbd" test "$tcg" != enabled && meson_option_add "-Dtcg=$tcg" test "$vfio_user_server" != auto && meson_option_add "-Dvfio_user_server=$vfio_user_server" diff --git a/meson.build b/meson.build index 3885fc1076..326996f582 100644 --- a/meson.build +++ b/meson.build @@ -643,6 +643,26 @@ else method: 'pkg-config', kwargs: static_kwargs) endif +slirp = not_found +if not get_option('slirp').auto() or have_system + slirp = dependency('slirp', required: get_option('slirp'), + method: 'pkg-config', kwargs: static_kwargs) + # slirp < 4.7 is incompatible with CFI support in QEMU. This is because + # it passes function pointers within libslirp as callbacks for timers. + # When using a system-wide shared libslirp, the type information for the + # callback is missing and the timer call produces a false positive with CFI. + # Do not use the "version" keyword argument to produce a better error. + # with control-flow integrity. + if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7') + if get_option('slirp').enabled() + error('Control-Flow Integrity requires libslirp 4.7.') + else + warning('Cannot use libslirp since Control-Flow Integrity requires libslirp >= 4.7.') + slirp = not_found + endif + endif +endif + vde = not_found if not get_option('vde').auto() or have_system or have_tools vde = cc.find_library('vdeplug', has_headers: ['libvdeplug.h'], @@ -2617,103 +2637,6 @@ if not get_option('capstone').auto() or have_system or have_user endif endif -slirp = not_found -slirp_opt = 'disabled' -if have_system - slirp_opt = get_option('slirp') - if slirp_opt in ['enabled', 'auto', 'system'] - have_internal = fs.exists(meson.current_source_dir() / 'slirp/meson.build') - slirp_dep_required = (slirp_opt == 'system' or - slirp_opt == 'enabled' and not have_internal) - slirp = dependency('slirp', kwargs: static_kwargs, - method: 'pkg-config', version: '>=4.1.0', - required: slirp_dep_required) - # slirp <4.7 is incompatible with CFI support in QEMU. This is because - # it passes function pointers within libslirp as callbacks for timers. - # When using a system-wide shared libslirp, the type information for the - # callback is missing and the timer call produces a false positive with CFI. - # Do not use the "version" keyword argument to produce a better error. - # with control-flow integrity. - if get_option('cfi') and slirp.found() and slirp.version().version_compare('<4.7') - if slirp_dep_required - error('Control-Flow Integrity requires libslirp 4.7.') - else - warning('Control-Flow Integrity requires libslirp 4.7, not using system-wide libslirp.') - slirp = not_found - endif - endif - if slirp.found() - slirp_opt = 'system' - elif have_internal - slirp_opt = 'internal' - else - slirp_opt = 'disabled' - endif - endif - if slirp_opt == 'internal' - slirp_deps = [] - if targetos == 'windows' - slirp_deps = cc.find_library('iphlpapi') - elif targetos == 'darwin' - slirp_deps = cc.find_library('resolv') - endif - slirp_conf = configuration_data() - slirp_conf.set('SLIRP_MAJOR_VERSION', meson.project_version().split('.')[0]) - slirp_conf.set('SLIRP_MINOR_VERSION', meson.project_version().split('.')[1]) - slirp_conf.set('SLIRP_MICRO_VERSION', meson.project_version().split('.')[2]) - slirp_conf.set_quoted('SLIRP_VERSION_STRING', meson.project_version()) - slirp_cargs = ['-DG_LOG_DOMAIN="Slirp"'] - slirp_files = [ - 'slirp/src/arp_table.c', - 'slirp/src/bootp.c', - 'slirp/src/cksum.c', - 'slirp/src/dhcpv6.c', - 'slirp/src/dnssearch.c', - 'slirp/src/if.c', - 'slirp/src/ip6_icmp.c', - 'slirp/src/ip6_input.c', - 'slirp/src/ip6_output.c', - 'slirp/src/ip_icmp.c', - 'slirp/src/ip_input.c', - 'slirp/src/ip_output.c', - 'slirp/src/mbuf.c', - 'slirp/src/misc.c', - 'slirp/src/ncsi.c', - 'slirp/src/ndp_table.c', - 'slirp/src/sbuf.c', - 'slirp/src/slirp.c', - 'slirp/src/socket.c', - 'slirp/src/state.c', - 'slirp/src/stream.c', - 'slirp/src/tcp_input.c', - 'slirp/src/tcp_output.c', - 'slirp/src/tcp_subr.c', - 'slirp/src/tcp_timer.c', - 'slirp/src/tftp.c', - 'slirp/src/udp.c', - 'slirp/src/udp6.c', - 'slirp/src/util.c', - 'slirp/src/version.c', - 'slirp/src/vmstate.c', - ] - - configure_file( - input : 'slirp/src/libslirp-version.h.in', - output : 'libslirp-version.h', - configuration: slirp_conf) - - slirp_inc = include_directories('slirp', 'slirp/src') - libslirp = static_library('slirp', - build_by_default: false, - sources: slirp_files, - c_args: slirp_cargs, - include_directories: slirp_inc) - slirp = declare_dependency(link_with: libslirp, - dependencies: slirp_deps, - include_directories: slirp_inc) - endif -endif - libvfio_user_dep = not_found if have_system and vfio_user_server_allowed have_internal = fs.exists(meson.current_source_dir() / 'subprojects/libvfio-user/meson.build') @@ -3718,7 +3641,7 @@ summary_info += {'genisoimage': config_host['GENISOIMAGE']} if targetos == 'windows' and have_ga summary_info += {'wixl': wixl} endif -if slirp_opt != 'disabled' and have_system +if slirp.found() and have_system summary_info += {'smbd': have_slirp_smbd ? smbd_path : false} endif summary(summary_info, bool_yn: true, section: 'Host binaries') @@ -3912,7 +3835,7 @@ summary_info += {'SDL image support': sdl_image} summary_info += {'GTK support': gtk} summary_info += {'pixman': pixman} summary_info += {'VTE support': vte} -summary_info += {'slirp support': slirp_opt == 'internal' ? slirp_opt : slirp} +summary_info += {'slirp support': slirp} summary_info += {'libtasn1': tasn1} summary_info += {'PAM': pam} summary_info += {'iconv support': iconv} diff --git a/meson_options.txt b/meson_options.txt index 63f0725174..6d25ef403b 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -199,6 +199,8 @@ option('l2tpv3', type : 'feature', value : 'auto', description: 'l2tpv3 network backend support') option('netmap', type : 'feature', value : 'auto', description: 'netmap network backend support') +option('slirp', type: 'feature', value: 'auto', + description: 'libslirp user mode network backend support') option('vde', type : 'feature', value : 'auto', description: 'vde network backend support') option('vmnet', type : 'feature', value : 'auto', @@ -264,9 +266,6 @@ option('vduse_blk_export', type: 'feature', value: 'auto', option('capstone', type: 'feature', value: 'auto', description: 'Whether and how to find the capstone library') -option('slirp', type: 'combo', value: 'auto', - choices: ['disabled', 'enabled', 'auto', 'system', 'internal'], - description: 'Whether and how to find the slirp library') option('fdt', type: 'combo', value: 'auto', choices: ['disabled', 'enabled', 'auto', 'system', 'internal'], description: 'Whether and how to find the libfdt library') diff --git a/scripts/archive-source.sh b/scripts/archive-source.sh index c6169db69f..23e042dacd 100755 --- a/scripts/archive-source.sh +++ b/scripts/archive-source.sh @@ -26,7 +26,7 @@ sub_file="${sub_tdir}/submodule.tar" # independent of what the developer currently has initialized # in their checkout, because the build environment is completely # different to the host OS. -submodules="dtc slirp meson ui/keycodemapdb" +submodules="dtc meson ui/keycodemapdb" submodules="$submodules tests/fp/berkeley-softfloat-3 tests/fp/berkeley-testfloat-3" sub_deinit="" diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 359b04e0e6..c68ba32ce2 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -35,8 +35,6 @@ meson_options_help() { printf "%s\n" ' --enable-qom-cast-debug cast debugging support' printf "%s\n" ' --enable-rng-none dummy RNG, avoid using /dev/(u)random and' printf "%s\n" ' getrandom()' - printf "%s\n" ' --enable-slirp[=CHOICE] Whether and how to find the slirp library' - printf "%s\n" ' (choices: auto/disabled/enabled/internal/system)' printf "%s\n" ' --enable-strip Strip targets on install' printf "%s\n" ' --enable-tcg-interpreter TCG with bytecode interpreter (slow)' printf "%s\n" ' --enable-trace-backends=CHOICES' @@ -141,6 +139,7 @@ meson_options_help() { printf "%s\n" ' sdl-image SDL Image support for icons' printf "%s\n" ' seccomp seccomp support' printf "%s\n" ' selinux SELinux support in qemu-nbd' + printf "%s\n" ' slirp libslirp user mode network backend support' printf "%s\n" ' slirp-smbd use smbd (at path --smbd=*) in slirp networking' printf "%s\n" ' smartcard CA smartcard emulation support' printf "%s\n" ' snappy snappy compression support' @@ -386,7 +385,6 @@ _meson_option_parse() { --disable-selinux) printf "%s" -Dselinux=disabled ;; --enable-slirp) printf "%s" -Dslirp=enabled ;; --disable-slirp) printf "%s" -Dslirp=disabled ;; - --enable-slirp=*) quote_sh "-Dslirp=$2" ;; --enable-slirp-smbd) printf "%s" -Dslirp_smbd=enabled ;; --disable-slirp-smbd) printf "%s" -Dslirp_smbd=disabled ;; --enable-smartcard) printf "%s" -Dsmartcard=enabled ;; diff --git a/slirp b/slirp deleted file mode 160000 index 9d59bb775d..0000000000 --- a/slirp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9d59bb775d6294c8b447a88512f7bb43f12a25a8 From a44558636aed935579701e7805684d1138383c7d Mon Sep 17 00:00:00 2001 From: Wilfred Mallawa Date: Tue, 23 Aug 2022 16:12:00 +1000 Subject: [PATCH 0622/1020] hw/ssi: ibex_spi: fixup typos in ibex_spi_host This patch fixes up minor typos in ibex_spi_host Signed-off-by: Wilfred Mallawa Reviewed-by: Alistair Francis Reviewed-by: Andrew Jones Message-Id: <20220823061201.132342-2-wilfred.mallawa@opensource.wdc.com> Signed-off-by: Alistair Francis --- hw/ssi/ibex_spi_host.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/ssi/ibex_spi_host.c b/hw/ssi/ibex_spi_host.c index d14580b409..601041d719 100644 --- a/hw/ssi/ibex_spi_host.c +++ b/hw/ssi/ibex_spi_host.c @@ -172,7 +172,7 @@ static void ibex_spi_host_irq(IbexSPIHostState *s) & R_INTR_STATE_SPI_EVENT_MASK; int err_irq = 0, event_irq = 0; - /* Error IRQ enabled and Error IRQ Cleared*/ + /* Error IRQ enabled and Error IRQ Cleared */ if (error_en && !err_pending) { /* Event enabled, Interrupt Test Error */ if (s->regs[IBEX_SPI_HOST_INTR_TEST] & R_INTR_TEST_ERROR_MASK) { @@ -434,7 +434,7 @@ static void ibex_spi_host_write(void *opaque, hwaddr addr, case IBEX_SPI_HOST_TXDATA: /* * This is a hardware `feature` where - * the first word written TXDATA after init is omitted entirely + * the first word written to TXDATA after init is omitted entirely */ if (s->init_status) { s->init_status = false; @@ -487,7 +487,7 @@ static void ibex_spi_host_write(void *opaque, hwaddr addr, break; case IBEX_SPI_HOST_ERROR_STATUS: /* - * Indicates that any errors that have occurred. + * Indicates any errors that have occurred. * When an error occurs, the corresponding bit must be cleared * here before issuing any further commands */ From 7a426f83c3192db8006ce29abc702dfa2eb00fc8 Mon Sep 17 00:00:00 2001 From: Wilfred Mallawa Date: Tue, 23 Aug 2022 16:12:04 +1000 Subject: [PATCH 0623/1020] hw/ssi: ibex_spi: update reg addr Updates the `EVENT_ENABLE` register to offset `0x34` as per OpenTitan spec [1]. [1] https://docs.opentitan.org/hw/ip/spi_host/doc/#Reg_event_enable Signed-off-by: Wilfred Mallawa Reviewed-by: Alistair Francis Message-Id: <20220823061201.132342-5-wilfred.mallawa@opensource.wdc.com> Signed-off-by: Alistair Francis --- hw/ssi/ibex_spi_host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/ssi/ibex_spi_host.c b/hw/ssi/ibex_spi_host.c index 601041d719..94d7da9cc2 100644 --- a/hw/ssi/ibex_spi_host.c +++ b/hw/ssi/ibex_spi_host.c @@ -93,7 +93,7 @@ REG32(ERROR_STATUS, 0x30) FIELD(ERROR_STATUS, CMDINVAL, 3, 1) FIELD(ERROR_STATUS, CSIDINVAL, 4, 1) FIELD(ERROR_STATUS, ACCESSINVAL, 5, 1) -REG32(EVENT_ENABLE, 0x30) +REG32(EVENT_ENABLE, 0x34) FIELD(EVENT_ENABLE, RXFULL, 0, 1) FIELD(EVENT_ENABLE, TXEMPTY, 1, 1) FIELD(EVENT_ENABLE, RXWM, 2, 1) From 0c2d4671916333e5b66fd923279fb6fb62315bed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 5 Sep 2022 17:39:39 +0100 Subject: [PATCH 0624/1020] docs/system: clean up code escape for riscv virt platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The example code is rendered slightly mangled due to missing code block. Properly escape the code block and add shell prompt and qemu to fit in with the other examples on the page. Signed-off-by: Alex BennĂ©e Reviewed-by: Alistair Francis Message-Id: <20220905163939.1599368-1-alex.bennee@linaro.org> Signed-off-by: Alistair Francis --- docs/system/riscv/virt.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst index f8ecec95f3..4b16e41d7f 100644 --- a/docs/system/riscv/virt.rst +++ b/docs/system/riscv/virt.rst @@ -168,14 +168,19 @@ Enabling TPM A TPM device can be connected to the virt board by following the steps below. -First launch the TPM emulator +First launch the TPM emulator: - swtpm socket --tpm2 -t -d --tpmstate dir=/tmp/tpm \ +.. code-block:: bash + + $ swtpm socket --tpm2 -t -d --tpmstate dir=/tmp/tpm \ --ctrl type=unixio,path=swtpm-sock -Then launch QEMU with: +Then launch QEMU with some additional arguments to link a TPM device to the backend: - ... +.. code-block:: bash + + $ qemu-system-riscv64 \ + ... other args .... \ -chardev socket,id=chrtpm,path=swtpm-sock \ -tpmdev emulator,id=tpm0,chardev=chrtpm \ -device tpm-tis-device,tpmdev=tpm0 From 513eb437aef7687ad1963d935ffb884fff3c4775 Mon Sep 17 00:00:00 2001 From: Rahul Pathak Date: Wed, 24 Aug 2022 20:22:55 +0530 Subject: [PATCH 0625/1020] target/riscv: Remove sideleg and sedeleg sideleg and sedeleg csrs are not part of riscv isa spec anymore, these csrs were part of N extension which is removed from the riscv isa specification. These commits removed all traces of these csrs from riscv spec (https://github.com/riscv/riscv-isa-manual) - commit f8d27f805b65 ("Remove or downgrade more references to N extension (#674)") commit b6cade07034d ("Remove N extension chapter for now") Signed-off-by: Rahul Pathak Reviewed-by: Andrew Jones Reviewed-by: Alistair Francis Message-Id: <20220824145255.400040-1-rpathak@ventanamicro.com> Signed-off-by: Alistair Francis --- disas/riscv.c | 2 -- target/riscv/cpu_bits.h | 2 -- 2 files changed, 4 deletions(-) diff --git a/disas/riscv.c b/disas/riscv.c index 489c2ae5e8..f107d94c4c 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -1304,8 +1304,6 @@ static const char *csr_name(int csrno) case 0x0043: return "utval"; case 0x0044: return "uip"; case 0x0100: return "sstatus"; - case 0x0102: return "sedeleg"; - case 0x0103: return "sideleg"; case 0x0104: return "sie"; case 0x0105: return "stvec"; case 0x0106: return "scounteren"; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 7be12cac2e..b762807e4e 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -190,8 +190,6 @@ /* Supervisor Trap Setup */ #define CSR_SSTATUS 0x100 -#define CSR_SEDELEG 0x102 -#define CSR_SIDELEG 0x103 #define CSR_SIE 0x104 #define CSR_STVEC 0x105 #define CSR_SCOUNTEREN 0x106 From a412829406905a7edf7a33ded754f89f50a33af1 Mon Sep 17 00:00:00 2001 From: Weiwei Li Date: Wed, 17 Aug 2022 16:37:56 +0800 Subject: [PATCH 0626/1020] target/riscv: fix csr check for cycle{h}, instret{h}, time{h}, hpmcounter3-31{h} - modify check for mcounteren to work in all less-privilege mode - modify check for scounteren to work only when S mode is enabled - distinguish the exception type raised by check for scounteren between U and VU mode Signed-off-by: Weiwei Li Signed-off-by: Junqiang Wang Reviewed-by: Alistair Francis Message-Id: <20220817083756.12471-1-liweiwei@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index b96db1b62b..092b425196 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -98,17 +98,22 @@ static RISCVException ctr(CPURISCVState *env, int csrno) skip_ext_pmu_check: - if (((env->priv == PRV_S) && (!get_field(env->mcounteren, ctr_mask))) || - ((env->priv == PRV_U) && (!get_field(env->scounteren, ctr_mask)))) { + if (env->priv < PRV_M && !get_field(env->mcounteren, ctr_mask)) { return RISCV_EXCP_ILLEGAL_INST; } if (riscv_cpu_virt_enabled(env)) { - if (!get_field(env->hcounteren, ctr_mask) && - get_field(env->mcounteren, ctr_mask)) { + if (!get_field(env->hcounteren, ctr_mask) || + (env->priv == PRV_U && !get_field(env->scounteren, ctr_mask))) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } } + + if (riscv_has_ext(env, RVS) && env->priv == PRV_U && + !get_field(env->scounteren, ctr_mask)) { + return RISCV_EXCP_ILLEGAL_INST; + } + #endif return RISCV_EXCP_NONE; } From 94452ac4cf263e8996613db8d981e4ea85bd019a Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Wed, 31 Aug 2022 09:41:22 +0100 Subject: [PATCH 0627/1020] target/riscv: remove fflags, frm, and fcsr from riscv-*-fpu.xml While testing some changes to GDB's handling for the RISC-V registers fcsr, fflags, and frm, I spotted that QEMU includes these registers twice in the target description it sends to GDB, once in the fpu feature, and once in the csr feature. Right now things basically work OK, QEMU maps these registers onto two different register numbers, e.g. fcsr maps to both 68 and 73, and GDB can use either of these to access the register. However, GDB's target descriptions don't really work this way, each register should appear just once in a target description, mapping the register name onto the number GDB should use when accessing the register on the target. Duplicate register names actually result in duplicate registers on the GDB side, however, as the registers have the same name, the user can only access one of these registers. Currently GDB has a hack in place, specifically for RISC-V, to spot the duplicate copies of these three registers, and hide them from the user, ensuring the user only ever sees a single copy of each. In this commit I propose fixing this issue on the QEMU side, and in the process, simplify the fpu register handling a little. I think we should, remove fflags, frm, and fcsr from the two (32-bit and 64-bit) fpu feature xml files. These files will only contain the 32 core floating point register f0 to f31. The fflags, frm, and fcsr registers will continue to be advertised in the csr feature as they currently are. With that change made, I will simplify riscv_gdb_get_fpu and riscv_gdb_set_fpu, removing the extra handling for the 3 status registers. Signed-off-by: Andrew Burgess Reviewed-by: Alistair Francis Message-Id: <0fbf2a5b12e3210ff3867d5cf7022b3f3462c9c8.1661934573.git.aburgess@redhat.com> Signed-off-by: Alistair Francis --- gdb-xml/riscv-32bit-fpu.xml | 4 ---- gdb-xml/riscv-64bit-fpu.xml | 4 ---- target/riscv/gdbstub.c | 32 ++------------------------------ 3 files changed, 2 insertions(+), 38 deletions(-) diff --git a/gdb-xml/riscv-32bit-fpu.xml b/gdb-xml/riscv-32bit-fpu.xml index 1eaae9119e..84a44ba8df 100644 --- a/gdb-xml/riscv-32bit-fpu.xml +++ b/gdb-xml/riscv-32bit-fpu.xml @@ -43,8 +43,4 @@ - - - - diff --git a/gdb-xml/riscv-64bit-fpu.xml b/gdb-xml/riscv-64bit-fpu.xml index 794854cc01..9856a9d1d3 100644 --- a/gdb-xml/riscv-64bit-fpu.xml +++ b/gdb-xml/riscv-64bit-fpu.xml @@ -49,8 +49,4 @@ - - - - diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 9ed049c29e..9974b7aac6 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -114,20 +114,6 @@ static int riscv_gdb_get_fpu(CPURISCVState *env, GByteArray *buf, int n) if (env->misa_ext & RVF) { return gdb_get_reg32(buf, env->fpr[n]); } - /* there is hole between ft11 and fflags in fpu.xml */ - } else if (n < 36 && n > 32) { - target_ulong val = 0; - int result; - /* - * CSR_FFLAGS is at index 1 in csr_register, and gdb says it is FP - * register 33, so we recalculate the map index. - * This also works for CSR_FRM and CSR_FCSR. - */ - result = riscv_csrrw_debug(env, n - 32, &val, - 0, 0); - if (result == RISCV_EXCP_NONE) { - return gdb_get_regl(buf, val); - } } return 0; } @@ -137,20 +123,6 @@ static int riscv_gdb_set_fpu(CPURISCVState *env, uint8_t *mem_buf, int n) if (n < 32) { env->fpr[n] = ldq_p(mem_buf); /* always 64-bit */ return sizeof(uint64_t); - /* there is hole between ft11 and fflags in fpu.xml */ - } else if (n < 36 && n > 32) { - target_ulong val = ldtul_p(mem_buf); - int result; - /* - * CSR_FFLAGS is at index 1 in csr_register, and gdb says it is FP - * register 33, so we recalculate the map index. - * This also works for CSR_FRM and CSR_FCSR. - */ - result = riscv_csrrw_debug(env, n - 32, NULL, - val, -1); - if (result == RISCV_EXCP_NONE) { - return sizeof(target_ulong); - } } return 0; } @@ -404,10 +376,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) CPURISCVState *env = &cpu->env; if (env->misa_ext & RVD) { gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, - 36, "riscv-64bit-fpu.xml", 0); + 32, "riscv-64bit-fpu.xml", 0); } else if (env->misa_ext & RVF) { gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu, - 36, "riscv-32bit-fpu.xml", 0); + 32, "riscv-32bit-fpu.xml", 0); } if (env->misa_ext & RVV) { gdb_register_coprocessor(cs, riscv_gdb_get_vector, riscv_gdb_set_vector, From 4c0f0b6619126637e802f07c9fe8e9fffbc1c4bb Mon Sep 17 00:00:00 2001 From: Andrew Burgess Date: Wed, 31 Aug 2022 09:41:23 +0100 Subject: [PATCH 0628/1020] target/riscv: remove fixed numbering from GDB xml feature files The fixed register numbering in the various GDB feature files for RISC-V only exists because these files were originally copied from the GDB source tree. However, the fixed numbering only exists in the GDB source tree so that GDB, when it connects to a target that doesn't provide a target description, will use a specific numbering scheme. That numbering scheme is designed to be compatible with the first versions of QEMU (for RISC-V), that didn't send a target description, and relied on a fixed numbering scheme. Because of the way that QEMU manages its target descriptions, recording the number of registers in each feature, and just relying on GDB's numbering starting from 0, then I propose that we remove all the fixed numbering from the RISC-V feature xml files, and just rely on the standard numbering scheme. Plenty of other targets manage their xml files this way, e.g. ARM, AArch64, Loongarch, m68k, rx, and s390. Signed-off-by: Andrew Burgess Acked-by: Alistair Francis Reviewed-by: Palmer Dabbelt Message-Id: <6069395f90e6fc24dac92197be815fedf42f5974.1661934573.git.aburgess@redhat.com> Signed-off-by: Alistair Francis --- gdb-xml/riscv-32bit-cpu.xml | 6 +----- gdb-xml/riscv-32bit-fpu.xml | 6 +----- gdb-xml/riscv-64bit-cpu.xml | 6 +----- gdb-xml/riscv-64bit-fpu.xml | 6 +----- 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/gdb-xml/riscv-32bit-cpu.xml b/gdb-xml/riscv-32bit-cpu.xml index 0d07aaec85..466f2c0648 100644 --- a/gdb-xml/riscv-32bit-cpu.xml +++ b/gdb-xml/riscv-32bit-cpu.xml @@ -5,13 +5,9 @@ are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> - - - + diff --git a/gdb-xml/riscv-32bit-fpu.xml b/gdb-xml/riscv-32bit-fpu.xml index 84a44ba8df..24aa087031 100644 --- a/gdb-xml/riscv-32bit-fpu.xml +++ b/gdb-xml/riscv-32bit-fpu.xml @@ -5,13 +5,9 @@ are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> - - - + diff --git a/gdb-xml/riscv-64bit-cpu.xml b/gdb-xml/riscv-64bit-cpu.xml index b8aa424ae4..c4d83de09b 100644 --- a/gdb-xml/riscv-64bit-cpu.xml +++ b/gdb-xml/riscv-64bit-cpu.xml @@ -5,13 +5,9 @@ are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> - - - + diff --git a/gdb-xml/riscv-64bit-fpu.xml b/gdb-xml/riscv-64bit-fpu.xml index 9856a9d1d3..d0f17f9984 100644 --- a/gdb-xml/riscv-64bit-fpu.xml +++ b/gdb-xml/riscv-64bit-fpu.xml @@ -5,10 +5,6 @@ are permitted in any medium without royalty provided the copyright notice and this notice are preserved. --> - - @@ -17,7 +13,7 @@ - + From 277b210dd86636cc910bf6cd9a5477d01a10603f Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 14 Sep 2022 12:11:06 +0200 Subject: [PATCH 0629/1020] target/riscv: Set the CPU resetvec directly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of using our properties to set a config value which then might be used to set the resetvec (depending on your timing), let's instead just set the resetvec directly in the env struct. This allows us to set the reset vec from the command line with: -global driver=riscv.hart_array,property=resetvec,value=0x20000400 Signed-off-by: Alistair Francis Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220914101108.82571-2-alistair.francis@wdc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 13 +++---------- target/riscv/cpu.h | 3 +-- target/riscv/machine.c | 6 +++--- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index aee14a239a..b29c88b9f0 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -228,13 +228,6 @@ static void set_vext_version(CPURISCVState *env, int vext_ver) env->vext_ver = vext_ver; } -static void set_resetvec(CPURISCVState *env, target_ulong resetvec) -{ -#ifndef CONFIG_USER_ONLY - env->resetvec = resetvec; -#endif -} - static void riscv_any_cpu_init(Object *obj) { CPURISCVState *env = &RISCV_CPU(obj)->env; @@ -336,7 +329,6 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj) set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU); set_priv_version(env, PRIV_VERSION_1_10_0); - set_resetvec(env, DEFAULT_RSTVEC); cpu->cfg.mmu = false; } #endif @@ -676,7 +668,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) riscv_set_feature(env, RISCV_FEATURE_DEBUG); } - set_resetvec(env, cpu->cfg.resetvec); #ifndef CONFIG_USER_ONLY if (cpu->cfg.ext_sstc) { @@ -1079,7 +1070,9 @@ static Property riscv_cpu_properties[] = { DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID), DEFINE_PROP_UINT64("mimpid", RISCVCPU, cfg.mimpid, RISCV_CPU_MIMPID), - DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec, DEFAULT_RSTVEC), +#ifndef CONFIG_USER_ONLY + DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec, DEFAULT_RSTVEC), +#endif DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 06751e1e3e..22344a620b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -190,7 +190,7 @@ struct CPUArchState { /* This contains QEMU specific information about the virt state. */ target_ulong virt; target_ulong geilen; - target_ulong resetvec; + uint64_t resetvec; target_ulong mhartid; /* @@ -474,7 +474,6 @@ struct RISCVCPUConfig { bool pmp; bool epmp; bool debug; - uint64_t resetvec; bool short_isa_string; }; diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 41098f6ad0..c4e6b3bba4 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -308,8 +308,8 @@ static const VMStateDescription vmstate_pmu_ctr_state = { const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", - .version_id = 4, - .minimum_version_id = 4, + .version_id = 5, + .minimum_version_id = 5, .post_load = riscv_cpu_post_load, .fields = (VMStateField[]) { VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), @@ -331,7 +331,7 @@ const VMStateDescription vmstate_riscv_cpu = { VMSTATE_UINT32(env.features, RISCVCPU), VMSTATE_UINTTL(env.priv, RISCVCPU), VMSTATE_UINTTL(env.virt, RISCVCPU), - VMSTATE_UINTTL(env.resetvec, RISCVCPU), + VMSTATE_UINT64(env.resetvec, RISCVCPU), VMSTATE_UINTTL(env.mhartid, RISCVCPU), VMSTATE_UINT64(env.mstatus, RISCVCPU), VMSTATE_UINT64(env.mip, RISCVCPU), From d057aaece7665d49e81ef8d8204b095351253f21 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 14 Sep 2022 12:11:07 +0200 Subject: [PATCH 0630/1020] hw/riscv: opentitan: Fixup resetvec The resetvec for the OpenTitan machine ended up being set to an out of date value, so let's fix that and bump it to the correct start address (after the boot ROM) Fixes: bf8803c64d75 "hw/riscv: opentitan: bump opentitan version" Signed-off-by: Alistair Francis Message-Id: <20220914101108.82571-3-alistair.francis@wdc.com> Signed-off-by: Alistair Francis --- hw/riscv/opentitan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index af13dbe3b1..45c92c9bbc 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -142,7 +142,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) &error_abort); object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, &error_abort); - object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x20000490, + object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x20000400, &error_abort); sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); From a06fded82e9edc471dbbe4321f856040b996b54c Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Wed, 14 Sep 2022 12:11:08 +0200 Subject: [PATCH 0631/1020] hw/riscv: opentitan: Expose the resetvec as a SoC property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On the OpenTitan hardware the resetvec is fixed at the start of ROM. In QEMU we don't run the ROM code and instead just jump to the next stage. This means we need to be a little more flexible about what the resetvec is. This patch allows us to set the resetvec from the command line with something like this: -global driver=riscv.lowrisc.ibex.soc,property=resetvec,value=0x20000400 This way as the next stage changes we can update the resetvec. Signed-off-by: Alistair Francis Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220914101108.82571-4-alistair.francis@wdc.com> Signed-off-by: Alistair Francis --- hw/riscv/opentitan.c | 8 +++++++- include/hw/riscv/opentitan.h | 2 ++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c index 45c92c9bbc..be7ff1eea0 100644 --- a/hw/riscv/opentitan.c +++ b/hw/riscv/opentitan.c @@ -142,7 +142,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) &error_abort); object_property_set_int(OBJECT(&s->cpus), "num-harts", ms->smp.cpus, &error_abort); - object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x20000400, + object_property_set_int(OBJECT(&s->cpus), "resetvec", s->resetvec, &error_abort); sysbus_realize(SYS_BUS_DEVICE(&s->cpus), &error_fatal); @@ -297,10 +297,16 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp) memmap[IBEX_DEV_PERI].base, memmap[IBEX_DEV_PERI].size); } +static Property lowrisc_ibex_soc_props[] = { + DEFINE_PROP_UINT32("resetvec", LowRISCIbexSoCState, resetvec, 0x20000400), + DEFINE_PROP_END_OF_LIST() +}; + static void lowrisc_ibex_soc_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); + device_class_set_props(dc, lowrisc_ibex_soc_props); dc->realize = lowrisc_ibex_soc_realize; /* Reason: Uses serial_hds in realize function, thus can't be used twice */ dc->user_creatable = false; diff --git a/include/hw/riscv/opentitan.h b/include/hw/riscv/opentitan.h index 26d960f288..6665cd5794 100644 --- a/include/hw/riscv/opentitan.h +++ b/include/hw/riscv/opentitan.h @@ -46,6 +46,8 @@ struct LowRISCIbexSoCState { IbexTimerState timer; IbexSPIHostState spi_host[OPENTITAN_NUM_SPI_HOSTS]; + uint32_t resetvec; + MemoryRegion flash_mem; MemoryRegion rom; MemoryRegion flash_alias; From 9e37653b5c73d8e43013ed78ee9d7644f23d146c Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Sun, 18 Sep 2022 16:32:44 +0800 Subject: [PATCH 0632/1020] target/riscv: Check the correct exception cause in vector GDB stub After RISCVException enum is introduced, riscv_csrrw_debug() returns RISCV_EXCP_NONE to indicate there's no error. RISC-V vector GDB stub should check the result against RISCV_EXCP_NONE instead of value 0. Otherwise, 'E14' packet would be incorrectly reported for vector CSRs when using "info reg vector" GDB command. Signed-off-by: Frank Chang Reviewed-by: Jim Shu Reviewed-by: Tommy Wu Reviewed-by: Alistair Francis Reviewed-by: LIU Zhiwei Message-Id: <20220918083245.13028-1-frank.chang@sifive.com> Signed-off-by: Alistair Francis --- target/riscv/gdbstub.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 9974b7aac6..6e7bbdbd5e 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -183,7 +183,7 @@ static int riscv_gdb_get_vector(CPURISCVState *env, GByteArray *buf, int n) target_ulong val = 0; int result = riscv_csrrw_debug(env, csrno, &val, 0, 0); - if (result == 0) { + if (result == RISCV_EXCP_NONE) { return gdb_get_regl(buf, val); } @@ -210,7 +210,7 @@ static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t *mem_buf, int n) target_ulong val = ldtul_p(mem_buf); int result = riscv_csrrw_debug(env, csrno, NULL, val, -1); - if (result == 0) { + if (result == RISCV_EXCP_NONE) { return sizeof(target_ulong); } From 9dfa6c2aec299fda9946c327e889087365a715b5 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Thu, 22 Sep 2022 09:52:32 +0200 Subject: [PATCH 0633/1020] hw/riscv/sifive_e: Fix inheritance of SiFiveEState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SiFiveEState inherits from SysBusDevice while it's TypeInfo claims it to inherit from TYPE_MACHINE. This is an inconsistency which can cause undefined behavior such as memory corruption. Change SiFiveEState to inherit from MachineState since it is registered as a machine. Fixes: 0869490b1c ("riscv: sifive_e: Manually define the machine") Signed-off-by: Bernhard Beschow Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220922075232.33653-1-shentey@gmail.com> Signed-off-by: Alistair Francis --- include/hw/riscv/sifive_e.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h index 83604da805..d738745925 100644 --- a/include/hw/riscv/sifive_e.h +++ b/include/hw/riscv/sifive_e.h @@ -22,6 +22,7 @@ #include "hw/riscv/riscv_hart.h" #include "hw/riscv/sifive_cpu.h" #include "hw/gpio/sifive_gpio.h" +#include "hw/boards.h" #define TYPE_RISCV_E_SOC "riscv.sifive.e.soc" #define RISCV_E_SOC(obj) \ @@ -41,7 +42,7 @@ typedef struct SiFiveESoCState { typedef struct SiFiveEState { /*< private >*/ - SysBusDevice parent_obj; + MachineState parent_obj; /*< public >*/ SiFiveESoCState soc; From 2dc7bf63cf77d23b287c8d78628d62046fba1bf4 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sun, 25 Sep 2022 14:48:03 +0100 Subject: [PATCH 0634/1020] target/m68k: increase size of m68k CPU features from uint32_t to uint64_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are already 32 feature bits in use, so change the size of the m68k CPU features to uint64_t (along with the associated m68k_feature() functions) to allow up to 64 feature bits to be used. At the same time make use of the BIT_ULL() macro when reading/writing the CPU feature bits to improve readability, and also update m68k_feature() to return a bool rather than an int. Signed-off-by: Mark Cave-Ayland Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220925134804.139706-2-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier --- target/m68k/cpu.c | 4 ++-- target/m68k/cpu.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index f681be3a2a..8d23c72056 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -38,12 +38,12 @@ static bool m68k_cpu_has_work(CPUState *cs) static void m68k_set_feature(CPUM68KState *env, int feature) { - env->features |= (1u << feature); + env->features |= BIT_ULL(feature); } static void m68k_unset_feature(CPUM68KState *env, int feature) { - env->features &= (-1u - (1u << feature)); + env->features &= ~BIT_ULL(feature); } static void m68k_cpu_reset(DeviceState *dev) diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index 67b6c12c28..f5c6e95cb4 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -154,7 +154,7 @@ typedef struct CPUArchState { struct {} end_reset_fields; /* Fields from here on are preserved across CPU reset. */ - uint32_t features; + uint64_t features; } CPUM68KState; /* @@ -539,9 +539,9 @@ enum m68k_features { M68K_FEATURE_TRAPCC, }; -static inline int m68k_feature(CPUM68KState *env, int feature) +static inline bool m68k_feature(CPUM68KState *env, int feature) { - return (env->features & (1u << feature)) != 0; + return (env->features & BIT_ULL(feature)) != 0; } void m68k_cpu_list(void); From b342e56b23dc2a0a1f30e21d67d001a1d0befbf0 Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sun, 25 Sep 2022 14:48:04 +0100 Subject: [PATCH 0635/1020] target/m68k: use M68K_FEATURE_MOVEFROMSR_PRIV feature for move_from_sr privilege check Now that M68K_FEATURE_M68000 has been renamed to M68K_FEATURE_M68K it is easier to see that the privilege exception check is wrong: it is currently only generated for ColdFire CPUs when in fact it should also be generated for Motorola CPUs from the 68010 onwards. Introduce a new M68K_FEATURE_MOVEFROMSR_PRIV feature which is set for all non- Motorola CPUs, and for all Motorola CPUs from the 68010 onwards and use it to determine whether a privilege exception should be generated for the MOVE-from-SR instruction. Signed-off-by: Mark Cave-Ayland Reviewed-by: Richard Henderson Message-Id: <20220925134804.139706-3-mark.cave-ayland@ilande.co.uk> Signed-off-by: Laurent Vivier --- target/m68k/cpu.c | 5 +++++ target/m68k/cpu.h | 2 ++ target/m68k/translate.c | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 8d23c72056..25d610db21 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -102,6 +102,7 @@ static void m5206_cpu_initfn(Object *obj) CPUM68KState *env = &cpu->env; m68k_set_feature(env, M68K_FEATURE_CF_ISA_A); + m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); } /* Base feature set, including isns. for m68k family */ @@ -129,6 +130,7 @@ static void m68010_cpu_initfn(Object *obj) m68k_set_feature(env, M68K_FEATURE_RTD); m68k_set_feature(env, M68K_FEATURE_BKPT); m68k_set_feature(env, M68K_FEATURE_MOVEC); + m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); } /* @@ -241,6 +243,7 @@ static void m5208_cpu_initfn(Object *obj) m68k_set_feature(env, M68K_FEATURE_BRAL); m68k_set_feature(env, M68K_FEATURE_CF_EMAC); m68k_set_feature(env, M68K_FEATURE_USP); + m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); } static void cfv4e_cpu_initfn(Object *obj) @@ -254,6 +257,7 @@ static void cfv4e_cpu_initfn(Object *obj) m68k_set_feature(env, M68K_FEATURE_CF_FPU); m68k_set_feature(env, M68K_FEATURE_CF_EMAC); m68k_set_feature(env, M68K_FEATURE_USP); + m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); } static void any_cpu_initfn(Object *obj) @@ -275,6 +279,7 @@ static void any_cpu_initfn(Object *obj) m68k_set_feature(env, M68K_FEATURE_USP); m68k_set_feature(env, M68K_FEATURE_EXT_FULL); m68k_set_feature(env, M68K_FEATURE_WORD_INDEX); + m68k_set_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV); } static void m68k_cpu_realizefn(DeviceState *dev, Error **errp) diff --git a/target/m68k/cpu.h b/target/m68k/cpu.h index f5c6e95cb4..3a9cfe2f33 100644 --- a/target/m68k/cpu.h +++ b/target/m68k/cpu.h @@ -537,6 +537,8 @@ enum m68k_features { M68K_FEATURE_UNALIGNED_DATA, /* TRAPcc insn. (680[2346]0, and CPU32) */ M68K_FEATURE_TRAPCC, + /* MOVE from SR privileged (from 68010) */ + M68K_FEATURE_MOVEFROMSR_PRIV, }; static inline bool m68k_feature(CPUM68KState *env, int feature) diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 233b9d8e57..9df17aa4b2 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -4624,7 +4624,7 @@ DISAS_INSN(move_from_sr) { TCGv sr; - if (IS_USER(s) && !m68k_feature(env, M68K_FEATURE_M68K)) { + if (IS_USER(s) && m68k_feature(env, M68K_FEATURE_MOVEFROMSR_PRIV)) { gen_exception(s, s->base.pc_next, EXCP_PRIVILEGE); return; } From 2cfa963126fe77fac034a43f986b2bf3e8fe6a4f Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Mon, 26 Sep 2022 13:39:00 +0200 Subject: [PATCH 0636/1020] m68k: align bootinfo strings and data to 4 bytes Various tools, such as kexec-tools and m68k-bootinfo, expect each bootinfo entry to be aligned to 4 bytes, not 2 bytes. So adjust the padding to fill this out as such. Also, break apart the padding additions from the other field length additions, so that it's more clear why these magic numbers are being added, and comment them too. Reported-by: Geert Uytterhoeven Cc: Laurent Vivier Signed-off-by: Jason A. Donenfeld Reviewed-by: Laurent Vivier Message-Id: <20220926113900.1256630-2-Jason@zx2c4.com> Signed-off-by: Laurent Vivier --- hw/m68k/bootinfo.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/hw/m68k/bootinfo.h b/hw/m68k/bootinfo.h index bd8b212fd3..897162b818 100644 --- a/hw/m68k/bootinfo.h +++ b/hw/m68k/bootinfo.h @@ -48,13 +48,14 @@ stw_phys(as, base, id); \ base += 2; \ stw_phys(as, base, \ - (sizeof(struct bi_record) + strlen(string) + 2) & ~1); \ + (sizeof(struct bi_record) + strlen(string) + \ + 1 /* null termination */ + 3 /* padding */) & ~3); \ base += 2; \ for (i = 0; string[i]; i++) { \ stb_phys(as, base++, string[i]); \ } \ stb_phys(as, base++, 0); \ - base = (base + 1) & ~1; \ + base = (base + 3) & ~3; \ } while (0) #define BOOTINFODATA(as, base, id, data, len) \ @@ -63,13 +64,14 @@ stw_phys(as, base, id); \ base += 2; \ stw_phys(as, base, \ - (sizeof(struct bi_record) + len + 3) & ~1); \ + (sizeof(struct bi_record) + len + \ + 2 /* length field */ + 3 /* padding */) & ~3); \ base += 2; \ stw_phys(as, base, len); \ base += 2; \ for (i = 0; i < len; ++i) { \ stb_phys(as, base++, data[i]); \ } \ - base = (base + 1) & ~1; \ + base = (base + 3) & ~3; \ } while (0) #endif From a42bd0016654cafd6ca8ca4dbb82fc921ca19ae4 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 9 Sep 2022 21:42:08 +0800 Subject: [PATCH 0637/1020] target/riscv: debug: Determine the trigger type from tdata1.type Current RISC-V debug assumes that only type 2 trigger is supported. To allow more types of triggers to be supported in the future (e.g. type 6 trigger, which is similar to type 2 trigger with additional functionality), we should determine the trigger type from tdata1.type. RV_MAX_TRIGGERS is also introduced in replacement of TRIGGER_TYPE2_NUM. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Signed-off-by: Bin Meng Reviewed-by: LIU Zhiwei [bmeng: fixed MXL_RV128 case, and moved macros to the following patch] Signed-off-by: Bin Meng Message-Id: <20220909134215.1843865-2-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 2 +- target/riscv/csr.c | 2 +- target/riscv/debug.c | 186 +++++++++++++++++++++++++++++------------ target/riscv/debug.h | 13 +-- target/riscv/machine.c | 2 +- 5 files changed, 139 insertions(+), 66 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 22344a620b..73bcad3c9b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -324,7 +324,7 @@ struct CPUArchState { /* trigger module */ target_ulong trigger_cur; - type2_trigger_t type2_trig[TRIGGER_TYPE2_NUM]; + type2_trigger_t type2_trig[RV_MAX_TRIGGERS]; /* machine specific rdtime callback */ uint64_t (*rdtime_fn)(void *); diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 092b425196..2c84c29bf0 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3070,7 +3070,7 @@ static RISCVException read_tdata(CPURISCVState *env, int csrno, target_ulong *val) { /* return 0 in tdata1 to end the trigger enumeration */ - if (env->trigger_cur >= TRIGGER_NUM && csrno == CSR_TDATA1) { + if (env->trigger_cur >= RV_MAX_TRIGGERS && csrno == CSR_TDATA1) { *val = 0; return RISCV_EXCP_NONE; } diff --git a/target/riscv/debug.c b/target/riscv/debug.c index fc6e13222f..9dd468753a 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -52,8 +52,15 @@ /* tdata availability of a trigger */ typedef bool tdata_avail[TDATA_NUM]; -static tdata_avail tdata_mapping[TRIGGER_NUM] = { - [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = { true, true, false }, +static tdata_avail tdata_mapping[TRIGGER_TYPE_NUM] = { + [TRIGGER_TYPE_NO_EXIST] = { false, false, false }, + [TRIGGER_TYPE_AD_MATCH] = { true, true, true }, + [TRIGGER_TYPE_INST_CNT] = { true, false, true }, + [TRIGGER_TYPE_INT] = { true, true, true }, + [TRIGGER_TYPE_EXCP] = { true, true, true }, + [TRIGGER_TYPE_AD_MATCH6] = { true, true, true }, + [TRIGGER_TYPE_EXT_SRC] = { true, false, false }, + [TRIGGER_TYPE_UNAVAIL] = { true, true, true } }; /* only breakpoint size 1/2/4/8 supported */ @@ -67,6 +74,27 @@ static int access_size[SIZE_NUM] = { [6 ... 15] = -1, }; +static inline target_ulong extract_trigger_type(CPURISCVState *env, + target_ulong tdata1) +{ + switch (riscv_cpu_mxl(env)) { + case MXL_RV32: + return extract32(tdata1, 28, 4); + case MXL_RV64: + case MXL_RV128: + return extract64(tdata1, 60, 4); + default: + g_assert_not_reached(); + } +} + +static inline target_ulong get_trigger_type(CPURISCVState *env, + target_ulong trigger_index) +{ + target_ulong tdata1 = env->type2_trig[trigger_index].mcontrol; + return extract_trigger_type(env, tdata1); +} + static inline target_ulong trigger_type(CPURISCVState *env, trigger_type_t type) { @@ -89,15 +117,17 @@ static inline target_ulong trigger_type(CPURISCVState *env, bool tdata_available(CPURISCVState *env, int tdata_index) { + int trigger_type = get_trigger_type(env, env->trigger_cur); + if (unlikely(tdata_index >= TDATA_NUM)) { return false; } - if (unlikely(env->trigger_cur >= TRIGGER_NUM)) { + if (unlikely(env->trigger_cur >= RV_MAX_TRIGGERS)) { return false; } - return tdata_mapping[env->trigger_cur][tdata_index]; + return tdata_mapping[trigger_type][tdata_index]; } target_ulong tselect_csr_read(CPURISCVState *env) @@ -137,6 +167,7 @@ static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val, qemu_log_mask(LOG_GUEST_ERROR, "ignoring type write to tdata1 register\n"); } + if (dmode != 0) { qemu_log_mask(LOG_UNIMP, "debug mode is not supported\n"); } @@ -261,9 +292,8 @@ static void type2_breakpoint_remove(CPURISCVState *env, target_ulong index) } static target_ulong type2_reg_read(CPURISCVState *env, - target_ulong trigger_index, int tdata_index) + target_ulong index, int tdata_index) { - uint32_t index = trigger_index - TRIGGER_TYPE2_IDX_0; target_ulong tdata; switch (tdata_index) { @@ -280,10 +310,9 @@ static target_ulong type2_reg_read(CPURISCVState *env, return tdata; } -static void type2_reg_write(CPURISCVState *env, target_ulong trigger_index, +static void type2_reg_write(CPURISCVState *env, target_ulong index, int tdata_index, target_ulong val) { - uint32_t index = trigger_index - TRIGGER_TYPE2_IDX_0; target_ulong new_val; switch (tdata_index) { @@ -309,35 +338,64 @@ static void type2_reg_write(CPURISCVState *env, target_ulong trigger_index, return; } -typedef target_ulong (*tdata_read_func)(CPURISCVState *env, - target_ulong trigger_index, - int tdata_index); - -static tdata_read_func trigger_read_funcs[TRIGGER_NUM] = { - [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = type2_reg_read, -}; - -typedef void (*tdata_write_func)(CPURISCVState *env, - target_ulong trigger_index, - int tdata_index, - target_ulong val); - -static tdata_write_func trigger_write_funcs[TRIGGER_NUM] = { - [TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = type2_reg_write, -}; - target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index) { - tdata_read_func read_func = trigger_read_funcs[env->trigger_cur]; + int trigger_type = get_trigger_type(env, env->trigger_cur); - return read_func(env, env->trigger_cur, tdata_index); + switch (trigger_type) { + case TRIGGER_TYPE_AD_MATCH: + return type2_reg_read(env, env->trigger_cur, tdata_index); + break; + case TRIGGER_TYPE_INST_CNT: + case TRIGGER_TYPE_INT: + case TRIGGER_TYPE_EXCP: + case TRIGGER_TYPE_AD_MATCH6: + case TRIGGER_TYPE_EXT_SRC: + qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n", + trigger_type); + break; + case TRIGGER_TYPE_NO_EXIST: + case TRIGGER_TYPE_UNAVAIL: + qemu_log_mask(LOG_GUEST_ERROR, "trigger type: %d does not exit\n", + trigger_type); + break; + default: + g_assert_not_reached(); + } + + return 0; } void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val) { - tdata_write_func write_func = trigger_write_funcs[env->trigger_cur]; + int trigger_type; - return write_func(env, env->trigger_cur, tdata_index, val); + if (tdata_index == TDATA1) { + trigger_type = extract_trigger_type(env, val); + } else { + trigger_type = get_trigger_type(env, env->trigger_cur); + } + + switch (trigger_type) { + case TRIGGER_TYPE_AD_MATCH: + type2_reg_write(env, env->trigger_cur, tdata_index, val); + break; + case TRIGGER_TYPE_INST_CNT: + case TRIGGER_TYPE_INT: + case TRIGGER_TYPE_EXCP: + case TRIGGER_TYPE_AD_MATCH6: + case TRIGGER_TYPE_EXT_SRC: + qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n", + trigger_type); + break; + case TRIGGER_TYPE_NO_EXIST: + case TRIGGER_TYPE_UNAVAIL: + qemu_log_mask(LOG_GUEST_ERROR, "trigger type: %d does not exit\n", + trigger_type); + break; + default: + g_assert_not_reached(); + } } void riscv_cpu_debug_excp_handler(CPUState *cs) @@ -364,18 +422,28 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs) CPUBreakpoint *bp; target_ulong ctrl; target_ulong pc; + int trigger_type; int i; QTAILQ_FOREACH(bp, &cs->breakpoints, entry) { - for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { - ctrl = env->type2_trig[i].mcontrol; - pc = env->type2_trig[i].maddress; + for (i = 0; i < RV_MAX_TRIGGERS; i++) { + trigger_type = get_trigger_type(env, i); - if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) { - /* check U/S/M bit against current privilege level */ - if ((ctrl >> 3) & BIT(env->priv)) { - return true; + switch (trigger_type) { + case TRIGGER_TYPE_AD_MATCH: + ctrl = env->type2_trig[i].mcontrol; + pc = env->type2_trig[i].maddress; + + if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) { + /* check U/S/M bit against current privilege level */ + if ((ctrl >> 3) & BIT(env->priv)) { + return true; + } } + break; + default: + /* other trigger types are not supported or irrelevant */ + break; } } } @@ -389,26 +457,36 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) CPURISCVState *env = &cpu->env; target_ulong ctrl; target_ulong addr; + int trigger_type; int flags; int i; - for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { - ctrl = env->type2_trig[i].mcontrol; - addr = env->type2_trig[i].maddress; - flags = 0; + for (i = 0; i < RV_MAX_TRIGGERS; i++) { + trigger_type = get_trigger_type(env, i); - if (ctrl & TYPE2_LOAD) { - flags |= BP_MEM_READ; - } - if (ctrl & TYPE2_STORE) { - flags |= BP_MEM_WRITE; - } + switch (trigger_type) { + case TRIGGER_TYPE_AD_MATCH: + ctrl = env->type2_trig[i].mcontrol; + addr = env->type2_trig[i].maddress; + flags = 0; - if ((wp->flags & flags) && (wp->vaddr == addr)) { - /* check U/S/M bit against current privilege level */ - if ((ctrl >> 3) & BIT(env->priv)) { - return true; + if (ctrl & TYPE2_LOAD) { + flags |= BP_MEM_READ; } + if (ctrl & TYPE2_STORE) { + flags |= BP_MEM_WRITE; + } + + if ((wp->flags & flags) && (wp->vaddr == addr)) { + /* check U/S/M bit against current privilege level */ + if ((ctrl >> 3) & BIT(env->priv)) { + return true; + } + } + break; + default: + /* other trigger types are not supported */ + break; } } @@ -417,11 +495,11 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) void riscv_trigger_init(CPURISCVState *env) { - target_ulong type2 = trigger_type(env, TRIGGER_TYPE_AD_MATCH); + target_ulong tdata1 = trigger_type(env, TRIGGER_TYPE_AD_MATCH); int i; - /* type 2 triggers */ - for (i = 0; i < TRIGGER_TYPE2_NUM; i++) { + /* init to type 2 triggers */ + for (i = 0; i < RV_MAX_TRIGGERS; i++) { /* * type = TRIGGER_TYPE_AD_MATCH * dmode = 0 (both debug and M-mode can write tdata) @@ -435,7 +513,7 @@ void riscv_trigger_init(CPURISCVState *env) * chain = 0 (unimplemented, always 0) * match = 0 (always 0, when any compare value equals tdata2) */ - env->type2_trig[i].mcontrol = type2; + env->type2_trig[i].mcontrol = tdata1; env->type2_trig[i].maddress = 0; env->type2_trig[i].bp = NULL; env->type2_trig[i].wp = NULL; diff --git a/target/riscv/debug.h b/target/riscv/debug.h index 27b9cac6b4..72e4edcd8c 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -22,13 +22,7 @@ #ifndef RISCV_DEBUG_H #define RISCV_DEBUG_H -/* trigger indexes implemented */ -enum { - TRIGGER_TYPE2_IDX_0 = 0, - TRIGGER_TYPE2_IDX_1, - TRIGGER_TYPE2_NUM, - TRIGGER_NUM = TRIGGER_TYPE2_NUM -}; +#define RV_MAX_TRIGGERS 2 /* register index of tdata CSRs */ enum { @@ -46,7 +40,8 @@ typedef enum { TRIGGER_TYPE_EXCP = 5, /* exception trigger */ TRIGGER_TYPE_AD_MATCH6 = 6, /* new address/data match trigger */ TRIGGER_TYPE_EXT_SRC = 7, /* external source trigger */ - TRIGGER_TYPE_UNAVAIL = 15 /* trigger exists, but unavailable */ + TRIGGER_TYPE_UNAVAIL = 15, /* trigger exists, but unavailable */ + TRIGGER_TYPE_NUM } trigger_type_t; typedef struct { @@ -56,7 +51,7 @@ typedef struct { struct CPUWatchpoint *wp; } type2_trigger_t; -/* tdata field masks */ +/* tdata1 field masks */ #define RV32_TYPE(t) ((uint32_t)(t) << 28) #define RV32_TYPE_MASK (0xf << 28) diff --git a/target/riscv/machine.c b/target/riscv/machine.c index c4e6b3bba4..a23cff4424 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -247,7 +247,7 @@ static const VMStateDescription vmstate_debug = { .needed = debug_needed, .fields = (VMStateField[]) { VMSTATE_UINTTL(env.trigger_cur, RISCVCPU), - VMSTATE_STRUCT_ARRAY(env.type2_trig, RISCVCPU, TRIGGER_TYPE2_NUM, + VMSTATE_STRUCT_ARRAY(env.type2_trig, RISCVCPU, RV_MAX_TRIGGERS, 0, vmstate_debug_type2, type2_trigger_t), VMSTATE_END_OF_LIST() } From 9d5a84db91f12bd843206a57e0cde01e6a9d488d Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 9 Sep 2022 21:42:09 +0800 Subject: [PATCH 0638/1020] target/riscv: debug: Introduce build_tdata1() to build tdata1 register content Introduce build_tdata1() to build tdata1 register content, which can be shared among all types of triggers. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Signed-off-by: Bin Meng Reviewed-by: LIU Zhiwei [bmeng: moved RV{32,64}_DATA_MASK definition to this patch] Signed-off-by: Bin Meng Message-Id: <20220909134215.1843865-3-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/debug.c | 15 ++++++++++----- target/riscv/debug.h | 2 ++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 9dd468753a..45aae87ec3 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -95,18 +95,23 @@ static inline target_ulong get_trigger_type(CPURISCVState *env, return extract_trigger_type(env, tdata1); } -static inline target_ulong trigger_type(CPURISCVState *env, - trigger_type_t type) +static inline target_ulong build_tdata1(CPURISCVState *env, + trigger_type_t type, + bool dmode, target_ulong data) { target_ulong tdata1; switch (riscv_cpu_mxl(env)) { case MXL_RV32: - tdata1 = RV32_TYPE(type); + tdata1 = RV32_TYPE(type) | + (dmode ? RV32_DMODE : 0) | + (data & RV32_DATA_MASK); break; case MXL_RV64: case MXL_RV128: - tdata1 = RV64_TYPE(type); + tdata1 = RV64_TYPE(type) | + (dmode ? RV64_DMODE : 0) | + (data & RV64_DATA_MASK); break; default: g_assert_not_reached(); @@ -495,7 +500,7 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) void riscv_trigger_init(CPURISCVState *env) { - target_ulong tdata1 = trigger_type(env, TRIGGER_TYPE_AD_MATCH); + target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0); int i; /* init to type 2 triggers */ diff --git a/target/riscv/debug.h b/target/riscv/debug.h index 72e4edcd8c..c422553c27 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -56,9 +56,11 @@ typedef struct { #define RV32_TYPE(t) ((uint32_t)(t) << 28) #define RV32_TYPE_MASK (0xf << 28) #define RV32_DMODE BIT(27) +#define RV32_DATA_MASK 0x7ffffff #define RV64_TYPE(t) ((uint64_t)(t) << 60) #define RV64_TYPE_MASK (0xfULL << 60) #define RV64_DMODE BIT_ULL(59) +#define RV64_DATA_MASK 0x7ffffffffffffff /* mcontrol field masks */ From 9495c4888a80809ab9dba6d6e536b21c018c77a4 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 9 Sep 2022 21:42:10 +0800 Subject: [PATCH 0639/1020] target/riscv: debug: Introduce tdata1, tdata2, and tdata3 CSRs Replace type2_trigger_t with the real tdata1, tdata2, and tdata3 CSRs, which allows us to support more types of triggers in the future. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Signed-off-by: Bin Meng Reviewed-by: LIU Zhiwei Message-Id: <20220909134215.1843865-4-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 6 ++- target/riscv/debug.c | 103 +++++++++++++++-------------------------- target/riscv/debug.h | 7 --- target/riscv/machine.c | 20 ++------ 4 files changed, 48 insertions(+), 88 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 73bcad3c9b..b131fa8c8e 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -324,7 +324,11 @@ struct CPUArchState { /* trigger module */ target_ulong trigger_cur; - type2_trigger_t type2_trig[RV_MAX_TRIGGERS]; + target_ulong tdata1[RV_MAX_TRIGGERS]; + target_ulong tdata2[RV_MAX_TRIGGERS]; + target_ulong tdata3[RV_MAX_TRIGGERS]; + struct CPUBreakpoint *cpu_breakpoint[RV_MAX_TRIGGERS]; + struct CPUWatchpoint *cpu_watchpoint[RV_MAX_TRIGGERS]; /* machine specific rdtime callback */ uint64_t (*rdtime_fn)(void *); diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 45aae87ec3..06feef7d67 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -91,8 +91,7 @@ static inline target_ulong extract_trigger_type(CPURISCVState *env, static inline target_ulong get_trigger_type(CPURISCVState *env, target_ulong trigger_index) { - target_ulong tdata1 = env->type2_trig[trigger_index].mcontrol; - return extract_trigger_type(env, tdata1); + return extract_trigger_type(env, env->tdata1[trigger_index]); } static inline target_ulong build_tdata1(CPURISCVState *env, @@ -188,6 +187,8 @@ static inline void warn_always_zero_bit(target_ulong val, target_ulong mask, } } +/* type 2 trigger */ + static uint32_t type2_breakpoint_size(CPURISCVState *env, target_ulong ctrl) { uint32_t size, sizelo, sizehi = 0; @@ -247,8 +248,8 @@ static target_ulong type2_mcontrol_validate(CPURISCVState *env, static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index) { - target_ulong ctrl = env->type2_trig[index].mcontrol; - target_ulong addr = env->type2_trig[index].maddress; + target_ulong ctrl = env->tdata1[index]; + target_ulong addr = env->tdata2[index]; bool enabled = type2_breakpoint_enabled(ctrl); CPUState *cs = env_cpu(env); int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; @@ -259,7 +260,7 @@ static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index) } if (ctrl & TYPE2_EXEC) { - cpu_breakpoint_insert(cs, addr, flags, &env->type2_trig[index].bp); + cpu_breakpoint_insert(cs, addr, flags, &env->cpu_breakpoint[index]); } if (ctrl & TYPE2_LOAD) { @@ -273,10 +274,10 @@ static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index) size = type2_breakpoint_size(env, ctrl); if (size != 0) { cpu_watchpoint_insert(cs, addr, size, flags, - &env->type2_trig[index].wp); + &env->cpu_watchpoint[index]); } else { cpu_watchpoint_insert(cs, addr, 8, flags, - &env->type2_trig[index].wp); + &env->cpu_watchpoint[index]); } } } @@ -285,36 +286,17 @@ static void type2_breakpoint_remove(CPURISCVState *env, target_ulong index) { CPUState *cs = env_cpu(env); - if (env->type2_trig[index].bp) { - cpu_breakpoint_remove_by_ref(cs, env->type2_trig[index].bp); - env->type2_trig[index].bp = NULL; + if (env->cpu_breakpoint[index]) { + cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]); + env->cpu_breakpoint[index] = NULL; } - if (env->type2_trig[index].wp) { - cpu_watchpoint_remove_by_ref(cs, env->type2_trig[index].wp); - env->type2_trig[index].wp = NULL; + if (env->cpu_watchpoint[index]) { + cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]); + env->cpu_watchpoint[index] = NULL; } } -static target_ulong type2_reg_read(CPURISCVState *env, - target_ulong index, int tdata_index) -{ - target_ulong tdata; - - switch (tdata_index) { - case TDATA1: - tdata = env->type2_trig[index].mcontrol; - break; - case TDATA2: - tdata = env->type2_trig[index].maddress; - break; - default: - g_assert_not_reached(); - } - - return tdata; -} - static void type2_reg_write(CPURISCVState *env, target_ulong index, int tdata_index, target_ulong val) { @@ -323,19 +305,23 @@ static void type2_reg_write(CPURISCVState *env, target_ulong index, switch (tdata_index) { case TDATA1: new_val = type2_mcontrol_validate(env, val); - if (new_val != env->type2_trig[index].mcontrol) { - env->type2_trig[index].mcontrol = new_val; + if (new_val != env->tdata1[index]) { + env->tdata1[index] = new_val; type2_breakpoint_remove(env, index); type2_breakpoint_insert(env, index); } break; case TDATA2: - if (val != env->type2_trig[index].maddress) { - env->type2_trig[index].maddress = val; + if (val != env->tdata2[index]) { + env->tdata2[index] = val; type2_breakpoint_remove(env, index); type2_breakpoint_insert(env, index); } break; + case TDATA3: + qemu_log_mask(LOG_UNIMP, + "tdata3 is not supported for type 2 trigger\n"); + break; default: g_assert_not_reached(); } @@ -345,30 +331,16 @@ static void type2_reg_write(CPURISCVState *env, target_ulong index, target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index) { - int trigger_type = get_trigger_type(env, env->trigger_cur); - - switch (trigger_type) { - case TRIGGER_TYPE_AD_MATCH: - return type2_reg_read(env, env->trigger_cur, tdata_index); - break; - case TRIGGER_TYPE_INST_CNT: - case TRIGGER_TYPE_INT: - case TRIGGER_TYPE_EXCP: - case TRIGGER_TYPE_AD_MATCH6: - case TRIGGER_TYPE_EXT_SRC: - qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n", - trigger_type); - break; - case TRIGGER_TYPE_NO_EXIST: - case TRIGGER_TYPE_UNAVAIL: - qemu_log_mask(LOG_GUEST_ERROR, "trigger type: %d does not exit\n", - trigger_type); - break; + switch (tdata_index) { + case TDATA1: + return env->tdata1[env->trigger_cur]; + case TDATA2: + return env->tdata2[env->trigger_cur]; + case TDATA3: + return env->tdata3[env->trigger_cur]; default: g_assert_not_reached(); } - - return 0; } void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val) @@ -436,8 +408,8 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs) switch (trigger_type) { case TRIGGER_TYPE_AD_MATCH: - ctrl = env->type2_trig[i].mcontrol; - pc = env->type2_trig[i].maddress; + ctrl = env->tdata1[i]; + pc = env->tdata2[i]; if ((ctrl & TYPE2_EXEC) && (bp->pc == pc)) { /* check U/S/M bit against current privilege level */ @@ -471,8 +443,8 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) switch (trigger_type) { case TRIGGER_TYPE_AD_MATCH: - ctrl = env->type2_trig[i].mcontrol; - addr = env->type2_trig[i].maddress; + ctrl = env->tdata1[i]; + addr = env->tdata2[i]; flags = 0; if (ctrl & TYPE2_LOAD) { @@ -518,9 +490,10 @@ void riscv_trigger_init(CPURISCVState *env) * chain = 0 (unimplemented, always 0) * match = 0 (always 0, when any compare value equals tdata2) */ - env->type2_trig[i].mcontrol = tdata1; - env->type2_trig[i].maddress = 0; - env->type2_trig[i].bp = NULL; - env->type2_trig[i].wp = NULL; + env->tdata1[i] = tdata1; + env->tdata2[i] = 0; + env->tdata3[i] = 0; + env->cpu_breakpoint[i] = NULL; + env->cpu_watchpoint[i] = NULL; } } diff --git a/target/riscv/debug.h b/target/riscv/debug.h index c422553c27..76146f373a 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -44,13 +44,6 @@ typedef enum { TRIGGER_TYPE_NUM } trigger_type_t; -typedef struct { - target_ulong mcontrol; - target_ulong maddress; - struct CPUBreakpoint *bp; - struct CPUWatchpoint *wp; -} type2_trigger_t; - /* tdata1 field masks */ #define RV32_TYPE(t) ((uint32_t)(t) << 28) diff --git a/target/riscv/machine.c b/target/riscv/machine.c index a23cff4424..c2a94a82b3 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -229,26 +229,16 @@ static bool debug_needed(void *opaque) return riscv_feature(env, RISCV_FEATURE_DEBUG); } -static const VMStateDescription vmstate_debug_type2 = { - .name = "cpu/debug/type2", - .version_id = 1, - .minimum_version_id = 1, - .fields = (VMStateField[]) { - VMSTATE_UINTTL(mcontrol, type2_trigger_t), - VMSTATE_UINTTL(maddress, type2_trigger_t), - VMSTATE_END_OF_LIST() - } -}; - static const VMStateDescription vmstate_debug = { .name = "cpu/debug", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .needed = debug_needed, .fields = (VMStateField[]) { VMSTATE_UINTTL(env.trigger_cur, RISCVCPU), - VMSTATE_STRUCT_ARRAY(env.type2_trig, RISCVCPU, RV_MAX_TRIGGERS, - 0, vmstate_debug_type2, type2_trigger_t), + VMSTATE_UINTTL_ARRAY(env.tdata1, RISCVCPU, RV_MAX_TRIGGERS), + VMSTATE_UINTTL_ARRAY(env.tdata2, RISCVCPU, RV_MAX_TRIGGERS), + VMSTATE_UINTTL_ARRAY(env.tdata3, RISCVCPU, RV_MAX_TRIGGERS), VMSTATE_END_OF_LIST() } }; From 6ea8d3fc40a8db8d22d00255cea9f9f8c927d643 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 9 Sep 2022 21:42:11 +0800 Subject: [PATCH 0640/1020] target/riscv: debug: Restrict the range of tselect value can be written The value of tselect CSR can be written should be limited within the range of supported triggers number. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Signed-off-by: Bin Meng Reviewed-by: LIU Zhiwei Message-Id: <20220909134215.1843865-5-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/debug.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 06feef7d67..d6666164cd 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -127,10 +127,6 @@ bool tdata_available(CPURISCVState *env, int tdata_index) return false; } - if (unlikely(env->trigger_cur >= RV_MAX_TRIGGERS)) { - return false; - } - return tdata_mapping[trigger_type][tdata_index]; } @@ -141,8 +137,9 @@ target_ulong tselect_csr_read(CPURISCVState *env) void tselect_csr_write(CPURISCVState *env, target_ulong val) { - /* all target_ulong bits of tselect are implemented */ - env->trigger_cur = val; + if (val < RV_MAX_TRIGGERS) { + env->trigger_cur = val; + } } static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val, From 31b9798d824512b7daf868cc8581f9a97a9d13a8 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 9 Sep 2022 21:42:12 +0800 Subject: [PATCH 0641/1020] target/riscv: debug: Introduce tinfo CSR tinfo.info: One bit for each possible type enumerated in tdata1. If the bit is set, then that type is supported by the currently selected trigger. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Signed-off-by: Bin Meng Reviewed-by: LIU Zhiwei Message-Id: <20220909134215.1843865-6-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_bits.h | 1 + target/riscv/csr.c | 8 ++++++++ target/riscv/debug.c | 10 +++++++--- target/riscv/debug.h | 2 ++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index b762807e4e..d8f5f0abed 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -319,6 +319,7 @@ #define CSR_TDATA1 0x7a1 #define CSR_TDATA2 0x7a2 #define CSR_TDATA3 0x7a3 +#define CSR_TINFO 0x7a4 /* Debug Mode Registers */ #define CSR_DCSR 0x7b0 diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 2c84c29bf0..5c9a7ee287 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3094,6 +3094,13 @@ static RISCVException write_tdata(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException read_tinfo(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = tinfo_csr_read(env); + return RISCV_EXCP_NONE; +} + /* * Functions to access Pointer Masking feature registers * We have to check if current priv lvl could modify @@ -3898,6 +3905,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_TDATA1] = { "tdata1", debug, read_tdata, write_tdata }, [CSR_TDATA2] = { "tdata2", debug, read_tdata, write_tdata }, [CSR_TDATA3] = { "tdata3", debug, read_tdata, write_tdata }, + [CSR_TINFO] = { "tinfo", debug, read_tinfo, write_ignore }, /* User Pointer Masking */ [CSR_UMTE] = { "umte", pointer_masking, read_umte, write_umte }, diff --git a/target/riscv/debug.c b/target/riscv/debug.c index d6666164cd..7d546ace42 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -37,9 +37,7 @@ * - tdata1 * - tdata2 * - tdata3 - * - * We don't support writable 'type' field in the tdata1 register, so there is - * no need to implement the "tinfo" CSR. + * - tinfo * * The following triggers are implemented: * @@ -372,6 +370,12 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val) } } +target_ulong tinfo_csr_read(CPURISCVState *env) +{ + /* assume all triggers support the same types of triggers */ + return BIT(TRIGGER_TYPE_AD_MATCH); +} + void riscv_cpu_debug_excp_handler(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); diff --git a/target/riscv/debug.h b/target/riscv/debug.h index 76146f373a..9f69c64591 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -95,6 +95,8 @@ void tselect_csr_write(CPURISCVState *env, target_ulong val); target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index); void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val); +target_ulong tinfo_csr_read(CPURISCVState *env); + void riscv_cpu_debug_excp_handler(CPUState *cs); bool riscv_cpu_debug_check_breakpoint(CPUState *cs); bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp); From d1c111411e6240c01ee3d54801a7e3eeb6acc3b1 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 9 Sep 2022 21:42:13 +0800 Subject: [PATCH 0642/1020] target/riscv: debug: Create common trigger actions function Trigger actions are shared among all triggers. Extract to a common function. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Signed-off-by: Bin Meng Reviewed-by: LIU Zhiwei [bmeng: handle the DBG_ACTION_NONE case] Signed-off-by: Bin Meng Message-Id: <20220909134215.1843865-7-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/debug.c | 59 ++++++++++++++++++++++++++++++++++++++++++-- target/riscv/debug.h | 13 ++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 7d546ace42..7a8910f980 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -92,6 +92,37 @@ static inline target_ulong get_trigger_type(CPURISCVState *env, return extract_trigger_type(env, env->tdata1[trigger_index]); } +static trigger_action_t get_trigger_action(CPURISCVState *env, + target_ulong trigger_index) +{ + target_ulong tdata1 = env->tdata1[trigger_index]; + int trigger_type = get_trigger_type(env, trigger_index); + trigger_action_t action = DBG_ACTION_NONE; + + switch (trigger_type) { + case TRIGGER_TYPE_AD_MATCH: + action = (tdata1 & TYPE2_ACTION) >> 12; + break; + case TRIGGER_TYPE_INST_CNT: + case TRIGGER_TYPE_INT: + case TRIGGER_TYPE_EXCP: + case TRIGGER_TYPE_AD_MATCH6: + case TRIGGER_TYPE_EXT_SRC: + qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n", + trigger_type); + break; + case TRIGGER_TYPE_NO_EXIST: + case TRIGGER_TYPE_UNAVAIL: + qemu_log_mask(LOG_GUEST_ERROR, "trigger type: %d does not exit\n", + trigger_type); + break; + default: + g_assert_not_reached(); + } + + return action; +} + static inline target_ulong build_tdata1(CPURISCVState *env, trigger_type_t type, bool dmode, target_ulong data) @@ -182,6 +213,30 @@ static inline void warn_always_zero_bit(target_ulong val, target_ulong mask, } } +static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index) +{ + trigger_action_t action = get_trigger_action(env, trigger_index); + + switch (action) { + case DBG_ACTION_NONE: + break; + case DBG_ACTION_BP: + riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); + break; + case DBG_ACTION_DBG_MODE: + case DBG_ACTION_TRACE0: + case DBG_ACTION_TRACE1: + case DBG_ACTION_TRACE2: + case DBG_ACTION_TRACE3: + case DBG_ACTION_EXT_DBG0: + case DBG_ACTION_EXT_DBG1: + qemu_log_mask(LOG_UNIMP, "action: %d is not supported\n", action); + break; + default: + g_assert_not_reached(); + } +} + /* type 2 trigger */ static uint32_t type2_breakpoint_size(CPURISCVState *env, target_ulong ctrl) @@ -384,11 +439,11 @@ void riscv_cpu_debug_excp_handler(CPUState *cs) if (cs->watchpoint_hit) { if (cs->watchpoint_hit->flags & BP_CPU) { cs->watchpoint_hit = NULL; - riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); + do_trigger_action(env, DBG_ACTION_BP); } } else { if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) { - riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0); + do_trigger_action(env, DBG_ACTION_BP); } } } diff --git a/target/riscv/debug.h b/target/riscv/debug.h index 9f69c64591..0e4859cf74 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -44,6 +44,19 @@ typedef enum { TRIGGER_TYPE_NUM } trigger_type_t; +/* actions */ +typedef enum { + DBG_ACTION_NONE = -1, /* sentinel value */ + DBG_ACTION_BP = 0, + DBG_ACTION_DBG_MODE, + DBG_ACTION_TRACE0, + DBG_ACTION_TRACE1, + DBG_ACTION_TRACE2, + DBG_ACTION_TRACE3, + DBG_ACTION_EXT_DBG0 = 8, + DBG_ACTION_EXT_DBG1 +} trigger_action_t; + /* tdata1 field masks */ #define RV32_TYPE(t) ((uint32_t)(t) << 28) From c32461d8eeb17490b1b1e969e2ce8f1ecd83bfbb Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 9 Sep 2022 21:42:14 +0800 Subject: [PATCH 0643/1020] target/riscv: debug: Check VU/VS modes for type 2 trigger Type 2 trigger cannot be fired in VU/VS modes. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Signed-off-by: Bin Meng Message-Id: <20220909134215.1843865-8-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/debug.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 7a8910f980..e16d5c070a 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -464,6 +464,11 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs) switch (trigger_type) { case TRIGGER_TYPE_AD_MATCH: + /* type 2 trigger cannot be fired in VU/VS mode */ + if (riscv_cpu_virt_enabled(env)) { + return false; + } + ctrl = env->tdata1[i]; pc = env->tdata2[i]; @@ -499,6 +504,11 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) switch (trigger_type) { case TRIGGER_TYPE_AD_MATCH: + /* type 2 trigger cannot be fired in VU/VS mode */ + if (riscv_cpu_virt_enabled(env)) { + return false; + } + ctrl = env->tdata1[i]; addr = env->tdata2[i]; flags = 0; From c472c142a7552f5b0e40378d5643a2810ef1b111 Mon Sep 17 00:00:00 2001 From: Frank Chang Date: Fri, 9 Sep 2022 21:42:15 +0800 Subject: [PATCH 0644/1020] target/riscv: debug: Add initial support of type 6 trigger Type 6 trigger is similar to a type 2 trigger, but provides additional functionality and should be used instead of type 2 in newer implementations. Signed-off-by: Frank Chang Reviewed-by: Bin Meng Signed-off-by: Bin Meng Message-Id: <20220909134215.1843865-9-bmeng.cn@gmail.com> Signed-off-by: Alistair Francis --- target/riscv/debug.c | 174 ++++++++++++++++++++++++++++++++++++++++++- target/riscv/debug.h | 18 +++++ 2 files changed, 188 insertions(+), 4 deletions(-) diff --git a/target/riscv/debug.c b/target/riscv/debug.c index e16d5c070a..26ea764407 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -39,7 +39,7 @@ * - tdata3 * - tinfo * - * The following triggers are implemented: + * The following triggers are initialized by default: * * Index | Type | tdata mapping | Description * ------+------+------------------------+------------ @@ -103,10 +103,12 @@ static trigger_action_t get_trigger_action(CPURISCVState *env, case TRIGGER_TYPE_AD_MATCH: action = (tdata1 & TYPE2_ACTION) >> 12; break; + case TRIGGER_TYPE_AD_MATCH6: + action = (tdata1 & TYPE6_ACTION) >> 12; + break; case TRIGGER_TYPE_INST_CNT: case TRIGGER_TYPE_INT: case TRIGGER_TYPE_EXCP: - case TRIGGER_TYPE_AD_MATCH6: case TRIGGER_TYPE_EXT_SRC: qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n", trigger_type); @@ -379,6 +381,123 @@ static void type2_reg_write(CPURISCVState *env, target_ulong index, return; } +/* type 6 trigger */ + +static inline bool type6_breakpoint_enabled(target_ulong ctrl) +{ + bool mode = !!(ctrl & (TYPE6_VU | TYPE6_VS | TYPE6_U | TYPE6_S | TYPE6_M)); + bool rwx = !!(ctrl & (TYPE6_LOAD | TYPE6_STORE | TYPE6_EXEC)); + + return mode && rwx; +} + +static target_ulong type6_mcontrol6_validate(CPURISCVState *env, + target_ulong ctrl) +{ + target_ulong val; + uint32_t size; + + /* validate the generic part first */ + val = tdata1_validate(env, ctrl, TRIGGER_TYPE_AD_MATCH6); + + /* validate unimplemented (always zero) bits */ + warn_always_zero_bit(ctrl, TYPE6_MATCH, "match"); + warn_always_zero_bit(ctrl, TYPE6_CHAIN, "chain"); + warn_always_zero_bit(ctrl, TYPE6_ACTION, "action"); + warn_always_zero_bit(ctrl, TYPE6_TIMING, "timing"); + warn_always_zero_bit(ctrl, TYPE6_SELECT, "select"); + warn_always_zero_bit(ctrl, TYPE6_HIT, "hit"); + + /* validate size encoding */ + size = extract32(ctrl, 16, 4); + if (access_size[size] == -1) { + qemu_log_mask(LOG_UNIMP, "access size %d is not supported, using SIZE_ANY\n", + size); + } else { + val |= (ctrl & TYPE6_SIZE); + } + + /* keep the mode and attribute bits */ + val |= (ctrl & (TYPE6_VU | TYPE6_VS | TYPE6_U | TYPE6_S | TYPE6_M | + TYPE6_LOAD | TYPE6_STORE | TYPE6_EXEC)); + + return val; +} + +static void type6_breakpoint_insert(CPURISCVState *env, target_ulong index) +{ + target_ulong ctrl = env->tdata1[index]; + target_ulong addr = env->tdata2[index]; + bool enabled = type6_breakpoint_enabled(ctrl); + CPUState *cs = env_cpu(env); + int flags = BP_CPU | BP_STOP_BEFORE_ACCESS; + uint32_t size; + + if (!enabled) { + return; + } + + if (ctrl & TYPE6_EXEC) { + cpu_breakpoint_insert(cs, addr, flags, &env->cpu_breakpoint[index]); + } + + if (ctrl & TYPE6_LOAD) { + flags |= BP_MEM_READ; + } + + if (ctrl & TYPE6_STORE) { + flags |= BP_MEM_WRITE; + } + + if (flags & BP_MEM_ACCESS) { + size = extract32(ctrl, 16, 4); + if (size != 0) { + cpu_watchpoint_insert(cs, addr, size, flags, + &env->cpu_watchpoint[index]); + } else { + cpu_watchpoint_insert(cs, addr, 8, flags, + &env->cpu_watchpoint[index]); + } + } +} + +static void type6_breakpoint_remove(CPURISCVState *env, target_ulong index) +{ + type2_breakpoint_remove(env, index); +} + +static void type6_reg_write(CPURISCVState *env, target_ulong index, + int tdata_index, target_ulong val) +{ + target_ulong new_val; + + switch (tdata_index) { + case TDATA1: + new_val = type6_mcontrol6_validate(env, val); + if (new_val != env->tdata1[index]) { + env->tdata1[index] = new_val; + type6_breakpoint_remove(env, index); + type6_breakpoint_insert(env, index); + } + break; + case TDATA2: + if (val != env->tdata2[index]) { + env->tdata2[index] = val; + type6_breakpoint_remove(env, index); + type6_breakpoint_insert(env, index); + } + break; + case TDATA3: + qemu_log_mask(LOG_UNIMP, + "tdata3 is not supported for type 6 trigger\n"); + break; + default: + g_assert_not_reached(); + } + + return; +} + target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index) { switch (tdata_index) { @@ -407,10 +526,12 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val) case TRIGGER_TYPE_AD_MATCH: type2_reg_write(env, env->trigger_cur, tdata_index, val); break; + case TRIGGER_TYPE_AD_MATCH6: + type6_reg_write(env, env->trigger_cur, tdata_index, val); + break; case TRIGGER_TYPE_INST_CNT: case TRIGGER_TYPE_INT: case TRIGGER_TYPE_EXCP: - case TRIGGER_TYPE_AD_MATCH6: case TRIGGER_TYPE_EXT_SRC: qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n", trigger_type); @@ -428,7 +549,8 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val) target_ulong tinfo_csr_read(CPURISCVState *env) { /* assume all triggers support the same types of triggers */ - return BIT(TRIGGER_TYPE_AD_MATCH); + return BIT(TRIGGER_TYPE_AD_MATCH) | + BIT(TRIGGER_TYPE_AD_MATCH6); } void riscv_cpu_debug_excp_handler(CPUState *cs) @@ -479,6 +601,24 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs) } } break; + case TRIGGER_TYPE_AD_MATCH6: + ctrl = env->tdata1[i]; + pc = env->tdata2[i]; + + if ((ctrl & TYPE6_EXEC) && (bp->pc == pc)) { + if (riscv_cpu_virt_enabled(env)) { + /* check VU/VS bit against current privilege level */ + if ((ctrl >> 23) & BIT(env->priv)) { + return true; + } + } else { + /* check U/S/M bit against current privilege level */ + if ((ctrl >> 3) & BIT(env->priv)) { + return true; + } + } + } + break; default: /* other trigger types are not supported or irrelevant */ break; @@ -527,6 +667,32 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) } } break; + case TRIGGER_TYPE_AD_MATCH6: + ctrl = env->tdata1[i]; + addr = env->tdata2[i]; + flags = 0; + + if (ctrl & TYPE6_LOAD) { + flags |= BP_MEM_READ; + } + if (ctrl & TYPE6_STORE) { + flags |= BP_MEM_WRITE; + } + + if ((wp->flags & flags) && (wp->vaddr == addr)) { + if (riscv_cpu_virt_enabled(env)) { + /* check VU/VS bit against current privilege level */ + if ((ctrl >> 23) & BIT(env->priv)) { + return true; + } + } else { + /* check U/S/M bit against current privilege level */ + if ((ctrl >> 3) & BIT(env->priv)) { + return true; + } + } + } + break; default: /* other trigger types are not supported */ break; diff --git a/target/riscv/debug.h b/target/riscv/debug.h index 0e4859cf74..a1226b4d29 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -85,6 +85,24 @@ typedef enum { #define TYPE2_HIT BIT(20) #define TYPE2_SIZEHI (0x3 << 21) /* RV64 only */ +/* mcontrol6 field masks */ + +#define TYPE6_LOAD BIT(0) +#define TYPE6_STORE BIT(1) +#define TYPE6_EXEC BIT(2) +#define TYPE6_U BIT(3) +#define TYPE6_S BIT(4) +#define TYPE6_M BIT(6) +#define TYPE6_MATCH (0xf << 7) +#define TYPE6_CHAIN BIT(11) +#define TYPE6_ACTION (0xf << 12) +#define TYPE6_SIZE (0xf << 16) +#define TYPE6_TIMING BIT(20) +#define TYPE6_SELECT BIT(21) +#define TYPE6_HIT BIT(22) +#define TYPE6_VU BIT(23) +#define TYPE6_VS BIT(24) + /* access size */ enum { SIZE_ANY = 0, From 5bda21c0ea02c1af160ddee6f0b62c569282294c Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 17 Aug 2022 15:48:01 +0800 Subject: [PATCH 0645/1020] target/riscv: rvv-1.0: Simplify vfwredsum code Remove duplicate code by wrapping vfwredsum_vs's OP function. Signed-off-by: Yang Liu Reviewed-by: Alistair Francis Reviewed-by: Frank Chang Message-Id: <20220817074802.20765-1-liuyang22@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/vector_helper.c | 62 ++++++++---------------------------- 1 file changed, 13 insertions(+), 49 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index d224861c2c..2828073497 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -4728,57 +4728,21 @@ GEN_VEXT_FRED(vfredmin_vs_h, uint16_t, uint16_t, H2, H2, float16_minimum_number) GEN_VEXT_FRED(vfredmin_vs_w, uint32_t, uint32_t, H4, H4, float32_minimum_number) GEN_VEXT_FRED(vfredmin_vs_d, uint64_t, uint64_t, H8, H8, float64_minimum_number) +/* Vector Widening Floating-Point Add Instructions */ +static uint32_t fwadd16(uint32_t a, uint16_t b, float_status *s) +{ + return float32_add(a, float16_to_float32(b, true, s), s); +} + +static uint64_t fwadd32(uint64_t a, uint32_t b, float_status *s) +{ + return float64_add(a, float32_to_float64(b, s), s); +} + /* Vector Widening Floating-Point Reduction Instructions */ /* Unordered reduce 2*SEW = 2*SEW + sum(promote(SEW)) */ -void HELPER(vfwredsum_vs_h)(void *vd, void *v0, void *vs1, - void *vs2, CPURISCVState *env, uint32_t desc) -{ - uint32_t vm = vext_vm(desc); - uint32_t vl = env->vl; - uint32_t esz = sizeof(uint32_t); - uint32_t vlenb = simd_maxsz(desc); - uint32_t vta = vext_vta(desc); - uint32_t i; - uint32_t s1 = *((uint32_t *)vs1 + H4(0)); - - for (i = env->vstart; i < vl; i++) { - uint16_t s2 = *((uint16_t *)vs2 + H2(i)); - if (!vm && !vext_elem_mask(v0, i)) { - continue; - } - s1 = float32_add(s1, float16_to_float32(s2, true, &env->fp_status), - &env->fp_status); - } - *((uint32_t *)vd + H4(0)) = s1; - env->vstart = 0; - /* set tail elements to 1s */ - vext_set_elems_1s(vd, vta, esz, vlenb); -} - -void HELPER(vfwredsum_vs_w)(void *vd, void *v0, void *vs1, - void *vs2, CPURISCVState *env, uint32_t desc) -{ - uint32_t vm = vext_vm(desc); - uint32_t vl = env->vl; - uint32_t esz = sizeof(uint64_t); - uint32_t vlenb = simd_maxsz(desc); - uint32_t vta = vext_vta(desc); - uint32_t i; - uint64_t s1 = *((uint64_t *)vs1); - - for (i = env->vstart; i < vl; i++) { - uint32_t s2 = *((uint32_t *)vs2 + H4(i)); - if (!vm && !vext_elem_mask(v0, i)) { - continue; - } - s1 = float64_add(s1, float32_to_float64(s2, &env->fp_status), - &env->fp_status); - } - *((uint64_t *)vd) = s1; - env->vstart = 0; - /* set tail elements to 1s */ - vext_set_elems_1s(vd, vta, esz, vlenb); -} +GEN_VEXT_FRED(vfwredsum_vs_h, uint32_t, uint16_t, H4, H2, fwadd16) +GEN_VEXT_FRED(vfwredsum_vs_w, uint64_t, uint32_t, H8, H4, fwadd32) /* *** Vector Mask Operations From a3ab69f9f6c000481c439923d16416b8941d5b37 Mon Sep 17 00:00:00 2001 From: Yang Liu Date: Wed, 17 Aug 2022 15:48:02 +0800 Subject: [PATCH 0646/1020] target/riscv: rvv-1.0: vf[w]redsum distinguish between ordered/unordered Starting with RVV1.0, the original vf[w]redsum_vs instruction was renamed to vf[w]redusum_vs. The distinction between ordered and unordered is also more consistent with other instructions, although there is no difference in implementation between the two for QEMU. Signed-off-by: Yang Liu Acked-by: Alistair Francis Reviewed-by: Frank Chang Message-Id: <20220817074802.20765-2-liuyang22@iscas.ac.cn> Signed-off-by: Alistair Francis --- target/riscv/helper.h | 15 ++++++++++----- target/riscv/insn32.decode | 6 ++++-- target/riscv/insn_trans/trans_rvv.c.inc | 6 ++++-- target/riscv/vector_helper.c | 19 +++++++++++++------ 4 files changed, 31 insertions(+), 15 deletions(-) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 4ef3b2251d..a03014fe67 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -1009,9 +1009,12 @@ DEF_HELPER_6(vwredsum_vs_b, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vwredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vwredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) -DEF_HELPER_6(vfredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) -DEF_HELPER_6(vfredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) -DEF_HELPER_6(vfredsum_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredusum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredusum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredusum_vs_d, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredosum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredosum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfredosum_vs_d, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vfredmax_vs_h, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vfredmax_vs_w, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vfredmax_vs_d, void, ptr, ptr, ptr, ptr, env, i32) @@ -1019,8 +1022,10 @@ DEF_HELPER_6(vfredmin_vs_h, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vfredmin_vs_w, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vfredmin_vs_d, void, ptr, ptr, ptr, ptr, env, i32) -DEF_HELPER_6(vfwredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) -DEF_HELPER_6(vfwredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwredusum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwredusum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwredosum_vs_h, void, ptr, ptr, ptr, ptr, env, i32) +DEF_HELPER_6(vfwredosum_vs_w, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vmand_mm, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vmnand_mm, void, ptr, ptr, ptr, ptr, env, i32) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 595fdcdad8..d0253b8104 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -664,11 +664,13 @@ vredmax_vs 000111 . ..... ..... 010 ..... 1010111 @r_vm vwredsumu_vs 110000 . ..... ..... 000 ..... 1010111 @r_vm vwredsum_vs 110001 . ..... ..... 000 ..... 1010111 @r_vm # Vector ordered and unordered reduction sum -vfredsum_vs 0000-1 . ..... ..... 001 ..... 1010111 @r_vm +vfredusum_vs 000001 . ..... ..... 001 ..... 1010111 @r_vm +vfredosum_vs 000011 . ..... ..... 001 ..... 1010111 @r_vm vfredmin_vs 000101 . ..... ..... 001 ..... 1010111 @r_vm vfredmax_vs 000111 . ..... ..... 001 ..... 1010111 @r_vm # Vector widening ordered and unordered float reduction sum -vfwredsum_vs 1100-1 . ..... ..... 001 ..... 1010111 @r_vm +vfwredusum_vs 110001 . ..... ..... 001 ..... 1010111 @r_vm +vfwredosum_vs 110011 . ..... ..... 001 ..... 1010111 @r_vm vmand_mm 011001 - ..... ..... 010 ..... 1010111 @r vmnand_mm 011101 - ..... ..... 010 ..... 1010111 @r vmandn_mm 011000 - ..... ..... 010 ..... 1010111 @r diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index e58208f363..4dea4413ae 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -3136,7 +3136,8 @@ static bool freduction_check(DisasContext *s, arg_rmrr *a) require_zve64f(s); } -GEN_OPFVV_TRANS(vfredsum_vs, freduction_check) +GEN_OPFVV_TRANS(vfredusum_vs, freduction_check) +GEN_OPFVV_TRANS(vfredosum_vs, freduction_check) GEN_OPFVV_TRANS(vfredmax_vs, freduction_check) GEN_OPFVV_TRANS(vfredmin_vs, freduction_check) @@ -3148,7 +3149,8 @@ static bool freduction_widen_check(DisasContext *s, arg_rmrr *a) (s->sew != MO_8); } -GEN_OPFVV_WIDEN_TRANS(vfwredsum_vs, freduction_widen_check) +GEN_OPFVV_WIDEN_TRANS(vfwredusum_vs, freduction_widen_check) +GEN_OPFVV_WIDEN_TRANS(vfwredosum_vs, freduction_widen_check) /* *** Vector Mask Operations diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 2828073497..b94f809eb3 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -4714,9 +4714,14 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ } /* Unordered sum */ -GEN_VEXT_FRED(vfredsum_vs_h, uint16_t, uint16_t, H2, H2, float16_add) -GEN_VEXT_FRED(vfredsum_vs_w, uint32_t, uint32_t, H4, H4, float32_add) -GEN_VEXT_FRED(vfredsum_vs_d, uint64_t, uint64_t, H8, H8, float64_add) +GEN_VEXT_FRED(vfredusum_vs_h, uint16_t, uint16_t, H2, H2, float16_add) +GEN_VEXT_FRED(vfredusum_vs_w, uint32_t, uint32_t, H4, H4, float32_add) +GEN_VEXT_FRED(vfredusum_vs_d, uint64_t, uint64_t, H8, H8, float64_add) + +/* Ordered sum */ +GEN_VEXT_FRED(vfredosum_vs_h, uint16_t, uint16_t, H2, H2, float16_add) +GEN_VEXT_FRED(vfredosum_vs_w, uint32_t, uint32_t, H4, H4, float32_add) +GEN_VEXT_FRED(vfredosum_vs_d, uint64_t, uint64_t, H8, H8, float64_add) /* Maximum value */ GEN_VEXT_FRED(vfredmax_vs_h, uint16_t, uint16_t, H2, H2, float16_maximum_number) @@ -4740,9 +4745,11 @@ static uint64_t fwadd32(uint64_t a, uint32_t b, float_status *s) } /* Vector Widening Floating-Point Reduction Instructions */ -/* Unordered reduce 2*SEW = 2*SEW + sum(promote(SEW)) */ -GEN_VEXT_FRED(vfwredsum_vs_h, uint32_t, uint16_t, H4, H2, fwadd16) -GEN_VEXT_FRED(vfwredsum_vs_w, uint64_t, uint32_t, H8, H4, fwadd32) +/* Ordered/unordered reduce 2*SEW = 2*SEW + sum(promote(SEW)) */ +GEN_VEXT_FRED(vfwredusum_vs_h, uint32_t, uint16_t, H4, H2, fwadd16) +GEN_VEXT_FRED(vfwredusum_vs_w, uint64_t, uint32_t, H8, H4, fwadd32) +GEN_VEXT_FRED(vfwredosum_vs_h, uint32_t, uint16_t, H4, H2, fwadd16) +GEN_VEXT_FRED(vfwredosum_vs_w, uint64_t, uint32_t, H8, H4, fwadd32) /* *** Vector Mask Operations From cea5aa85691d7f26b7ea995417d41a32802691b7 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Aug 2022 08:38:26 +0200 Subject: [PATCH 0647/1020] usb/msd: move usb_msd_packet_complete() Change ordering to avoid adding forward declarations in following patches. Fix comment code style while being at it. No functional change. Signed-off-by: Gerd Hoffmann Message-Id: <20220830063827.813053-2-kraxel@redhat.com> --- hw/usb/dev-storage.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 98639696e6..140ef2aeaa 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -177,6 +177,20 @@ static const USBDesc desc = { .str = desc_strings, }; +static void usb_msd_packet_complete(MSDState *s) +{ + USBPacket *p = s->packet; + + /* + * Set s->packet to NULL before calling usb_packet_complete + * because another request may be issued before + * usb_packet_complete returns. + */ + trace_usb_msd_packet_complete(); + s->packet = NULL; + usb_packet_complete(&s->dev, p); +} + static void usb_msd_copy_data(MSDState *s, USBPacket *p) { uint32_t len; @@ -208,18 +222,6 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p) memset(&s->csw, 0, sizeof(s->csw)); } -static void usb_msd_packet_complete(MSDState *s) -{ - USBPacket *p = s->packet; - - /* Set s->packet to NULL before calling usb_packet_complete - because another request may be issued before - usb_packet_complete returns. */ - trace_usb_msd_packet_complete(); - s->packet = NULL; - usb_packet_complete(&s->dev, p); -} - void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) { MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); From 12b69878fc7b4b92b1bbd3959f2c3d4c717881fb Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Aug 2022 08:38:27 +0200 Subject: [PATCH 0648/1020] usb/msd: add usb_msd_fatal_error() and fix guest-triggerable assert Add handler for fatal errors. Moves device into error state where it stops responding until the guest resets it. Guest can send illegal requests where scsi command and usb packet transfer directions are inconsistent. Use the new usb_msd_fatal_error() function instead of assert() in that case. Reported-by: Qiang Liu Signed-off-by: Gerd Hoffmann Tested-by: Qiang Liu Message-Id: <20220830063827.813053-3-kraxel@redhat.com> --- hw/usb/dev-storage.c | 30 +++++++++++++++++++++++++++++- hw/usb/trace-events | 1 + include/hw/usb/msd.h | 1 + 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c index 140ef2aeaa..e3bcffb3e0 100644 --- a/hw/usb/dev-storage.c +++ b/hw/usb/dev-storage.c @@ -191,6 +191,23 @@ static void usb_msd_packet_complete(MSDState *s) usb_packet_complete(&s->dev, p); } +static void usb_msd_fatal_error(MSDState *s) +{ + trace_usb_msd_fatal_error(); + + if (s->packet) { + s->packet->status = USB_RET_STALL; + usb_msd_packet_complete(s); + } + + /* + * Guest messed up up device state with illegal requests. Go + * ignore any requests until the guests resets the device (and + * brings it into a known state that way). + */ + s->needs_reset = true; +} + static void usb_msd_copy_data(MSDState *s, USBPacket *p) { uint32_t len; @@ -227,7 +244,11 @@ void usb_msd_transfer_data(SCSIRequest *req, uint32_t len) MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent); USBPacket *p = s->packet; - assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV)); + if ((s->mode == USB_MSDM_DATAOUT) != (req->cmd.mode == SCSI_XFER_TO_DEV)) { + usb_msd_fatal_error(s); + return; + } + s->scsi_len = len; s->scsi_off = 0; if (p) { @@ -317,6 +338,8 @@ void usb_msd_handle_reset(USBDevice *dev) memset(&s->csw, 0, sizeof(s->csw)); s->mode = USB_MSDM_CBW; + + s->needs_reset = false; } static void usb_msd_handle_control(USBDevice *dev, USBPacket *p, @@ -382,6 +405,11 @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p) SCSIDevice *scsi_dev; uint32_t len; + if (s->needs_reset) { + p->status = USB_RET_STALL; + return; + } + switch (p->pid) { case USB_TOKEN_OUT: if (devep != 2) diff --git a/hw/usb/trace-events b/hw/usb/trace-events index 914ca71668..b65269892c 100644 --- a/hw/usb/trace-events +++ b/hw/usb/trace-events @@ -263,6 +263,7 @@ usb_msd_packet_complete(void) "" usb_msd_cmd_submit(unsigned lun, unsigned tag, unsigned flags, unsigned len, unsigned data_len) "lun %u, tag 0x%x, flags 0x%08x, len %d, data-len %d" usb_msd_cmd_complete(unsigned status, unsigned tag) "status %d, tag 0x%x" usb_msd_cmd_cancel(unsigned tag) "tag 0x%x" +usb_msd_fatal_error(void) "" # dev-uas.c usb_uas_reset(int addr) "dev %d" diff --git a/include/hw/usb/msd.h b/include/hw/usb/msd.h index 54e9f38bda..f9fd862b52 100644 --- a/include/hw/usb/msd.h +++ b/include/hw/usb/msd.h @@ -40,6 +40,7 @@ struct MSDState { bool removable; bool commandlog; SCSIDevice *scsi_dev; + bool needs_reset; }; typedef struct MSDState MSDState; From 145cdaba0f7ea721080e1289dc7a31bb2066406f Mon Sep 17 00:00:00 2001 From: Qiang Liu Date: Sun, 4 Sep 2022 20:59:26 +0800 Subject: [PATCH 0649/1020] hcd-xhci: drop operation with secondary stream arrays enabled The abort() in xhci_find_stream() can be triggered via enabling the secondary stream arrays by setting linear stream array (LSA) bit (in endpoint context) to 0. We may show warnings and drop this operation. Fixes: 024426acc0a2 ("usb-xhci: usb3 streams") Reported-by: Qiang Liu Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1192 Signed-off-by: Qiang Liu Message-Id: <20220904125926.2141607-1-cyruscyliu@gmail.com> Signed-off-by: Gerd Hoffmann --- hw/usb/hcd-xhci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index acd60b1a49..8299f35e66 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1020,7 +1020,9 @@ static XHCIStreamContext *xhci_find_stream(XHCIEPContext *epctx, } sctx = epctx->pstreams + streamid; } else { - FIXME("secondary streams not implemented yet"); + fprintf(stderr, "xhci: FIXME: secondary streams not implemented yet"); + *cc_error = CC_INVALID_STREAM_TYPE_ERROR; + return NULL; } if (sctx->sct == -1) { From a89003780d0a96b79314da4a4cdb148ff1dcb397 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 6 Sep 2022 19:30:50 +0100 Subject: [PATCH 0650/1020] usbnet: Add missing usb_wakeup() call in usbnet_receive() usbnet_receive() does not currently wake up the USB endpoint, leading to a dead RX datapath when used with a host controller such as xHCI that relies on being woken up. Fix by adding a call to usb_wakeup() at the end of usbnet_receive(). Signed-off-by: Michael Brown Message-Id: <20220906183053.3625472-2-mcb30@ipxe.org> Signed-off-by: Gerd Hoffmann --- hw/usb/dev-network.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 6c49c16015..61bf598870 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -647,6 +647,7 @@ struct USBNetState { uint8_t in_buf[2048]; USBEndpoint *intr; + USBEndpoint *bulk_in; char usbstring_mac[13]; NICState *nic; @@ -1317,6 +1318,7 @@ static ssize_t usbnet_receive(NetClientState *nc, const uint8_t *buf, size_t siz memcpy(in_buf, buf, size); s->in_len = total_size; s->in_ptr = 0; + usb_wakeup(s->bulk_in, 0); return size; } @@ -1359,6 +1361,7 @@ static void usb_net_realize(USBDevice *dev, Error **errp) s->filter = 0; s->vendorid = 0x1234; s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); + s->bulk_in = usb_ep_get(dev, USB_TOKEN_IN, 2); qemu_macaddr_default_if_unset(&s->conf.macaddr); s->nic = qemu_new_nic(&net_usbnet_info, &s->conf, From 954cbf7bb53476e99091f9c99a8014af2491f6ef Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 6 Sep 2022 19:30:51 +0100 Subject: [PATCH 0651/1020] usbnet: Accept mandatory USB_CDC_SET_ETHERNET_PACKET_FILTER request The USB_CDC_SET_ETHERNET_PACKET_FILTER request is mandatory for CDC-ECM devices. Accept this request, ignoring the actual filter value (to match the existing behaviour for RNDIS). Signed-off-by: Michael Brown Message-Id: <20220906183053.3625472-3-mcb30@ipxe.org> Signed-off-by: Gerd Hoffmann --- hw/usb/dev-network.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 61bf598870..155df935cd 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1122,6 +1122,12 @@ static void usb_net_handle_control(USBDevice *dev, USBPacket *p, #endif break; + case ClassInterfaceOutRequest | USB_CDC_SET_ETHERNET_PACKET_FILTER: + if (is_rndis(s)) { + goto fail; + } + break; + default: fail: fprintf(stderr, "usbnet: failed control transaction: " From 2423ee233872d07c7607ce26f9225c64b30b0dc3 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 6 Sep 2022 19:30:52 +0100 Subject: [PATCH 0652/1020] usbnet: Detect short packets as sent by the xHCI controller The xHCI controller will ignore the endpoint MTU and so may deliver packets of any length. Detect short packets as being any packet that has a length of zero or a length that is not a multiple of the MTU. Signed-off-by: Michael Brown Message-Id: <20220906183053.3625472-4-mcb30@ipxe.org> Signed-off-by: Gerd Hoffmann --- hw/usb/dev-network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 155df935cd..9d83974ec9 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -1211,7 +1211,7 @@ static void usb_net_handle_dataout(USBNetState *s, USBPacket *p) s->out_ptr += sz; if (!is_rndis(s)) { - if (p->iov.size < 64) { + if (p->iov.size % 64 || p->iov.size == 0) { qemu_send_packet(qemu_get_queue(s->nic), s->out_buf, s->out_ptr); s->out_ptr = 0; } From f3def4dd42531cb542bb0e004f375b9d89fd5853 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 6 Sep 2022 19:30:53 +0100 Subject: [PATCH 0653/1020] usbnet: Report link-up via interrupt endpoint in CDC-ECM mode Signed-off-by: Michael Brown Message-Id: <20220906183053.3625472-5-mcb30@ipxe.org> Signed-off-by: Gerd Hoffmann --- hw/usb/dev-network.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c index 9d83974ec9..ac1adca543 100644 --- a/hw/usb/dev-network.c +++ b/hw/usb/dev-network.c @@ -91,6 +91,8 @@ enum usbstring_idx { #define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43 #define USB_CDC_GET_ETHERNET_STATISTIC 0x44 +#define USB_CDC_NETWORK_CONNECTION 0x00 + #define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ #define STATUS_BYTECOUNT 16 /* 8 byte header + data */ @@ -640,6 +642,8 @@ struct USBNetState { uint16_t filter; uint32_t vendorid; + uint16_t connection; + unsigned int out_ptr; uint8_t out_buf[2048]; @@ -1140,18 +1144,28 @@ static void usb_net_handle_control(USBDevice *dev, USBPacket *p, static void usb_net_handle_statusin(USBNetState *s, USBPacket *p) { - le32 buf[2]; + le32 rbuf[2]; + uint16_t ebuf[4]; if (p->iov.size < 8) { p->status = USB_RET_STALL; return; } - buf[0] = cpu_to_le32(1); - buf[1] = cpu_to_le32(0); - usb_packet_copy(p, buf, 8); - if (!s->rndis_resp.tqh_first) { - p->status = USB_RET_NAK; + if (is_rndis(s)) { + rbuf[0] = cpu_to_le32(1); + rbuf[1] = cpu_to_le32(0); + usb_packet_copy(p, rbuf, 8); + if (!s->rndis_resp.tqh_first) { + p->status = USB_RET_NAK; + } + } else { + ebuf[0] = + cpu_to_be16(ClassInterfaceRequest | USB_CDC_NETWORK_CONNECTION); + ebuf[1] = cpu_to_le16(s->connection); + ebuf[2] = cpu_to_le16(1); + ebuf[3] = cpu_to_le16(0); + usb_packet_copy(p, ebuf, 8); } #ifdef TRAFFIC_DEBUG @@ -1366,6 +1380,7 @@ static void usb_net_realize(USBDevice *dev, Error **errp) s->media_state = 0; /* NDIS_MEDIA_STATE_CONNECTED */; s->filter = 0; s->vendorid = 0x1234; + s->connection = 1; /* Connected */ s->intr = usb_ep_get(dev, USB_TOKEN_IN, 1); s->bulk_in = usb_ep_get(dev, USB_TOKEN_IN, 2); From 663df1cc68729adc0468d632fb19f6106ddcdca8 Mon Sep 17 00:00:00 2001 From: Alexandre Ratchov Date: Wed, 7 Sep 2022 15:23:42 +0200 Subject: [PATCH 0654/1020] audio: Add sndio backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sndio is the native API used by OpenBSD, although it has been ported to other *BSD's and Linux (packages for Ubuntu, Debian, Void, Arch, etc.). Signed-off-by: Brad Smith Signed-off-by: Alexandre Ratchov Reviewed-by: Volker RĂ¼melin Tested-by: Volker RĂ¼melin Message-Id: Signed-off-by: Gerd Hoffmann --- MAINTAINERS | 7 + audio/audio.c | 1 + audio/audio_template.h | 2 + audio/meson.build | 1 + audio/sndioaudio.c | 565 ++++++++++++++++++++++++++++++++++ meson.build | 9 +- meson_options.txt | 4 +- qapi/audio.json | 25 +- qemu-options.hx | 16 + scripts/meson-buildoptions.sh | 7 +- 10 files changed, 632 insertions(+), 5 deletions(-) create mode 100644 audio/sndioaudio.c diff --git a/MAINTAINERS b/MAINTAINERS index 738c4eb647..269e07cf47 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2438,6 +2438,7 @@ X: audio/jackaudio.c X: audio/ossaudio.c X: audio/paaudio.c X: audio/sdlaudio.c +X: audio/sndioaudio.c X: audio/spiceaudio.c F: qapi/audio.json @@ -2482,6 +2483,12 @@ R: Thomas Huth S: Odd Fixes F: audio/sdlaudio.c +Sndio Audio backend +M: Gerd Hoffmann +R: Alexandre Ratchov +S: Odd Fixes +F: audio/sndioaudio.c + Block layer core M: Kevin Wolf M: Hanna Reitz diff --git a/audio/audio.c b/audio/audio.c index cfa4119c05..5600593da0 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -2030,6 +2030,7 @@ void audio_create_pdos(Audiodev *dev) CASE(OSS, oss, Oss); CASE(PA, pa, Pa); CASE(SDL, sdl, Sdl); + CASE(SNDIO, sndio, ); CASE(SPICE, spice, ); CASE(WAV, wav, ); diff --git a/audio/audio_template.h b/audio/audio_template.h index 7192b19e73..81860cea62 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -336,6 +336,8 @@ AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev) return qapi_AudiodevPaPerDirectionOptions_base(dev->u.pa.TYPE); case AUDIODEV_DRIVER_SDL: return qapi_AudiodevSdlPerDirectionOptions_base(dev->u.sdl.TYPE); + case AUDIODEV_DRIVER_SNDIO: + return dev->u.sndio.TYPE; case AUDIODEV_DRIVER_SPICE: return dev->u.spice.TYPE; case AUDIODEV_DRIVER_WAV: diff --git a/audio/meson.build b/audio/meson.build index 3abee90860..34aed78342 100644 --- a/audio/meson.build +++ b/audio/meson.build @@ -17,6 +17,7 @@ foreach m : [ ['pa', pulse, files('paaudio.c')], ['sdl', sdl, files('sdlaudio.c')], ['jack', jack, files('jackaudio.c')], + ['sndio', sndio, files('sndioaudio.c')], ['spice', spice, files('spiceaudio.c')] ] if m[1].found() diff --git a/audio/sndioaudio.c b/audio/sndioaudio.c new file mode 100644 index 0000000000..7c45276d36 --- /dev/null +++ b/audio/sndioaudio.c @@ -0,0 +1,565 @@ +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2019 Alexandre Ratchov + */ + +/* + * TODO : + * + * Use a single device and open it in full-duplex rather than + * opening it twice (once for playback once for recording). + * + * This is the only way to ensure that playback doesn't drift with respect + * to recording, which is what guest systems expect. + */ + +#include +#include +#include "qemu/osdep.h" +#include "qemu/main-loop.h" +#include "audio.h" +#include "trace.h" + +#define AUDIO_CAP "sndio" +#include "audio_int.h" + +/* default latency in microseconds if no option is set */ +#define SNDIO_LATENCY_US 50000 + +typedef struct SndioVoice { + union { + HWVoiceOut out; + HWVoiceIn in; + } hw; + struct sio_par par; + struct sio_hdl *hdl; + struct pollfd *pfds; + struct pollindex { + struct SndioVoice *self; + int index; + } *pindexes; + unsigned char *buf; + size_t buf_size; + size_t sndio_pos; + size_t qemu_pos; + unsigned int mode; + unsigned int nfds; + bool enabled; +} SndioVoice; + +typedef struct SndioConf { + const char *devname; + unsigned int latency; +} SndioConf; + +/* needed for forward reference */ +static void sndio_poll_in(void *arg); +static void sndio_poll_out(void *arg); + +/* + * stop polling descriptors + */ +static void sndio_poll_clear(SndioVoice *self) +{ + struct pollfd *pfd; + int i; + + for (i = 0; i < self->nfds; i++) { + pfd = &self->pfds[i]; + qemu_set_fd_handler(pfd->fd, NULL, NULL, NULL); + } + + self->nfds = 0; +} + +/* + * write data to the device until it blocks or + * all of our buffered data is written + */ +static void sndio_write(SndioVoice *self) +{ + size_t todo, n; + + todo = self->qemu_pos - self->sndio_pos; + + /* + * transfer data to device, until it blocks + */ + while (todo > 0) { + n = sio_write(self->hdl, self->buf + self->sndio_pos, todo); + if (n == 0) { + break; + } + self->sndio_pos += n; + todo -= n; + } + + if (self->sndio_pos == self->buf_size) { + /* + * we complete the block + */ + self->sndio_pos = 0; + self->qemu_pos = 0; + } +} + +/* + * read data from the device until it blocks or + * there no room any longer + */ +static void sndio_read(SndioVoice *self) +{ + size_t todo, n; + + todo = self->buf_size - self->sndio_pos; + + /* + * transfer data from the device, until it blocks + */ + while (todo > 0) { + n = sio_read(self->hdl, self->buf + self->sndio_pos, todo); + if (n == 0) { + break; + } + self->sndio_pos += n; + todo -= n; + } +} + +/* + * Set handlers for all descriptors libsndio needs to + * poll + */ +static void sndio_poll_wait(SndioVoice *self) +{ + struct pollfd *pfd; + int events, i; + + events = 0; + if (self->mode == SIO_PLAY) { + if (self->sndio_pos < self->qemu_pos) { + events |= POLLOUT; + } + } else { + if (self->sndio_pos < self->buf_size) { + events |= POLLIN; + } + } + + /* + * fill the given array of descriptors with the events sndio + * wants, they are different from our 'event' variable because + * sndio may use descriptors internally. + */ + self->nfds = sio_pollfd(self->hdl, self->pfds, events); + + for (i = 0; i < self->nfds; i++) { + pfd = &self->pfds[i]; + if (pfd->fd < 0) { + continue; + } + qemu_set_fd_handler(pfd->fd, + (pfd->events & POLLIN) ? sndio_poll_in : NULL, + (pfd->events & POLLOUT) ? sndio_poll_out : NULL, + &self->pindexes[i]); + pfd->revents = 0; + } +} + +/* + * call-back called when one of the descriptors + * became readable or writable + */ +static void sndio_poll_event(SndioVoice *self, int index, int event) +{ + int revents; + + /* + * ensure we're not called twice this cycle + */ + sndio_poll_clear(self); + + /* + * make self->pfds[] look as we're returning from poll syscal, + * this is how sio_revents expects events to be. + */ + self->pfds[index].revents = event; + + /* + * tell sndio to handle events and return whether we can read or + * write without blocking. + */ + revents = sio_revents(self->hdl, self->pfds); + if (self->mode == SIO_PLAY) { + if (revents & POLLOUT) { + sndio_write(self); + } + + if (self->qemu_pos < self->buf_size) { + audio_run(self->hw.out.s, "sndio_out"); + } + } else { + if (revents & POLLIN) { + sndio_read(self); + } + + if (self->qemu_pos < self->sndio_pos) { + audio_run(self->hw.in.s, "sndio_in"); + } + } + + /* + * audio_run() may have changed state + */ + if (self->enabled) { + sndio_poll_wait(self); + } +} + +/* + * return the upper limit of the amount of free play buffer space + */ +static size_t sndio_buffer_get_free(HWVoiceOut *hw) +{ + SndioVoice *self = (SndioVoice *) hw; + + return self->buf_size - self->qemu_pos; +} + +/* + * return a buffer where data to play can be stored, + * its size is stored in the location pointed by the size argument. + */ +static void *sndio_get_buffer_out(HWVoiceOut *hw, size_t *size) +{ + SndioVoice *self = (SndioVoice *) hw; + + *size = self->buf_size - self->qemu_pos; + return self->buf + self->qemu_pos; +} + +/* + * put back to sndio back-end a buffer returned by sndio_get_buffer_out() + */ +static size_t sndio_put_buffer_out(HWVoiceOut *hw, void *buf, size_t size) +{ + SndioVoice *self = (SndioVoice *) hw; + + self->qemu_pos += size; + sndio_poll_wait(self); + return size; +} + +/* + * return a buffer from where recorded data is available, + * its size is stored in the location pointed by the size argument. + * it may not exceed the initial value of "*size". + */ +static void *sndio_get_buffer_in(HWVoiceIn *hw, size_t *size) +{ + SndioVoice *self = (SndioVoice *) hw; + size_t todo, max_todo; + + /* + * unlike the get_buffer_out() method, get_buffer_in() + * must return a buffer of at most the given size, see audio.c + */ + max_todo = *size; + + todo = self->sndio_pos - self->qemu_pos; + if (todo > max_todo) { + todo = max_todo; + } + + *size = todo; + return self->buf + self->qemu_pos; +} + +/* + * discard the given amount of recorded data + */ +static void sndio_put_buffer_in(HWVoiceIn *hw, void *buf, size_t size) +{ + SndioVoice *self = (SndioVoice *) hw; + + self->qemu_pos += size; + if (self->qemu_pos == self->buf_size) { + self->qemu_pos = 0; + self->sndio_pos = 0; + } + sndio_poll_wait(self); +} + +/* + * call-back called when one of our descriptors becomes writable + */ +static void sndio_poll_out(void *arg) +{ + struct pollindex *pindex = (struct pollindex *) arg; + + sndio_poll_event(pindex->self, pindex->index, POLLOUT); +} + +/* + * call-back called when one of our descriptors becomes readable + */ +static void sndio_poll_in(void *arg) +{ + struct pollindex *pindex = (struct pollindex *) arg; + + sndio_poll_event(pindex->self, pindex->index, POLLIN); +} + +static void sndio_fini(SndioVoice *self) +{ + if (self->hdl) { + sio_close(self->hdl); + self->hdl = NULL; + } + + g_free(self->pfds); + g_free(self->pindexes); + g_free(self->buf); +} + +static int sndio_init(SndioVoice *self, + struct audsettings *as, int mode, Audiodev *dev) +{ + AudiodevSndioOptions *opts = &dev->u.sndio; + unsigned long long latency; + const char *dev_name; + struct sio_par req; + unsigned int nch; + int i, nfds; + + dev_name = opts->has_dev ? opts->dev : SIO_DEVANY; + latency = opts->has_latency ? opts->latency : SNDIO_LATENCY_US; + + /* open the device in non-blocking mode */ + self->hdl = sio_open(dev_name, mode, 1); + if (self->hdl == NULL) { + dolog("failed to open device\n"); + return -1; + } + + self->mode = mode; + + sio_initpar(&req); + + switch (as->fmt) { + case AUDIO_FORMAT_S8: + req.bits = 8; + req.sig = 1; + break; + case AUDIO_FORMAT_U8: + req.bits = 8; + req.sig = 0; + break; + case AUDIO_FORMAT_S16: + req.bits = 16; + req.sig = 1; + break; + case AUDIO_FORMAT_U16: + req.bits = 16; + req.sig = 0; + break; + case AUDIO_FORMAT_S32: + req.bits = 32; + req.sig = 1; + break; + case AUDIO_FORMAT_U32: + req.bits = 32; + req.sig = 0; + break; + default: + dolog("unknown audio sample format\n"); + return -1; + } + + if (req.bits > 8) { + req.le = as->endianness ? 0 : 1; + } + + req.rate = as->freq; + if (mode == SIO_PLAY) { + req.pchan = as->nchannels; + } else { + req.rchan = as->nchannels; + } + + /* set on-device buffer size */ + req.appbufsz = req.rate * latency / 1000000; + + if (!sio_setpar(self->hdl, &req)) { + dolog("failed set audio params\n"); + goto fail; + } + + if (!sio_getpar(self->hdl, &self->par)) { + dolog("failed get audio params\n"); + goto fail; + } + + nch = (mode == SIO_PLAY) ? self->par.pchan : self->par.rchan; + + /* + * With the default setup, sndio supports any combination of parameters + * so these checks are mostly to catch configuration errors. + */ + if (self->par.bits != req.bits || self->par.bps != req.bits / 8 || + self->par.sig != req.sig || (req.bits > 8 && self->par.le != req.le) || + self->par.rate != as->freq || nch != as->nchannels) { + dolog("unsupported audio params\n"); + goto fail; + } + + /* + * we use one block as buffer size; this is how + * transfers get well aligned + */ + self->buf_size = self->par.round * self->par.bps * nch; + + self->buf = g_malloc(self->buf_size); + if (self->buf == NULL) { + dolog("failed to allocate audio buffer\n"); + goto fail; + } + + nfds = sio_nfds(self->hdl); + + self->pfds = g_malloc_n(nfds, sizeof(struct pollfd)); + if (self->pfds == NULL) { + dolog("failed to allocate pollfd structures\n"); + goto fail; + } + + self->pindexes = g_malloc_n(nfds, sizeof(struct pollindex)); + if (self->pindexes == NULL) { + dolog("failed to allocate pollindex structures\n"); + goto fail; + } + + for (i = 0; i < nfds; i++) { + self->pindexes[i].self = self; + self->pindexes[i].index = i; + } + + return 0; +fail: + sndio_fini(self); + return -1; +} + +static void sndio_enable(SndioVoice *self, bool enable) +{ + if (enable) { + sio_start(self->hdl); + self->enabled = true; + sndio_poll_wait(self); + } else { + self->enabled = false; + sndio_poll_clear(self); + sio_stop(self->hdl); + } +} + +static void sndio_enable_out(HWVoiceOut *hw, bool enable) +{ + SndioVoice *self = (SndioVoice *) hw; + + sndio_enable(self, enable); +} + +static void sndio_enable_in(HWVoiceIn *hw, bool enable) +{ + SndioVoice *self = (SndioVoice *) hw; + + sndio_enable(self, enable); +} + +static int sndio_init_out(HWVoiceOut *hw, struct audsettings *as, void *opaque) +{ + SndioVoice *self = (SndioVoice *) hw; + + if (sndio_init(self, as, SIO_PLAY, opaque) == -1) { + return -1; + } + + audio_pcm_init_info(&hw->info, as); + hw->samples = self->par.round; + return 0; +} + +static int sndio_init_in(HWVoiceIn *hw, struct audsettings *as, void *opaque) +{ + SndioVoice *self = (SndioVoice *) hw; + + if (sndio_init(self, as, SIO_REC, opaque) == -1) { + return -1; + } + + audio_pcm_init_info(&hw->info, as); + hw->samples = self->par.round; + return 0; +} + +static void sndio_fini_out(HWVoiceOut *hw) +{ + SndioVoice *self = (SndioVoice *) hw; + + sndio_fini(self); +} + +static void sndio_fini_in(HWVoiceIn *hw) +{ + SndioVoice *self = (SndioVoice *) hw; + + sndio_fini(self); +} + +static void *sndio_audio_init(Audiodev *dev) +{ + assert(dev->driver == AUDIODEV_DRIVER_SNDIO); + return dev; +} + +static void sndio_audio_fini(void *opaque) +{ +} + +static struct audio_pcm_ops sndio_pcm_ops = { + .init_out = sndio_init_out, + .fini_out = sndio_fini_out, + .enable_out = sndio_enable_out, + .write = audio_generic_write, + .buffer_get_free = sndio_buffer_get_free, + .get_buffer_out = sndio_get_buffer_out, + .put_buffer_out = sndio_put_buffer_out, + .init_in = sndio_init_in, + .fini_in = sndio_fini_in, + .read = audio_generic_read, + .enable_in = sndio_enable_in, + .get_buffer_in = sndio_get_buffer_in, + .put_buffer_in = sndio_put_buffer_in, +}; + +static struct audio_driver sndio_audio_driver = { + .name = "sndio", + .descr = "sndio https://sndio.org", + .init = sndio_audio_init, + .fini = sndio_audio_fini, + .pcm_ops = &sndio_pcm_ops, + .can_be_default = 1, + .max_voices_out = INT_MAX, + .max_voices_in = INT_MAX, + .voice_size_out = sizeof(SndioVoice), + .voice_size_in = sizeof(SndioVoice) +}; + +static void register_audio_sndio(void) +{ + audio_driver_register(&sndio_audio_driver); +} + +type_init(register_audio_sndio); diff --git a/meson.build b/meson.build index d9ac91ff36..13db89c65a 100644 --- a/meson.build +++ b/meson.build @@ -675,6 +675,11 @@ if not get_option('jack').auto() or have_system jack = dependency('jack', required: get_option('jack'), method: 'pkg-config', kwargs: static_kwargs) endif +sndio = not_found +if not get_option('sndio').auto() or have_system + sndio = dependency('sndio', required: get_option('sndio'), + method: 'pkg-config', kwargs: static_kwargs) +endif spice_protocol = not_found if not get_option('spice_protocol').auto() or have_system @@ -1591,6 +1596,7 @@ if have_system 'oss': oss.found(), 'pa': pulse.found(), 'sdl': sdl.found(), + 'sndio': sndio.found(), } foreach k, v: audio_drivers_available config_host_data.set('CONFIG_AUDIO_' + k.to_upper(), v) @@ -1598,7 +1604,7 @@ if have_system # Default to native drivers first, OSS second, SDL third audio_drivers_priority = \ - [ 'pa', 'coreaudio', 'dsound', 'oss' ] + \ + [ 'pa', 'coreaudio', 'dsound', 'sndio', 'oss' ] + \ (targetos == 'linux' ? [] : [ 'sdl' ]) audio_drivers_default = [] foreach k: audio_drivers_priority @@ -3922,6 +3928,7 @@ if vnc.found() endif if targetos not in ['darwin', 'haiku', 'windows'] summary_info += {'OSS support': oss} + summary_info += {'sndio support': sndio} elif targetos == 'darwin' summary_info += {'CoreAudio support': coreaudio} elif targetos == 'windows' diff --git a/meson_options.txt b/meson_options.txt index 63f0725174..9df9e86d7d 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -21,7 +21,7 @@ option('tls_priority', type : 'string', value : 'NORMAL', option('default_devices', type : 'boolean', value : true, description: 'Include a default selection of devices in emulators') option('audio_drv_list', type: 'array', value: ['default'], - choices: ['alsa', 'coreaudio', 'default', 'dsound', 'jack', 'oss', 'pa', 'sdl'], + choices: ['alsa', 'coreaudio', 'default', 'dsound', 'jack', 'oss', 'pa', 'sdl', 'sndio'], description: 'Set audio driver list') option('block_drv_rw_whitelist', type : 'string', value : '', description: 'set block driver read-write whitelist (by default affects only QEMU, not tools like qemu-img)') @@ -240,6 +240,8 @@ option('oss', type: 'feature', value: 'auto', description: 'OSS sound support') option('pa', type: 'feature', value: 'auto', description: 'PulseAudio sound support') +option('sndio', type: 'feature', value: 'auto', + description: 'sndio sound support') option('vhost_kernel', type: 'feature', value: 'auto', description: 'vhost kernel backend support') diff --git a/qapi/audio.json b/qapi/audio.json index 8099e3d7f1..1e0a24bdfc 100644 --- a/qapi/audio.json +++ b/qapi/audio.json @@ -106,6 +106,28 @@ '*out': 'AudiodevAlsaPerDirectionOptions', '*threshold': 'uint32' } } +## +# @AudiodevSndioOptions: +# +# Options of the sndio audio backend. +# +# @in: options of the capture stream +# +# @out: options of the playback stream +# +# @dev: the name of the sndio device to use (default 'default') +# +# @latency: play buffer size (in microseconds) +# +# Since: 7.2 +## +{ 'struct': 'AudiodevSndioOptions', + 'data': { + '*in': 'AudiodevPerDirectionOptions', + '*out': 'AudiodevPerDirectionOptions', + '*dev': 'str', + '*latency': 'uint32'} } + ## # @AudiodevCoreaudioPerDirectionOptions: # @@ -387,7 +409,7 @@ ## { 'enum': 'AudiodevDriver', 'data': [ 'none', 'alsa', 'coreaudio', 'dbus', 'dsound', 'jack', 'oss', 'pa', - 'sdl', 'spice', 'wav' ] } + 'sdl', 'sndio', 'spice', 'wav' ] } ## # @Audiodev: @@ -418,5 +440,6 @@ 'oss': 'AudiodevOssOptions', 'pa': 'AudiodevPaOptions', 'sdl': 'AudiodevSdlOptions', + 'sndio': 'AudiodevSndioOptions', 'spice': 'AudiodevGenericOptions', 'wav': 'AudiodevWavOptions' } } diff --git a/qemu-options.hx b/qemu-options.hx index d8b5ce5b43..2ff06884f4 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -769,6 +769,9 @@ DEF("audiodev", HAS_ARG, QEMU_OPTION_audiodev, "-audiodev sdl,id=id[,prop[=value][,...]]\n" " in|out.buffer-count= number of buffers\n" #endif +#ifdef CONFIG_AUDIO_SNDIO + "-audiodev sndio,id=id[,prop[=value][,...]]\n" +#endif #ifdef CONFIG_SPICE "-audiodev spice,id=id[,prop[=value][,...]]\n" #endif @@ -935,6 +938,19 @@ SRST ``in|out.buffer-count=count`` Sets the count of the buffers. +``-audiodev sndio,id=id[,prop[=value][,...]]`` + Creates a backend using SNDIO. This backend is available on + OpenBSD and most other Unix-like systems. + + Sndio specific options are: + + ``in|out.dev=device`` + Specify the sndio device to use for input and/or output. Default + is ``default``. + + ``in|out.latency=usecs`` + Sets the desired period length in microseconds. + ``-audiodev spice,id=id[,prop[=value][,...]]`` Creates a backend that sends audio through SPICE. This backend requires ``-spice`` and automatically selected in that case, so diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index 359b04e0e6..f08e3a8a7e 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -1,7 +1,7 @@ # This file is generated by meson-buildoptions.py, do not edit! meson_options_help() { - printf "%s\n" ' --audio-drv-list=CHOICES Set audio driver list [default] (choices:' - printf "%s\n" ' alsa/coreaudio/default/dsound/jack/oss/pa/sdl)' + printf "%s\n" ' --audio-drv-list=CHOICES Set audio driver list [default] (choices: alsa/co' + printf "%s\n" ' reaudio/default/dsound/jack/oss/pa/sdl/sndio)' printf "%s\n" ' --block-drv-ro-whitelist=VALUE' printf "%s\n" ' set block driver read-only whitelist (by default' printf "%s\n" ' affects only QEMU, not tools like qemu-img)' @@ -144,6 +144,7 @@ meson_options_help() { printf "%s\n" ' slirp-smbd use smbd (at path --smbd=*) in slirp networking' printf "%s\n" ' smartcard CA smartcard emulation support' printf "%s\n" ' snappy snappy compression support' + printf "%s\n" ' sndio sndio sound support' printf "%s\n" ' sparse sparse checker' printf "%s\n" ' spice Spice server support' printf "%s\n" ' spice-protocol Spice protocol support' @@ -393,6 +394,8 @@ _meson_option_parse() { --disable-smartcard) printf "%s" -Dsmartcard=disabled ;; --enable-snappy) printf "%s" -Dsnappy=enabled ;; --disable-snappy) printf "%s" -Dsnappy=disabled ;; + --enable-sndio) printf "%s" -Dsndio=enabled ;; + --disable-sndio) printf "%s" -Dsndio=disabled ;; --enable-sparse) printf "%s" -Dsparse=enabled ;; --disable-sparse) printf "%s" -Dsparse=disabled ;; --sphinx-build=*) quote_sh "-Dsphinx_build=$2" ;; From 12f4abf6a245c43d8411577fd400373c85f08c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sat, 17 Sep 2022 15:16:25 +0200 Subject: [PATCH 0655/1020] Revert "audio: Log context for audio bug" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 8e30d39bade3010387177ca23dbc2244352ed4a3. Revert commit 8e30d39bad "audio: Log context for audio bug" to make error propagation work again. Signed-off-by: Volker RĂ¼melin Message-Id: <20220917131626.7521-1-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann --- audio/audio.c | 25 +++++++++++++------------ audio/audio_template.h | 27 +++++++++++++++------------ 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/audio/audio.c b/audio/audio.c index 5600593da0..d96a130559 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -118,6 +118,7 @@ int audio_bug (const char *funcname, int cond) AUD_log (NULL, "I am sorry\n"); } AUD_log (NULL, "Context:\n"); + abort(); } return cond; @@ -138,7 +139,7 @@ static inline int audio_bits_to_index (int bits) default: audio_bug ("bits_to_index", 1); AUD_log (NULL, "invalid bits %d\n", bits); - abort(); + return 0; } } @@ -156,7 +157,7 @@ void *audio_calloc (const char *funcname, int nmemb, size_t size) AUD_log (NULL, "%s passed invalid arguments to audio_calloc\n", funcname); AUD_log (NULL, "nmemb=%d size=%zu (len=%zu)\n", nmemb, size, len); - abort(); + return NULL; } return g_malloc0 (len); @@ -543,7 +544,7 @@ static size_t audio_pcm_hw_get_live_in(HWVoiceIn *hw) size_t live = hw->total_samples_captured - audio_pcm_hw_find_min_in (hw); if (audio_bug(__func__, live > hw->conv_buf->size)) { dolog("live=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); - abort(); + return 0; } return live; } @@ -581,7 +582,7 @@ static size_t audio_pcm_sw_read(SWVoiceIn *sw, void *buf, size_t size) } if (audio_bug(__func__, live > hw->conv_buf->size)) { dolog("live_in=%zu hw->conv_buf->size=%zu\n", live, hw->conv_buf->size); - abort(); + return 0; } rpos = audio_ring_posb(hw->conv_buf->pos, live, hw->conv_buf->size); @@ -656,7 +657,7 @@ static size_t audio_pcm_hw_get_live_out (HWVoiceOut *hw, int *nb_live) if (audio_bug(__func__, live > hw->mix_buf->size)) { dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); - abort(); + return 0; } return live; } @@ -706,7 +707,7 @@ static size_t audio_pcm_sw_write(SWVoiceOut *sw, void *buf, size_t size) live = sw->total_hw_samples_mixed; if (audio_bug(__func__, live > hwsamples)) { dolog("live=%zu hw->mix_buf->size=%zu\n", live, hwsamples); - abort(); + return 0; } if (live == hwsamples) { @@ -998,7 +999,7 @@ static size_t audio_get_avail (SWVoiceIn *sw) if (audio_bug(__func__, live > sw->hw->conv_buf->size)) { dolog("live=%zu sw->hw->conv_buf->size=%zu\n", live, sw->hw->conv_buf->size); - abort(); + return 0; } ldebug ( @@ -1028,7 +1029,7 @@ static size_t audio_get_free(SWVoiceOut *sw) if (audio_bug(__func__, live > sw->hw->mix_buf->size)) { dolog("live=%zu sw->hw->mix_buf->size=%zu\n", live, sw->hw->mix_buf->size); - abort(); + return 0; } dead = sw->hw->mix_buf->size - live; @@ -1170,7 +1171,7 @@ static void audio_run_out (AudioState *s) if (audio_bug(__func__, live > hw->mix_buf->size)) { dolog("live=%zu hw->mix_buf->size=%zu\n", live, hw->mix_buf->size); - abort(); + continue; } if (hw->pending_disable && !nb_live) { @@ -1203,7 +1204,7 @@ static void audio_run_out (AudioState *s) if (audio_bug(__func__, hw->mix_buf->pos >= hw->mix_buf->size)) { dolog("hw->mix_buf->pos=%zu hw->mix_buf->size=%zu played=%zu\n", hw->mix_buf->pos, hw->mix_buf->size, played); - abort(); + hw->mix_buf->pos = 0; } #ifdef DEBUG_OUT @@ -1223,7 +1224,7 @@ static void audio_run_out (AudioState *s) if (audio_bug(__func__, played > sw->total_hw_samples_mixed)) { dolog("played=%zu sw->total_hw_samples_mixed=%zu\n", played, sw->total_hw_samples_mixed); - abort(); + played = sw->total_hw_samples_mixed; } sw->total_hw_samples_mixed -= played; @@ -1346,7 +1347,7 @@ static void audio_run_capture (AudioState *s) if (audio_bug(__func__, captured > sw->total_hw_samples_mixed)) { dolog("captured=%zu sw->total_hw_samples_mixed=%zu\n", captured, sw->total_hw_samples_mixed); - abort(); + captured = sw->total_hw_samples_mixed; } sw->total_hw_samples_mixed -= captured; diff --git a/audio/audio_template.h b/audio/audio_template.h index 81860cea62..98ab557684 100644 --- a/audio/audio_template.h +++ b/audio/audio_template.h @@ -59,13 +59,12 @@ static void glue(audio_init_nb_voices_, TYPE)(AudioState *s, if (audio_bug(__func__, !voice_size && max_voices)) { dolog ("drv=`%s' voice_size=0 max_voices=%d\n", drv->name, max_voices); - abort(); + glue (s->nb_hw_voices_, TYPE) = 0; } if (audio_bug(__func__, voice_size && !max_voices)) { dolog ("drv=`%s' voice_size=%d max_voices=0\n", drv->name, voice_size); - abort(); } } @@ -82,7 +81,6 @@ static void glue(audio_pcm_hw_alloc_resources_, TYPE)(HW *hw) size_t samples = hw->samples; if (audio_bug(__func__, samples == 0)) { dolog("Attempted to allocate empty buffer\n"); - abort(); } HWBUF = g_malloc0(sizeof(STSampleBuffer) + sizeof(st_sample) * samples); @@ -254,12 +252,12 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, if (audio_bug(__func__, !drv)) { dolog ("No host audio driver\n"); - abort(); + return NULL; } if (audio_bug(__func__, !drv->pcm_ops)) { dolog ("Host audio driver without pcm_ops\n"); - abort(); + return NULL; } hw = audio_calloc(__func__, 1, glue(drv->voice_size_, TYPE)); @@ -277,13 +275,12 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, QLIST_INIT (&hw->cap_head); #endif if (glue (hw->pcm_ops->init_, TYPE) (hw, as, s->drv_opaque)) { - g_free(hw); - return NULL; + goto err0; } if (audio_bug(__func__, hw->samples <= 0)) { dolog("hw->samples=%zd\n", hw->samples); - abort(); + goto err1; } if (hw->info.is_float) { @@ -312,6 +309,12 @@ static HW *glue(audio_pcm_hw_add_new_, TYPE)(AudioState *s, audio_attach_capture (hw); #endif return hw; + + err1: + glue (hw->pcm_ops->fini_, TYPE) (hw); + err0: + g_free (hw); + return NULL; } AudiodevPerDirectionOptions *glue(audio_get_pdo_, TYPE)(Audiodev *dev) @@ -434,7 +437,7 @@ void glue (AUD_close_, TYPE) (QEMUSoundCard *card, SW *sw) if (sw) { if (audio_bug(__func__, !card)) { dolog ("card=%p\n", card); - abort(); + return; } glue (audio_close_, TYPE) (sw); @@ -456,7 +459,7 @@ SW *glue (AUD_open_, TYPE) ( if (audio_bug(__func__, !card || !name || !callback_fn || !as)) { dolog ("card=%p name=%p callback_fn=%p as=%p\n", card, name, callback_fn, as); - abort(); + goto fail; } s = card->state; @@ -467,12 +470,12 @@ SW *glue (AUD_open_, TYPE) ( if (audio_bug(__func__, audio_validate_settings(as))) { audio_print_settings (as); - abort(); + goto fail; } if (audio_bug(__func__, !s->drv)) { dolog ("Can not open `%s' (no host audio driver)\n", name); - abort(); + goto fail; } if (sw && audio_pcm_info_eq (&sw->info, as)) { From 0cbc8bd4694f32687bf47c6da48efa48fac35fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Volker=20R=C3=BCmelin?= Date: Sat, 17 Sep 2022 15:16:26 +0200 Subject: [PATCH 0656/1020] audio: remove abort() in audio_bug() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit ab32b78cd1 "audio: Simplify audio_bug() removing old code" introduced abort() in audio_bug() for regular builds. audio_bug() was never meant to abort QEMU for the following reasons. - There's code in audio_bug() that expects audio_bug() gets called more than once with error condition true. The variable 'shown' is only 0 on first error. - All call sites test the return code of audio_bug(), print an error context message and handle the errror. - The abort() in audio_bug() enables a class of guest-triggered aborts similar to the Launchpad Bug #1910603 at https://bugs.launchpad.net/bugs/1910603. Fixes: ab32b78cd1 "audio: Simplify audio_bug() removing old code" Buglink: https://bugs.launchpad.net/bugs/1910603 Signed-off-by: Volker RĂ¼melin Message-Id: <20220917131626.7521-2-vr_qemu@t-online.de> Signed-off-by: Gerd Hoffmann --- audio/audio.c | 1 - 1 file changed, 1 deletion(-) diff --git a/audio/audio.c b/audio/audio.c index d96a130559..df6818ed55 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -118,7 +118,6 @@ int audio_bug (const char *funcname, int cond) AUD_log (NULL, "I am sorry\n"); } AUD_log (NULL, "Context:\n"); - abort(); } return cond; From 205ccfd7a5ec86bd9a5678b8bd157562fc9a1643 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 6 Sep 2021 17:31:03 +0200 Subject: [PATCH 0657/1020] hw/display/ati_2d: Fix buffer overflow in ati_2d_blt (CVE-2021-3638) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building QEMU with DEBUG_ATI defined then running with '-device ati-vga,romfile="" -d unimp,guest_errors -trace ati\*' we get: ati_mm_write 4 0x16c0 DP_CNTL <- 0x1 ati_mm_write 4 0x146c DP_GUI_MASTER_CNTL <- 0x2 ati_mm_write 4 0x16c8 DP_MIX <- 0xff0000 ati_mm_write 4 0x16c4 DP_DATATYPE <- 0x2 ati_mm_write 4 0x224 CRTC_OFFSET <- 0x0 ati_mm_write 4 0x142c DST_PITCH_OFFSET <- 0xfe00000 ati_mm_write 4 0x1420 DST_Y <- 0x3fff ati_mm_write 4 0x1410 DST_HEIGHT <- 0x3fff ati_mm_write 4 0x1588 DST_WIDTH_X <- 0x3fff3fff ati_2d_blt: vram:0x7fff5fa00000 addr:0 ds:0x7fff61273800 stride:2560 bpp:32 rop:0xff ati_2d_blt: 0 0 0, 0 127 0, (0,0) -> (16383,16383) 16383x16383 > ^ ati_2d_blt: pixman_fill(dst:0x7fff5fa00000, stride:254, bpp:8, x:16383, y:16383, w:16383, h:16383, xor:0xff000000) Thread 3 "qemu-system-i38" received signal SIGSEGV, Segmentation fault. (gdb) bt #0 0x00007ffff7f62ce0 in sse2_fill.lto_priv () at /lib64/libpixman-1.so.0 #1 0x00007ffff7f09278 in pixman_fill () at /lib64/libpixman-1.so.0 #2 0x0000555557b5a9af in ati_2d_blt (s=0x631000028800) at hw/display/ati_2d.c:196 #3 0x0000555557b4b5a2 in ati_mm_write (opaque=0x631000028800, addr=5512, data=1073692671, size=4) at hw/display/ati.c:843 #4 0x0000555558b90ec4 in memory_region_write_accessor (mr=0x631000039cc0, addr=5512, ..., size=4, ...) at softmmu/memory.c:492 Commit 584acf34cb0 ("ati-vga: Fix reverse bit blts") introduced the local dst_x and dst_y which adjust the (x, y) coordinates depending on the direction in the SRCCOPY ROP3 operation, but forgot to address the same issue for the PATCOPY, BLACKNESS and WHITENESS operations, which also call pixman_fill(). Fix that now by using the adjusted coordinates in the pixman_fill call, and update the related debug printf(). Reported-by: Qiang Liu Fixes: 584acf34cb0 ("ati-vga: Fix reverse bit blts") Signed-off-by: Philippe Mathieu-DaudĂ© Tested-by: Mauro Matteo Cascella Message-Id: <20210906153103.1661195-1-philmd@redhat.com> Signed-off-by: Gerd Hoffmann --- hw/display/ati_2d.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hw/display/ati_2d.c b/hw/display/ati_2d.c index 4dc10ea795..692bec91de 100644 --- a/hw/display/ati_2d.c +++ b/hw/display/ati_2d.c @@ -84,7 +84,7 @@ void ati_2d_blt(ATIVGAState *s) DPRINTF("%d %d %d, %d %d %d, (%d,%d) -> (%d,%d) %dx%d %c %c\n", s->regs.src_offset, s->regs.dst_offset, s->regs.default_offset, s->regs.src_pitch, s->regs.dst_pitch, s->regs.default_pitch, - s->regs.src_x, s->regs.src_y, s->regs.dst_x, s->regs.dst_y, + s->regs.src_x, s->regs.src_y, dst_x, dst_y, s->regs.dst_width, s->regs.dst_height, (s->regs.dp_cntl & DST_X_LEFT_TO_RIGHT ? '>' : '<'), (s->regs.dp_cntl & DST_Y_TOP_TO_BOTTOM ? 'v' : '^')); @@ -180,11 +180,11 @@ void ati_2d_blt(ATIVGAState *s) dst_stride /= sizeof(uint32_t); DPRINTF("pixman_fill(%p, %d, %d, %d, %d, %d, %d, %x)\n", dst_bits, dst_stride, bpp, - s->regs.dst_x, s->regs.dst_y, + dst_x, dst_y, s->regs.dst_width, s->regs.dst_height, filler); pixman_fill((uint32_t *)dst_bits, dst_stride, bpp, - s->regs.dst_x, s->regs.dst_y, + dst_x, dst_y, s->regs.dst_width, s->regs.dst_height, filler); if (dst_bits >= s->vga.vram_ptr + s->vga.vbe_start_addr && From 49a99ecb2290571b2e3f464c13e9c73b87ca91c4 Mon Sep 17 00:00:00 2001 From: Dongwon Kim Date: Thu, 8 Sep 2022 18:40:52 -0700 Subject: [PATCH 0658/1020] virtio-gpu: update scanout if there is any area covered by the rect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The scanout is currently updated only if the whole rect is inside the scanout space. This is not a correct condition because the scanout should be updated even a small area in the scanout space is covered by the rect. Cc: Gerd Hoffmann Signed-off-by: Dongwon Kim Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220909014052.7297-1-dongwon.kim@intel.com> Signed-off-by: Gerd Hoffmann --- hw/display/virtio-gpu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c index 20cc703dcc..5e15c79b94 100644 --- a/hw/display/virtio-gpu.c +++ b/hw/display/virtio-gpu.c @@ -515,9 +515,10 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g, for (i = 0; i < g->parent_obj.conf.max_outputs; i++) { scanout = &g->parent_obj.scanout[i]; if (scanout->resource_id == res->resource_id && - rf.r.x >= scanout->x && rf.r.y >= scanout->y && - rf.r.x + rf.r.width <= scanout->x + scanout->width && - rf.r.y + rf.r.height <= scanout->y + scanout->height && + rf.r.x < scanout->x + scanout->width && + rf.r.x + rf.r.width >= scanout->x && + rf.r.y < scanout->y + scanout->height && + rf.r.y + rf.r.height >= scanout->y && console_has_gl(scanout->con)) { dpy_gl_update(scanout->con, 0, 0, scanout->width, scanout->height); From 8dc2779180f0cadd7df93a946b84c8117955d299 Mon Sep 17 00:00:00 2001 From: Ding Hui Date: Wed, 14 Sep 2022 20:16:47 +0800 Subject: [PATCH 0659/1020] e1000e: set RX desc status with DD flag in a separate operation Like commit 034d00d48581 ("e1000: set RX descriptor status in a separate operation"), there is also same issue in e1000e, which would cause lost packets or stop sending packets to VM with DPDK. Do similar fix in e1000e. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/402 Signed-off-by: Ding Hui Signed-off-by: Jason Wang --- hw/net/e1000e_core.c | 53 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/hw/net/e1000e_core.c b/hw/net/e1000e_core.c index 82aa61fedc..fc9cdb4528 100644 --- a/hw/net/e1000e_core.c +++ b/hw/net/e1000e_core.c @@ -1364,6 +1364,57 @@ struct NetRxPkt *pkt, const E1000E_RSSInfo *rss_info, } } +static inline void +e1000e_pci_dma_write_rx_desc(E1000ECore *core, dma_addr_t addr, + uint8_t *desc, dma_addr_t len) +{ + PCIDevice *dev = core->owner; + + if (e1000e_rx_use_legacy_descriptor(core)) { + struct e1000_rx_desc *d = (struct e1000_rx_desc *) desc; + size_t offset = offsetof(struct e1000_rx_desc, status); + uint8_t status = d->status; + + d->status &= ~E1000_RXD_STAT_DD; + pci_dma_write(dev, addr, desc, len); + + if (status & E1000_RXD_STAT_DD) { + d->status = status; + pci_dma_write(dev, addr + offset, &status, sizeof(status)); + } + } else { + if (core->mac[RCTL] & E1000_RCTL_DTYP_PS) { + union e1000_rx_desc_packet_split *d = + (union e1000_rx_desc_packet_split *) desc; + size_t offset = offsetof(union e1000_rx_desc_packet_split, + wb.middle.status_error); + uint32_t status = d->wb.middle.status_error; + + d->wb.middle.status_error &= ~E1000_RXD_STAT_DD; + pci_dma_write(dev, addr, desc, len); + + if (status & E1000_RXD_STAT_DD) { + d->wb.middle.status_error = status; + pci_dma_write(dev, addr + offset, &status, sizeof(status)); + } + } else { + union e1000_rx_desc_extended *d = + (union e1000_rx_desc_extended *) desc; + size_t offset = offsetof(union e1000_rx_desc_extended, + wb.upper.status_error); + uint32_t status = d->wb.upper.status_error; + + d->wb.upper.status_error &= ~E1000_RXD_STAT_DD; + pci_dma_write(dev, addr, desc, len); + + if (status & E1000_RXD_STAT_DD) { + d->wb.upper.status_error = status; + pci_dma_write(dev, addr + offset, &status, sizeof(status)); + } + } + } +} + typedef struct e1000e_ba_state_st { uint16_t written[MAX_PS_BUFFERS]; uint8_t cur_idx; @@ -1600,7 +1651,7 @@ e1000e_write_packet_to_guest(E1000ECore *core, struct NetRxPkt *pkt, e1000e_write_rx_descr(core, desc, is_last ? core->rx_pkt : NULL, rss_info, do_ps ? ps_hdr_len : 0, &bastate.written); - pci_dma_write(d, base, &desc, core->rx_desc_len); + e1000e_pci_dma_write_rx_desc(core, base, desc, core->rx_desc_len); e1000e_ring_advance(core, rxi, core->rx_desc_len / E1000_MIN_RX_DESC_LEN); From 17fb889f8a63ceba94d02d21781750b48e0705a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 6 Sep 2022 17:07:14 +0200 Subject: [PATCH 0660/1020] vdpa: Make VhostVDPAState cvq_cmd_in_buffer control ack type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows to simplify the code. Rename to status while we're at it. Signed-off-by: Eugenio PĂ©rez Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 6ce68fcd3f..535315c1d0 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -35,7 +35,9 @@ typedef struct VhostVDPAState { VHostNetState *vhost_net; /* Control commands shadow buffers */ - void *cvq_cmd_out_buffer, *cvq_cmd_in_buffer; + void *cvq_cmd_out_buffer; + virtio_net_ctrl_ack *status; + bool started; } VhostVDPAState; @@ -158,7 +160,7 @@ static void vhost_vdpa_cleanup(NetClientState *nc) struct vhost_dev *dev = &s->vhost_net->dev; qemu_vfree(s->cvq_cmd_out_buffer); - qemu_vfree(s->cvq_cmd_in_buffer); + qemu_vfree(s->status); if (dev->vq_index + dev->nvqs == dev->vq_index_end) { g_clear_pointer(&s->vhost_vdpa.iova_tree, vhost_iova_tree_delete); } @@ -310,7 +312,7 @@ static int vhost_vdpa_net_cvq_start(NetClientState *nc) return r; } - r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer, + r = vhost_vdpa_cvq_map_buf(&s->vhost_vdpa, s->status, vhost_vdpa_net_cvq_cmd_page_len(), true); if (unlikely(r < 0)) { vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); @@ -327,7 +329,7 @@ static void vhost_vdpa_net_cvq_stop(NetClientState *nc) if (s->vhost_vdpa.shadow_vqs_enabled) { vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_out_buffer); - vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->cvq_cmd_in_buffer); + vhost_vdpa_cvq_unmap_buf(&s->vhost_vdpa, s->status); } } @@ -340,7 +342,7 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, .iov_len = out_len, }; const struct iovec in = { - .iov_base = s->cvq_cmd_in_buffer, + .iov_base = s->status, .iov_len = sizeof(virtio_net_ctrl_ack), }; VhostShadowVirtqueue *svq = g_ptr_array_index(s->vhost_vdpa.shadow_vqs, 0); @@ -396,7 +398,7 @@ static int vhost_vdpa_net_load(NetClientState *nc) return dev_written; } - return *((virtio_net_ctrl_ack *)s->cvq_cmd_in_buffer) != VIRTIO_NET_OK; + return *s->status != VIRTIO_NET_OK; } return 0; @@ -491,8 +493,7 @@ static int vhost_vdpa_net_handle_ctrl_avail(VhostShadowVirtqueue *svq, goto out; } - memcpy(&status, s->cvq_cmd_in_buffer, sizeof(status)); - if (status != VIRTIO_NET_OK) { + if (*s->status != VIRTIO_NET_OK) { return VIRTIO_NET_ERR; } @@ -549,9 +550,9 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer, s->cvq_cmd_out_buffer = qemu_memalign(qemu_real_host_page_size(), vhost_vdpa_net_cvq_cmd_page_len()); memset(s->cvq_cmd_out_buffer, 0, vhost_vdpa_net_cvq_cmd_page_len()); - s->cvq_cmd_in_buffer = qemu_memalign(qemu_real_host_page_size(), - vhost_vdpa_net_cvq_cmd_page_len()); - memset(s->cvq_cmd_in_buffer, 0, vhost_vdpa_net_cvq_cmd_page_len()); + s->status = qemu_memalign(qemu_real_host_page_size(), + vhost_vdpa_net_cvq_cmd_page_len()); + memset(s->status, 0, vhost_vdpa_net_cvq_cmd_page_len()); s->vhost_vdpa.shadow_vq_ops = &vhost_vdpa_net_svq_ops; s->vhost_vdpa.shadow_vq_ops_opaque = s; From f73c0c43ac1ddeb21804b8683e1c674ad1b4c7d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 6 Sep 2022 17:07:15 +0200 Subject: [PATCH 0661/1020] vdpa: extract vhost_vdpa_net_load_mac from vhost_vdpa_net_load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since there may be many commands we need to issue to load the NIC state, let's split them in individual functions Signed-off-by: Eugenio PĂ©rez Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 62 +++++++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 535315c1d0..e799e744cd 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -365,12 +365,47 @@ static ssize_t vhost_vdpa_net_cvq_add(VhostVDPAState *s, size_t out_len, return vhost_svq_poll(svq); } +static ssize_t vhost_vdpa_net_load_cmd(VhostVDPAState *s, uint8_t class, + uint8_t cmd, const void *data, + size_t data_size) +{ + const struct virtio_net_ctrl_hdr ctrl = { + .class = class, + .cmd = cmd, + }; + + assert(data_size < vhost_vdpa_net_cvq_cmd_page_len() - sizeof(ctrl)); + + memcpy(s->cvq_cmd_out_buffer, &ctrl, sizeof(ctrl)); + memcpy(s->cvq_cmd_out_buffer + sizeof(ctrl), data, data_size); + + return vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + data_size, + sizeof(virtio_net_ctrl_ack)); +} + +static int vhost_vdpa_net_load_mac(VhostVDPAState *s, const VirtIONet *n) +{ + uint64_t features = n->parent_obj.guest_features; + if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) { + ssize_t dev_written = vhost_vdpa_net_load_cmd(s, VIRTIO_NET_CTRL_MAC, + VIRTIO_NET_CTRL_MAC_ADDR_SET, + n->mac, sizeof(n->mac)); + if (unlikely(dev_written < 0)) { + return dev_written; + } + + return *s->status != VIRTIO_NET_OK; + } + + return 0; +} + static int vhost_vdpa_net_load(NetClientState *nc) { VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); - const struct vhost_vdpa *v = &s->vhost_vdpa; + struct vhost_vdpa *v = &s->vhost_vdpa; const VirtIONet *n; - uint64_t features; + int r; assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA); @@ -379,26 +414,9 @@ static int vhost_vdpa_net_load(NetClientState *nc) } n = VIRTIO_NET(v->dev->vdev); - features = n->parent_obj.guest_features; - if (features & BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR)) { - const struct virtio_net_ctrl_hdr ctrl = { - .class = VIRTIO_NET_CTRL_MAC, - .cmd = VIRTIO_NET_CTRL_MAC_ADDR_SET, - }; - char *cursor = s->cvq_cmd_out_buffer; - ssize_t dev_written; - - memcpy(cursor, &ctrl, sizeof(ctrl)); - cursor += sizeof(ctrl); - memcpy(cursor, n->mac, sizeof(n->mac)); - - dev_written = vhost_vdpa_net_cvq_add(s, sizeof(ctrl) + sizeof(n->mac), - sizeof(virtio_net_ctrl_ack)); - if (unlikely(dev_written < 0)) { - return dev_written; - } - - return *s->status != VIRTIO_NET_OK; + r = vhost_vdpa_net_load_mac(s, n); + if (unlikely(r < 0)) { + return r; } return 0; From f64c7cda6973b0ea7477d999b11139306b3d04d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 6 Sep 2022 17:07:16 +0200 Subject: [PATCH 0662/1020] vdpa: Add vhost_vdpa_net_load_mq MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Same way as with the MAC, restore the expected number of queues at device's start. Signed-off-by: Eugenio PĂ©rez Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index e799e744cd..3950e4f25d 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -400,6 +400,28 @@ static int vhost_vdpa_net_load_mac(VhostVDPAState *s, const VirtIONet *n) return 0; } +static int vhost_vdpa_net_load_mq(VhostVDPAState *s, + const VirtIONet *n) +{ + struct virtio_net_ctrl_mq mq; + uint64_t features = n->parent_obj.guest_features; + ssize_t dev_written; + + if (!(features & BIT_ULL(VIRTIO_NET_F_MQ))) { + return 0; + } + + mq.virtqueue_pairs = cpu_to_le16(n->curr_queue_pairs); + dev_written = vhost_vdpa_net_load_cmd(s, VIRTIO_NET_CTRL_MQ, + VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &mq, + sizeof(mq)); + if (unlikely(dev_written < 0)) { + return dev_written; + } + + return *s->status != VIRTIO_NET_OK; +} + static int vhost_vdpa_net_load(NetClientState *nc) { VhostVDPAState *s = DO_UPCAST(VhostVDPAState, nc, nc); @@ -418,6 +440,10 @@ static int vhost_vdpa_net_load(NetClientState *nc) if (unlikely(r < 0)) { return r; } + r = vhost_vdpa_net_load_mq(s, n); + if (unlikely(r)) { + return r; + } return 0; } From 275ba561cd3f7b17675046792ecbdea184e948f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 6 Sep 2022 17:07:17 +0200 Subject: [PATCH 0663/1020] vdpa: validate MQ CVQ commands MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So we are sure we can update the device model properly before sending to the device. Signed-off-by: Eugenio PĂ©rez Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 3950e4f25d..c6cbe2fb5c 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -486,6 +486,15 @@ static bool vhost_vdpa_net_cvq_validate_cmd(const void *out_buf, size_t len) __func__, ctrl.cmd); }; break; + case VIRTIO_NET_CTRL_MQ: + switch (ctrl.cmd) { + case VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET: + return true; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid mq cmd %u\n", + __func__, ctrl.cmd); + }; + break; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid control class %u\n", __func__, ctrl.class); From ca8717f931463833da3ce5ca9712c9341ba8c308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 6 Sep 2022 17:07:18 +0200 Subject: [PATCH 0664/1020] virtio-net: Update virtio-net curr_queue_pairs in vdpa backends MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was returned as error before. Instead of it, simply update the corresponding field so qemu can send it in the migration data. Signed-off-by: Eugenio PĂ©rez Acked-by: Si-Wei Liu Signed-off-by: Jason Wang --- hw/net/virtio-net.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index dd0d056fde..63a8332cd0 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -1412,19 +1412,14 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd, return VIRTIO_NET_ERR; } - /* Avoid changing the number of queue_pairs for vdpa device in - * userspace handler. A future fix is needed to handle the mq - * change in userspace handler with vhost-vdpa. Let's disable - * the mq handling from userspace for now and only allow get - * done through the kernel. Ripples may be seen when falling - * back to userspace, but without doing it qemu process would - * crash on a recursive entry to virtio_net_set_status(). - */ - if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { - return VIRTIO_NET_ERR; - } - n->curr_queue_pairs = queue_pairs; + if (nc->peer && nc->peer->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) { + /* + * Avoid updating the backend for a vdpa device: We're only interested + * in updating the device model queues. + */ + return VIRTIO_NET_OK; + } /* stop the backend before changing the number of queue_pairs to avoid handling a * disabled queue */ virtio_net_set_status(vdev, vdev->status); From 72b99a87cebf803b4427297a59b44d090c065eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eugenio=20P=C3=A9rez?= Date: Tue, 6 Sep 2022 17:07:19 +0200 Subject: [PATCH 0665/1020] vdpa: Allow MQ feature in SVQ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finally enable SVQ with MQ feature. Signed-off-by: Eugenio PĂ©rez Signed-off-by: Jason Wang --- net/vhost-vdpa.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index c6cbe2fb5c..4bc3fd01a8 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -94,6 +94,7 @@ static const uint64_t vdpa_svq_device_features = BIT_ULL(VIRTIO_NET_F_MRG_RXBUF) | BIT_ULL(VIRTIO_NET_F_STATUS) | BIT_ULL(VIRTIO_NET_F_CTRL_VQ) | + BIT_ULL(VIRTIO_NET_F_MQ) | BIT_ULL(VIRTIO_F_ANY_LAYOUT) | BIT_ULL(VIRTIO_NET_F_CTRL_MAC_ADDR) | BIT_ULL(VIRTIO_NET_F_RSC_EXT) | From bf769f742c3624952f125b303878a77ea870c156 Mon Sep 17 00:00:00 2001 From: lu zhipeng Date: Fri, 23 Sep 2022 23:50:46 +0800 Subject: [PATCH 0666/1020] virtio: del net client if net_init_tap_one failed If the net tap initializes successful, but failed during network card hot-plugging, the net-tap will remains, so cleanup. Signed-off-by: lu zhipeng Signed-off-by: Jason Wang --- net/tap.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/net/tap.c b/net/tap.c index b3ddfd4a74..e203d07a12 100644 --- a/net/tap.c +++ b/net/tap.c @@ -686,7 +686,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, tap_set_sndbuf(s->fd, tap, &err); if (err) { error_propagate(errp, err); - return; + goto failed; } if (tap->has_fd || tap->has_fds) { @@ -726,12 +726,12 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } else { warn_report_err(err); } - return; + goto failed; } if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) { error_setg_errno(errp, errno, "%s: Can't use file descriptor %d", name, fd); - return; + goto failed; } } else { vhostfd = open("/dev/vhost-net", O_RDWR); @@ -743,11 +743,11 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, warn_report("tap: open vhost char device failed: %s", strerror(errno)); } - return; + goto failed; } if (!g_unix_set_fd_nonblocking(vhostfd, true, NULL)) { error_setg_errno(errp, errno, "Failed to set FD nonblocking"); - return; + goto failed; } } options.opaque = (void *)(uintptr_t)vhostfd; @@ -760,11 +760,17 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, } else { warn_report(VHOST_NET_INIT_FAILED); } - return; + goto failed; } } else if (vhostfdname) { error_setg(errp, "vhostfd(s)= is not valid without vhost"); + goto failed; } + + return; + +failed: + qemu_del_net_client(&s->nc); } static int get_fds(char *str, char *fds[], int max) From 7b72aa1d81d263c9d84bc02b89ea10892a08b451 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:44 +0200 Subject: [PATCH 0667/1020] linux-user: Add missing signals in strace output Some of the guest signal numbers are currently not converted to their representative names in the strace output, e.g. SIGVTALRM. This patch introduces a smart way to generate and keep in sync the host-to-guest and guest-to-host signal conversion tables for usage in the qemu signal and strace code. This ensures that any signals will now show up in both tables. There is no functional change in this patch - with the exception that yet missing signal names now show up in the strace code too. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20220918194555.83535-2-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/signal-common.h | 46 ++++++++++++++++++++++++++++++++++++++ linux-user/signal.c | 37 +++--------------------------- linux-user/strace.c | 30 +++++++++---------------- 3 files changed, 60 insertions(+), 53 deletions(-) diff --git a/linux-user/signal-common.h b/linux-user/signal-common.h index 6a7e4a93fc..3e2dc604c2 100644 --- a/linux-user/signal-common.h +++ b/linux-user/signal-common.h @@ -118,4 +118,50 @@ static inline void finish_sigsuspend_mask(int ret) } } +#if defined(SIGSTKFLT) && defined(TARGET_SIGSTKFLT) +#define MAKE_SIG_ENTRY_SIGSTKFLT MAKE_SIG_ENTRY(SIGSTKFLT) +#else +#define MAKE_SIG_ENTRY_SIGSTKFLT +#endif + +#if defined(SIGIOT) && defined(TARGET_SIGIOT) +#define MAKE_SIG_ENTRY_SIGIOT MAKE_SIG_ENTRY(SIGIOT) +#else +#define MAKE_SIG_ENTRY_SIGIOT +#endif + +#define MAKE_SIGNAL_LIST \ + MAKE_SIG_ENTRY(SIGHUP) \ + MAKE_SIG_ENTRY(SIGINT) \ + MAKE_SIG_ENTRY(SIGQUIT) \ + MAKE_SIG_ENTRY(SIGILL) \ + MAKE_SIG_ENTRY(SIGTRAP) \ + MAKE_SIG_ENTRY(SIGABRT) \ + MAKE_SIG_ENTRY(SIGBUS) \ + MAKE_SIG_ENTRY(SIGFPE) \ + MAKE_SIG_ENTRY(SIGKILL) \ + MAKE_SIG_ENTRY(SIGUSR1) \ + MAKE_SIG_ENTRY(SIGSEGV) \ + MAKE_SIG_ENTRY(SIGUSR2) \ + MAKE_SIG_ENTRY(SIGPIPE) \ + MAKE_SIG_ENTRY(SIGALRM) \ + MAKE_SIG_ENTRY(SIGTERM) \ + MAKE_SIG_ENTRY(SIGCHLD) \ + MAKE_SIG_ENTRY(SIGCONT) \ + MAKE_SIG_ENTRY(SIGSTOP) \ + MAKE_SIG_ENTRY(SIGTSTP) \ + MAKE_SIG_ENTRY(SIGTTIN) \ + MAKE_SIG_ENTRY(SIGTTOU) \ + MAKE_SIG_ENTRY(SIGURG) \ + MAKE_SIG_ENTRY(SIGXCPU) \ + MAKE_SIG_ENTRY(SIGXFSZ) \ + MAKE_SIG_ENTRY(SIGVTALRM) \ + MAKE_SIG_ENTRY(SIGPROF) \ + MAKE_SIG_ENTRY(SIGWINCH) \ + MAKE_SIG_ENTRY(SIGIO) \ + MAKE_SIG_ENTRY(SIGPWR) \ + MAKE_SIG_ENTRY(SIGSYS) \ + MAKE_SIG_ENTRY_SIGSTKFLT \ + MAKE_SIG_ENTRY_SIGIOT + #endif diff --git a/linux-user/signal.c b/linux-user/signal.c index 8d29bfaa6b..61c6fa3fcf 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -53,40 +53,9 @@ abi_ulong default_rt_sigreturn; QEMU_BUILD_BUG_ON(__SIGRTMAX + 1 != _NSIG); #endif static uint8_t host_to_target_signal_table[_NSIG] = { - [SIGHUP] = TARGET_SIGHUP, - [SIGINT] = TARGET_SIGINT, - [SIGQUIT] = TARGET_SIGQUIT, - [SIGILL] = TARGET_SIGILL, - [SIGTRAP] = TARGET_SIGTRAP, - [SIGABRT] = TARGET_SIGABRT, -/* [SIGIOT] = TARGET_SIGIOT,*/ - [SIGBUS] = TARGET_SIGBUS, - [SIGFPE] = TARGET_SIGFPE, - [SIGKILL] = TARGET_SIGKILL, - [SIGUSR1] = TARGET_SIGUSR1, - [SIGSEGV] = TARGET_SIGSEGV, - [SIGUSR2] = TARGET_SIGUSR2, - [SIGPIPE] = TARGET_SIGPIPE, - [SIGALRM] = TARGET_SIGALRM, - [SIGTERM] = TARGET_SIGTERM, -#ifdef SIGSTKFLT - [SIGSTKFLT] = TARGET_SIGSTKFLT, -#endif - [SIGCHLD] = TARGET_SIGCHLD, - [SIGCONT] = TARGET_SIGCONT, - [SIGSTOP] = TARGET_SIGSTOP, - [SIGTSTP] = TARGET_SIGTSTP, - [SIGTTIN] = TARGET_SIGTTIN, - [SIGTTOU] = TARGET_SIGTTOU, - [SIGURG] = TARGET_SIGURG, - [SIGXCPU] = TARGET_SIGXCPU, - [SIGXFSZ] = TARGET_SIGXFSZ, - [SIGVTALRM] = TARGET_SIGVTALRM, - [SIGPROF] = TARGET_SIGPROF, - [SIGWINCH] = TARGET_SIGWINCH, - [SIGIO] = TARGET_SIGIO, - [SIGPWR] = TARGET_SIGPWR, - [SIGSYS] = TARGET_SIGSYS, +#define MAKE_SIG_ENTRY(sig) [sig] = TARGET_##sig, + MAKE_SIGNAL_LIST +#undef MAKE_SIG_ENTRY /* next signals stay the same */ }; diff --git a/linux-user/strace.c b/linux-user/strace.c index 7d882526da..a4eeef7ae1 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -17,6 +17,7 @@ #include "qemu.h" #include "user-internals.h" #include "strace.h" +#include "signal-common.h" struct syscallname { int nr; @@ -141,30 +142,21 @@ if( cmd == val ) { \ qemu_log("%d", cmd); } +static const char * const target_signal_name[] = { +#define MAKE_SIG_ENTRY(sig) [TARGET_##sig] = #sig, + MAKE_SIGNAL_LIST +#undef MAKE_SIG_ENTRY +}; + static void print_signal(abi_ulong arg, int last) { const char *signal_name = NULL; - switch(arg) { - case TARGET_SIGHUP: signal_name = "SIGHUP"; break; - case TARGET_SIGINT: signal_name = "SIGINT"; break; - case TARGET_SIGQUIT: signal_name = "SIGQUIT"; break; - case TARGET_SIGILL: signal_name = "SIGILL"; break; - case TARGET_SIGABRT: signal_name = "SIGABRT"; break; - case TARGET_SIGFPE: signal_name = "SIGFPE"; break; - case TARGET_SIGKILL: signal_name = "SIGKILL"; break; - case TARGET_SIGSEGV: signal_name = "SIGSEGV"; break; - case TARGET_SIGPIPE: signal_name = "SIGPIPE"; break; - case TARGET_SIGALRM: signal_name = "SIGALRM"; break; - case TARGET_SIGTERM: signal_name = "SIGTERM"; break; - case TARGET_SIGUSR1: signal_name = "SIGUSR1"; break; - case TARGET_SIGUSR2: signal_name = "SIGUSR2"; break; - case TARGET_SIGCHLD: signal_name = "SIGCHLD"; break; - case TARGET_SIGCONT: signal_name = "SIGCONT"; break; - case TARGET_SIGSTOP: signal_name = "SIGSTOP"; break; - case TARGET_SIGTTIN: signal_name = "SIGTTIN"; break; - case TARGET_SIGTTOU: signal_name = "SIGTTOU"; break; + + if (arg < ARRAY_SIZE(target_signal_name)) { + signal_name = target_signal_name[arg]; } + if (signal_name == NULL) { print_raw_param("%ld", arg, last); return; From aad43d15422c358ece148e39887fbd0821bca657 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:45 +0200 Subject: [PATCH 0668/1020] linux-user: Add missing clock_gettime64() syscall strace Allow linux-user to strace the clock_gettime64() syscall. This syscall is used a lot on 32-bit guest architectures which use newer glibc versions. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20220918194555.83535-3-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 53 ++++++++++++++++++++++++++++++++++++++++++ linux-user/strace.list | 4 ++++ 2 files changed, 57 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index a4eeef7ae1..816e679995 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -82,6 +82,7 @@ UNUSED static void print_buf(abi_long addr, abi_long len, int last); UNUSED static void print_raw_param(const char *, abi_long, int); UNUSED static void print_timeval(abi_ulong, int); UNUSED static void print_timespec(abi_ulong, int); +UNUSED static void print_timespec64(abi_ulong, int); UNUSED static void print_timezone(abi_ulong, int); UNUSED static void print_itimerval(abi_ulong, int); UNUSED static void print_number(abi_long, int); @@ -795,6 +796,24 @@ print_syscall_ret_clock_gettime(CPUArchState *cpu_env, const struct syscallname #define print_syscall_ret_clock_getres print_syscall_ret_clock_gettime #endif +#if defined(TARGET_NR_clock_gettime64) +static void +print_syscall_ret_clock_gettime64(CPUArchState *cpu_env, const struct syscallname *name, + abi_long ret, abi_long arg0, abi_long arg1, + abi_long arg2, abi_long arg3, abi_long arg4, + abi_long arg5) +{ + if (!print_syscall_err(ret)) { + qemu_log(TARGET_ABI_FMT_ld, ret); + qemu_log(" ("); + print_timespec64(arg1, 1); + qemu_log(")"); + } + + qemu_log("\n"); +} +#endif + #ifdef TARGET_NR_gettimeofday static void print_syscall_ret_gettimeofday(CPUArchState *cpu_env, const struct syscallname *name, @@ -1652,6 +1671,27 @@ print_timespec(abi_ulong ts_addr, int last) } } +static void +print_timespec64(abi_ulong ts_addr, int last) +{ + if (ts_addr) { + struct target__kernel_timespec *ts; + + ts = lock_user(VERIFY_READ, ts_addr, sizeof(*ts), 1); + if (!ts) { + print_pointer(ts_addr, last); + return; + } + qemu_log("{tv_sec = %lld" + ",tv_nsec = %lld}%s", + (long long)tswap64(ts->tv_sec), (long long)tswap64(ts->tv_nsec), + get_comma(last)); + unlock_user(ts, ts_addr, 0); + } else { + qemu_log("NULL%s", get_comma(last)); + } +} + static void print_timezone(abi_ulong tz_addr, int last) { @@ -2267,6 +2307,19 @@ print_clock_gettime(CPUArchState *cpu_env, const struct syscallname *name, #define print_clock_getres print_clock_gettime #endif +#if defined(TARGET_NR_clock_gettime64) +static void +print_clock_gettime64(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_enums(clockids, arg0, 0); + print_pointer(arg1, 1); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_clock_settime static void print_clock_settime(CPUArchState *cpu_env, const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index 72e17b1acf..a78cdf3cdf 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1676,3 +1676,7 @@ #ifdef TARGET_NR_copy_file_range { TARGET_NR_copy_file_range, "copy_file_range", "%s(%d,%p,%d,%p,"TARGET_ABI_FMT_lu",%u)", NULL, NULL }, #endif +#ifdef TARGET_NR_clock_gettime64 +{ TARGET_NR_clock_gettime64, "clock_gettime64" , NULL, print_clock_gettime64, + print_syscall_ret_clock_gettime64 }, +#endif From cc054c6f139cf54ce8fbefd6fd536f50b4cba694 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:46 +0200 Subject: [PATCH 0669/1020] linux-user: Add pidfd_open(), pidfd_send_signal() and pidfd_getfd() syscalls I noticed those were missing when running the glib2.0 testsuite. Add the syscalls including the strace output. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20220918194555.83535-4-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 28 ++++++++++++++++++++++++++++ linux-user/strace.list | 9 +++++++++ linux-user/syscall.c | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index 816e679995..5ac64df02b 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -3317,6 +3317,34 @@ print_openat(CPUArchState *cpu_env, const struct syscallname *name, } #endif +#ifdef TARGET_NR_pidfd_send_signal +static void +print_pidfd_send_signal(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + void *p; + target_siginfo_t uinfo; + + print_syscall_prologue(name); + print_raw_param("%d", arg0, 0); + print_signal(arg1, 0); + + p = lock_user(VERIFY_READ, arg2, sizeof(target_siginfo_t), 1); + if (p) { + get_target_siginfo(&uinfo, p); + print_siginfo(&uinfo); + + unlock_user(p, arg2, 0); + } else { + print_pointer(arg2, 1); + } + + print_raw_param("%u", arg3, 0); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_mq_unlink static void print_mq_unlink(CPUArchState *cpu_env, const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index a78cdf3cdf..4d8b7f6a5e 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -1664,6 +1664,15 @@ #ifdef TARGET_NR_pipe2 { TARGET_NR_pipe2, "pipe2", NULL, NULL, NULL }, #endif +#ifdef TARGET_NR_pidfd_open +{ TARGET_NR_pidfd_open, "pidfd_open", "%s(%d,%u)", NULL, NULL }, +#endif +#ifdef TARGET_NR_pidfd_send_signal +{ TARGET_NR_pidfd_send_signal, "pidfd_send_signal", NULL, print_pidfd_send_signal, NULL }, +#endif +#ifdef TARGET_NR_pidfd_getfd +{ TARGET_NR_pidfd_getfd, "pidfd_getfd", "%s(%d,%d,%u)", NULL, NULL }, +#endif #ifdef TARGET_NR_atomic_cmpxchg_32 { TARGET_NR_atomic_cmpxchg_32, "atomic_cmpxchg_32", NULL, NULL, NULL }, #endif diff --git a/linux-user/syscall.c b/linux-user/syscall.c index abf82bab2a..850410c9b5 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -346,6 +346,16 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val, _syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val, const struct timespec *,timeout,int *,uaddr2,int,val3) #endif +#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open) +_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags); +#endif +#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal) +_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info, + unsigned int, flags); +#endif +#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd) +_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags); +#endif #define __NR_sys_sched_getaffinity __NR_sched_getaffinity _syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len, unsigned long *, user_mask_ptr); @@ -8683,6 +8693,30 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, ret = do_open_by_handle_at(arg1, arg2, arg3); fd_trans_unregister(ret); return ret; +#endif +#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open) + case TARGET_NR_pidfd_open: + return get_errno(pidfd_open(arg1, arg2)); +#endif +#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal) + case TARGET_NR_pidfd_send_signal: + { + siginfo_t uinfo; + + p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1); + if (!p) { + return -TARGET_EFAULT; + } + target_to_host_siginfo(&uinfo, p); + unlock_user(p, arg3, 0); + ret = get_errno(pidfd_send_signal(arg1, target_to_host_signal(arg2), + &uinfo, arg4)); + } + return ret; +#endif +#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd) + case TARGET_NR_pidfd_getfd: + return get_errno(pidfd_getfd(arg1, arg2, arg3)); #endif case TARGET_NR_close: fd_trans_unregister(arg1); From 35dffc568164f08ebdb42bc8eb6307fed9af0ffe Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:47 +0200 Subject: [PATCH 0670/1020] linux-user: Log failing executable in EXCP_DUMP() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Enhance the EXCP_DUMP() macro to print out the failing program too. During debugging it's sometimes hard to track down the actual failing program if you are e.g. building a whole debian package. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220918194555.83535-5-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/cpu_loop-common.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/cpu_loop-common.h b/linux-user/cpu_loop-common.h index dc0042e4de..36ff5b14f2 100644 --- a/linux-user/cpu_loop-common.h +++ b/linux-user/cpu_loop-common.h @@ -27,9 +27,11 @@ do { \ CPUState *cs = env_cpu(env); \ fprintf(stderr, fmt , ## __VA_ARGS__); \ + fprintf(stderr, "Failing executable: %s\n", exec_path); \ cpu_dump_state(cs, stderr, 0); \ if (qemu_log_separate()) { \ qemu_log(fmt, ## __VA_ARGS__); \ + qemu_log("Failing executable: %s\n", exec_path); \ log_cpu_state(cs, 0); \ } \ } while (0) From 12640b4fe96fe23dc344b03378dda1eea5b7a191 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:48 +0200 Subject: [PATCH 0671/1020] linux-user/hppa: Use EXCP_DUMP() to show enhanced debug info Enhance the hppa linux-user cpu_loop() to show more debugging info on hard errors. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20220918194555.83535-6-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/hppa/cpu_loop.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/linux-user/hppa/cpu_loop.c b/linux-user/hppa/cpu_loop.c index 64263c3dc4..1ef3b46191 100644 --- a/linux-user/hppa/cpu_loop.c +++ b/linux-user/hppa/cpu_loop.c @@ -147,12 +147,15 @@ void cpu_loop(CPUHPPAState *env) force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f); break; case EXCP_ILL: + EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", trapnr); force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPN, env->iaoq_f); break; case EXCP_PRIV_OPR: + EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", trapnr); force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f); break; case EXCP_PRIV_REG: + EXCP_DUMP(env, "qemu: got CPU exception 0x%x - aborting\n", trapnr); force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVREG, env->iaoq_f); break; case EXCP_OVERFLOW: @@ -171,7 +174,8 @@ void cpu_loop(CPUHPPAState *env) /* just indicate that signals should be handled asap */ break; default: - g_assert_not_reached(); + EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); + abort(); } process_pending_signals(env); } From 770525f8eac9a2d048896fd54e4c596af747f238 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:49 +0200 Subject: [PATCH 0672/1020] linux-user/hppa: Dump IIR on register dump MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include the IIR register (which holds the opcode of the failing instruction) when dumping the hppa registers. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220918194555.83535-7-deller@gmx.de> Signed-off-by: Laurent Vivier --- target/hppa/helper.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/target/hppa/helper.c b/target/hppa/helper.c index e2758d8df3..74b8747083 100644 --- a/target/hppa/helper.c +++ b/target/hppa/helper.c @@ -85,9 +85,11 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags) char psw_c[20]; int i; - qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx "\n", + qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx + " IIR " TREG_FMT_lx "\n", hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f), - hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b)); + hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b), + env->cr[CR_IIR]); psw_c[0] = (psw & PSW_W ? 'W' : '-'); psw_c[1] = (psw & PSW_E ? 'E' : '-'); From 105d599a33462bd64529bc3bacc68e2d0fbb876b Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:50 +0200 Subject: [PATCH 0673/1020] linux-user: Fix strace of chmod() if mode == 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the mode parameter of chmod() is zero, this value isn't shown when stracing a program: chmod("filename",) This patch fixes it up to show the zero-value as well: chmod("filename",000) Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220918194555.83535-8-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/linux-user/strace.c b/linux-user/strace.c index 5ac64df02b..2f539845bb 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -1505,6 +1505,11 @@ print_file_mode(abi_long mode, int last) const char *sep = ""; const struct flags *m; + if (mode == 0) { + qemu_log("000%s", get_comma(last)); + return; + } + for (m = &mode_flags[0]; m->f_string != NULL; m++) { if ((m->f_value & mode) == m->f_value) { qemu_log("%s%s", m->f_string, sep); From 9c9b5d7b9220d2f52a2df24373c8f35604f444fc Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:51 +0200 Subject: [PATCH 0674/1020] linux-user/hppa: Set TASK_UNMAPPED_BASE to 0xfa000000 for hppa arch On the parisc architecture the stack grows upwards. Move the TASK_UNMAPPED_BASE to high memory area as it's done by the kernel on physical machines. Signed-off-by: Helge Deller Message-Id: <20220918194555.83535-9-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/mmap.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 6a828e8418..83fdae7034 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -253,8 +253,12 @@ static int mmap_frag(abi_ulong real_start, # define TASK_UNMAPPED_BASE (1ul << 38) #endif #else +#ifdef TARGET_HPPA +# define TASK_UNMAPPED_BASE 0xfa000000 +#else # define TASK_UNMAPPED_BASE 0x40000000 #endif +#endif abi_ulong mmap_next_start = TASK_UNMAPPED_BASE; unsigned long last_brk; From 05f3adc982caf4d10128f087775385decc7fb3b3 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:52 +0200 Subject: [PATCH 0675/1020] linux-user: Add strace for clock_nanosleep() Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20220918194555.83535-10-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 15 +++++++++++++++ linux-user/strace.list | 3 ++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 2f539845bb..6f818212d5 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -3567,6 +3567,21 @@ print_unshare(CPUArchState *cpu_env, const struct syscallname *name, } #endif +#ifdef TARGET_NR_clock_nanosleep +static void +print_clock_nanosleep(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_enums(clockids, arg0, 0); + print_raw_param("%d", arg1, 0); + print_timespec(arg2, 0); + print_timespec(arg3, 1); + print_syscall_epilogue(name); +} +#endif + #ifdef TARGET_NR_utime static void print_utime(CPUArchState *cpu_env, const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index 4d8b7f6a5e..215d971b2a 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -91,7 +91,8 @@ print_syscall_ret_clock_gettime }, #endif #ifdef TARGET_NR_clock_nanosleep -{ TARGET_NR_clock_nanosleep, "clock_nanosleep" , NULL, NULL, NULL }, +{ TARGET_NR_clock_nanosleep, "clock_nanosleep" , NULL, print_clock_nanosleep, + NULL }, #endif #ifdef TARGET_NR_clock_settime { TARGET_NR_clock_settime, "clock_settime" , NULL, print_clock_settime, NULL }, From 811ee5cfc5da2e0b94eb11192ce2700fcd7063d1 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sun, 18 Sep 2022 21:45:53 +0200 Subject: [PATCH 0676/1020] linux-user: Show timespec on strace for futex() Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20220918194555.83535-11-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 6f818212d5..b6b9abaea4 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -3714,11 +3714,20 @@ print_futex(CPUArchState *cpu_env, const struct syscallname *name, abi_long arg0, abi_long arg1, abi_long arg2, abi_long arg3, abi_long arg4, abi_long arg5) { + abi_long op = arg1 & FUTEX_CMD_MASK; print_syscall_prologue(name); print_pointer(arg0, 0); print_futex_op(arg1, 0); print_raw_param(",%d", arg2, 0); - print_pointer(arg3, 0); /* struct timespec */ + switch (op) { + case FUTEX_WAIT: + case FUTEX_WAIT_BITSET: + print_timespec(arg3, 0); + break; + default: + print_pointer(arg3, 0); + break; + } print_pointer(arg4, 0); print_raw_param("%d", arg4, 1); print_syscall_epilogue(name); From 9f22020b91ae235be2b27c47d11e842872ec5e85 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 6 Sep 2022 02:08:35 +0200 Subject: [PATCH 0677/1020] linux-user: Provide MADV_* definitions Provide MADV_* definitions using target_mman.h header, similar to what kernel does. Most architectures use the same values, with the exception of alpha and hppa. Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Message-Id: <20220906000839.1672934-2-iii@linux.ibm.com> Signed-off-by: Laurent Vivier --- linux-user/aarch64/target_mman.h | 1 + linux-user/alpha/target_mman.h | 8 +++ linux-user/arm/target_mman.h | 1 + linux-user/cris/target_mman.h | 1 + linux-user/generic/target_mman.h | 92 ++++++++++++++++++++++++++++ linux-user/hexagon/target_mman.h | 1 + linux-user/hppa/target_mman.h | 15 +++++ linux-user/i386/target_mman.h | 1 + linux-user/loongarch64/target_mman.h | 1 + linux-user/m68k/target_mman.h | 1 + linux-user/microblaze/target_mman.h | 1 + linux-user/mips/target_mman.h | 1 + linux-user/mips64/target_mman.h | 1 + linux-user/nios2/target_mman.h | 1 + linux-user/openrisc/target_mman.h | 1 + linux-user/ppc/target_mman.h | 1 + linux-user/riscv/target_mman.h | 1 + linux-user/s390x/target_mman.h | 1 + linux-user/sh4/target_mman.h | 1 + linux-user/sparc/target_mman.h | 1 + linux-user/x86_64/target_mman.h | 1 + linux-user/xtensa/target_mman.h | 1 + 22 files changed, 134 insertions(+) create mode 100644 linux-user/aarch64/target_mman.h create mode 100644 linux-user/alpha/target_mman.h create mode 100644 linux-user/arm/target_mman.h create mode 100644 linux-user/cris/target_mman.h create mode 100644 linux-user/generic/target_mman.h create mode 100644 linux-user/hexagon/target_mman.h create mode 100644 linux-user/hppa/target_mman.h create mode 100644 linux-user/i386/target_mman.h create mode 100644 linux-user/loongarch64/target_mman.h create mode 100644 linux-user/m68k/target_mman.h create mode 100644 linux-user/microblaze/target_mman.h create mode 100644 linux-user/mips/target_mman.h create mode 100644 linux-user/mips64/target_mman.h create mode 100644 linux-user/nios2/target_mman.h create mode 100644 linux-user/openrisc/target_mman.h create mode 100644 linux-user/ppc/target_mman.h create mode 100644 linux-user/riscv/target_mman.h create mode 100644 linux-user/s390x/target_mman.h create mode 100644 linux-user/sh4/target_mman.h create mode 100644 linux-user/sparc/target_mman.h create mode 100644 linux-user/x86_64/target_mman.h create mode 100644 linux-user/xtensa/target_mman.h diff --git a/linux-user/aarch64/target_mman.h b/linux-user/aarch64/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/aarch64/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/alpha/target_mman.h b/linux-user/alpha/target_mman.h new file mode 100644 index 0000000000..cd6e3d70a6 --- /dev/null +++ b/linux-user/alpha/target_mman.h @@ -0,0 +1,8 @@ +#ifndef ALPHA_TARGET_MMAN_H +#define ALPHA_TARGET_MMAN_H + +#define TARGET_MADV_DONTNEED 6 + +#include "../generic/target_mman.h" + +#endif diff --git a/linux-user/arm/target_mman.h b/linux-user/arm/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/arm/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/cris/target_mman.h b/linux-user/cris/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/cris/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/generic/target_mman.h b/linux-user/generic/target_mman.h new file mode 100644 index 0000000000..1436a3c543 --- /dev/null +++ b/linux-user/generic/target_mman.h @@ -0,0 +1,92 @@ +#ifndef LINUX_USER_TARGET_MMAN_H +#define LINUX_USER_TARGET_MMAN_H + +#ifndef TARGET_MADV_NORMAL +#define TARGET_MADV_NORMAL 0 +#endif + +#ifndef TARGET_MADV_RANDOM +#define TARGET_MADV_RANDOM 1 +#endif + +#ifndef TARGET_MADV_SEQUENTIAL +#define TARGET_MADV_SEQUENTIAL 2 +#endif + +#ifndef TARGET_MADV_WILLNEED +#define TARGET_MADV_WILLNEED 3 +#endif + +#ifndef TARGET_MADV_DONTNEED +#define TARGET_MADV_DONTNEED 4 +#endif + +#ifndef TARGET_MADV_FREE +#define TARGET_MADV_FREE 8 +#endif + +#ifndef TARGET_MADV_REMOVE +#define TARGET_MADV_REMOVE 9 +#endif + +#ifndef TARGET_MADV_DONTFORK +#define TARGET_MADV_DONTFORK 10 +#endif + +#ifndef TARGET_MADV_DOFORK +#define TARGET_MADV_DOFORK 11 +#endif + +#ifndef TARGET_MADV_MERGEABLE +#define TARGET_MADV_MERGEABLE 12 +#endif + +#ifndef TARGET_MADV_UNMERGEABLE +#define TARGET_MADV_UNMERGEABLE 13 +#endif + +#ifndef TARGET_MADV_HUGEPAGE +#define TARGET_MADV_HUGEPAGE 14 +#endif + +#ifndef TARGET_MADV_NOHUGEPAGE +#define TARGET_MADV_NOHUGEPAGE 15 +#endif + +#ifndef TARGET_MADV_DONTDUMP +#define TARGET_MADV_DONTDUMP 16 +#endif + +#ifndef TARGET_MADV_DODUMP +#define TARGET_MADV_DODUMP 17 +#endif + +#ifndef TARGET_MADV_WIPEONFORK +#define TARGET_MADV_WIPEONFORK 18 +#endif + +#ifndef TARGET_MADV_KEEPONFORK +#define TARGET_MADV_KEEPONFORK 19 +#endif + +#ifndef TARGET_MADV_COLD +#define TARGET_MADV_COLD 20 +#endif + +#ifndef TARGET_MADV_PAGEOUT +#define TARGET_MADV_PAGEOUT 21 +#endif + +#ifndef TARGET_MADV_POPULATE_READ +#define TARGET_MADV_POPULATE_READ 22 +#endif + +#ifndef TARGET_MADV_POPULATE_WRITE +#define TARGET_MADV_POPULATE_WRITE 23 +#endif + +#ifndef TARGET_MADV_DONTNEED_LOCKED +#define TARGET_MADV_DONTNEED_LOCKED 24 +#endif + +#endif diff --git a/linux-user/hexagon/target_mman.h b/linux-user/hexagon/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/hexagon/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/hppa/target_mman.h b/linux-user/hppa/target_mman.h new file mode 100644 index 0000000000..66dd9f7941 --- /dev/null +++ b/linux-user/hppa/target_mman.h @@ -0,0 +1,15 @@ +#ifndef HPPA_TARGET_MMAN_H +#define HPPA_TARGET_MMAN_H + +#define TARGET_MADV_MERGEABLE 65 +#define TARGET_MADV_UNMERGEABLE 66 +#define TARGET_MADV_HUGEPAGE 67 +#define TARGET_MADV_NOHUGEPAGE 68 +#define TARGET_MADV_DONTDUMP 69 +#define TARGET_MADV_DODUMP 70 +#define TARGET_MADV_WIPEONFORK 71 +#define TARGET_MADV_KEEPONFORK 72 + +#include "../generic/target_mman.h" + +#endif diff --git a/linux-user/i386/target_mman.h b/linux-user/i386/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/i386/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/loongarch64/target_mman.h b/linux-user/loongarch64/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/loongarch64/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/m68k/target_mman.h b/linux-user/m68k/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/m68k/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/microblaze/target_mman.h b/linux-user/microblaze/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/microblaze/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/mips/target_mman.h b/linux-user/mips/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/mips/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/mips64/target_mman.h b/linux-user/mips64/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/mips64/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/nios2/target_mman.h b/linux-user/nios2/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/nios2/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/openrisc/target_mman.h b/linux-user/openrisc/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/openrisc/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/ppc/target_mman.h b/linux-user/ppc/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/ppc/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/riscv/target_mman.h b/linux-user/riscv/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/riscv/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/s390x/target_mman.h b/linux-user/s390x/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/s390x/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/sh4/target_mman.h b/linux-user/sh4/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/sh4/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/sparc/target_mman.h b/linux-user/sparc/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/sparc/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/x86_64/target_mman.h b/linux-user/x86_64/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/x86_64/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" diff --git a/linux-user/xtensa/target_mman.h b/linux-user/xtensa/target_mman.h new file mode 100644 index 0000000000..e7ba6070fe --- /dev/null +++ b/linux-user/xtensa/target_mman.h @@ -0,0 +1 @@ +#include "../generic/target_mman.h" From 8655b4c7099dd198836610bdfb22f09d332b28d3 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 6 Sep 2022 02:08:36 +0200 Subject: [PATCH 0678/1020] linux-user: Fix madvise(MADV_DONTNEED) on alpha MADV_DONTNEED has a different value on alpha, compared to all the other architectures. Fix by using TARGET_MADV_DONTNEED instead of MADV_DONTNEED. Fixes: 892a4f6a750a ("linux-user: Add partial support for MADV_DONTNEED") Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Message-Id: <20220906000839.1672934-3-iii@linux.ibm.com> Signed-off-by: Laurent Vivier --- linux-user/mmap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 83fdae7034..942bec7e85 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -22,6 +22,7 @@ #include "qemu.h" #include "user-internals.h" #include "user-mmap.h" +#include "target_mman.h" static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER; static __thread int mmap_lock_count; @@ -897,7 +898,7 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice) * anonymous mappings. In this case passthrough is safe, so do it. */ mmap_lock(); - if (advice == MADV_DONTNEED && + if (advice == TARGET_MADV_DONTNEED && can_passthrough_madv_dontneed(start, end)) { ret = get_errno(madvise(g2h_untagged(start), len, MADV_DONTNEED)); if (ret == 0) { From 375ce49be285c5ff73674674350cc99807dfac83 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 6 Sep 2022 02:08:37 +0200 Subject: [PATCH 0679/1020] linux-user: Implement stracing madvise() The default implementation has several problems: the first argument is not displayed as a pointer, making it harder to grep; the third argument is not symbolized; and there are several extra unused arguments. Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Message-Id: <20220906000839.1672934-4-iii@linux.ibm.com> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 41 +++++++++++++++++++++++++++++++++++++++++ linux-user/strace.list | 2 +- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index b6b9abaea4..2deb84a2c1 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -18,6 +18,7 @@ #include "user-internals.h" #include "strace.h" #include "signal-common.h" +#include "target_mman.h" struct syscallname { int nr; @@ -3019,6 +3020,46 @@ print_stat(CPUArchState *cpu_env, const struct syscallname *name, #define print_lstat64 print_stat #endif +#if defined(TARGET_NR_madvise) +static struct enums madvise_advice[] = { + ENUM_TARGET(MADV_NORMAL), + ENUM_TARGET(MADV_RANDOM), + ENUM_TARGET(MADV_SEQUENTIAL), + ENUM_TARGET(MADV_WILLNEED), + ENUM_TARGET(MADV_DONTNEED), + ENUM_TARGET(MADV_FREE), + ENUM_TARGET(MADV_REMOVE), + ENUM_TARGET(MADV_DONTFORK), + ENUM_TARGET(MADV_DOFORK), + ENUM_TARGET(MADV_MERGEABLE), + ENUM_TARGET(MADV_UNMERGEABLE), + ENUM_TARGET(MADV_HUGEPAGE), + ENUM_TARGET(MADV_NOHUGEPAGE), + ENUM_TARGET(MADV_DONTDUMP), + ENUM_TARGET(MADV_DODUMP), + ENUM_TARGET(MADV_WIPEONFORK), + ENUM_TARGET(MADV_KEEPONFORK), + ENUM_TARGET(MADV_COLD), + ENUM_TARGET(MADV_PAGEOUT), + ENUM_TARGET(MADV_POPULATE_READ), + ENUM_TARGET(MADV_POPULATE_WRITE), + ENUM_TARGET(MADV_DONTNEED_LOCKED), + ENUM_END, +}; + +static void +print_madvise(CPUArchState *cpu_env, const struct syscallname *name, + abi_long arg0, abi_long arg1, abi_long arg2, + abi_long arg3, abi_long arg4, abi_long arg5) +{ + print_syscall_prologue(name); + print_pointer(arg0, 0); + print_raw_param("%d", arg1, 0); + print_enums(madvise_advice, arg2, 1); + print_syscall_epilogue(name); +} +#endif + #if defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) static void print_fstat(CPUArchState *cpu_env, const struct syscallname *name, diff --git a/linux-user/strace.list b/linux-user/strace.list index 215d971b2a..c6f748505a 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -542,7 +542,7 @@ { TARGET_NR_lstat64, "lstat64" , NULL, print_lstat64, NULL }, #endif #ifdef TARGET_NR_madvise -{ TARGET_NR_madvise, "madvise" , NULL, NULL, NULL }, +{ TARGET_NR_madvise, "madvise" , NULL, print_madvise, NULL }, #endif #ifdef TARGET_NR_madvise1 { TARGET_NR_madvise1, "madvise1" , NULL, NULL, NULL }, From f93b76958a358e82bfdd1474598fe75184afeb4d Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 6 Sep 2022 02:08:38 +0200 Subject: [PATCH 0680/1020] linux-user: Passthrough MADV_DONTNEED for certain file mappings This is a follow-up for commit 892a4f6a750a ("linux-user: Add partial support for MADV_DONTNEED"), which added passthrough for anonymous mappings. File mappings can be handled in a similar manner. In order to do that, mark pages, for which mmap() was passed through, with PAGE_PASSTHROUGH, and then allow madvise() passthrough for these pages. Drop the explicit PAGE_ANON check, since anonymous mappings are expected to have PAGE_PASSTHROUGH anyway. Add PAGE_PASSTHROUGH to PAGE_STICKY in order to keep it on mprotect(). Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Message-Id: <20220725125043.43048-1-iii@linux.ibm.com> Message-Id: <20220906000839.1672934-5-iii@linux.ibm.com> Signed-off-by: Laurent Vivier --- accel/tcg/translate-all.c | 2 +- include/exec/cpu-all.h | 6 ++++++ linux-user/mmap.c | 27 ++++++++++++++++++++++----- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index f5e8592d4a..d71d04d338 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2258,7 +2258,7 @@ int page_get_flags(target_ulong address) #ifndef PAGE_TARGET_STICKY #define PAGE_TARGET_STICKY 0 #endif -#define PAGE_STICKY (PAGE_ANON | PAGE_TARGET_STICKY) +#define PAGE_STICKY (PAGE_ANON | PAGE_PASSTHROUGH | PAGE_TARGET_STICKY) /* Modify the flags of a page and invalidate the code if necessary. The flag PAGE_WRITE_ORG is positioned automatically depending diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 491629b9ba..16b7df41bf 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -262,6 +262,12 @@ extern const TargetPageBits target_page; #define PAGE_TARGET_1 0x0200 #define PAGE_TARGET_2 0x0400 +/* + * For linux-user, indicates that the page is mapped with the same semantics + * in both guest and host. + */ +#define PAGE_PASSTHROUGH 0x0800 + #if defined(CONFIG_USER_ONLY) void page_dump(FILE *f); diff --git a/linux-user/mmap.c b/linux-user/mmap.c index 942bec7e85..e557f3626e 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -431,7 +431,8 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong align) abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot, int flags, int fd, abi_ulong offset) { - abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; + abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len, + passthrough_start = -1, passthrough_end = -1; int page_flags, host_prot; mmap_lock(); @@ -544,6 +545,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot, host_start += offset - host_offset; } start = h2g(host_start); + passthrough_start = start; + passthrough_end = start + len; } else { if (start & ~TARGET_PAGE_MASK) { errno = EINVAL; @@ -626,6 +629,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot, host_prot, flags, fd, offset1); if (p == MAP_FAILED) goto fail; + passthrough_start = real_start; + passthrough_end = real_end; } } the_end1: @@ -633,7 +638,18 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot, page_flags |= PAGE_ANON; } page_flags |= PAGE_RESET; - page_set_flags(start, start + len, page_flags); + if (passthrough_start == passthrough_end) { + page_set_flags(start, start + len, page_flags); + } else { + if (start < passthrough_start) { + page_set_flags(start, passthrough_start, page_flags); + } + page_set_flags(passthrough_start, passthrough_end, + page_flags | PAGE_PASSTHROUGH); + if (passthrough_end < start + len) { + page_set_flags(passthrough_end, start + len, page_flags); + } + } the_end: trace_target_mmap_complete(start); if (qemu_loglevel_mask(CPU_LOG_PAGE)) { @@ -852,7 +868,7 @@ static bool can_passthrough_madv_dontneed(abi_ulong start, abi_ulong end) } for (addr = start; addr < end; addr += TARGET_PAGE_SIZE) { - if (!(page_get_flags(addr) & PAGE_ANON)) { + if (!(page_get_flags(addr) & PAGE_PASSTHROUGH)) { return false; } } @@ -894,8 +910,9 @@ abi_long target_madvise(abi_ulong start, abi_ulong len_in, int advice) * This is a hint, so ignoring and returning success is ok. * * This breaks MADV_DONTNEED, completely implementing which is quite - * complicated. However, there is one low-hanging fruit: host-page-aligned - * anonymous mappings. In this case passthrough is safe, so do it. + * complicated. However, there is one low-hanging fruit: mappings that are + * known to have the same semantics in the host and the guest. In this case + * passthrough is safe, so do it. */ mmap_lock(); if (advice == TARGET_MADV_DONTNEED && From 38b870cc8c5e9d079649d8769c8f271f28953d24 Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Tue, 6 Sep 2022 02:08:39 +0200 Subject: [PATCH 0681/1020] tests/tcg/linux-test: Add linux-madvise test Add a test that checks madvise(MADV_DONTNEED) behavior with anonymous and file mappings in order to prevent regressions. Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Message-Id: <20220906000839.1672934-6-iii@linux.ibm.com> Signed-off-by: Laurent Vivier --- tests/tcg/multiarch/linux/linux-madvise.c | 70 +++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 tests/tcg/multiarch/linux/linux-madvise.c diff --git a/tests/tcg/multiarch/linux/linux-madvise.c b/tests/tcg/multiarch/linux/linux-madvise.c new file mode 100644 index 0000000000..29d0997e68 --- /dev/null +++ b/tests/tcg/multiarch/linux/linux-madvise.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +static void test_anonymous(void) +{ + int pagesize = getpagesize(); + char *page; + int ret; + + page = mmap(NULL, pagesize, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + assert(page != MAP_FAILED); + + /* Check that mprotect() does not interfere with MADV_DONTNEED. */ + ret = mprotect(page, pagesize, PROT_READ | PROT_WRITE); + assert(ret == 0); + + /* Check that MADV_DONTNEED clears the page. */ + *page = 42; + ret = madvise(page, pagesize, MADV_DONTNEED); + assert(ret == 0); + assert(*page == 0); + + ret = munmap(page, pagesize); + assert(ret == 0); +} + +static void test_file(void) +{ + char tempname[] = "/tmp/.cmadviseXXXXXX"; + int pagesize = getpagesize(); + ssize_t written; + char c = 42; + char *page; + int ret; + int fd; + + fd = mkstemp(tempname); + assert(fd != -1); + ret = unlink(tempname); + assert(ret == 0); + written = write(fd, &c, sizeof(c)); + assert(written == sizeof(c)); + page = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE, fd, 0); + assert(page != MAP_FAILED); + + /* Check that mprotect() does not interfere with MADV_DONTNEED. */ + ret = mprotect(page, pagesize, PROT_READ | PROT_WRITE); + assert(ret == 0); + + /* Check that MADV_DONTNEED resets the page. */ + *page = 0; + ret = madvise(page, pagesize, MADV_DONTNEED); + assert(ret == 0); + assert(*page == c); + + ret = munmap(page, pagesize); + assert(ret == 0); + ret = close(fd); + assert(ret == 0); +} + +int main(void) +{ + test_anonymous(); + test_file(); + + return EXIT_SUCCESS; +} From d124853bd73057cd6a60c810413f1a416bd04d34 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Sep 2022 13:44:55 +0200 Subject: [PATCH 0682/1020] linux-user: Fix TARGET_PROT_SEM for XTENSA The xtensa platform has a value of 0x10 for PROT_SEM. Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20220924114501.21767-2-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/syscall_defs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 85b0f33e91..1e3577bfa5 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -1246,7 +1246,7 @@ struct target_winsize { #include "termbits.h" -#if defined(TARGET_MIPS) +#if defined(TARGET_MIPS) || defined(TARGET_XTENSA) #define TARGET_PROT_SEM 0x10 #else #define TARGET_PROT_SEM 0x08 From 785783bab1ae879817a26f6757a997ebdc5e89c5 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Sep 2022 13:44:56 +0200 Subject: [PATCH 0683/1020] linux-user: Add proper strace format strings for getdents()/getdents64() Signed-off-by: Helge Deller Message-Id: <20220924114501.21767-3-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.list | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/strace.list b/linux-user/strace.list index c6f748505a..f8a771b4f2 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -279,10 +279,10 @@ { TARGET_NR_getcwd, "getcwd" , "%s(%p,%d)", NULL, NULL }, #endif #ifdef TARGET_NR_getdents -{ TARGET_NR_getdents, "getdents" , NULL, NULL, NULL }, +{ TARGET_NR_getdents, "getdents" , "%s(%d,%p,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_getdents64 -{ TARGET_NR_getdents64, "getdents64" , NULL, NULL, NULL }, +{ TARGET_NR_getdents64, "getdents64" , "%s(%d,%p,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_getdomainname { TARGET_NR_getdomainname, "getdomainname" , NULL, NULL, NULL }, From 47393189ce9e23b560865e361f4ab8fb93a904d0 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Sep 2022 13:44:57 +0200 Subject: [PATCH 0684/1020] linux-user/hppa: Add signal trampoline for hppa target In Linux kernel v5.18 the vDSO for signal trampoline was added. This code mimiks the bare minimum of this vDSO and thus avoids that the parisc emulation needs executable stacks. Signed-off-by: Helge Deller Message-Id: <20220924114501.21767-4-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/hppa/signal.c | 41 +++++++++++++++++++++++++-------- linux-user/hppa/target_signal.h | 14 +---------- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c index 962f551c04..396e310dc9 100644 --- a/linux-user/hppa/signal.c +++ b/linux-user/hppa/signal.c @@ -41,7 +41,7 @@ struct target_ucontext { }; struct target_rt_sigframe { - abi_uint tramp[9]; + abi_uint tramp[2]; /* syscall restart return address */ target_siginfo_t info; struct target_ucontext uc; /* hidden location of upper halves of pa2.0 64-bit gregs */ @@ -101,9 +101,15 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc) __get_user(env->cr[CR_SAR], &sc->sc_sar); } -/* No, this doesn't look right, but it's copied straight from the kernel. */ +#if TARGET_ABI_BITS == 32 +#define SIGFRAME 64 +#define FUNCTIONCALLFRAME 48 +#else +#define SIGFRAME 128 +#define FUNCTIONCALLFRAME 96 +#endif #define PARISC_RT_SIGFRAME_SIZE32 \ - ((sizeof(struct target_rt_sigframe) + 48 + 64) & -64) + ((sizeof(struct target_rt_sigframe) + FUNCTIONCALLFRAME + SIGFRAME) & -SIGFRAME) void setup_rt_frame(int sig, struct target_sigaction *ka, target_siginfo_t *info, @@ -118,7 +124,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, if ((ka->sa_flags & TARGET_SA_ONSTACK) && !sas_ss_flags(sp)) { sp = (ts->sigaltstack_used.ss_sp + 0x7f) & ~0x3f; } - frame_addr = QEMU_ALIGN_UP(sp, 64); + frame_addr = QEMU_ALIGN_UP(sp, SIGFRAME); sp = frame_addr + PARISC_RT_SIGFRAME_SIZE32; trace_user_setup_rt_frame(env, frame_addr); @@ -139,14 +145,9 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, setup_sigcontext(&frame->uc.tuc_mcontext, env); - __put_user(0x34190000, frame->tramp + 0); /* ldi 0,%r25 */ - __put_user(0x3414015a, frame->tramp + 1); /* ldi __NR_rt_sigreturn,%r20 */ - __put_user(0xe4008200, frame->tramp + 2); /* be,l 0x100(%sr2,%r0) */ - __put_user(0x08000240, frame->tramp + 3); /* nop */ - unlock_user_struct(frame, frame_addr, 1); - env->gr[2] = h2g(frame->tramp); + env->gr[2] = default_rt_sigreturn; env->gr[30] = sp; env->gr[26] = sig; env->gr[25] = h2g(&frame->info); @@ -197,3 +198,23 @@ long do_rt_sigreturn(CPUArchState *env) force_sig(TARGET_SIGSEGV); return -QEMU_ESIGRETURN; } + +void setup_sigtramp(abi_ulong sigtramp_page) +{ + uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6*4, 0); + abi_ulong SIGFRAME_CONTEXT_REGS32; + assert(tramp != NULL); + + SIGFRAME_CONTEXT_REGS32 = offsetof(struct target_rt_sigframe, uc.tuc_mcontext); + SIGFRAME_CONTEXT_REGS32 -= PARISC_RT_SIGFRAME_SIZE32; + + __put_user(SIGFRAME_CONTEXT_REGS32, tramp + 0); + __put_user(0x08000240, tramp + 1); /* nop - b/c dwarf2 unwind routines */ + __put_user(0x34190000, tramp + 2); /* ldi 0, %r25 (in_syscall=0) */ + __put_user(0x3414015a, tramp + 3); /* ldi __NR_rt_sigreturn, %r20 */ + __put_user(0xe4008200, tramp + 4); /* ble 0x100(%sr2, %r0) */ + __put_user(0x08000240, tramp + 5); /* nop */ + + default_rt_sigreturn = (sigtramp_page + 8) | 3; + unlock_user(tramp, sigtramp_page, 6*4); +} diff --git a/linux-user/hppa/target_signal.h b/linux-user/hppa/target_signal.h index af6c2fce58..190bb3d653 100644 --- a/linux-user/hppa/target_signal.h +++ b/linux-user/hppa/target_signal.h @@ -70,18 +70,6 @@ typedef struct target_sigaltstack { /* mask for all SS_xxx flags */ #define TARGET_SS_FLAG_BITS TARGET_SS_AUTODISARM -/* - * We cannot use a bare sigtramp page for hppa-linux. - * - * Unlike other guests where we use the instructions at PC to validate - * an offset from SP, the hppa libgcc signal frame fallback unwinding uses - * the PC address itself to find the frame. This is due to the fact that - * the hppa grows the stack upward, and the frame is of unknown size. - * - * TODO: We should be able to use a VDSO to address this, by providing - * proper unwind info for the sigtramp code, at which point the fallback - * unwinder will not be used. - */ -#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 0 +#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1 #endif /* HPPA_TARGET_SIGNAL_H */ From f43882052f330ce5f5a1a2553466df5aa0808fa0 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Sep 2022 13:44:58 +0200 Subject: [PATCH 0685/1020] linux-user/hppa: Drop stack guard page on hppa target The stack-overflow check when building the "grep" debian package fails on the debian hppa target. Reason is, that the guard page at the top of the stack (which is added by qemu) prevents the fault handler in the grep program to properly detect the stack overflow. The Linux kernel on a physical machine doesn't install a guard page either, so drop it and as such fix the build of "grep". Signed-off-by: Helge Deller Message-Id: <20220924114501.21767-5-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index ba5c4c02e5..c7e3f1d47c 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -2096,9 +2096,15 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm, if (size < STACK_LOWER_LIMIT) { size = STACK_LOWER_LIMIT; } - guard = TARGET_PAGE_SIZE; - if (guard < qemu_real_host_page_size()) { - guard = qemu_real_host_page_size(); + + if (STACK_GROWS_DOWN) { + guard = TARGET_PAGE_SIZE; + if (guard < qemu_real_host_page_size()) { + guard = qemu_real_host_page_size(); + } + } else { + /* no guard page for hppa target where stack grows upwards. */ + guard = 0; } prot = PROT_READ | PROT_WRITE; @@ -2118,7 +2124,6 @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm, info->stack_limit = error + guard; return info->stack_limit + size - sizeof(void *); } else { - target_mprotect(error + size, guard, PROT_NONE); info->stack_limit = error + size; return error; } From 0a3346b5938530178e20abea5219e80130cf0204 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Sep 2022 13:44:59 +0200 Subject: [PATCH 0686/1020] linux-user/hppa: Increase guest stack size to 80MB for hppa target The hppa target requires a much bigger stack than many other targets, and the Linux kernel allocates 80 MB by default for it. This patch increases the guest stack for hppa to 80MB, and prevents that this default stack size gets reduced by a lower stack limit on the host. Since the stack grows upwards on hppa, the stack_limit value marks the upper boundary of the stack. Fix the output of /proc/self/maps (in the guest) to show the [stack] marker on the correct memory area. Signed-off-by: Helge Deller Message-Id: <20220924114501.21767-6-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/hppa/target_syscall.h | 2 ++ linux-user/main.c | 9 +++++++-- linux-user/syscall.c | 4 ++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/linux-user/hppa/target_syscall.h b/linux-user/hppa/target_syscall.h index 4b382c1fcf..9a8f8ca628 100644 --- a/linux-user/hppa/target_syscall.h +++ b/linux-user/hppa/target_syscall.h @@ -26,4 +26,6 @@ struct target_pt_regs { #define TARGET_MCL_FUTURE 2 #define TARGET_MCL_ONFAULT 4 +#define TARGET_DEFAULT_STACK_SIZE 80 * 1024 * 1024UL + #endif /* HPPA_TARGET_SYSCALL_H */ diff --git a/linux-user/main.c b/linux-user/main.c index e44bdb17b8..88fccfe261 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -124,10 +124,14 @@ static void usage(int exitcode); static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; const char *qemu_uname_release; +#if !defined(TARGET_DEFAULT_STACK_SIZE) /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so we allocate a bigger stack. Need a better solution, for example by remapping the process stack directly at the right place */ -unsigned long guest_stack_size = 8 * 1024 * 1024UL; +#define TARGET_DEFAULT_STACK_SIZE 8 * 1024 * 1024UL +#endif + +unsigned long guest_stack_size = TARGET_DEFAULT_STACK_SIZE; /***********************************************************/ /* Helper routines for implementing atomic operations. */ @@ -668,7 +672,8 @@ int main(int argc, char **argv, char **envp) struct rlimit lim; if (getrlimit(RLIMIT_STACK, &lim) == 0 && lim.rlim_cur != RLIM_INFINITY - && lim.rlim_cur == (target_long)lim.rlim_cur) { + && lim.rlim_cur == (target_long)lim.rlim_cur + && lim.rlim_cur > guest_stack_size) { guest_stack_size = lim.rlim_cur; } } diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 850410c9b5..f87b36b249 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8036,7 +8036,11 @@ static int open_self_maps(CPUArchState *cpu_env, int fd) continue; } +#ifdef TARGET_HPPA + if (h2g(max) == ts->info->stack_limit) { +#else if (h2g(min) == ts->info->stack_limit) { +#endif path = "[stack]"; } else { path = e->path; From e935b735085dfa61d8e6d276b6f9e7687796a3c7 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 21 Sep 2022 11:31:31 +0200 Subject: [PATCH 0687/1020] x86: return modified setup_data only if read as memory, not as file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If setup_data is being read into a specific memory location, then generally the setup_data address parameter is read first, so that the caller knows where to read it into. In that case, we should return setup_data containing the absolute addresses that are hard coded and determined a priori. This is the case when kernels are loaded by BIOS, for example. In contrast, when setup_data is read as a file, then we shouldn't modify setup_data, since the absolute address will be wrong by definition. This is the case when OVMF loads the image. This allows setup_data to be used like normal, without crashing when EFI tries to use it. (As a small development note, strangely, fw_cfg_add_file_callback() was exported but fw_cfg_add_bytes_callback() wasn't, so this makes that consistent.) Cc: Gerd Hoffmann Cc: Laurent Vivier Cc: Michael S. Tsirkin Cc: Paolo Bonzini Cc: Peter Maydell Cc: Philippe Mathieu-DaudĂ© Cc: Richard Henderson Suggested-by: Ard Biesheuvel Reviewed-by: Ard Biesheuvel Signed-off-by: Jason A. Donenfeld Message-Id: <20220921093134.2936487-1-Jason@zx2c4.com> Signed-off-by: Paolo Bonzini --- hw/i386/x86.c | 46 ++++++++++++++++++++++++++++++--------- hw/nvram/fw_cfg.c | 12 +++++----- include/hw/nvram/fw_cfg.h | 22 +++++++++++++++++++ 3 files changed, 64 insertions(+), 16 deletions(-) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 050eedc0c8..96d205927e 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -37,6 +37,7 @@ #include "sysemu/whpx.h" #include "sysemu/numa.h" #include "sysemu/replay.h" +#include "sysemu/reset.h" #include "sysemu/sysemu.h" #include "sysemu/cpu-timers.h" #include "sysemu/xen.h" @@ -764,6 +765,24 @@ static bool load_elfboot(const char *kernel_filename, return true; } +typedef struct SetupDataFixup { + void *pos; + hwaddr orig_val, new_val; + uint32_t addr; +} SetupDataFixup; + +static void fixup_setup_data(void *opaque) +{ + SetupDataFixup *fixup = opaque; + stq_p(fixup->pos, fixup->new_val); +} + +static void reset_setup_data(void *opaque) +{ + SetupDataFixup *fixup = opaque; + stq_p(fixup->pos, fixup->orig_val); +} + void x86_load_linux(X86MachineState *x86ms, FWCfgState *fw_cfg, int acpi_data_size, @@ -1088,8 +1107,11 @@ void x86_load_linux(X86MachineState *x86ms, qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH); } - /* Offset 0x250 is a pointer to the first setup_data link. */ - stq_p(header + 0x250, first_setup_data); + fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); + fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); + fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size); + sev_load_ctx.kernel_data = (char *)kernel; + sev_load_ctx.kernel_size = kernel_size; /* * If we're starting an encrypted VM, it will be OVMF based, which uses the @@ -1099,16 +1121,20 @@ void x86_load_linux(X86MachineState *x86ms, * file the user passed in. */ if (!sev_enabled()) { + SetupDataFixup *fixup = g_malloc(sizeof(*fixup)); + memcpy(setup, header, MIN(sizeof(header), setup_size)); + /* Offset 0x250 is a pointer to the first setup_data link. */ + fixup->pos = setup + 0x250; + fixup->orig_val = ldq_p(fixup->pos); + fixup->new_val = first_setup_data; + fixup->addr = cpu_to_le32(real_addr); + fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_SETUP_ADDR, fixup_setup_data, NULL, + fixup, &fixup->addr, sizeof(fixup->addr), true); + qemu_register_reset(reset_setup_data, fixup); + } else { + fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr); } - - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); - fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); - fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size); - sev_load_ctx.kernel_data = (char *)kernel; - sev_load_ctx.kernel_size = kernel_size; - - fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_ADDR, real_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_SETUP_SIZE, setup_size); fw_cfg_add_bytes(fw_cfg, FW_CFG_SETUP_DATA, setup, setup_size); sev_load_ctx.setup_data = (char *)setup; diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c index d605f3f45a..564bda3395 100644 --- a/hw/nvram/fw_cfg.c +++ b/hw/nvram/fw_cfg.c @@ -692,12 +692,12 @@ static const VMStateDescription vmstate_fw_cfg = { } }; -static void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key, - FWCfgCallback select_cb, - FWCfgWriteCallback write_cb, - void *callback_opaque, - void *data, size_t len, - bool read_only) +void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key, + FWCfgCallback select_cb, + FWCfgWriteCallback write_cb, + void *callback_opaque, + void *data, size_t len, + bool read_only) { int arch = !!(key & FW_CFG_ARCH_LOCAL); diff --git a/include/hw/nvram/fw_cfg.h b/include/hw/nvram/fw_cfg.h index 0e7a8bc7af..e4fef393be 100644 --- a/include/hw/nvram/fw_cfg.h +++ b/include/hw/nvram/fw_cfg.h @@ -117,6 +117,28 @@ struct FWCfgMemState { */ void fw_cfg_add_bytes(FWCfgState *s, uint16_t key, void *data, size_t len); +/** + * fw_cfg_add_bytes_callback: + * @s: fw_cfg device being modified + * @key: selector key value for new fw_cfg item + * @select_cb: callback function when selecting + * @write_cb: callback function after a write + * @callback_opaque: argument to be passed into callback function + * @data: pointer to start of item data + * @len: size of item data + * @read_only: is file read only + * + * Add a new fw_cfg item, available by selecting the given key, as a raw + * "blob" of the given size. The data referenced by the starting pointer + * is only linked, NOT copied, into the data structure of the fw_cfg device. + */ +void fw_cfg_add_bytes_callback(FWCfgState *s, uint16_t key, + FWCfgCallback select_cb, + FWCfgWriteCallback write_cb, + void *callback_opaque, + void *data, size_t len, + bool read_only); + /** * fw_cfg_add_string: * @s: fw_cfg device being modified From eebb38a5633a77f5fa79d6486d5b2fcf8fbe3c07 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 21 Sep 2022 11:31:32 +0200 Subject: [PATCH 0688/1020] x86: use typedef for SetupData struct The preferred style is SetupData as a typedef, not setup_data as a plain struct. Cc: Paolo Bonzini Cc: Ard Biesheuvel Suggested-by: Michael S. Tsirkin Signed-off-by: Jason A. Donenfeld Message-Id: <20220921093134.2936487-2-Jason@zx2c4.com> Signed-off-by: Paolo Bonzini --- hw/i386/x86.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 96d205927e..1ee0b1b413 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -653,12 +653,12 @@ DeviceState *ioapic_init_secondary(GSIState *gsi_state) return dev; } -struct setup_data { +typedef struct SetupData { uint64_t next; uint32_t type; uint32_t len; uint8_t data[]; -} __attribute__((packed)); +} __attribute__((packed)) SetupData; /* @@ -799,7 +799,7 @@ void x86_load_linux(X86MachineState *x86ms, FILE *f; char *vmode; MachineState *machine = MACHINE(x86ms); - struct setup_data *setup_data; + SetupData *setup_data; const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; const char *dtb_filename = machine->dtb; @@ -1082,11 +1082,11 @@ void x86_load_linux(X86MachineState *x86ms, } setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16); - kernel_size = setup_data_offset + sizeof(struct setup_data) + dtb_size; + kernel_size = setup_data_offset + sizeof(SetupData) + dtb_size; kernel = g_realloc(kernel, kernel_size); - setup_data = (struct setup_data *)(kernel + setup_data_offset); + setup_data = (SetupData *)(kernel + setup_data_offset); setup_data->next = cpu_to_le64(first_setup_data); first_setup_data = prot_addr + setup_data_offset; setup_data->type = cpu_to_le32(SETUP_DTB); @@ -1097,9 +1097,9 @@ void x86_load_linux(X86MachineState *x86ms, if (!legacy_no_rng_seed) { setup_data_offset = QEMU_ALIGN_UP(kernel_size, 16); - kernel_size = setup_data_offset + sizeof(struct setup_data) + RNG_SEED_LENGTH; + kernel_size = setup_data_offset + sizeof(SetupData) + RNG_SEED_LENGTH; kernel = g_realloc(kernel, kernel_size); - setup_data = (struct setup_data *)(kernel + setup_data_offset); + setup_data = (SetupData *)(kernel + setup_data_offset); setup_data->next = cpu_to_le64(first_setup_data); first_setup_data = prot_addr + setup_data_offset; setup_data->type = cpu_to_le32(SETUP_RNG_SEED); From 763a2828bf313ed55878b09759dc435355035f2e Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 21 Sep 2022 11:31:33 +0200 Subject: [PATCH 0689/1020] x86: reinitialize RNG seed on system reboot Since this is read from fw_cfg on each boot, the kernel zeroing it out alone is insufficient to prevent it from being used twice. And indeed on reboot we always want a new seed, not the old one. So re-fill it in this circumstance. Cc: Paolo Bonzini Signed-off-by: Jason A. Donenfeld Message-Id: <20220921093134.2936487-3-Jason@zx2c4.com> Signed-off-by: Paolo Bonzini --- hw/i386/x86.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index 1ee0b1b413..f9a4ddaa4a 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -783,6 +783,12 @@ static void reset_setup_data(void *opaque) stq_p(fixup->pos, fixup->orig_val); } +static void reset_rng_seed(void *opaque) +{ + SetupData *setup_data = opaque; + qemu_guest_getrandom_nofail(setup_data->data, le32_to_cpu(setup_data->len)); +} + void x86_load_linux(X86MachineState *x86ms, FWCfgState *fw_cfg, int acpi_data_size, @@ -1105,6 +1111,7 @@ void x86_load_linux(X86MachineState *x86ms, setup_data->type = cpu_to_le32(SETUP_RNG_SEED); setup_data->len = cpu_to_le32(RNG_SEED_LENGTH); qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH); + qemu_register_reset(reset_rng_seed, setup_data); } fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); From ffe2d2382e5f1aae1abc4081af407905ef380311 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 21 Sep 2022 11:31:34 +0200 Subject: [PATCH 0690/1020] x86: re-enable rng seeding via SetupData MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts 3824e25db1 ("x86: disable rng seeding via setup_data"), but for 7.2 rather than 7.1, now that modifying setup_data is safe to do. Cc: Laurent Vivier Cc: Michael S. Tsirkin Cc: Paolo Bonzini Cc: Peter Maydell Cc: Philippe Mathieu-DaudĂ© Cc: Richard Henderson Cc: Ard Biesheuvel Acked-by: Gerd Hoffmann Signed-off-by: Jason A. Donenfeld Message-Id: <20220921093134.2936487-4-Jason@zx2c4.com> Signed-off-by: Paolo Bonzini --- hw/i386/microvm.c | 2 +- hw/i386/pc_piix.c | 3 ++- hw/i386/pc_q35.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index 52cafa003d..7fe8cce03e 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -332,7 +332,7 @@ static void microvm_memory_init(MicrovmMachineState *mms) rom_set_fw(fw_cfg); if (machine->kernel_filename != NULL) { - x86_load_linux(x86ms, fw_cfg, 0, true, true); + x86_load_linux(x86ms, fw_cfg, 0, true, false); } if (mms->option_roms) { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 8043a250ad..0b1a79c0fa 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -439,7 +439,6 @@ static void pc_i440fx_7_2_machine_options(MachineClass *m) m->alias = "pc"; m->is_default = true; pcmc->default_cpu_version = 1; - pcmc->legacy_no_rng_seed = true; } DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL, @@ -447,9 +446,11 @@ DEFINE_I440FX_MACHINE(v7_2, "pc-i440fx-7.2", NULL, static void pc_i440fx_7_1_machine_options(MachineClass *m) { + PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_7_2_machine_options(m); m->alias = NULL; m->is_default = false; + pcmc->legacy_no_rng_seed = true; compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len); compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len); } diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index 53eda50e81..a496bd6e74 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -376,7 +376,6 @@ static void pc_q35_7_2_machine_options(MachineClass *m) pc_q35_machine_options(m); m->alias = "q35"; pcmc->default_cpu_version = 1; - pcmc->legacy_no_rng_seed = true; } DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL, @@ -384,8 +383,10 @@ DEFINE_Q35_MACHINE(v7_2, "pc-q35-7.2", NULL, static void pc_q35_7_1_machine_options(MachineClass *m) { + PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_7_2_machine_options(m); m->alias = NULL; + pcmc->legacy_no_rng_seed = true; compat_props_add(m->compat_props, hw_compat_7_1, hw_compat_7_1_len); compat_props_add(m->compat_props, pc_compat_7_1, pc_compat_7_1_len); } From 2fc7eb689704687f890688507e15bbbe71275f63 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 11:22:37 +0200 Subject: [PATCH 0691/1020] qboot: rebuild based on latest commit df22fbb751 ("qboot: update to latest submodule") updated the qboot submodule from a5300c49 to 8ca302e8. However, qboot isn't built during the QEMU's build process but rather is included in binary form. So rebuild it here. Cc: Paolo Bonzini Signed-off-by: Jason A. Donenfeld [Rebuilt it myself for paranoia. - Paolo] Signed-off-by: Paolo Bonzini --- pc-bios/qboot.rom | Bin 65536 -> 65536 bytes 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 pc-bios/qboot.rom diff --git a/pc-bios/qboot.rom b/pc-bios/qboot.rom old mode 100644 new mode 100755 index 7634106a0766913077e88dfcb1021c1168dcad3c..684000f57aad8925c81890d97345500eb266827e GIT binary patch delta 8383 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 delta 9151 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 SEQnQ-4%R&t{Vp*}=KleWh?AlK From 7089977a24133b3b1dd0864f4138efe3b906af4b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 6 Jun 2022 11:35:41 +0200 Subject: [PATCH 0692/1020] configure: do not invoke as/ld directly for pc-bios/optionrom Just use using the compiler binary, with -nostdlib in the case of the linker; the compiler driver (whether i686-*-gcc, or x86_64-*-gcc with the -m32 option) will then pick the right magic option to as and ld. Signed-off-by: Paolo Bonzini --- configure | 22 +++++----------------- pc-bios/optionrom/Makefile | 12 ++++-------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/configure b/configure index cc4ecd6008..894e37310f 100755 --- a/configure +++ b/configure @@ -2320,23 +2320,11 @@ probe_target_compiler i386-softmmu if test -n "$target_cc" && test "$targetos" != "darwin" && test "$targetos" != "sunos" && \ test "$targetos" != "haiku" && test "$softmmu" = yes ; then - # Different host OS linkers have different ideas about the name of the ELF - # emulation. Linux and OpenBSD/amd64 use 'elf_i386'; FreeBSD uses the _fbsd - # variant; OpenBSD/i386 uses the _obsd variant; and Windows uses i386pe. - for emu in elf_i386 elf_i386_fbsd elf_i386_obsd i386pe; do - if "$target_ld" -verbose 2>&1 | grep -q "^[[:space:]]*${emu}[[:space:]]*$"; then - ld_i386_emulation="$emu" - break - fi - done - if test -n "$ld_i386_emulation"; then - roms="pc-bios/optionrom" - config_mak=pc-bios/optionrom/config.mak - echo "# Automatically generated by configure - do not modify" > $config_mak - echo "TOPSRC_DIR=$source_path" >> $config_mak - echo "LD_I386_EMULATION=$ld_i386_emulation" >> $config_mak - write_target_makefile >> $config_mak - fi + roms="pc-bios/optionrom" + config_mak=pc-bios/optionrom/config.mak + echo "# Automatically generated by configure - do not modify" > $config_mak + echo "TOPSRC_DIR=$source_path" >> $config_mak + write_target_makefile >> $config_mak fi probe_target_compiler ppc-softmmu diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index e90ca2e1c6..3e06c11dea 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -20,28 +20,24 @@ override CFLAGS += $(call cc-option, -fcf-protection=none) # Flags for dependency generation override CPPFLAGS += -MMD -MP -MT $@ -MF $(@D)/$(*F).d -override CFLAGS += $(filter -W%, $(QEMU_CFLAGS)) override CFLAGS += $(call cc-option, -fno-pie) +override CFLAGS += $(call cc-option, -no-pie) override CFLAGS += -ffreestanding -I$(TOPSRC_DIR)/include override CFLAGS += $(call cc-option, -fno-stack-protector) override CFLAGS += $(call cc-option, -Wno-array-bounds) -Wa = -Wa, -override ASFLAGS += -32 -override CFLAGS += $(call cc-option, $(Wa)-32) - -override LDFLAGS = -m $(LD_I386_EMULATION) -T $(SRC_DIR)/flat.lds +override LDFLAGS = -nostdlib -Wl,-T,$(SRC_DIR)/flat.lds pvh.img: pvh.o pvh_main.o %.o: %.S - $(call quiet-command,$(CC) $(CPPFLAGS) -E -o - $< | $(AS) $(ASFLAGS) -o $@,"AS","$@") + $(call quiet-command,$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<,"AS","$@") %.o: %.c $(call quiet-command,$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@,"CC","$@") %.img: %.o - $(call quiet-command,$(LD) $(LDFLAGS) -s -o $@ $^,"BUILD","$@") + $(call quiet-command,$(CC) $(CFLAGS) $(LDFLAGS) -s -o $@ $^,"BUILD","$@") %.raw: %.img $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"BUILD","$@") From 4c184e70ad01289f89a9a780d154b00d6a86cccd Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Sep 2022 13:45:00 +0200 Subject: [PATCH 0693/1020] linux-user/hppa: Allow PROT_GROWSUP and PROT_GROWSDOWN in mprotect() The hppa platform uses an upwards-growing stack and required in Linux kernels < 5.18 an executable stack for signal processing. For that some executables and libraries are marked to have an executable stack, for which glibc uses the mprotect() syscall to mark the stack like this: mprotect(xfa000000,4096,PROT_EXEC|PROT_READ|PROT_WRITE|PROT_GROWSUP). Currently qemu will return -TARGET_EINVAL for this syscall because of the checks in validate_prot_to_pageflags(), which doesn't allow the PROT_GROWSUP or PROT_GROWSDOWN flags and thus triggers this error in the guest: error while loading shared libraries: libc.so.6: cannot enable executable stack as shared object requires: Invalid argument Allow mprotect() to handle both flags and thus fix the guest. The glibc tst-execstack testcase can be used to reproduce the issue. Signed-off-by: Helge Deller Message-Id: <20220924114501.21767-7-deller@gmx.de> [lvivier: s/elif TARGET_HPPA/elif defined(TARGET_HPPA)/] Signed-off-by: Laurent Vivier --- linux-user/mmap.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/mmap.c b/linux-user/mmap.c index e557f3626e..28f3bc85ed 100644 --- a/linux-user/mmap.c +++ b/linux-user/mmap.c @@ -106,6 +106,8 @@ static int validate_prot_to_pageflags(int *host_prot, int prot) page_flags |= PAGE_MTE; } } +#elif defined(TARGET_HPPA) + valid |= PROT_GROWSDOWN | PROT_GROWSUP; #endif return prot & ~valid ? 0 : page_flags; From 2319a53758efd0a2a1b45d94d3a3b721730cbc00 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Sat, 24 Sep 2022 13:45:01 +0200 Subject: [PATCH 0694/1020] linux-user/hppa: Fix setup_sigcontext() We don't emulate a preemptive kernel on this level, and the hppa architecture doesn't allow context switches on the gateway page. So we always have to return to sc_iaoq[] and not to gr[31]. This fixes the remaining random segfaults which still occured. Signed-off-by: Helge Deller Message-Id: <20220924114501.21767-8-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/hppa/signal.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/linux-user/hppa/signal.c b/linux-user/hppa/signal.c index 396e310dc9..f253a15864 100644 --- a/linux-user/hppa/signal.c +++ b/linux-user/hppa/signal.c @@ -49,23 +49,13 @@ struct target_rt_sigframe { static void setup_sigcontext(struct target_sigcontext *sc, CPUArchState *env) { - int flags = 0; int i; - /* ??? if on_sig_stack, flags |= 1 (PARISC_SC_FLAG_ONSTACK). */ - - if (env->iaoq_f < TARGET_PAGE_SIZE) { - /* In the gateway page, executing a syscall. */ - flags |= 2; /* PARISC_SC_FLAG_IN_SYSCALL */ - __put_user(env->gr[31], &sc->sc_iaoq[0]); - __put_user(env->gr[31] + 4, &sc->sc_iaoq[1]); - } else { - __put_user(env->iaoq_f, &sc->sc_iaoq[0]); - __put_user(env->iaoq_b, &sc->sc_iaoq[1]); - } + __put_user(env->iaoq_f, &sc->sc_iaoq[0]); + __put_user(env->iaoq_b, &sc->sc_iaoq[1]); __put_user(0, &sc->sc_iasq[0]); __put_user(0, &sc->sc_iasq[1]); - __put_user(flags, &sc->sc_flags); + __put_user(0, &sc->sc_flags); __put_user(cpu_hppa_get_psw(env), &sc->sc_gr[0]); for (i = 1; i < 32; ++i) { From 9b9145f04d303354d8da1112577ece26aaf478dd Mon Sep 17 00:00:00 2001 From: fanwenjie Date: Wed, 31 Aug 2022 11:55:25 +0800 Subject: [PATCH 0695/1020] linux-user: fix bug about missing signum convert of sigqueue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: 66fb9763af ("basic signal handling") Fixes: cf8b8bfc50 ("linux-user: add support for rt_tgsigqueueinfo() system call") Signed-off-by: fanwenjie Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f87b36b249..54b29f3b40 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -9728,7 +9728,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, } target_to_host_siginfo(&uinfo, p); unlock_user(p, arg3, 0); - ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); + ret = get_errno(sys_rt_sigqueueinfo(arg1, target_to_host_signal(arg2), &uinfo)); } return ret; case TARGET_NR_rt_tgsigqueueinfo: @@ -9741,7 +9741,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, } target_to_host_siginfo(&uinfo, p); unlock_user(p, arg4, 0); - ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo)); + ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, target_to_host_signal(arg3), &uinfo)); } return ret; #ifdef TARGET_NR_sigreturn From 9e59899f8c75e3a7b327eb42ef61818d7f06992e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 25 Jul 2022 12:00:35 +0100 Subject: [PATCH 0696/1020] linux-user: Don't assume 0 is not a valid host timer_t value For handling guest POSIX timers, we currently use an array g_posix_timers[], whose entries are a host timer_t value, or 0 for "this slot is unused". When the guest calls the timer_create syscall we look through the array for a slot containing 0, and use that for the new timer. This scheme assumes that host timer_t values can never be zero. This is unfortunately not a valid assumption -- for some host libc versions, timer_t values are simply indexes starting at 0. When using this kind of host libc, the effect is that the first and second timers end up sharing a slot, and so when the guest tries to operate on the first timer it changes the second timer instead. Rework the timer allocation code, so that: * the 'slot in use' indication uses a separate array from the host timer_t array * we grab the free slot atomically, to avoid races when multiple threads call timer_create simultaneously * releasing an allocated slot is abstracted out into a new free_host_timer_slot() function called in the correct places This fixes: * problems on hosts where timer_t 0 is valid * the FIXME in next_free_host_timer() about locking * bugs in the error paths in timer_create where we forgot to release the slot we grabbed, or forgot to free the host timer Reported-by: Jon Alduan Signed-off-by: Peter Maydell Message-Id: <20220725110035.1273441-1-peter.maydell@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 54b29f3b40..e0e0f05812 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -525,20 +525,25 @@ _syscall4(int, sys_prlimit64, pid_t, pid, int, resource, #if defined(TARGET_NR_timer_create) /* Maximum of 32 active POSIX timers allowed at any one time. */ -static timer_t g_posix_timers[32] = { 0, } ; +#define GUEST_TIMER_MAX 32 +static timer_t g_posix_timers[GUEST_TIMER_MAX]; +static int g_posix_timer_allocated[GUEST_TIMER_MAX]; static inline int next_free_host_timer(void) { - int k ; - /* FIXME: Does finding the next free slot require a lock? */ - for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) { - if (g_posix_timers[k] == 0) { - g_posix_timers[k] = (timer_t) 1; + int k; + for (k = 0; k < ARRAY_SIZE(g_posix_timer_allocated); k++) { + if (qatomic_xchg(g_posix_timer_allocated + k, 1) == 0) { return k; } } return -1; } + +static inline void free_host_timer_slot(int id) +{ + qatomic_store_release(g_posix_timer_allocated + id, 0); +} #endif static inline int host_to_target_errno(int host_errno) @@ -12896,15 +12901,18 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, phost_sevp = &host_sevp; ret = target_to_host_sigevent(phost_sevp, arg2); if (ret != 0) { + free_host_timer_slot(timer_index); return ret; } } ret = get_errno(timer_create(clkid, phost_sevp, phtimer)); if (ret) { - phtimer = NULL; + free_host_timer_slot(timer_index); } else { if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) { + timer_delete(*phtimer); + free_host_timer_slot(timer_index); return -TARGET_EFAULT; } } @@ -13040,7 +13048,7 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, } else { timer_t htimer = g_posix_timers[timerid]; ret = get_errno(timer_delete(htimer)); - g_posix_timers[timerid] = 0; + free_host_timer_slot(timerid); } return ret; } From 2941e0fa050314cd200f24e3b99da61440b106ab Mon Sep 17 00:00:00 2001 From: Ilya Leoshkevich Date: Wed, 17 Aug 2022 14:39:02 +0200 Subject: [PATCH 0697/1020] linux-user/s390x: Save/restore fpc when handling a signal Linux kernel does this in fpregs_store() and fpregs_load(), so qemu-user should do this as well. Found by running valgrind's none/tests/s390x/test_sig. Signed-off-by: Ilya Leoshkevich Reviewed-by: Richard Henderson Message-Id: <20220817123902.585623-1-iii@linux.ibm.com> Signed-off-by: Laurent Vivier --- linux-user/s390x/signal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-user/s390x/signal.c b/linux-user/s390x/signal.c index 4979c4b017..f72165576f 100644 --- a/linux-user/s390x/signal.c +++ b/linux-user/s390x/signal.c @@ -146,6 +146,7 @@ static void save_sigregs(CPUS390XState *env, target_sigregs *sregs) * We have to store the fp registers to current->thread.fp_regs * to merge them with the emulated registers. */ + __put_user(env->fpc, &sregs->fpregs.fpc); for (i = 0; i < 16; i++) { __put_user(*get_freg(env, i), &sregs->fpregs.fprs[i]); } @@ -331,6 +332,7 @@ static void restore_sigregs(CPUS390XState *env, target_sigregs *sc) for (i = 0; i < 16; i++) { __get_user(env->aregs[i], &sc->regs.acrs[i]); } + __get_user(env->fpc, &sc->fpregs.fpc); for (i = 0; i < 16; i++) { __get_user(*get_freg(env, i), &sc->fpregs.fprs[i]); } From fcdc0ab4b4d09bac65c192726af1c1bcb28de8e4 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Wed, 3 Aug 2022 11:30:08 +0100 Subject: [PATCH 0698/1020] linux-user: Introduce stubs for ELF AT_BASE_PLATFORM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AT_BASE_PLATFORM is a elf auxiliary vector pointing to a string to pass some architecture information. See getauxval(3) man-page. Signed-off-by: Jiaxun Yang Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220803103009.95972-2-jiaxun.yang@flygoat.com> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index c7e3f1d47c..581fbc858b 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1776,6 +1776,10 @@ static inline void init_thread(struct target_pt_regs *regs, #endif /* TARGET_HEXAGON */ +#ifndef ELF_BASE_PLATFORM +#define ELF_BASE_PLATFORM (NULL) +#endif + #ifndef ELF_PLATFORM #define ELF_PLATFORM (NULL) #endif @@ -2220,8 +2224,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, int i; abi_ulong u_rand_bytes; uint8_t k_rand_bytes[16]; - abi_ulong u_platform; - const char *k_platform; + abi_ulong u_platform, u_base_platform; + const char *k_platform, *k_base_platform; const int n = sizeof(elf_addr_t); sp = p; @@ -2243,6 +2247,22 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, } } + u_base_platform = 0; + k_base_platform = ELF_BASE_PLATFORM; + if (k_base_platform) { + size_t len = strlen(k_base_platform) + 1; + if (STACK_GROWS_DOWN) { + sp -= (len + n - 1) & ~(n - 1); + u_base_platform = sp; + /* FIXME - check return value of memcpy_to_target() for failure */ + memcpy_to_target(sp, k_base_platform, len); + } else { + memcpy_to_target(sp, k_base_platform, len); + u_base_platform = sp; + sp += len + 1; + } + } + u_platform = 0; k_platform = ELF_PLATFORM; if (k_platform) { @@ -2284,6 +2304,8 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, } size = (DLINFO_ITEMS + 1) * 2; + if (k_base_platform) + size += 2; if (k_platform) size += 2; #ifdef DLINFO_ARCH_ITEMS @@ -2361,6 +2383,9 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc, NEW_AUX_ENT(AT_HWCAP2, (abi_ulong) ELF_HWCAP2); #endif + if (u_base_platform) { + NEW_AUX_ENT(AT_BASE_PLATFORM, u_base_platform); + } if (u_platform) { NEW_AUX_ENT(AT_PLATFORM, u_platform); } From fbf47c18aa8687b1c6a929fbcd8bb36dfc386454 Mon Sep 17 00:00:00 2001 From: Jiaxun Yang Date: Wed, 3 Aug 2022 11:30:09 +0100 Subject: [PATCH 0699/1020] linux-user: Set ELF_BASE_PLATFORM for MIPS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Match most appropriate base platform string based on insn_flags. Logic is aligned with aligned with set_isa() from arch/mips/kernel/cpu-probe.c in Linux kernel. Signed-off-by: Jiaxun Yang Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220803103009.95972-3-jiaxun.yang@flygoat.com> Signed-off-by: Laurent Vivier --- linux-user/elfload.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 581fbc858b..20894b633f 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1080,6 +1080,37 @@ static uint32_t get_elf_hwcap(void) #define elf_check_abi(x) (!((x) & EF_MIPS_ABI2)) #endif +#define ELF_BASE_PLATFORM get_elf_base_platform() + +#define MATCH_PLATFORM_INSN(_flags, _base_platform) \ + do { if ((cpu->env.insn_flags & (_flags)) == _flags) \ + { return _base_platform; } } while (0) + +static const char *get_elf_base_platform(void) +{ + MIPSCPU *cpu = MIPS_CPU(thread_cpu); + + /* 64 bit ISAs goes first */ + MATCH_PLATFORM_INSN(CPU_MIPS64R6, "mips64r6"); + MATCH_PLATFORM_INSN(CPU_MIPS64R5, "mips64r5"); + MATCH_PLATFORM_INSN(CPU_MIPS64R2, "mips64r2"); + MATCH_PLATFORM_INSN(CPU_MIPS64R1, "mips64"); + MATCH_PLATFORM_INSN(CPU_MIPS5, "mips5"); + MATCH_PLATFORM_INSN(CPU_MIPS4, "mips4"); + MATCH_PLATFORM_INSN(CPU_MIPS3, "mips3"); + + /* 32 bit ISAs */ + MATCH_PLATFORM_INSN(CPU_MIPS32R6, "mips32r6"); + MATCH_PLATFORM_INSN(CPU_MIPS32R5, "mips32r5"); + MATCH_PLATFORM_INSN(CPU_MIPS32R2, "mips32r2"); + MATCH_PLATFORM_INSN(CPU_MIPS32R1, "mips32"); + MATCH_PLATFORM_INSN(CPU_MIPS2, "mips2"); + + /* Fallback */ + return "mips"; +} +#undef MATCH_PLATFORM_INSN + static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) { From 0fbc0f8da1ec69991472a42ba601376e3f7c6b2d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 19:09:59 -0700 Subject: [PATCH 0700/1020] linux-user: Combine do_futex and do_futex_time64 Pass a boolean to select between time32 and time64. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220829021006.67305-2-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 67 ++++++++------------------------------------ 1 file changed, 11 insertions(+), 56 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e0e0f05812..af3a605fc4 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7768,9 +7768,10 @@ static int do_safe_futex(int *uaddr, int op, int val, futexes locally would make futexes shared between multiple processes tricky. However they're probably useless because guest atomic operations won't work either. */ -#if defined(TARGET_NR_futex) -static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val, - target_ulong timeout, target_ulong uaddr2, int val3) +#if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64) +static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr, + int op, int val, target_ulong timeout, + target_ulong uaddr2, int val3) { struct timespec ts, *pts; int base_op; @@ -7787,7 +7788,11 @@ static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val, case FUTEX_WAIT_BITSET: if (timeout) { pts = &ts; - target_to_host_timespec(pts, timeout); + if (time64 + ? target_to_host_timespec64(pts, timeout) + : target_to_host_timespec(pts, timeout)) { + return -TARGET_EFAULT; + } } else { pts = NULL; } @@ -7817,56 +7822,6 @@ static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val, } #endif -#if defined(TARGET_NR_futex_time64) -static int do_futex_time64(CPUState *cpu, target_ulong uaddr, int op, - int val, target_ulong timeout, - target_ulong uaddr2, int val3) -{ - struct timespec ts, *pts; - int base_op; - - /* ??? We assume FUTEX_* constants are the same on both host - and target. */ -#ifdef FUTEX_CMD_MASK - base_op = op & FUTEX_CMD_MASK; -#else - base_op = op; -#endif - switch (base_op) { - case FUTEX_WAIT: - case FUTEX_WAIT_BITSET: - if (timeout) { - pts = &ts; - if (target_to_host_timespec64(pts, timeout)) { - return -TARGET_EFAULT; - } - } else { - pts = NULL; - } - return do_safe_futex(g2h(cpu, uaddr), op, - tswap32(val), pts, NULL, val3); - case FUTEX_WAKE: - return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0); - case FUTEX_FD: - return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0); - case FUTEX_REQUEUE: - case FUTEX_CMP_REQUEUE: - case FUTEX_WAKE_OP: - /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the - TIMEOUT parameter is interpreted as a uint32_t by the kernel. - But the prototype takes a `struct timespec *'; insert casts - to satisfy the compiler. We do not need to tswap TIMEOUT - since it's not compared to guest memory. */ - pts = (struct timespec *)(uintptr_t) timeout; - return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2), - (base_op == FUTEX_CMP_REQUEUE - ? tswap32(val3) : val3)); - default: - return -TARGET_ENOSYS; - } -} -#endif - #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname, abi_long handle, abi_long mount_id, @@ -12372,11 +12327,11 @@ static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_futex case TARGET_NR_futex: - return do_futex(cpu, arg1, arg2, arg3, arg4, arg5, arg6); + return do_futex(cpu, false, arg1, arg2, arg3, arg4, arg5, arg6); #endif #ifdef TARGET_NR_futex_time64 case TARGET_NR_futex_time64: - return do_futex_time64(cpu, arg1, arg2, arg3, arg4, arg5, arg6); + return do_futex(cpu, true, arg1, arg2, arg3, arg4, arg5, arg6); #endif #ifdef CONFIG_INOTIFY #if defined(TARGET_NR_inotify_init) From 57b9ccd4c03dc5f175c4bd7d7406a15fb4d24aca Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 19:10:00 -0700 Subject: [PATCH 0701/1020] linux-user: Sink call to do_safe_futex Leave only the argument adjustments within the shift, and sink the actual syscall to the end. Sink the timespec conversion as well, as there will be more users. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220829021006.67305-3-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 60 +++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index af3a605fc4..17e17f4804 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7773,11 +7773,11 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr, int op, int val, target_ulong timeout, target_ulong uaddr2, int val3) { - struct timespec ts, *pts; + struct timespec ts, *pts = NULL; + void *haddr2 = NULL; int base_op; - /* ??? We assume FUTEX_* constants are the same on both host - and target. */ + /* We assume FUTEX_* constants are the same on both host and target. */ #ifdef FUTEX_CMD_MASK base_op = op & FUTEX_CMD_MASK; #else @@ -7786,39 +7786,41 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr, switch (base_op) { case FUTEX_WAIT: case FUTEX_WAIT_BITSET: - if (timeout) { - pts = &ts; - if (time64 - ? target_to_host_timespec64(pts, timeout) - : target_to_host_timespec(pts, timeout)) { - return -TARGET_EFAULT; - } - } else { - pts = NULL; - } - return do_safe_futex(g2h(cpu, uaddr), - op, tswap32(val), pts, NULL, val3); + val = tswap32(val); + break; case FUTEX_WAKE: - return do_safe_futex(g2h(cpu, uaddr), - op, val, NULL, NULL, 0); + timeout = 0; + break; case FUTEX_FD: - return do_safe_futex(g2h(cpu, uaddr), - op, val, NULL, NULL, 0); - case FUTEX_REQUEUE: + timeout = 0; + break; case FUTEX_CMP_REQUEUE: + val3 = tswap32(val3); + /* fall through */ + case FUTEX_REQUEUE: case FUTEX_WAKE_OP: - /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the - TIMEOUT parameter is interpreted as a uint32_t by the kernel. - But the prototype takes a `struct timespec *'; insert casts - to satisfy the compiler. We do not need to tswap TIMEOUT - since it's not compared to guest memory. */ - pts = (struct timespec *)(uintptr_t) timeout; - return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2), - (base_op == FUTEX_CMP_REQUEUE - ? tswap32(val3) : val3)); + /* + * For these, the 4th argument is not TIMEOUT, but VAL2. + * But the prototype of do_safe_futex takes a pointer, so + * insert casts to satisfy the compiler. We do not need + * to tswap VAL2 since it's not compared to guest memory. + */ + pts = (struct timespec *)(uintptr_t)timeout; + timeout = 0; + haddr2 = g2h(cpu, uaddr2); + break; default: return -TARGET_ENOSYS; } + if (timeout) { + pts = &ts; + if (time64 + ? target_to_host_timespec64(pts, timeout) + : target_to_host_timespec(pts, timeout)) { + return -TARGET_EFAULT; + } + } + return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3); } #endif From a6180f8aede726c1648b1ae3a602058c93f859c8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 19:10:01 -0700 Subject: [PATCH 0702/1020] linux-user: Implement FUTEX_WAKE_BITSET Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220829021006.67305-4-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 17e17f4804..e2b6b564e6 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7789,6 +7789,7 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr, val = tswap32(val); break; case FUTEX_WAKE: + case FUTEX_WAKE_BITSET: timeout = 0; break; case FUTEX_FD: From 0f9467311260c23eed758f97c75d83f1815acb29 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 19:10:02 -0700 Subject: [PATCH 0703/1020] linux-user: Convert signal number for FUTEX_FD The val argument to FUTEX_FD is a signal number. Convert to match the host, as it will be converted back when the signal is delivered. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220829021006.67305-5-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e2b6b564e6..3f144e3c1f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7793,6 +7793,7 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr, timeout = 0; break; case FUTEX_FD: + val = target_to_host_signal(val); timeout = 0; break; case FUTEX_CMP_REQUEUE: From c72a90df47b990572ac4fdb7e918005466446db9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 19:10:03 -0700 Subject: [PATCH 0704/1020] linux-user: Implement PI futexes Define the missing FUTEX_* constants in syscall_defs.h Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220829021006.67305-6-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/syscall.c | 10 ++++++++++ linux-user/syscall_defs.h | 3 +++ 2 files changed, 13 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 3f144e3c1f..2e954d8dbd 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -7788,8 +7788,17 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr, case FUTEX_WAIT_BITSET: val = tswap32(val); break; + case FUTEX_WAIT_REQUEUE_PI: + val = tswap32(val); + haddr2 = g2h(cpu, uaddr2); + break; + case FUTEX_LOCK_PI: + case FUTEX_LOCK_PI2: + break; case FUTEX_WAKE: case FUTEX_WAKE_BITSET: + case FUTEX_TRYLOCK_PI: + case FUTEX_UNLOCK_PI: timeout = 0; break; case FUTEX_FD: @@ -7797,6 +7806,7 @@ static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr, timeout = 0; break; case FUTEX_CMP_REQUEUE: + case FUTEX_CMP_REQUEUE_PI: val3 = tswap32(val3); /* fall through */ case FUTEX_REQUEUE: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index 1e3577bfa5..01ee10a88f 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -2699,6 +2699,9 @@ struct target_drm_i915_getparam { #define FUTEX_TRYLOCK_PI 8 #define FUTEX_WAIT_BITSET 9 #define FUTEX_WAKE_BITSET 10 +#define FUTEX_WAIT_REQUEUE_PI 11 +#define FUTEX_CMP_REQUEUE_PI 12 +#define FUTEX_LOCK_PI2 13 #define FUTEX_PRIVATE_FLAG 128 #define FUTEX_CLOCK_REALTIME 256 From 53b578f31fda28b2cf83ca28d0c7a5159416d32b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 19:10:04 -0700 Subject: [PATCH 0705/1020] linux-user: Update print_futex_op Use a table for the names; print unknown values in hex, since the value contains flags. Signed-off-by: Richard Henderson Message-Id: <20220829021006.67305-7-richard.henderson@linaro.org> [lv: update print_futex() according to "linux-user: Show timespec on strace for futex()"] Signed-off-by: Laurent Vivier --- linux-user/strace.c | 66 +++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index 2deb84a2c1..faa7331256 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -3710,44 +3710,37 @@ print_munmap(CPUArchState *cpu_env, const struct syscallname *name, #endif #ifdef TARGET_NR_futex -static void print_futex_op(abi_long tflag, int last) +static void print_futex_op(int cmd, int last) { -#define print_op(val) \ -if( cmd == val ) { \ - qemu_log(#val); \ - return; \ -} + static const char * const futex_names[] = { +#define NAME(X) [X] = #X + NAME(FUTEX_WAIT), + NAME(FUTEX_WAKE), + NAME(FUTEX_FD), + NAME(FUTEX_REQUEUE), + NAME(FUTEX_CMP_REQUEUE), + NAME(FUTEX_WAKE_OP), + NAME(FUTEX_LOCK_PI), + NAME(FUTEX_UNLOCK_PI), + NAME(FUTEX_TRYLOCK_PI), + NAME(FUTEX_WAIT_BITSET), + NAME(FUTEX_WAKE_BITSET), + NAME(FUTEX_WAIT_REQUEUE_PI), + NAME(FUTEX_CMP_REQUEUE_PI), + NAME(FUTEX_LOCK_PI2), +#undef NAME + }; - int cmd = (int)tflag; -#ifdef FUTEX_PRIVATE_FLAG - if (cmd & FUTEX_PRIVATE_FLAG) { - qemu_log("FUTEX_PRIVATE_FLAG|"); - cmd &= ~FUTEX_PRIVATE_FLAG; + unsigned base_cmd = cmd & FUTEX_CMD_MASK; + + if (base_cmd < ARRAY_SIZE(futex_names)) { + qemu_log("%s%s%s", + (cmd & FUTEX_PRIVATE_FLAG ? "FUTEX_PRIVATE_FLAG|" : ""), + (cmd & FUTEX_CLOCK_REALTIME ? "FUTEX_CLOCK_REALTIME|" : ""), + futex_names[base_cmd]); + } else { + qemu_log("0x%x", cmd); } -#endif -#ifdef FUTEX_CLOCK_REALTIME - if (cmd & FUTEX_CLOCK_REALTIME) { - qemu_log("FUTEX_CLOCK_REALTIME|"); - cmd &= ~FUTEX_CLOCK_REALTIME; - } -#endif - print_op(FUTEX_WAIT) - print_op(FUTEX_WAKE) - print_op(FUTEX_FD) - print_op(FUTEX_REQUEUE) - print_op(FUTEX_CMP_REQUEUE) - print_op(FUTEX_WAKE_OP) - print_op(FUTEX_LOCK_PI) - print_op(FUTEX_UNLOCK_PI) - print_op(FUTEX_TRYLOCK_PI) -#ifdef FUTEX_WAIT_BITSET - print_op(FUTEX_WAIT_BITSET) -#endif -#ifdef FUTEX_WAKE_BITSET - print_op(FUTEX_WAKE_BITSET) -#endif - /* unknown values */ - qemu_log("%d", cmd); } static void @@ -3763,6 +3756,9 @@ print_futex(CPUArchState *cpu_env, const struct syscallname *name, switch (op) { case FUTEX_WAIT: case FUTEX_WAIT_BITSET: + case FUTEX_LOCK_PI: + case FUTEX_LOCK_PI2: + case FUTEX_WAIT_REQUEUE_PI: print_timespec(arg3, 0); break; default: From c5a1c6b88cad2e8c4d81b03dda48d49ea0be9cca Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 19:10:05 -0700 Subject: [PATCH 0706/1020] linux-user: Lock log around strace Do not allow syscall arguments to be interleaved between threads. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier Message-Id: <20220829021006.67305-8-richard.henderson@linaro.org> Signed-off-by: Laurent Vivier --- linux-user/strace.c | 65 ++++++++++++++++++++++++++++++++------------- 1 file changed, 46 insertions(+), 19 deletions(-) diff --git a/linux-user/strace.c b/linux-user/strace.c index faa7331256..37bc96df9b 100644 --- a/linux-user/strace.c +++ b/linux-user/strace.c @@ -3919,26 +3919,37 @@ print_syscall(CPUArchState *cpu_env, int num, abi_long arg4, abi_long arg5, abi_long arg6) { int i; - const char *format="%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")"; + FILE *f; + const char *format = "%s(" TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," + TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld "," + TARGET_ABI_FMT_ld "," TARGET_ABI_FMT_ld ")"; - qemu_log("%d ", getpid()); + f = qemu_log_trylock(); + if (!f) { + return; + } + fprintf(f, "%d ", getpid()); - for(i=0;i Date: Tue, 6 Sep 2022 14:09:41 +0800 Subject: [PATCH 0707/1020] hw/xen: set pci Atomic Ops requests for passthrough device Make guest os access pci device control 2 reg for passthrough device as struct XenPTRegInfo described in the file hw/xen/xen_pt.h. /* reg read only field mask (ON:RO/ROS, OFF:other) */ uint32_t ro_mask; /* reg emulate field mask (ON:emu, OFF:passthrough) */ uint32_t emu_mask; Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1196 Signed-off-by: Aaron Liu Signed-off-by: Ruili Ji Message-ID: Reviewed-by: Paul Durrant Signed-off-by: Anthony PERARD --- hw/xen/xen_pt_config_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/xen/xen_pt_config_init.c b/hw/xen/xen_pt_config_init.c index 4758514ddf..cde898b744 100644 --- a/hw/xen/xen_pt_config_init.c +++ b/hw/xen/xen_pt_config_init.c @@ -985,8 +985,8 @@ static XenPTRegInfo xen_pt_emu_reg_pcie[] = { .offset = 0x28, .size = 2, .init_val = 0x0000, - .ro_mask = 0xFFE0, - .emu_mask = 0xFFFF, + .ro_mask = 0xFFA0, + .emu_mask = 0xFFBF, .init = xen_pt_devctrl2_reg_init, .u.w.read = xen_pt_word_reg_read, .u.w.write = xen_pt_word_reg_write, From 3039fd4b6e9b80ab35b34493181202a22b952812 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:39 +0800 Subject: [PATCH 0708/1020] tests/qtest: i440fx-test: Rewrite create_blob_file() to be portable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously request_{bios, pflash} cases were skipped on win32, mainly due to create_blob_file() calling mmap() which does not exist on win32. This rewirtes create_blob_file() to be portable, so that we can enable these cases on Windows. Suggested-by: Marc-AndrĂ© Lureau Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220925113032.1949844-2-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/i440fx-test.c | 52 ++++++++++----------------------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/tests/qtest/i440fx-test.c b/tests/qtest/i440fx-test.c index 3890f1237c..795fd85343 100644 --- a/tests/qtest/i440fx-test.c +++ b/tests/qtest/i440fx-test.c @@ -278,56 +278,34 @@ static void test_i440fx_pam(gconstpointer opaque) qtest_end(); } -#ifndef _WIN32 - #define BLOB_SIZE ((size_t)65536) #define ISA_BIOS_MAXSZ ((size_t)(128 * 1024)) -/* Create a blob file, and return its absolute pathname as a dynamically +/* + * Create a blob file, and return its absolute pathname as a dynamically * allocated string. * The file is closed before the function returns. - * In case of error, NULL is returned. The function prints the error message. + * In case of error, the function aborts and prints the error message. */ static char *create_blob_file(void) { - int ret, fd; + int i, fd; char *pathname; GError *error = NULL; + g_autofree uint8_t *buf = g_malloc(BLOB_SIZE); - ret = -1; fd = g_file_open_tmp("blob_XXXXXX", &pathname, &error); - if (fd == -1) { - fprintf(stderr, "unable to create blob file: %s\n", error->message); - g_error_free(error); - } else { - if (ftruncate(fd, BLOB_SIZE) == -1) { - fprintf(stderr, "ftruncate(\"%s\", %zu): %s\n", pathname, - BLOB_SIZE, strerror(errno)); - } else { - void *buf; + g_assert_no_error(error); + close(fd); - buf = mmap(NULL, BLOB_SIZE, PROT_WRITE, MAP_SHARED, fd, 0); - if (buf == MAP_FAILED) { - fprintf(stderr, "mmap(\"%s\", %zu): %s\n", pathname, BLOB_SIZE, - strerror(errno)); - } else { - size_t i; - - for (i = 0; i < BLOB_SIZE; ++i) { - ((uint8_t *)buf)[i] = i; - } - munmap(buf, BLOB_SIZE); - ret = 0; - } - } - close(fd); - if (ret == -1) { - unlink(pathname); - g_free(pathname); - } + for (i = 0; i < BLOB_SIZE; i++) { + buf[i] = i; } - return ret == -1 ? NULL : pathname; + g_file_set_contents(pathname, (char *)buf, BLOB_SIZE, &error); + g_assert_no_error(error); + + return pathname; } static void test_i440fx_firmware(FirmwareTestFixture *fixture, @@ -398,8 +376,6 @@ static void request_pflash(FirmwareTestFixture *fixture, fixture->is_bios = false; } -#endif /* _WIN32 */ - int main(int argc, char **argv) { TestData data; @@ -410,10 +386,8 @@ int main(int argc, char **argv) qtest_add_data_func("i440fx/defaults", &data, test_i440fx_defaults); qtest_add_data_func("i440fx/pam", &data, test_i440fx_pam); -#ifndef _WIN32 add_firmware_test("i440fx/firmware/bios", request_bios); add_firmware_test("i440fx/firmware/pflash", request_pflash); -#endif return g_test_run(); } From d9eefd35b678d6c1fa8c523de6441ef722f5321a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:43 +0800 Subject: [PATCH 0709/1020] tests/qtest: ahci-test: Avoid using hardcoded /tmp This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220925113032.1949844-6-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/ahci-test.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c index f1e510b0ac..1d5929d8c3 100644 --- a/tests/qtest/ahci-test.c +++ b/tests/qtest/ahci-test.c @@ -44,9 +44,9 @@ #define TEST_IMAGE_SIZE_MB_SMALL 64 /*** Globals ***/ -static char tmp_path[] = "/tmp/qtest.XXXXXX"; -static char debug_path[] = "/tmp/qtest-blkdebug.XXXXXX"; -static char mig_socket[] = "/tmp/qtest-migration.XXXXXX"; +static char *tmp_path; +static char *debug_path; +static char *mig_socket; static bool ahci_pedantic; static const char *imgfmt; static unsigned test_image_size_mb; @@ -1437,10 +1437,10 @@ static void test_ncq_simple(void) static int prepare_iso(size_t size, unsigned char **buf, char **name) { - char cdrom_path[] = "/tmp/qtest.iso.XXXXXX"; + g_autofree char *cdrom_path = NULL; unsigned char *patt; ssize_t ret; - int fd = mkstemp(cdrom_path); + int fd = g_file_open_tmp("qtest.iso.XXXXXX", &cdrom_path, NULL); g_assert(fd != -1); g_assert(buf); @@ -1872,7 +1872,7 @@ int main(int argc, char **argv) } /* Create a temporary image */ - fd = mkstemp(tmp_path); + fd = g_file_open_tmp("qtest.XXXXXX", &tmp_path, NULL); g_assert(fd >= 0); if (have_qemu_img()) { imgfmt = "qcow2"; @@ -1889,12 +1889,12 @@ int main(int argc, char **argv) close(fd); /* Create temporary blkdebug instructions */ - fd = mkstemp(debug_path); + fd = g_file_open_tmp("qtest-blkdebug.XXXXXX", &debug_path, NULL); g_assert(fd >= 0); close(fd); /* Reserve a hollow file to use as a socket for migration tests */ - fd = mkstemp(mig_socket); + fd = g_file_open_tmp("qtest-migration.XXXXXX", &mig_socket, NULL); g_assert(fd >= 0); close(fd); @@ -1947,8 +1947,11 @@ int main(int argc, char **argv) /* Cleanup */ unlink(tmp_path); + g_free(tmp_path); unlink(debug_path); + g_free(debug_path); unlink(mig_socket); + g_free(mig_socket); return ret; } From 39df79e4ed89cd835784ede8563ee41aa1f8265d Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:44 +0800 Subject: [PATCH 0710/1020] tests/qtest: aspeed_smc-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Reviewed-by: CĂ©dric Le Goater Message-Id: <20220925113032.1949844-7-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/aspeed_smc-test.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/qtest/aspeed_smc-test.c b/tests/qtest/aspeed_smc-test.c index 05ce941566..c713a3700b 100644 --- a/tests/qtest/aspeed_smc-test.c +++ b/tests/qtest/aspeed_smc-test.c @@ -608,16 +608,15 @@ static void test_write_block_protect_bottom_bit(void) flash_reset(); } -static char tmp_path[] = "/tmp/qtest.m25p80.XXXXXX"; - int main(int argc, char **argv) { + g_autofree char *tmp_path = NULL; int ret; int fd; g_test_init(&argc, &argv, NULL); - fd = mkstemp(tmp_path); + fd = g_file_open_tmp("qtest.m25p80.XXXXXX", &tmp_path, NULL); g_assert(fd >= 0); ret = ftruncate(fd, FLASH_SIZE); g_assert(ret == 0); From 4bcea44b9af7981e2074c74298e89ea3f97a3174 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:45 +0800 Subject: [PATCH 0711/1020] tests/qtest: boot-serial-test: Avoid using hardcoded /tmp This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220925113032.1949844-8-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/boot-serial-test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index 2f99d71cab..72310ba30e 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -224,14 +224,14 @@ static bool check_guest_output(QTestState *qts, const testdef_t *test, int fd) static void test_machine(const void *data) { const testdef_t *test = data; - char serialtmp[] = "/tmp/qtest-boot-serial-sXXXXXX"; - char codetmp[] = "/tmp/qtest-boot-serial-cXXXXXX"; + g_autofree char *serialtmp = NULL; + g_autofree char *codetmp = NULL; const char *codeparam = ""; const uint8_t *code = NULL; QTestState *qts; int ser_fd; - ser_fd = mkstemp(serialtmp); + ser_fd = g_file_open_tmp("qtest-boot-serial-sXXXXXX", &serialtmp, NULL); g_assert(ser_fd != -1); if (test->kernel) { @@ -246,7 +246,7 @@ static void test_machine(const void *data) ssize_t wlen; int code_fd; - code_fd = mkstemp(codetmp); + code_fd = g_file_open_tmp("qtest-boot-serial-cXXXXXX", &codetmp, NULL); g_assert(code_fd != -1); wlen = write(code_fd, code, test->codesize); g_assert(wlen == test->codesize); From 39180d4e944caa0a9818f73acc4fadc2fbd2f422 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:46 +0800 Subject: [PATCH 0712/1020] tests/qtest: cxl-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_dir_make_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-9-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/cxl-test.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/qtest/cxl-test.c b/tests/qtest/cxl-test.c index 2e14da7dee..cbe0fb549b 100644 --- a/tests/qtest/cxl-test.c +++ b/tests/qtest/cxl-test.c @@ -93,10 +93,9 @@ static void cxl_2root_port(void) static void cxl_t3d(void) { g_autoptr(GString) cmdline = g_string_new(NULL); - char template[] = "/tmp/cxl-test-XXXXXX"; - const char *tmpfs; + g_autofree const char *tmpfs = NULL; - tmpfs = g_mkdtemp(template); + tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); g_string_printf(cmdline, QEMU_PXB_CMD QEMU_RP QEMU_T3D, tmpfs, tmpfs); @@ -107,10 +106,9 @@ static void cxl_t3d(void) static void cxl_1pxb_2rp_2t3d(void) { g_autoptr(GString) cmdline = g_string_new(NULL); - char template[] = "/tmp/cxl-test-XXXXXX"; - const char *tmpfs; + g_autofree const char *tmpfs = NULL; - tmpfs = g_mkdtemp(template); + tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); g_string_printf(cmdline, QEMU_PXB_CMD QEMU_2RP QEMU_2T3D, tmpfs, tmpfs, tmpfs, tmpfs); @@ -122,10 +120,9 @@ static void cxl_1pxb_2rp_2t3d(void) static void cxl_2pxb_4rp_4t3d(void) { g_autoptr(GString) cmdline = g_string_new(NULL); - char template[] = "/tmp/cxl-test-XXXXXX"; - const char *tmpfs; + g_autofree const char *tmpfs = NULL; - tmpfs = g_mkdtemp(template); + tmpfs = g_dir_make_tmp("cxl-test-XXXXXX", NULL); g_string_printf(cmdline, QEMU_2PXB_CMD QEMU_4RP QEMU_4T3D, tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, tmpfs, From 394bcc5bc5247697f2091ac4b4686e39bfabba37 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:47 +0800 Subject: [PATCH 0713/1020] tests/qtest: fdc-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-10-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/fdc-test.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/qtest/fdc-test.c b/tests/qtest/fdc-test.c index 52ade90a7d..1f9b99ad6d 100644 --- a/tests/qtest/fdc-test.c +++ b/tests/qtest/fdc-test.c @@ -68,7 +68,7 @@ enum { DSKCHG = 0x80, }; -static char test_image[] = "/tmp/qtest.XXXXXX"; +static char *test_image; #define assert_bit_set(data, mask) g_assert_cmphex((data) & (mask), ==, (mask)) #define assert_bit_clear(data, mask) g_assert_cmphex((data) & (mask), ==, 0) @@ -608,7 +608,7 @@ int main(int argc, char **argv) int ret; /* Create a temporary raw image */ - fd = mkstemp(test_image); + fd = g_file_open_tmp("qtest.XXXXXX", &test_image, NULL); g_assert(fd >= 0); ret = ftruncate(fd, TEST_IMAGE_SIZE); g_assert(ret == 0); @@ -640,6 +640,7 @@ int main(int argc, char **argv) /* Cleanup */ qtest_end(); unlink(test_image); + g_free(test_image); return ret; } From 9e5d84037fcff3c5936b1e7776cc2363920ad1f1 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:48 +0800 Subject: [PATCH 0714/1020] tests/qtest: generic_fuzz: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_dir_make_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-11-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/fuzz/generic_fuzz_configs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/fuzz/generic_fuzz_configs.h b/tests/qtest/fuzz/generic_fuzz_configs.h index 0775e6702b..a825b78c14 100644 --- a/tests/qtest/fuzz/generic_fuzz_configs.h +++ b/tests/qtest/fuzz/generic_fuzz_configs.h @@ -20,8 +20,8 @@ typedef struct generic_fuzz_config { } generic_fuzz_config; static inline gchar *generic_fuzzer_virtio_9p_args(void){ - char tmpdir[] = "/tmp/qemu-fuzz.XXXXXX"; - g_assert_nonnull(g_mkdtemp(tmpdir)); + g_autofree char *tmpdir = g_dir_make_tmp("qemu-fuzz.XXXXXX", NULL); + g_assert_nonnull(tmpdir); return g_strdup_printf("-machine q35 -nodefaults " "-device virtio-9p,fsdev=hshare,mount_tag=hshare " From 3ff220a0acc1d46d528600af937badf246cb05f3 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:49 +0800 Subject: [PATCH 0715/1020] tests/qtest: virtio_blk_fuzz: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-12-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/fuzz/virtio_blk_fuzz.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/fuzz/virtio_blk_fuzz.c b/tests/qtest/fuzz/virtio_blk_fuzz.c index 236d078cc8..a9fb9ecf6c 100644 --- a/tests/qtest/fuzz/virtio_blk_fuzz.c +++ b/tests/qtest/fuzz/virtio_blk_fuzz.c @@ -181,10 +181,10 @@ static void drive_destroy(void *path) static char *drive_create(void) { int fd, ret; - char *t_path = g_strdup("/tmp/qtest.XXXXXX"); + char *t_path; /* Create a temporary raw image */ - fd = mkstemp(t_path); + fd = g_file_open_tmp("qtest.XXXXXX", &t_path, NULL); g_assert_cmpint(fd, >=, 0); ret = ftruncate(fd, TEST_IMAGE_SIZE); g_assert_cmpint(ret, ==, 0); From 354aeeabecebb24cb7765b261f7a8ba084d3ef0e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:51 +0800 Subject: [PATCH 0716/1020] tests/qtest: ide-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-14-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/ide-test.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c index 5bcb75a7e5..25302be6dc 100644 --- a/tests/qtest/ide-test.c +++ b/tests/qtest/ide-test.c @@ -121,8 +121,8 @@ enum { static QPCIBus *pcibus = NULL; static QGuestAllocator guest_malloc; -static char tmp_path[] = "/tmp/qtest.XXXXXX"; -static char debug_path[] = "/tmp/qtest-blkdebug.XXXXXX"; +static char *tmp_path; +static char *debug_path; static QTestState *ide_test_start(const char *cmdline_fmt, ...) { @@ -1015,12 +1015,12 @@ int main(int argc, char **argv) int ret; /* Create temporary blkdebug instructions */ - fd = mkstemp(debug_path); + fd = g_file_open_tmp("qtest-blkdebug.XXXXXX", &debug_path, NULL); g_assert(fd >= 0); close(fd); /* Create a temporary raw image */ - fd = mkstemp(tmp_path); + fd = g_file_open_tmp("qtest.XXXXXX", &tmp_path, NULL); g_assert(fd >= 0); ret = ftruncate(fd, TEST_IMAGE_SIZE); g_assert(ret == 0); @@ -1049,7 +1049,9 @@ int main(int argc, char **argv) /* Cleanup */ unlink(tmp_path); + g_free(tmp_path); unlink(debug_path); + g_free(debug_path); return ret; } From c20413558a49326599b15c3854c0df68a0b45895 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:55 +0800 Subject: [PATCH 0717/1020] tests/qtest: vhost-user-blk-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_get_tmp_dir() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-18-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/vhost-user-blk-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/qtest/vhost-user-blk-test.c b/tests/qtest/vhost-user-blk-test.c index a81c2a2715..07a4c2d500 100644 --- a/tests/qtest/vhost-user-blk-test.c +++ b/tests/qtest/vhost-user-blk-test.c @@ -841,7 +841,8 @@ static char *create_listen_socket(int *fd) char *path; /* No race because our pid makes the path unique */ - path = g_strdup_printf("/tmp/qtest-%d-sock.XXXXXX", getpid()); + path = g_strdup_printf("%s/qtest-%d-sock.XXXXXX", + g_get_tmp_dir(), getpid()); tmp_fd = mkstemp(path); g_assert_cmpint(tmp_fd, >=, 0); close(tmp_fd); From bc989a2b870629276fcbb9f5ee380d5c53e145cc Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:57 +0800 Subject: [PATCH 0718/1020] tests/qtest: virtio-blk-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-20-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/virtio-blk-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/virtio-blk-test.c b/tests/qtest/virtio-blk-test.c index dc5eed31c8..19c01f808b 100644 --- a/tests/qtest/virtio-blk-test.c +++ b/tests/qtest/virtio-blk-test.c @@ -49,10 +49,10 @@ static void drive_destroy(void *path) static char *drive_create(void) { int fd, ret; - char *t_path = g_strdup("/tmp/qtest.XXXXXX"); + char *t_path; /* Create a temporary raw image */ - fd = mkstemp(t_path); + fd = g_file_open_tmp("qtest.XXXXXX", &t_path, NULL); g_assert_cmpint(fd, >=, 0); ret = ftruncate(fd, TEST_IMAGE_SIZE); g_assert_cmpint(ret, ==, 0); From 28ea545b33f79dfd734d9a842a3a2cc9bf89d5e8 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:58 +0800 Subject: [PATCH 0719/1020] tests/qtest: virtio-scsi-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-21-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/virtio-scsi-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/virtio-scsi-test.c b/tests/qtest/virtio-scsi-test.c index 8ceb12aacd..ceaa7f2415 100644 --- a/tests/qtest/virtio-scsi-test.c +++ b/tests/qtest/virtio-scsi-test.c @@ -268,7 +268,7 @@ static void test_iothread_attach_node(void *obj, void *data, QVirtioSCSIPCI *scsi_pci = obj; QVirtioSCSI *scsi = &scsi_pci->scsi; QVirtioSCSIQueues *vs; - char tmp_path[] = "/tmp/qtest.XXXXXX"; + g_autofree char *tmp_path = NULL; int fd; int ret; @@ -282,7 +282,7 @@ static void test_iothread_attach_node(void *obj, void *data, vs = qvirtio_scsi_init(scsi->vdev); /* Create a temporary qcow2 overlay*/ - fd = mkstemp(tmp_path); + fd = g_file_open_tmp("qtest.XXXXXX", &tmp_path, NULL); g_assert(fd >= 0); close(fd); From b6dabc82b070850711881feaa0d8028ee7c396dc Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:29:59 +0800 Subject: [PATCH 0720/1020] tests/qtest: libqtest: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The qtest library was written to use hardcoded /tmp directory for temporary files. Update to use g_get_tmp_dir() and g_dir_make_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-22-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/libqtest.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 7c9fc07de4..d8ffa0e7b1 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -265,8 +265,10 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args) s = g_new(QTestState, 1); - socket_path = g_strdup_printf("/tmp/qtest-%d.sock", getpid()); - qmp_socket_path = g_strdup_printf("/tmp/qtest-%d.qmp", getpid()); + socket_path = g_strdup_printf("%s/qtest-%d.sock", + g_get_tmp_dir(), getpid()); + qmp_socket_path = g_strdup_printf("%s/qtest-%d.qmp", + g_get_tmp_dir(), getpid()); /* It's possible that if an earlier test run crashed it might * have left a stale unix socket lying around. Delete any @@ -390,10 +392,12 @@ QTestState *qtest_initf(const char *fmt, ...) QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd) { int sock_fd_init; - char *sock_path, sock_dir[] = "/tmp/qtest-serial-XXXXXX"; + g_autofree char *sock_dir = NULL; + char *sock_path; QTestState *qts; - g_assert_true(g_mkdtemp(sock_dir) != NULL); + sock_dir = g_dir_make_tmp("qtest-serial-XXXXXX", NULL); + g_assert_true(sock_dir != NULL); sock_path = g_strdup_printf("%s/sock", sock_dir); sock_fd_init = init_socket(sock_path); From e0e5b3dc0024f76a27b4643c4158cc5463713d9c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:00 +0800 Subject: [PATCH 0721/1020] tests/unit: test-image-locking: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-23-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/unit/test-image-locking.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/test-image-locking.c b/tests/unit/test-image-locking.c index ba057bd66c..a47299c247 100644 --- a/tests/unit/test-image-locking.c +++ b/tests/unit/test-image-locking.c @@ -76,10 +76,10 @@ static void check_locked_bytes(int fd, uint64_t perm_locks, static void test_image_locking_basic(void) { BlockBackend *blk1, *blk2, *blk3; - char img_path[] = "/tmp/qtest.XXXXXX"; + g_autofree char *img_path = NULL; uint64_t perm, shared_perm; - int fd = mkstemp(img_path); + int fd = g_file_open_tmp("qtest.XXXXXX", &img_path, NULL); assert(fd >= 0); perm = BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ; @@ -117,10 +117,10 @@ static void test_image_locking_basic(void) static void test_set_perm_abort(void) { BlockBackend *blk1, *blk2; - char img_path[] = "/tmp/qtest.XXXXXX"; + g_autofree char *img_path = NULL; uint64_t perm, shared_perm; int r; - int fd = mkstemp(img_path); + int fd = g_file_open_tmp("qtest.XXXXXX", &img_path, NULL); assert(fd >= 0); perm = BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ; From 5b9f2781c251aa0b98cf9a3b025b803a7e23e638 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:01 +0800 Subject: [PATCH 0722/1020] tests/unit: test-qga: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_get_tmp_dir() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-24-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/unit/test-qga.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test-qga.c b/tests/unit/test-qga.c index b6ea7c7304..b4e0a14573 100644 --- a/tests/unit/test-qga.c +++ b/tests/unit/test-qga.c @@ -60,7 +60,7 @@ fixture_setup(TestFixture *fixture, gconstpointer data, gchar **envp) fixture->loop = g_main_loop_new(NULL, FALSE); - fixture->test_dir = g_strdup("/tmp/qgatest.XXXXXX"); + fixture->test_dir = g_strdup_printf("%s/qgatest.XXXXXX", g_get_tmp_dir()); g_assert_nonnull(g_mkdtemp(fixture->test_dir)); path = g_build_filename(fixture->test_dir, "sock", NULL); From 786e46ee68d7920d4bead184c42950a4b0e2e75a Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:02 +0800 Subject: [PATCH 0723/1020] tests: vhost-user-bridge: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-25-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/vhost-user-bridge.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/vhost-user-bridge.c b/tests/vhost-user-bridge.c index 9b1dab2f28..fecdf915e7 100644 --- a/tests/vhost-user-bridge.c +++ b/tests/vhost-user-bridge.c @@ -631,7 +631,6 @@ static void *notifier_thread(void *arg) static void vubr_host_notifier_setup(VubrDev *dev) { - char template[] = "/tmp/vubr-XXXXXX"; pthread_t thread; size_t length; void *addr; @@ -639,7 +638,7 @@ vubr_host_notifier_setup(VubrDev *dev) length = qemu_real_host_page_size() * VHOST_USER_BRIDGE_MAX_QUEUES; - fd = mkstemp(template); + fd = g_file_open_tmp("vubr-XXXXXX", NULL, NULL); if (fd < 0) { vubr_die("mkstemp()"); } From cac4373aa0953fe4a96268d28a35401cf0747f07 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:06 +0800 Subject: [PATCH 0724/1020] tests/qtest: Skip running virtio-net-test cases that require socketpair() for win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the virtio-net-test test cases require socketpair() to do the test setup. Skip them for win32. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-29-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/virtio-net-test.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/qtest/virtio-net-test.c b/tests/qtest/virtio-net-test.c index 6ded252901..dff43f0f60 100644 --- a/tests/qtest/virtio-net-test.c +++ b/tests/qtest/virtio-net-test.c @@ -165,8 +165,6 @@ static void stop_cont_test(void *obj, void *data, QGuestAllocator *t_alloc) rx_stop_cont_test(dev, t_alloc, rx, sv[0]); } -#endif - static void hotplug(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtioPCIDevice *dev = obj; @@ -286,6 +284,8 @@ static void *virtio_net_test_setup(GString *cmd_line, void *arg) return sv; } +#endif /* _WIN32 */ + static void large_tx(void *obj, void *data, QGuestAllocator *t_alloc) { QVirtioNet *dev = obj; @@ -319,16 +319,15 @@ static void *virtio_net_test_setup_nosocket(GString *cmd_line, void *arg) static void register_virtio_net_test(void) { - QOSGraphTestOptions opts = { - .before = virtio_net_test_setup, - }; + QOSGraphTestOptions opts = { 0 }; - qos_add_test("hotplug", "virtio-net-pci", hotplug, &opts); #ifndef _WIN32 + opts.before = virtio_net_test_setup; + qos_add_test("hotplug", "virtio-net-pci", hotplug, &opts); qos_add_test("basic", "virtio-net", send_recv_test, &opts); qos_add_test("rx_stop_cont", "virtio-net", stop_cont_test, &opts); -#endif qos_add_test("announce-self", "virtio-net", announce_self, &opts); +#endif /* These tests do not need a loopback backend. */ opts.before = virtio_net_test_setup_nosocket; From 8bf5bb2e04f33dd869f1221ec949359874b6c604 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:07 +0800 Subject: [PATCH 0725/1020] tests/qtest: Build test-filter-{mirror, redirector} cases for posix only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test-filter-{mirror,redirector} cases use socketpair() API that is only available on POSIX and should only be built for POSIX. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-30-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/meson.build | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index e910cb32ca..455f1bbb7e 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -39,9 +39,14 @@ qtests_pci = \ qtests_cxl = \ (config_all_devices.has_key('CONFIG_CXL') ? ['cxl-test'] : []) +qtests_filter = \ + (slirp.found() ? ['test-netfilter'] : []) + \ + (config_host.has_key('CONFIG_POSIX') ? ['test-filter-mirror'] : []) + \ + (config_host.has_key('CONFIG_POSIX') ? ['test-filter-redirector'] : []) + qtests_i386 = \ - (slirp.found() ? ['pxe-test', 'test-netfilter'] : []) + \ - (config_host.has_key('CONFIG_POSIX') ? ['test-filter-mirror'] : []) + \ + (slirp.found() ? ['pxe-test'] : []) + \ + qtests_filter + \ (have_tools ? ['ahci-test'] : []) + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ (config_all_devices.has_key('CONFIG_SGA') ? ['boot-serial-test'] : []) + \ @@ -95,8 +100,7 @@ qtests_i386 = \ 'vmgenid-test', 'migration-test', 'test-x86-cpuid-compat', - 'numa-test', - 'test-filter-redirector' + 'numa-test' ] if dbus_display @@ -120,30 +124,25 @@ endif qtests_x86_64 = qtests_i386 qtests_alpha = ['boot-serial-test'] + \ - ['test-filter-mirror', 'test-filter-redirector'] + \ - (slirp.found() ? ['test-netfilter'] : []) + \ + qtests_filter + \ (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) qtests_avr = [ 'boot-serial-test' ] qtests_hppa = ['boot-serial-test'] + \ - ['test-filter-mirror', 'test-filter-redirector'] + \ - (slirp.found() ? ['test-netfilter'] : []) + \ + qtests_filter + \ (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) qtests_m68k = ['boot-serial-test'] + \ - ['test-filter-mirror', 'test-filter-redirector'] + \ - (slirp.found() ? ['test-netfilter'] : []) + qtests_filter qtests_microblaze = ['boot-serial-test'] + \ - ['test-filter-mirror', 'test-filter-redirector'] + \ - (slirp.found() ? ['test-netfilter'] : []) + qtests_filter qtests_microblazeel = qtests_microblaze qtests_mips = \ - ['test-filter-mirror', 'test-filter-redirector'] + \ - (slirp.found() ? ['test-netfilter'] : []) + \ + qtests_filter + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ (config_all_devices.has_key('CONFIG_VGA') ? ['display-vga-test'] : []) @@ -152,8 +151,7 @@ qtests_mips64 = qtests_mips qtests_mips64el = qtests_mips qtests_ppc = \ - ['test-filter-mirror', 'test-filter-redirector'] + \ - (slirp.found() ? ['test-netfilter'] : []) + \ + qtests_filter + \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ (config_all_devices.has_key('CONFIG_M48T59') ? ['m48t59-test'] : []) + \ (config_all_devices.has_key('CONFIG_TCG') ? ['prom-env-test'] : []) + \ @@ -174,13 +172,11 @@ qtests_sh4 = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-te qtests_sh4eb = (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) qtests_sparc = ['prom-env-test', 'm48t59-test', 'boot-serial-test'] + \ - ['test-filter-mirror', 'test-filter-redirector'] + \ - (slirp.found() ? ['test-netfilter'] : []) + qtests_filter qtests_sparc64 = \ (config_all_devices.has_key('CONFIG_ISA_TESTDEV') ? ['endianness-test'] : []) + \ - (slirp.found() ? ['test-netfilter'] : []) + \ - ['test-filter-mirror', 'test-filter-redirector'] + \ + qtests_filter + \ ['prom-env-test', 'boot-serial-test'] qtests_npcm7xx = \ From b82cbbf0f229f0295e917c69b40e6c12365782e8 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:08 +0800 Subject: [PATCH 0726/1020] tests/qtest: qmp-test: Skip running test_qmp_oob for win32 The test_qmp_oob test case calls mkfifo() which does not exist on win32. Exclude it. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220925113032.1949844-31-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/qmp-test.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c index bf7304c7dc..23b2a37942 100644 --- a/tests/qtest/qmp-test.c +++ b/tests/qtest/qmp-test.c @@ -159,6 +159,8 @@ static void test_qmp_protocol(void) qtest_quit(qts); } +#ifndef _WIN32 + /* Out-of-band tests */ char tmpdir[] = "/tmp/qmp-test-XXXXXX"; @@ -277,6 +279,8 @@ static void test_qmp_oob(void) qtest_quit(qts); } +#endif /* _WIN32 */ + /* Preconfig tests */ static void test_qmp_preconfig(void) @@ -336,7 +340,10 @@ int main(int argc, char *argv[]) g_test_init(&argc, &argv, NULL); qtest_add_func("qmp/protocol", test_qmp_protocol); +#ifndef _WIN32 + /* This case calls mkfifo() which does not exist on win32 */ qtest_add_func("qmp/oob", test_qmp_oob); +#endif qtest_add_func("qmp/preconfig", test_qmp_preconfig); qtest_add_func("qmp/missing-any-arg", test_qmp_missing_any_arg); From 39f0e991e10706447cad782e0de48ad9724aadf7 Mon Sep 17 00:00:00 2001 From: Xuzhou Cheng Date: Sun, 25 Sep 2022 19:30:10 +0800 Subject: [PATCH 0727/1020] tests/qtest: libqtest: Adapt global_qtest declaration for win32 Commit dd2107497275 ("tests/libqtest: Use libqtest-single.h in tests that require global_qtest") moved global_qtest to libqtest-single.h, by declaring global_qtest attribute to be common and weak. This trick unfortunately does not work on Windows, and building qtest test cases results in multiple definition errors of the weak symbol global_qtest, as Windows PE does not have the concept of the so-called weak symbol like ELF in the *nix world. However Windows does provide a trick to declare a variable to be a common symbol, via __declspec(selectany) [1]. It does not provide the "strong override weak" effect but we don't need it in our use case anyway. So let's use it for win32. [1] https://docs.microsoft.com/en-us/cpp/cpp/selectany Signed-off-by: Xuzhou Cheng Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220925113032.1949844-33-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/libqtest-single.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/qtest/libqtest-single.h b/tests/qtest/libqtest-single.h index 4e7d0ae1dc..851724cbcb 100644 --- a/tests/qtest/libqtest-single.h +++ b/tests/qtest/libqtest-single.h @@ -13,7 +13,11 @@ #include "libqtest.h" +#ifndef _WIN32 QTestState *global_qtest __attribute__((common, weak)); +#else +__declspec(selectany) QTestState *global_qtest; +#endif /** * qtest_start: From 490081b282766df0e91de3903d948f1eed6fe6d2 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:12 +0800 Subject: [PATCH 0728/1020] tests/qtest: libqtest: Exclude the *_fds APIs for win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libqmp.c::qmp_fd_vsend_fds() is not available on Windows, hence any APIs in libqtest that call libqmp.c::qmp_fd_vsend_fds() should be excluded for win32 too. This includes the following: * qtest_qmp_vsend_fds() * qtest_vqmp_fds() * qtest_qmp_fds() * qtest_qmp_add_client() Note qtest_qmp_vsend() was wrongly written to call qmp_fd_vsend_fds() previously, but it should call the non fds version API qmp_fd_vsend(). Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-35-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/libqtest.c | 10 +++++++++- tests/qtest/libqtest.h | 8 ++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index d8ffa0e7b1..5c4a509c58 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -592,17 +592,20 @@ int qtest_socket_server(const char *socket_path) return sock; } +#ifndef _WIN32 void qtest_qmp_vsend_fds(QTestState *s, int *fds, size_t fds_num, const char *fmt, va_list ap) { qmp_fd_vsend_fds(s->qmp_fd, fds, fds_num, fmt, ap); } +#endif void qtest_qmp_vsend(QTestState *s, const char *fmt, va_list ap) { - qmp_fd_vsend_fds(s->qmp_fd, NULL, 0, fmt, ap); + qmp_fd_vsend(s->qmp_fd, fmt, ap); } +#ifndef _WIN32 QDict *qtest_vqmp_fds(QTestState *s, int *fds, size_t fds_num, const char *fmt, va_list ap) { @@ -611,6 +614,7 @@ QDict *qtest_vqmp_fds(QTestState *s, int *fds, size_t fds_num, /* Receive reply */ return qtest_qmp_receive(s); } +#endif QDict *qtest_vqmp(QTestState *s, const char *fmt, va_list ap) { @@ -620,6 +624,7 @@ QDict *qtest_vqmp(QTestState *s, const char *fmt, va_list ap) return qtest_qmp_receive(s); } +#ifndef _WIN32 QDict *qtest_qmp_fds(QTestState *s, int *fds, size_t fds_num, const char *fmt, ...) { @@ -631,6 +636,7 @@ QDict *qtest_qmp_fds(QTestState *s, int *fds, size_t fds_num, va_end(ap); return response; } +#endif QDict *qtest_qmp(QTestState *s, const char *fmt, ...) { @@ -1327,6 +1333,7 @@ void qtest_qmp_device_add(QTestState *qts, const char *driver, const char *id, qobject_unref(args); } +#ifndef _WIN32 void qtest_qmp_add_client(QTestState *qts, const char *protocol, int fd) { QDict *resp; @@ -1346,6 +1353,7 @@ void qtest_qmp_add_client(QTestState *qts, const char *protocol, int fd) g_assert(!qdict_haskey(resp, "error")); qobject_unref(resp); } +#endif /* * Generic hot-unplugging test via the device_del QMP command. diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h index 94b187837d..3abc75964d 100644 --- a/tests/qtest/libqtest.h +++ b/tests/qtest/libqtest.h @@ -94,6 +94,7 @@ void qtest_kill_qemu(QTestState *s); */ void qtest_quit(QTestState *s); +#ifndef _WIN32 /** * qtest_qmp_fds: * @s: #QTestState instance to operate on. @@ -108,6 +109,7 @@ void qtest_quit(QTestState *s); QDict *qtest_qmp_fds(QTestState *s, int *fds, size_t fds_num, const char *fmt, ...) G_GNUC_PRINTF(4, 5); +#endif /* _WIN32 */ /** * qtest_qmp: @@ -152,6 +154,7 @@ void qtest_qmp_send_raw(QTestState *s, const char *fmt, ...) */ int qtest_socket_server(const char *socket_path); +#ifndef _WIN32 /** * qtest_vqmp_fds: * @s: #QTestState instance to operate on. @@ -167,6 +170,7 @@ int qtest_socket_server(const char *socket_path); QDict *qtest_vqmp_fds(QTestState *s, int *fds, size_t fds_num, const char *fmt, va_list ap) G_GNUC_PRINTF(4, 0); +#endif /* _WIN32 */ /** * qtest_vqmp: @@ -181,6 +185,7 @@ QDict *qtest_vqmp_fds(QTestState *s, int *fds, size_t fds_num, QDict *qtest_vqmp(QTestState *s, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0); +#ifndef _WIN32 /** * qtest_qmp_vsend_fds: * @s: #QTestState instance to operate on. @@ -196,6 +201,7 @@ QDict *qtest_vqmp(QTestState *s, const char *fmt, va_list ap) void qtest_qmp_vsend_fds(QTestState *s, int *fds, size_t fds_num, const char *fmt, va_list ap) G_GNUC_PRINTF(4, 0); +#endif /* _WIN32 */ /** * qtest_qmp_vsend: @@ -743,6 +749,7 @@ void qtest_qmp_device_add_qdict(QTestState *qts, const char *drv, void qtest_qmp_device_add(QTestState *qts, const char *driver, const char *id, const char *fmt, ...) G_GNUC_PRINTF(4, 5); +#ifndef _WIN32 /** * qtest_qmp_add_client: * @qts: QTestState instance to operate on @@ -752,6 +759,7 @@ void qtest_qmp_device_add(QTestState *qts, const char *driver, const char *id, * Call QMP ``getfd`` followed by ``add_client`` with the given @fd. */ void qtest_qmp_add_client(QTestState *qts, const char *protocol, int fd); +#endif /* _WIN32 */ /** * qtest_qmp_device_del: From be181f87eb75d21ad82819e92175a2d6716527e0 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:15 +0800 Subject: [PATCH 0729/1020] tests/qtest: {ahci, ide}-test: Use relative path for temporary files for win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These test cases uses "blkdebug:path/to/config:path/to/image" for testing. On Windows, absolute file paths contain the delimiter ':' which causes the blkdebug filename parser fail to parse filenames. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Thomas Huth Message-Id: <20220925113032.1949844-38-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/ahci-test.c | 21 ++++++++++++++++++--- tests/qtest/ide-test.c | 20 ++++++++++++++++++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/tests/qtest/ahci-test.c b/tests/qtest/ahci-test.c index 1d5929d8c3..66652fed04 100644 --- a/tests/qtest/ahci-test.c +++ b/tests/qtest/ahci-test.c @@ -1833,7 +1833,7 @@ static void create_ahci_io_test(enum IOMode type, enum AddrMode addr, int main(int argc, char **argv) { - const char *arch; + const char *arch, *base; int ret; int fd; int c; @@ -1871,8 +1871,22 @@ int main(int argc, char **argv) return 0; } + /* + * "base" stores the starting point where we create temporary files. + * + * On Windows, this is set to the relative path of current working + * directory, because the absolute path causes the blkdebug filename + * parser fail to parse "blkdebug:path/to/config:path/to/image". + */ +#ifndef _WIN32 + base = g_get_tmp_dir(); +#else + base = "."; +#endif + /* Create a temporary image */ - fd = g_file_open_tmp("qtest.XXXXXX", &tmp_path, NULL); + tmp_path = g_strdup_printf("%s/qtest.XXXXXX", base); + fd = g_mkstemp(tmp_path); g_assert(fd >= 0); if (have_qemu_img()) { imgfmt = "qcow2"; @@ -1889,7 +1903,8 @@ int main(int argc, char **argv) close(fd); /* Create temporary blkdebug instructions */ - fd = g_file_open_tmp("qtest-blkdebug.XXXXXX", &debug_path, NULL); + debug_path = g_strdup_printf("%s/qtest-blkdebug.XXXXXX", base); + fd = g_mkstemp(debug_path); g_assert(fd >= 0); close(fd); diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c index 25302be6dc..5e3e28aea2 100644 --- a/tests/qtest/ide-test.c +++ b/tests/qtest/ide-test.c @@ -1011,16 +1011,32 @@ static void test_cdrom_dma(void) int main(int argc, char **argv) { + const char *base; int fd; int ret; + /* + * "base" stores the starting point where we create temporary files. + * + * On Windows, this is set to the relative path of current working + * directory, because the absolute path causes the blkdebug filename + * parser fail to parse "blkdebug:path/to/config:path/to/image". + */ +#ifndef _WIN32 + base = g_get_tmp_dir(); +#else + base = "."; +#endif + /* Create temporary blkdebug instructions */ - fd = g_file_open_tmp("qtest-blkdebug.XXXXXX", &debug_path, NULL); + debug_path = g_strdup_printf("%s/qtest-blkdebug.XXXXXX", base); + fd = g_mkstemp(debug_path); g_assert(fd >= 0); close(fd); /* Create a temporary raw image */ - fd = g_file_open_tmp("qtest.XXXXXX", &tmp_path, NULL); + tmp_path = g_strdup_printf("%s/qtest.XXXXXX", base); + fd = g_mkstemp(tmp_path); g_assert(fd >= 0); ret = ftruncate(fd, TEST_IMAGE_SIZE); g_assert(ret == 0); From 4b83dd0efdbbf0e9213aa8e789ab0700e191ae24 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:16 +0800 Subject: [PATCH 0730/1020] tests/qtest: bios-tables-test: Adapt the case for win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Single quotes in the arguments (oem_id='CRASH ') are not removed in the Windows environment before it is passed to the QEMU executable. The space in the argument causes the "-acpitable" option parser to think that all of its parameters are done, hence it complains: '-acpitable' requires one of 'data' or 'file' Change to use double quotes which works fine on all platforms. Also /dev/null does not work on win32, and nul should be used. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Acked-by: Michael S. Tsirkin Message-Id: <20220925113032.1949844-39-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/bios-tables-test.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c index 46a46fe0aa..2ebeb530b2 100644 --- a/tests/qtest/bios-tables-test.c +++ b/tests/qtest/bios-tables-test.c @@ -1615,6 +1615,12 @@ static void test_acpi_virt_viot(void) free_test_data(&data); } +#ifndef _WIN32 +# define DEV_NULL "/dev/null" +#else +# define DEV_NULL "nul" +#endif + static void test_acpi_q35_slic(void) { test_data data = { @@ -1622,9 +1628,9 @@ static void test_acpi_q35_slic(void) .variant = ".slic", }; - test_acpi_one("-acpitable sig=SLIC,oem_id='CRASH ',oem_table_id='ME'," - "oem_rev=00002210,asl_compiler_id='qemu'," - "asl_compiler_rev=00000000,data=/dev/null", + test_acpi_one("-acpitable sig=SLIC,oem_id=\"CRASH \",oem_table_id=ME," + "oem_rev=00002210,asl_compiler_id=qemu," + "asl_compiler_rev=00000000,data=" DEV_NULL, &data); free_test_data(&data); } From 4dc8be388320b95ee965e28893381c9193eca663 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:17 +0800 Subject: [PATCH 0731/1020] tests/qtest: migration-test: Disable IO redirection for win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On Windows the QEMU executable is created via CreateProcess() and IO redirection does not work, so don't bother adding IO redirection to the command line. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-40-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/migration-test.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 4728d528bb..3db1177377 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -647,7 +647,16 @@ static int test_migrate_start(QTestState **from, QTestState **to, } if (!getenv("QTEST_LOG") && args->hide_stderr) { +#ifndef _WIN32 ignore_stderr = "2>/dev/null"; +#else + /* + * On Windows the QEMU executable is created via CreateProcess() and + * IO redirection does not work, so don't bother adding IO redirection + * to the command line. + */ + ignore_stderr = ""; +#endif } else { ignore_stderr = ""; } From 6b2906d65ca2e1fc2c71be1ce8992eaa3c5d7eab Mon Sep 17 00:00:00 2001 From: Xuzhou Cheng Date: Sun, 25 Sep 2022 19:30:18 +0800 Subject: [PATCH 0732/1020] tests/qtest: ide-test: Open file in binary mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By default Windows opens file in text mode, while a POSIX compliant implementation treats text files and binary files the same. The fopen() 'mode' string can include the letter 'b' to indicate binary mode shall be used. POSIX spec says the character 'b' shall have no effect, but is allowed for ISO C standard conformance. Let's add the letter 'b' which works on both POSIX and Windows. Signed-off-by: Xuzhou Cheng Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-41-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/ide-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c index 5e3e28aea2..4ea89c26c9 100644 --- a/tests/qtest/ide-test.c +++ b/tests/qtest/ide-test.c @@ -892,7 +892,7 @@ static void cdrom_pio_impl(int nblocks) /* Prepopulate the CDROM with an interesting pattern */ generate_pattern(pattern, patt_len, ATAPI_BLOCK_SIZE); - fh = fopen(tmp_path, "w+"); + fh = fopen(tmp_path, "wb+"); ret = fwrite(pattern, ATAPI_BLOCK_SIZE, patt_blocks, fh); g_assert_cmpint(ret, ==, patt_blocks); fclose(fh); @@ -993,7 +993,7 @@ static void test_cdrom_dma(void) prdt[0].size = cpu_to_le32(len | PRDT_EOT); generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE); - fh = fopen(tmp_path, "w+"); + fh = fopen(tmp_path, "wb+"); ret = fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh); g_assert_cmpint(ret, ==, 16); fclose(fh); From a68667066ad0b171a8938fb3f6bf0ad964362593 Mon Sep 17 00:00:00 2001 From: Xuzhou Cheng Date: Sun, 25 Sep 2022 19:30:19 +0800 Subject: [PATCH 0733/1020] tests/qtest: virtio-net-failover: Disable migration tests for win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These tests use the exec migration protocol, which is unsupported on Windows as of today. Disable these tests for now. Signed-off-by: Xuzhou Cheng Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-42-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/virtio-net-failover.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/qtest/virtio-net-failover.c b/tests/qtest/virtio-net-failover.c index 443ee56de9..4a809590bf 100644 --- a/tests/qtest/virtio-net-failover.c +++ b/tests/qtest/virtio-net-failover.c @@ -588,6 +588,7 @@ static void test_hotplug_2_reverse(void) machine_stop(qts); } +#ifndef _WIN32 static QDict *migrate_status(QTestState *qts) { QDict *resp, *ret; @@ -1827,6 +1828,7 @@ static void test_multi_in(gconstpointer opaque) machine_stop(qts); } +#endif /* _WIN32 */ int main(int argc, char **argv) { @@ -1857,7 +1859,11 @@ int main(int argc, char **argv) qtest_add_func("failover-virtio-net/hotplug/2_reverse", test_hotplug_2_reverse); - /* migration tests */ +#ifndef _WIN32 + /* + * These migration tests cases use the exec migration protocol, + * which is unsupported on Windows. + */ qtest_add_data_func("failover-virtio-net/migrate/on/out", tmpfile, test_migrate_out); qtest_add_data_func("failover-virtio-net/migrate/on/in", tmpfile, @@ -1886,6 +1892,7 @@ int main(int argc, char **argv) tmpfile, test_multi_out); qtest_add_data_func("failover-virtio-net/migrate/multi/in", tmpfile, test_multi_in); +#endif /* _WIN32 */ ret = g_test_run(); From e6f59e4c0b86a82cdaeacbd0ee94183b896523df Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:22 +0800 Subject: [PATCH 0734/1020] tests/qtest: microbit-test: Fix socket access for win32 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sockets on Windows do not use *nix-style file descriptors, so write()/read()/close() do not work on Windows. Switch over to use send()/recv()/closesocket() which work with sockets on all platforms. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-45-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/microbit-test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/qtest/microbit-test.c b/tests/qtest/microbit-test.c index b71daae9a9..4bc267020b 100644 --- a/tests/qtest/microbit-test.c +++ b/tests/qtest/microbit-test.c @@ -51,7 +51,7 @@ static void uart_rw_to_rxd(QTestState *qts, int sock_fd, const char *in, { int i, in_len = strlen(in); - g_assert_true(write(sock_fd, in, in_len) == in_len); + g_assert_true(send(sock_fd, in, in_len, 0) == in_len); for (i = 0; i < in_len; i++) { g_assert_true(uart_wait_for_event(qts, NRF51_UART_BASE + A_UART_RXDRDY)); @@ -77,7 +77,7 @@ static void test_nrf51_uart(void) char s[10]; QTestState *qts = qtest_init_with_serial("-M microbit", &sock_fd); - g_assert_true(write(sock_fd, "c", 1) == 1); + g_assert_true(send(sock_fd, "c", 1, 0) == 1); g_assert_cmphex(qtest_readl(qts, NRF51_UART_BASE + A_UART_RXD), ==, 0x00); qtest_writel(qts, NRF51_UART_BASE + A_UART_ENABLE, 0x04); @@ -97,17 +97,17 @@ static void test_nrf51_uart(void) qtest_writel(qts, NRF51_UART_BASE + A_UART_STARTTX, 0x01); uart_w_to_txd(qts, "d"); - g_assert_true(read(sock_fd, s, 10) == 1); + g_assert_true(recv(sock_fd, s, 10, 0) == 1); g_assert_cmphex(s[0], ==, 'd'); qtest_writel(qts, NRF51_UART_BASE + A_UART_SUSPEND, 0x01); qtest_writel(qts, NRF51_UART_BASE + A_UART_TXD, 'h'); qtest_writel(qts, NRF51_UART_BASE + A_UART_STARTTX, 0x01); uart_w_to_txd(qts, "world"); - g_assert_true(read(sock_fd, s, 10) == 5); + g_assert_true(recv(sock_fd, s, 10, 0) == 5); g_assert_true(memcmp(s, "world", 5) == 0); - close(sock_fd); + closesocket(sock_fd); qtest_quit(qts); } From 3665fadd468b3fb02371e57d1ab7de60c882038b Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:23 +0800 Subject: [PATCH 0735/1020] tests/qtest: libqtest: Replace the call to close a socket with closesocket() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit close() is a *nix function. It works on any file descriptor, and sockets in *nix are an example of a file descriptor. closesocket() is a Windows-specific function, which works only specifically with sockets. Sockets on Windows do not use *nix-style file descriptors, and socket() returns a handle to a kernel object instead, so it must be closed with closesocket(). In QEMU there is already a logic to handle such platform difference in os-posix.h and os-win32.h, that: * closesocket maps to close on POSIX * closesocket maps to a wrapper that calls the real closesocket() on Windows Replace the call to close a socket with closesocket() instead. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220925113032.1949844-46-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/libqtest.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index 5c4a509c58..4f4b2d6477 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -97,7 +97,7 @@ static int socket_accept(int sock) (void *)&timeout, sizeof(timeout))) { fprintf(stderr, "%s failed to set SO_RCVTIMEO: %s\n", __func__, strerror(errno)); - close(sock); + closesocket(sock); return -1; } @@ -108,7 +108,7 @@ static int socket_accept(int sock) if (ret == -1) { fprintf(stderr, "%s failed: %s\n", __func__, strerror(errno)); } - close(sock); + closesocket(sock); return ret; } @@ -421,8 +421,8 @@ void qtest_quit(QTestState *s) qtest_remove_abrt_handler(s); qtest_kill_qemu(s); - close(s->fd); - close(s->qmp_fd); + closesocket(s->fd); + closesocket(s->qmp_fd); g_string_free(s->rx, true); for (GList *it = s->pending_events; it != NULL; it = it->next) { From 2c73437d8de59942bbe6dde0029922744c4c4f81 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:28 +0800 Subject: [PATCH 0736/1020] tests/qtest: migration-test: Skip running some TLS cases for win32 Some migration test cases use TLS to communicate, but they fail on Windows with the following error messages: qemu-system-x86_64: TLS handshake failed: Insufficient credentials for that request. qemu-system-x86_64: TLS handshake failed: Error in the pull function. query-migrate shows failed migration: TLS handshake failed: Error in the pull function. Disable them temporarily. Signed-off-by: Bin Meng Message-Id: <20220925113032.1949844-51-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- tests/qtest/migration-test.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index 3db1177377..0d153d6b5e 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -1402,6 +1402,7 @@ static void test_precopy_unix_dirty_ring(void) } #ifdef CONFIG_GNUTLS +#ifndef _WIN32 static void test_precopy_unix_tls_psk(void) { g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); @@ -1414,6 +1415,7 @@ static void test_precopy_unix_tls_psk(void) test_precopy_common(&args); } +#endif /* _WIN32 */ #ifdef CONFIG_TASN1 static void test_precopy_unix_tls_x509_default_host(void) @@ -1522,6 +1524,7 @@ static void test_precopy_tcp_plain(void) } #ifdef CONFIG_GNUTLS +#ifndef _WIN32 static void test_precopy_tcp_tls_psk_match(void) { MigrateCommon args = { @@ -1532,6 +1535,7 @@ static void test_precopy_tcp_tls_psk_match(void) test_precopy_common(&args); } +#endif /* _WIN32 */ static void test_precopy_tcp_tls_psk_mismatch(void) { @@ -1929,6 +1933,7 @@ static void test_multifd_tcp_zstd(void) #endif #ifdef CONFIG_GNUTLS +#ifndef _WIN32 static void * test_migrate_multifd_tcp_tls_psk_start_match(QTestState *from, QTestState *to) @@ -1936,6 +1941,7 @@ test_migrate_multifd_tcp_tls_psk_start_match(QTestState *from, test_migrate_precopy_tcp_multifd_start_common(from, to, "none"); return test_migrate_tls_psk_start_match(from, to); } +#endif /* _WIN32 */ static void * test_migrate_multifd_tcp_tls_psk_start_mismatch(QTestState *from, @@ -1987,6 +1993,7 @@ test_migrate_multifd_tls_x509_start_reject_anon_client(QTestState *from, } #endif /* CONFIG_TASN1 */ +#ifndef _WIN32 static void test_multifd_tcp_tls_psk_match(void) { MigrateCommon args = { @@ -1996,6 +2003,7 @@ static void test_multifd_tcp_tls_psk_match(void) }; test_precopy_common(&args); } +#endif /* _WIN32 */ static void test_multifd_tcp_tls_psk_mismatch(void) { @@ -2492,8 +2500,10 @@ int main(int argc, char **argv) qtest_add_func("/migration/precopy/unix/plain", test_precopy_unix_plain); qtest_add_func("/migration/precopy/unix/xbzrle", test_precopy_unix_xbzrle); #ifdef CONFIG_GNUTLS +#ifndef _WIN32 qtest_add_func("/migration/precopy/unix/tls/psk", test_precopy_unix_tls_psk); +#endif if (has_uffd) { /* @@ -2519,8 +2529,10 @@ int main(int argc, char **argv) qtest_add_func("/migration/precopy/tcp/plain", test_precopy_tcp_plain); #ifdef CONFIG_GNUTLS +#ifndef _WIN32 qtest_add_func("/migration/precopy/tcp/tls/psk/match", test_precopy_tcp_tls_psk_match); +#endif qtest_add_func("/migration/precopy/tcp/tls/psk/mismatch", test_precopy_tcp_tls_psk_mismatch); #ifdef CONFIG_TASN1 @@ -2564,8 +2576,10 @@ int main(int argc, char **argv) test_multifd_tcp_zstd); #endif #ifdef CONFIG_GNUTLS +#ifndef _WIN32 qtest_add_func("/migration/multifd/tcp/tls/psk/match", test_multifd_tcp_tls_psk_match); +#endif qtest_add_func("/migration/multifd/tcp/tls/psk/mismatch", test_multifd_tcp_tls_psk_mismatch); #ifdef CONFIG_TASN1 From 3070eeba8510ce755d6cd75e761126c01f065a24 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 25 Sep 2022 19:30:30 +0800 Subject: [PATCH 0737/1020] .gitlab-ci.d/windows.yml: Display meson test logs When CI fails we don't know what causes the failure. Displaying the meson test logs can be helpful. Signed-off-by: Bin Meng Reviewed-by: Thomas Huth Message-Id: <20220925113032.1949844-53-bmeng.cn@gmail.com> Signed-off-by: Thomas Huth --- .gitlab-ci.d/windows.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index 86a4339c48..ba59844d12 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -61,7 +61,7 @@ msys2-64bit: - .\msys64\usr\bin\bash -lc './configure --target-list=x86_64-softmmu --enable-capstone --without-default-devices' - .\msys64\usr\bin\bash -lc 'make' - - .\msys64\usr\bin\bash -lc 'make check' + - .\msys64\usr\bin\bash -lc 'make check || { cat build/meson-logs/testlog.txt; exit 1; } ;' msys2-32bit: extends: .shared_msys2_builder @@ -94,4 +94,4 @@ msys2-32bit: - cd output - ..\msys64\usr\bin\bash -lc "../configure --target-list=ppc64-softmmu" - ..\msys64\usr\bin\bash -lc 'make' - - ..\msys64\usr\bin\bash -lc 'make check' + - ..\msys64\usr\bin\bash -lc 'make check || { cat meson-logs/testlog.txt; exit 1; } ;' From 9bcc0f7de7a6a04bd184ac4a1dbcbc3ccd53a6c0 Mon Sep 17 00:00:00 2001 From: Michael Labiuk Date: Tue, 20 Sep 2022 13:48:36 +0300 Subject: [PATCH 0738/1020] tests/x86: Move common code to function in device-plug-test Move common code for device removing to function. Signed-off-by: Michael Labiuk Message-Id: <20220920104842.605530-2-michael.labiuk@virtuozzo.com> Reviewed-by: Thomas Huth Signed-off-by: Thomas Huth --- tests/qtest/device-plug-test.c | 42 ++++++++++++++-------------------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/tests/qtest/device-plug-test.c b/tests/qtest/device-plug-test.c index a1fb99c8ff..e595b45b66 100644 --- a/tests/qtest/device-plug-test.c +++ b/tests/qtest/device-plug-test.c @@ -61,6 +61,18 @@ static void wait_device_deleted_event(QTestState *qtest, const char *id) } } +static void process_device_remove(QTestState *qtest, const char *id) +{ + /* + * Request device removal. As the guest is not running, the request won't + * be processed. However during system reset, the removal will be + * handled, removing the device. + */ + device_del(qtest, id); + system_reset(qtest); + wait_device_deleted_event(qtest, id); +} + static void test_pci_unplug_request(void) { const char *arch = qtest_get_arch(); @@ -73,14 +85,7 @@ static void test_pci_unplug_request(void) QTestState *qtest = qtest_initf("%s -device virtio-mouse-pci,id=dev0", machine_addition); - /* - * Request device removal. As the guest is not running, the request won't - * be processed. However during system reset, the removal will be - * handled, removing the device. - */ - device_del(qtest, "dev0"); - system_reset(qtest); - wait_device_deleted_event(qtest, "dev0"); + process_device_remove(qtest, "dev0"); qtest_quit(qtest); } @@ -98,14 +103,7 @@ static void test_pci_unplug_json_request(void) "%s -device \"{'driver': 'virtio-mouse-pci', 'id': 'dev0'}\"", machine_addition); - /* - * Request device removal. As the guest is not running, the request won't - * be processed. However during system reset, the removal will be - * handled, removing the device. - */ - device_del(qtest, "dev0"); - system_reset(qtest); - wait_device_deleted_event(qtest, "dev0"); + process_device_remove(qtest, "dev0"); qtest_quit(qtest); } @@ -128,9 +126,7 @@ static void test_spapr_cpu_unplug_request(void) "-device power9_v2.0-spapr-cpu-core,core-id=1,id=dev0"); /* similar to test_pci_unplug_request */ - device_del(qtest, "dev0"); - system_reset(qtest); - wait_device_deleted_event(qtest, "dev0"); + process_device_remove(qtest, "dev0"); qtest_quit(qtest); } @@ -144,9 +140,7 @@ static void test_spapr_memory_unplug_request(void) "-device pc-dimm,id=dev0,memdev=mem0"); /* similar to test_pci_unplug_request */ - device_del(qtest, "dev0"); - system_reset(qtest); - wait_device_deleted_event(qtest, "dev0"); + process_device_remove(qtest, "dev0"); qtest_quit(qtest); } @@ -158,9 +152,7 @@ static void test_spapr_phb_unplug_request(void) qtest = qtest_initf("-device spapr-pci-host-bridge,index=1,id=dev0"); /* similar to test_pci_unplug_request */ - device_del(qtest, "dev0"); - system_reset(qtest); - wait_device_deleted_event(qtest, "dev0"); + process_device_remove(qtest, "dev0"); qtest_quit(qtest); } From 52ca92d6d7b287e3d1b326168f57fc00ebd47b64 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 27 Sep 2022 19:05:50 +0800 Subject: [PATCH 0739/1020] tests/qtest: hd-geo-test: Avoid using hardcoded /tmp This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Message-Id: <20220927110632.1973965-13-bmeng.cn@gmail.com> Reviewed-by: Thomas Huth Signed-off-by: Thomas Huth --- tests/qtest/hd-geo-test.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/tests/qtest/hd-geo-test.c b/tests/qtest/hd-geo-test.c index 413cf964c0..ba772f4d7a 100644 --- a/tests/qtest/hd-geo-test.c +++ b/tests/qtest/hd-geo-test.c @@ -27,16 +27,16 @@ static char *create_test_img(int secs) { - char *template = strdup("/tmp/qtest.XXXXXX"); + char *template; int fd, ret; - fd = mkstemp(template); + fd = g_file_open_tmp("qtest.XXXXXX", &template, NULL); g_assert(fd >= 0); ret = ftruncate(fd, (off_t)secs * 512); close(fd); if (ret) { - free(template); + g_free(template); template = NULL; } @@ -422,9 +422,8 @@ static MBRpartitions empty_mbr = { {false, 0, 0, 0, 0, 0, 0, 0, 0}, static char *create_qcow2_with_mbr(MBRpartitions mbr, uint64_t sectors) { - const char *template = "/tmp/qtest.XXXXXX"; - char *raw_path = strdup(template); - char *qcow2_path = strdup(template); + g_autofree char *raw_path = NULL; + char *qcow2_path; char cmd[100 + 2 * PATH_MAX]; uint8_t buf[512] = {}; int i, ret, fd, offset; @@ -468,7 +467,7 @@ static char *create_qcow2_with_mbr(MBRpartitions mbr, uint64_t sectors) offset += 0x10; } - fd = mkstemp(raw_path); + fd = g_file_open_tmp("qtest.XXXXXX", &raw_path, NULL); g_assert(fd >= 0); close(fd); @@ -478,7 +477,7 @@ static char *create_qcow2_with_mbr(MBRpartitions mbr, uint64_t sectors) g_assert(ret == sizeof(buf)); close(fd); - fd = mkstemp(qcow2_path); + fd = g_file_open_tmp("qtest.XXXXXX", &qcow2_path, NULL); g_assert(fd >= 0); close(fd); @@ -506,7 +505,6 @@ static char *create_qcow2_with_mbr(MBRpartitions mbr, uint64_t sectors) free(qemu_img_abs_path); unlink(raw_path); - free(raw_path); return qcow2_path; } @@ -714,7 +712,7 @@ static void test_override(TestArgs *args, CHSResult expected[]) for (i = 0; i < args->n_drives; i++) { unlink(args->drives[i]); - free(args->drives[i]); + g_free(args->drives[i]); } g_free(args->drives); g_strfreev(args->argv); @@ -867,7 +865,7 @@ static void test_override_scsi_hot_unplug(void) for (i = 0; i < args->n_drives; i++) { unlink(args->drives[i]); - free(args->drives[i]); + g_free(args->drives[i]); } g_free(args->drives); g_strfreev(args->argv); @@ -927,7 +925,7 @@ static void test_override_virtio_hot_unplug(void) for (i = 0; i < args->n_drives; i++) { unlink(args->drives[i]); - free(args->drives[i]); + g_free(args->drives[i]); } g_free(args->drives); g_strfreev(args->argv); @@ -987,7 +985,7 @@ test_add_done: for (i = 0; i < backend_last; i++) { if (img_file_name[i]) { unlink(img_file_name[i]); - free(img_file_name[i]); + g_free(img_file_name[i]); } } From 8189b27d3b183e27e3720f4a06b6d950542cba64 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 27 Sep 2022 19:05:53 +0800 Subject: [PATCH 0740/1020] tests/qtest: pflash-cfi02-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_file_open_tmp() for a portable implementation. Signed-off-by: Bin Meng Message-Id: <20220927110632.1973965-16-bmeng.cn@gmail.com> Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Thomas Huth --- tests/qtest/pflash-cfi02-test.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/qtest/pflash-cfi02-test.c b/tests/qtest/pflash-cfi02-test.c index 7fce614b64..0b52c2ca5c 100644 --- a/tests/qtest/pflash-cfi02-test.c +++ b/tests/qtest/pflash-cfi02-test.c @@ -56,7 +56,7 @@ typedef struct { QTestState *qtest; } FlashConfig; -static char image_path[] = "/tmp/qtest.XXXXXX"; +static char *image_path; /* * The pflash implementation allows some parameters to be unspecified. We want @@ -608,6 +608,7 @@ static void test_cfi_in_autoselect(const void *opaque) static void cleanup(void *opaque) { unlink(image_path); + g_free(image_path); } /* @@ -635,16 +636,14 @@ static const FlashConfig configuration[] = { int main(int argc, char **argv) { - int fd = mkstemp(image_path); - if (fd == -1) { - g_printerr("Failed to create temporary file %s: %s\n", image_path, - strerror(errno)); - exit(EXIT_FAILURE); - } + GError *err = NULL; + int fd = g_file_open_tmp("qtest.XXXXXX", &image_path, &err); + g_assert_no_error(err); + if (ftruncate(fd, UNIFORM_FLASH_SIZE) < 0) { int error_code = errno; close(fd); - unlink(image_path); + cleanup(NULL); g_printerr("Failed to truncate file %s to %u MB: %s\n", image_path, UNIFORM_FLASH_SIZE, strerror(error_code)); exit(EXIT_FAILURE); From c12fea71a0195b71715f4c1b190232bebb2e9cf6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 27 Sep 2022 19:05:54 +0800 Subject: [PATCH 0741/1020] tests/qtest: qmp-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_dir_make_tmp() for a portable implementation. Signed-off-by: Bin Meng Message-Id: <20220927110632.1973965-17-bmeng.cn@gmail.com> Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Thomas Huth --- tests/qtest/qmp-test.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/qtest/qmp-test.c b/tests/qtest/qmp-test.c index 23b2a37942..22957fa49c 100644 --- a/tests/qtest/qmp-test.c +++ b/tests/qtest/qmp-test.c @@ -163,14 +163,15 @@ static void test_qmp_protocol(void) /* Out-of-band tests */ -char tmpdir[] = "/tmp/qmp-test-XXXXXX"; +char *tmpdir; char *fifo_name; static void setup_blocking_cmd(void) { - if (!g_mkdtemp(tmpdir)) { - g_error("g_mkdtemp: %s", strerror(errno)); - } + GError *err = NULL; + tmpdir = g_dir_make_tmp("qmp-test-XXXXXX", &err); + g_assert_no_error(err); + fifo_name = g_strdup_printf("%s/fifo", tmpdir); if (mkfifo(fifo_name, 0666)) { g_error("mkfifo: %s", strerror(errno)); @@ -181,6 +182,7 @@ static void cleanup_blocking_cmd(void) { unlink(fifo_name); rmdir(tmpdir); + g_free(tmpdir); } static void send_cmd_that_blocks(QTestState *s, const char *id) From e6efe236c1d1f2451d59a7151c50d1c79360857c Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 27 Sep 2022 19:05:56 +0800 Subject: [PATCH 0742/1020] tests/qtest: vhost-user-test: Avoid using hardcoded /tmp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This case was written to use hardcoded /tmp directory for temporary files. Update to use g_dir_make_tmp() for a portable implementation. Signed-off-by: Bin Meng Message-Id: <20220927110632.1973965-19-bmeng.cn@gmail.com> Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Thomas Huth --- tests/qtest/vhost-user-test.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index d7d6cfc9bd..84498941a6 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -482,8 +482,8 @@ static TestServer *test_server_new(const gchar *name, struct vhost_user_ops *ops) { TestServer *server = g_new0(TestServer, 1); - char template[] = "/tmp/vhost-test-XXXXXX"; - const char *tmpfs; + g_autofree const char *tmpfs = NULL; + GError *err = NULL; server->context = g_main_context_new(); server->loop = g_main_loop_new(server->context, FALSE); @@ -491,9 +491,11 @@ static TestServer *test_server_new(const gchar *name, /* run the main loop thread so the chardev may operate */ server->thread = g_thread_new(NULL, thread_function, server->loop); - tmpfs = g_mkdtemp(template); + tmpfs = g_dir_make_tmp("vhost-test-XXXXXX", &err); if (!tmpfs) { - g_test_message("g_mkdtemp on path (%s): %s", template, strerror(errno)); + g_test_message("g_dir_make_tmp on path (%s): %s", tmpfs, + err->message); + g_error_free(err); } g_assert(tmpfs); From 65a2eff0f53871166dee6767494f0cc6ffbf4a14 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 27 Sep 2022 19:06:17 +0800 Subject: [PATCH 0743/1020] tests/qtest: boot-serial-test: Close the serial file before starting QEMU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This qtest executable created a serial chardev file to be passed to the QEMU executable. The serial file was created by g_file_open_tmp(), which internally opens the file with FILE_SHARE_WRITE security attribute on Windows. Based on [1], there is only one case that allows the first call to CreateFile() with GENERIC_READ & FILE_SHARE_WRITE, and second call to CreateFile() with GENERIC_WRITE & FILE_SHARE_READ. All other combinations require FILE_SHARE_WRITE in the second call. But there is no way for the second call (in this case the QEMU executable) to know what combination was passed to the first call, unless FILE_SHARE_WRITE is passed to the second call. Two processes shouldn't share the same file for writing with a chardev. Let's close the serial file before starting QEMU. [1] https://docs.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files Signed-off-by: Bin Meng Message-Id: <20220927110632.1973965-40-bmeng.cn@gmail.com> Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Thomas Huth --- tests/qtest/boot-serial-test.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c index 72310ba30e..b216519b62 100644 --- a/tests/qtest/boot-serial-test.c +++ b/tests/qtest/boot-serial-test.c @@ -233,6 +233,7 @@ static void test_machine(const void *data) ser_fd = g_file_open_tmp("qtest-boot-serial-sXXXXXX", &serialtmp, NULL); g_assert(ser_fd != -1); + close(ser_fd); if (test->kernel) { code = test->kernel; @@ -266,6 +267,8 @@ static void test_machine(const void *data) unlink(codetmp); } + ser_fd = open(serialtmp, O_RDONLY); + g_assert(ser_fd != -1); if (!check_guest_output(qts, test, ser_fd)) { g_error("Failed to find expected string. Please check '%s'", serialtmp); From 0b49bc1b713d6e3896179f9700c8c35e511075f6 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Tue, 27 Sep 2022 19:06:32 +0800 Subject: [PATCH 0744/1020] docs/devel: testing: Document writing portable test cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the best practices of how to write portable test cases that can be built and run successfully on both Linux and Windows hosts. Signed-off-by: Bin Meng Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220927110632.1973965-55-bmeng.cn@gmail.com> Reviewed-by: Thomas Huth Signed-off-by: Thomas Huth --- docs/devel/testing.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index aea5b42356..fbb98faabe 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -81,6 +81,36 @@ QTest cases can be executed with make check-qtest +Writing portable test cases +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Both unit tests and qtests can run on POSIX hosts as well as Windows hosts. +Care must be taken when writing portable test cases that can be built and run +successfully on various hosts. The following list shows some best practices: + +* Use portable APIs from glib whenever necessary, e.g.: g_setenv(), + g_mkdtemp(), g_mkdir(). +* Avoid using hardcoded /tmp for temporary file directory. + Use g_get_tmp_dir() instead. +* Bear in mind that Windows has different special string representation for + stdin/stdout/stderr and null devices. For example if your test case uses + "/dev/fd/2" and "/dev/null" on Linux, remember to use "2" and "nul" on + Windows instead. Also IO redirection does not work on Windows, so avoid + using "2>nul" whenever necessary. +* If your test cases uses the blkdebug feature, use relative path to pass + the config and image file paths in the command line as Windows absolute + path contains the delimiter ":" which will confuse the blkdebug parser. +* Use double quotes in your extra QEMU commmand line in your test cases + instead of single quotes, as Windows does not drop single quotes when + passing the command line to QEMU. +* Windows opens a file in text mode by default, while a POSIX compliant + implementation treats text files and binary files the same. So if your + test cases opens a file to write some data and later wants to compare the + written data with the original one, be sure to pass the letter 'b' as + part of the mode string to fopen(), or O_BINARY flag for the open() call. +* If a certain test case can only run on POSIX or Linux hosts, use a proper + #ifdef in the codes. If the whole test suite cannot run on Windows, disable + the build in the meson.build file. + QAPI schema tests ~~~~~~~~~~~~~~~~~ From 429c72800654503e0073906f63fdc9a641639bdc Mon Sep 17 00:00:00 2001 From: Kunkun Jiang Date: Mon, 11 Jul 2022 09:46:51 +0800 Subject: [PATCH 0745/1020] vfio/migration: Fix incorrect initialization value for parameters in VFIOMigration The structure VFIOMigration of a VFIODevice is allocated and initialized in vfio_migration_init(). "device_state" and "vm_running" are initialized to 0, indicating that VFIO device is_STOP and VM is not-running. The initialization value is incorrect. According to the agreement, default state of VFIO device is _RUNNING. And if a VFIO device is hot-plugged while the VM is running, "vm_running" should be 1. This patch fixes it. Fixes: 02a7e71b1e5b ("vfio: Add VM state change handler to know state of VM") Signed-off-by: Kunkun Jiang Link: https://lore.kernel.org/r/20220711014651.1327-1-jiangkunkun@huawei.com Signed-off-by: Alex Williamson --- hw/vfio/migration.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c index a6ad1f8945..3de4252111 100644 --- a/hw/vfio/migration.c +++ b/hw/vfio/migration.c @@ -806,6 +806,8 @@ static int vfio_migration_init(VFIODevice *vbasedev, } vbasedev->migration = g_new0(VFIOMigration, 1); + vbasedev->migration->device_state = VFIO_DEVICE_STATE_RUNNING; + vbasedev->migration->vm_running = runstate_is_running(); ret = vfio_region_setup(obj, vbasedev, &vbasedev->migration->region, info->index, "migration"); From 85b6d2b5fc25c9c0d10d493b3728183ab8f8e68a Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Thu, 15 Sep 2022 11:18:27 -0600 Subject: [PATCH 0746/1020] vfio/common: Fix vfio_iommu_type1_info use after free MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On error, vfio_get_iommu_info() frees and clears *info, but vfio_connect_container() continues to use the pointer regardless of the return value. Restructure the code such that a failure of this function triggers an error and clean up the remainder of the function, including updating an outdated comment that had drifted from its relevant line of code and using host page size for a default for better compatibility on non-4KB systems. Reported-by: Nicolin Chen Link: https://lore.kernel.org/all/20220910004245.2878-1-nicolinc@nvidia.com/ Signed-off-by: Alex Williamson Reviewed-by: Philippe Mathieu-DaudĂ© Reviewed-by: Nicolin Chen Tested-by: Nicolin Chen Link: https://lore.kernel.org/r/166326219630.3388898.12882473157184946072.stgit@omen Signed-off-by: Alex Williamson --- hw/vfio/common.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/hw/vfio/common.c b/hw/vfio/common.c index ace9562a9b..6b5d8c0bf6 100644 --- a/hw/vfio/common.c +++ b/hw/vfio/common.c @@ -2111,29 +2111,31 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as, { struct vfio_iommu_type1_info *info; - /* - * FIXME: This assumes that a Type1 IOMMU can map any 64-bit - * IOVA whatsoever. That's not actually true, but the current - * kernel interface doesn't tell us what it can map, and the - * existing Type1 IOMMUs generally support any IOVA we're - * going to actually try in practice. - */ ret = vfio_get_iommu_info(container, &info); - - if (ret || !(info->flags & VFIO_IOMMU_INFO_PGSIZES)) { - /* Assume 4k IOVA page size */ - info->iova_pgsizes = 4096; + if (ret) { + error_setg_errno(errp, -ret, "Failed to get VFIO IOMMU info"); + goto enable_discards_exit; } - vfio_host_win_add(container, 0, (hwaddr)-1, info->iova_pgsizes); - container->pgsizes = info->iova_pgsizes; - /* The default in the kernel ("dma_entry_limit") is 65535. */ - container->dma_max_mappings = 65535; - if (!ret) { - vfio_get_info_dma_avail(info, &container->dma_max_mappings); - vfio_get_iommu_info_migration(container, info); + if (info->flags & VFIO_IOMMU_INFO_PGSIZES) { + container->pgsizes = info->iova_pgsizes; + } else { + container->pgsizes = qemu_real_host_page_size(); } + + if (!vfio_get_info_dma_avail(info, &container->dma_max_mappings)) { + container->dma_max_mappings = 65535; + } + vfio_get_iommu_info_migration(container, info); g_free(info); + + /* + * FIXME: We should parse VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE + * information to get the actual window extent rather than assume + * a 64-bit IOVA address space. + */ + vfio_host_win_add(container, 0, (hwaddr)-1, container->pgsizes); + break; } case VFIO_SPAPR_TCE_v2_IOMMU: From 4a877b82f7f99f7366fbb4820687d88dcf97478f Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 27 Sep 2022 11:35:38 +0200 Subject: [PATCH 0747/1020] linux-user: Add parameters of getrandom() syscall for strace Signed-off-by: Helge Deller Reviewed-by: Laurent Vivier Message-Id: <20220927093538.8954-2-deller@gmx.de> Signed-off-by: Laurent Vivier --- linux-user/strace.list | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-user/strace.list b/linux-user/strace.list index f8a771b4f2..a87415bf3d 100644 --- a/linux-user/strace.list +++ b/linux-user/strace.list @@ -352,7 +352,7 @@ { TARGET_NR_getpriority, "getpriority", "%s(%#x,%#x)", NULL, NULL }, #endif #ifdef TARGET_NR_getrandom -{ TARGET_NR_getrandom, "getrandom", NULL, NULL, NULL }, +{ TARGET_NR_getrandom, "getrandom", "%s(%p,%u,%u)", NULL, NULL }, #endif #ifdef TARGET_NR_getresgid { TARGET_NR_getresgid, "getresgid" , NULL, NULL, NULL }, From 5433af7697ba97531d97e16e721cfe8a90722198 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sat, 10 Sep 2022 13:44:47 +0200 Subject: [PATCH 0748/1020] watchdog: remove -watchdog option This was deprecated in 6.2 and is ready to go. It removes quite a bit of code that handled the registration of watchdog models. Signed-off-by: Paolo Bonzini --- docs/about/deprecated.rst | 5 ---- docs/about/removed-features.rst | 5 ++++ hw/watchdog/sbsa_gwdt.c | 6 ----- hw/watchdog/watchdog.c | 43 --------------------------------- hw/watchdog/wdt_aspeed.c | 6 ----- hw/watchdog/wdt_diag288.c | 6 ----- hw/watchdog/wdt_i6300esb.c | 6 ----- hw/watchdog/wdt_ib700.c | 6 ----- hw/watchdog/wdt_imx2.c | 6 ----- include/sysemu/watchdog.h | 12 --------- qemu-options.hx | 33 ++----------------------- softmmu/vl.c | 16 ------------ 12 files changed, 7 insertions(+), 143 deletions(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index a72fedba5f..93affe3669 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -81,11 +81,6 @@ the process listing. This is replaced by the new ``password-secret`` option which lets the password be securely provided on the command line using a ``secret`` object instance. -``-watchdog`` (since 6.2) -''''''''''''''''''''''''' - -Use ``-device`` instead. - ``-smp`` ("parameter=0" SMP configurations) (since 6.2) ''''''''''''''''''''''''''''''''''''''''''''''''''''''' diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index a4aa3dca69..63df9848fd 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -403,6 +403,11 @@ Sound card devices should be created using ``-device`` or ``-audio``. The exception is ``pcspk`` which can be activated using ``-machine pcspk-audiodev=``. +``-watchdog`` (since 7.2) +''''''''''''''''''''''''' + +Use ``-device`` instead. + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/hw/watchdog/sbsa_gwdt.c b/hw/watchdog/sbsa_gwdt.c index e49cacd0e2..7aa57a8c51 100644 --- a/hw/watchdog/sbsa_gwdt.c +++ b/hw/watchdog/sbsa_gwdt.c @@ -24,11 +24,6 @@ #include "qemu/log.h" #include "qemu/module.h" -static WatchdogTimerModel model = { - .wdt_name = TYPE_WDT_SBSA, - .wdt_description = "SBSA-compliant generic watchdog device", -}; - static const VMStateDescription vmstate_sbsa_gwdt = { .name = "sbsa-gwdt", .version_id = 1, @@ -287,7 +282,6 @@ static const TypeInfo wdt_sbsa_gwdt_info = { static void wdt_sbsa_gwdt_register_types(void) { - watchdog_add_model(&model); type_register_static(&wdt_sbsa_gwdt_info); } diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c index 1437e6c5b6..6c082a3263 100644 --- a/hw/watchdog/watchdog.c +++ b/hw/watchdog/watchdog.c @@ -32,49 +32,6 @@ #include "qemu/help_option.h" static WatchdogAction watchdog_action = WATCHDOG_ACTION_RESET; -static QLIST_HEAD(, WatchdogTimerModel) watchdog_list; - -void watchdog_add_model(WatchdogTimerModel *model) -{ - QLIST_INSERT_HEAD(&watchdog_list, model, entry); -} - -/* Returns: - * 0 = continue - * 1 = exit program with error - * 2 = exit program without error - */ -int select_watchdog(const char *p) -{ - WatchdogTimerModel *model; - QemuOpts *opts; - - /* -watchdog ? lists available devices and exits cleanly. */ - if (is_help_option(p)) { - QLIST_FOREACH(model, &watchdog_list, entry) { - fprintf(stderr, "\t%s\t%s\n", - model->wdt_name, model->wdt_description); - } - return 2; - } - - QLIST_FOREACH(model, &watchdog_list, entry) { - if (strcasecmp(model->wdt_name, p) == 0) { - /* add the device */ - opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, - &error_abort); - qemu_opt_set(opts, "driver", p, &error_abort); - return 0; - } - } - - fprintf(stderr, "Unknown -watchdog device. Supported devices are:\n"); - QLIST_FOREACH(model, &watchdog_list, entry) { - fprintf(stderr, "\t%s\t%s\n", - model->wdt_name, model->wdt_description); - } - return 1; -} WatchdogAction get_watchdog_action(void) { diff --git a/hw/watchdog/wdt_aspeed.c b/hw/watchdog/wdt_aspeed.c index 31855afdf4..d753693a2e 100644 --- a/hw/watchdog/wdt_aspeed.c +++ b/hw/watchdog/wdt_aspeed.c @@ -202,11 +202,6 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data, return; } -static WatchdogTimerModel model = { - .wdt_name = TYPE_ASPEED_WDT, - .wdt_description = "Aspeed watchdog device", -}; - static const VMStateDescription vmstate_aspeed_wdt = { .name = "vmstate_aspeed_wdt", .version_id = 0, @@ -416,7 +411,6 @@ static const TypeInfo aspeed_1030_wdt_info = { static void wdt_aspeed_register_types(void) { - watchdog_add_model(&model); type_register_static(&aspeed_wdt_info); type_register_static(&aspeed_2400_wdt_info); type_register_static(&aspeed_2500_wdt_info); diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c index 9e8882a11c..76d89fbf78 100644 --- a/hw/watchdog/wdt_diag288.c +++ b/hw/watchdog/wdt_diag288.c @@ -19,11 +19,6 @@ #include "migration/vmstate.h" #include "qemu/log.h" -static WatchdogTimerModel model = { - .wdt_name = TYPE_WDT_DIAG288, - .wdt_description = "diag288 device for s390x platform", -}; - static const VMStateDescription vmstate_diag288 = { .name = "vmstate_diag288", .version_id = 0, @@ -138,7 +133,6 @@ static const TypeInfo wdt_diag288_info = { static void wdt_diag288_register_types(void) { - watchdog_add_model(&model); type_register_static(&wdt_diag288_info); } diff --git a/hw/watchdog/wdt_i6300esb.c b/hw/watchdog/wdt_i6300esb.c index f99a1c9d29..5693ec6a09 100644 --- a/hw/watchdog/wdt_i6300esb.c +++ b/hw/watchdog/wdt_i6300esb.c @@ -457,11 +457,6 @@ static void i6300esb_exit(PCIDevice *dev) timer_free(d->timer); } -static WatchdogTimerModel model = { - .wdt_name = "i6300esb", - .wdt_description = "Intel 6300ESB", -}; - static void i6300esb_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -493,7 +488,6 @@ static const TypeInfo i6300esb_info = { static void i6300esb_register_types(void) { - watchdog_add_model(&model); type_register_static(&i6300esb_info); } diff --git a/hw/watchdog/wdt_ib700.c b/hw/watchdog/wdt_ib700.c index 91d1bdc0da..b116c3a3aa 100644 --- a/hw/watchdog/wdt_ib700.c +++ b/hw/watchdog/wdt_ib700.c @@ -128,11 +128,6 @@ static void wdt_ib700_reset(DeviceState *dev) timer_del(s->timer); } -static WatchdogTimerModel model = { - .wdt_name = "ib700", - .wdt_description = "iBASE 700", -}; - static void wdt_ib700_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); @@ -153,7 +148,6 @@ static const TypeInfo wdt_ib700_info = { static void wdt_ib700_register_types(void) { - watchdog_add_model(&model); type_register_static(&wdt_ib700_info); } diff --git a/hw/watchdog/wdt_imx2.c b/hw/watchdog/wdt_imx2.c index c3128370b5..e776a2fbd4 100644 --- a/hw/watchdog/wdt_imx2.c +++ b/hw/watchdog/wdt_imx2.c @@ -291,14 +291,8 @@ static const TypeInfo imx2_wdt_info = { .class_init = imx2_wdt_class_init, }; -static WatchdogTimerModel model = { - .wdt_name = "imx2-watchdog", - .wdt_description = "i.MX2 Watchdog", -}; - static void imx2_wdt_register_type(void) { - watchdog_add_model(&model); type_register_static(&imx2_wdt_info); } type_init(imx2_wdt_register_type) diff --git a/include/sysemu/watchdog.h b/include/sysemu/watchdog.h index d2d4901dbb..745c89b02b 100644 --- a/include/sysemu/watchdog.h +++ b/include/sysemu/watchdog.h @@ -25,20 +25,8 @@ #include "qemu/queue.h" #include "qapi/qapi-types-run-state.h" -struct WatchdogTimerModel { - QLIST_ENTRY(WatchdogTimerModel) entry; - - /* Short name of the device - used to select it on the command line. */ - const char *wdt_name; - /* Longer description (eg. manufacturer and full model number). */ - const char *wdt_description; -}; -typedef struct WatchdogTimerModel WatchdogTimerModel; - /* in hw/watchdog.c */ -int select_watchdog(const char *p); WatchdogAction get_watchdog_action(void); -void watchdog_add_model(WatchdogTimerModel *model); void watchdog_perform_action(void); #endif /* QEMU_WATCHDOG_H */ diff --git a/qemu-options.hx b/qemu-options.hx index d8b5ce5b43..df4b8c8f1a 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4330,7 +4330,7 @@ SRST ``-action panic=none`` ``-action reboot=shutdown,shutdown=pause`` - ``-watchdog i6300esb -action watchdog=pause`` + ``-device i6300esb -action watchdog=pause`` ERST @@ -4448,35 +4448,6 @@ SRST specifies the snapshot name used to load the initial VM state. ERST -DEF("watchdog", HAS_ARG, QEMU_OPTION_watchdog, \ - "-watchdog model\n" \ - " enable virtual hardware watchdog [default=none]\n", - QEMU_ARCH_ALL) -SRST -``-watchdog model`` - Create a virtual hardware watchdog device. Once enabled (by a guest - action), the watchdog must be periodically polled by an agent inside - the guest or else the guest will be restarted. Choose a model for - which your guest has drivers. - - The model is the model of hardware watchdog to emulate. Use - ``-watchdog help`` to list available hardware models. Only one - watchdog can be enabled for a guest. - - The following models may be available: - - ``ib700`` - iBASE 700 is a very simple ISA watchdog with a single timer. - - ``i6300esb`` - Intel 6300ESB I/O controller hub is a much more featureful - PCI-based dual-timer watchdog. - - ``diag288`` - A virtual watchdog for s390x backed by the diagnose 288 - hypercall (currently KVM only). -ERST - DEF("watchdog-action", HAS_ARG, QEMU_OPTION_watchdog_action, \ "-watchdog-action reset|shutdown|poweroff|inject-nmi|pause|debug|none\n" \ " action when watchdog fires [default=reset]\n", @@ -4498,7 +4469,7 @@ SRST Examples: - ``-watchdog i6300esb -watchdog-action pause``; \ ``-watchdog ib700`` + ``-device i6300esb -watchdog-action pause`` ERST diff --git a/softmmu/vl.c b/softmmu/vl.c index e62b9cc35d..b8788e765a 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -53,7 +53,6 @@ #include "hw/isa/isa.h" #include "hw/scsi/scsi.h" #include "hw/display/vga.h" -#include "sysemu/watchdog.h" #include "hw/firmware/smbios.h" #include "hw/acpi/acpi.h" #include "hw/xen/xen.h" @@ -181,7 +180,6 @@ static Chardev **serial_hds; static const char *log_mask; static const char *log_file; static bool list_data_dirs; -static const char *watchdog; static const char *qtest_chrdev; static const char *qtest_log; @@ -2329,12 +2327,6 @@ static void qemu_process_sugar_options(void) } object_register_sugar_prop("memory-backend", "prealloc", "on", false); } - - if (watchdog) { - int i = select_watchdog(watchdog); - if (i > 0) - exit (i == 1 ? 1 : 0); - } } /* -action processing */ @@ -3107,14 +3099,6 @@ void qemu_init(int argc, char **argv, char **envp) default_monitor = 0; } break; - case QEMU_OPTION_watchdog: - if (watchdog) { - error_report("only one watchdog option may be given"); - exit(1); - } - warn_report("-watchdog is deprecated; use -device instead."); - watchdog = optarg; - break; case QEMU_OPTION_action: olist = qemu_find_opts("action"); if (!qemu_opts_parse_noisily(olist, optarg, false)) { From a39fe10557462648b8bee7aec5e24aad75ebd32d Mon Sep 17 00:00:00 2001 From: Arwed Meyer Date: Sun, 11 Sep 2022 20:18:36 +0200 Subject: [PATCH 0749/1020] msmouse: Handle mouse reset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Detect mouse reset via RTS or DTR line: Don't send or process anything while in reset. When coming out of reset, send ID sequence first thing. This allows msmouse to be detected by common mouse drivers. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/77 Signed-off-by: Arwed Meyer Acked-by: Marc-AndrĂ© Lureau Message-Id: <20220911181840.8933-2-arwed.meyer@gmx.de> --- chardev/msmouse.c | 63 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/chardev/msmouse.c b/chardev/msmouse.c index eb9231dcdb..95fa488339 100644 --- a/chardev/msmouse.c +++ b/chardev/msmouse.c @@ -25,17 +25,20 @@ #include "qemu/osdep.h" #include "qemu/module.h" #include "chardev/char.h" +#include "chardev/char-serial.h" #include "ui/console.h" #include "ui/input.h" #include "qom/object.h" -#define MSMOUSE_LO6(n) ((n) & 0x3f) -#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) +#define MSMOUSE_LO6(n) ((n) & 0x3f) +#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) +#define MSMOUSE_PWR(cm) (cm & (CHR_TIOCM_RTS | CHR_TIOCM_DTR)) struct MouseChardev { Chardev parent; QemuInputHandlerState *hs; + int tiocm; int axis[INPUT_AXIS__MAX]; bool btns[INPUT_BUTTON__MAX]; bool btnc[INPUT_BUTTON__MAX]; @@ -109,6 +112,11 @@ static void msmouse_input_event(DeviceState *dev, QemuConsole *src, InputMoveEvent *move; InputBtnEvent *btn; + /* Ignore events if serial mouse powered down. */ + if (!MSMOUSE_PWR(mouse->tiocm)) { + return; + } + switch (evt->type) { case INPUT_EVENT_KIND_REL: move = evt->u.rel.data; @@ -132,6 +140,11 @@ static void msmouse_input_sync(DeviceState *dev) MouseChardev *mouse = MOUSE_CHARDEV(dev); Chardev *chr = CHARDEV(dev); + /* Ignore events if serial mouse powered down. */ + if (!MSMOUSE_PWR(mouse->tiocm)) { + return; + } + msmouse_queue_event(mouse); msmouse_chr_accept_input(chr); } @@ -142,6 +155,50 @@ static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len) return len; } +static int msmouse_ioctl(Chardev *chr, int cmd, void *arg) +{ + MouseChardev *mouse = MOUSE_CHARDEV(chr); + int c; + int *targ = (int *)arg; + + switch (cmd) { + case CHR_IOCTL_SERIAL_SET_TIOCM: + c = mouse->tiocm; + mouse->tiocm = *(int *)arg; + if (MSMOUSE_PWR(mouse->tiocm)) { + if (!MSMOUSE_PWR(c)) { + /* + * Power on after reset: send "M3" + * cause we behave like a 3 button logitech + * mouse. + */ + mouse->outbuf[0] = 'M'; + mouse->outbuf[1] = '3'; + mouse->outlen = 2; + /* Start sending data to serial. */ + msmouse_chr_accept_input(chr); + } + break; + } + /* + * Reset mouse buffers on power down. + * Mouse won't send anything without power. + */ + mouse->outlen = 0; + memset(mouse->axis, 0, sizeof(mouse->axis)); + memset(mouse->btns, false, sizeof(mouse->btns)); + memset(mouse->btnc, false, sizeof(mouse->btns)); + break; + case CHR_IOCTL_SERIAL_GET_TIOCM: + /* Remember line control status. */ + *targ = mouse->tiocm; + break; + default: + return -ENOTSUP; + } + return 0; +} + static void char_msmouse_finalize(Object *obj) { MouseChardev *mouse = MOUSE_CHARDEV(obj); @@ -166,6 +223,7 @@ static void msmouse_chr_open(Chardev *chr, *be_opened = false; mouse->hs = qemu_input_handler_register((DeviceState *)mouse, &msmouse_handler); + mouse->tiocm = 0; } static void char_msmouse_class_init(ObjectClass *oc, void *data) @@ -175,6 +233,7 @@ static void char_msmouse_class_init(ObjectClass *oc, void *data) cc->open = msmouse_chr_open; cc->chr_write = msmouse_chr_write; cc->chr_accept_input = msmouse_chr_accept_input; + cc->chr_ioctl = msmouse_ioctl; } static const TypeInfo char_msmouse_type_info = { From 8f9abdf586d48552273abe38cf55058f7d0c85fd Mon Sep 17 00:00:00 2001 From: Arwed Meyer Date: Sun, 11 Sep 2022 20:18:37 +0200 Subject: [PATCH 0750/1020] chardev: src buffer const for write functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make source buffers const for char be write functions. This allows using buffers returned by fifo as buf parameter and source buffer should not be changed by write functions anyway. Signed-off-by: Arwed Meyer Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220911181840.8933-3-arwed.meyer@gmx.de> --- chardev/char.c | 4 ++-- include/chardev/char.h | 4 ++-- include/sysemu/replay.h | 2 +- replay/replay-char.c | 2 +- stubs/replay-tools.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/chardev/char.c b/chardev/char.c index 0169d8dde4..b005df3ccf 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -193,7 +193,7 @@ int qemu_chr_be_can_write(Chardev *s) return be->chr_can_read(be->opaque); } -void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len) +void qemu_chr_be_write_impl(Chardev *s, const uint8_t *buf, int len) { CharBackend *be = s->be; @@ -202,7 +202,7 @@ void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len) } } -void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len) +void qemu_chr_be_write(Chardev *s, const uint8_t *buf, int len) { if (qemu_chr_replay(s)) { if (replay_mode == REPLAY_MODE_PLAY) { diff --git a/include/chardev/char.h b/include/chardev/char.h index a319b5fdff..44cd82e405 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -186,7 +186,7 @@ int qemu_chr_be_can_write(Chardev *s); * the caller should call @qemu_chr_be_can_write to determine how much data * the front end can currently accept. */ -void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len); +void qemu_chr_be_write(Chardev *s, const uint8_t *buf, int len); /** * qemu_chr_be_write_impl: @@ -195,7 +195,7 @@ void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len); * * Implementation of back end writing. Used by replay module. */ -void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len); +void qemu_chr_be_write_impl(Chardev *s, const uint8_t *buf, int len); /** * qemu_chr_be_update_read_handlers: diff --git a/include/sysemu/replay.h b/include/sysemu/replay.h index 73dee9ccdf..7ec0882b50 100644 --- a/include/sysemu/replay.h +++ b/include/sysemu/replay.h @@ -198,7 +198,7 @@ uint64_t blkreplay_next_id(void); /*! Registers char driver to save it's events */ void replay_register_char_driver(struct Chardev *chr); /*! Saves write to char device event to the log */ -void replay_chr_be_write(struct Chardev *s, uint8_t *buf, int len); +void replay_chr_be_write(struct Chardev *s, const uint8_t *buf, int len); /*! Writes char write return value to the replay log. */ void replay_char_write_event_save(int res, int offset); /*! Reads char write return value from the replay log. */ diff --git a/replay/replay-char.c b/replay/replay-char.c index d2025948cf..a31aded032 100644 --- a/replay/replay-char.c +++ b/replay/replay-char.c @@ -48,7 +48,7 @@ void replay_register_char_driver(Chardev *chr) char_drivers[drivers_count++] = chr; } -void replay_chr_be_write(Chardev *s, uint8_t *buf, int len) +void replay_chr_be_write(Chardev *s, const uint8_t *buf, int len) { CharEvent *event = g_new0(CharEvent, 1); diff --git a/stubs/replay-tools.c b/stubs/replay-tools.c index f2e72bb225..3e8ca3212d 100644 --- a/stubs/replay-tools.c +++ b/stubs/replay-tools.c @@ -53,7 +53,7 @@ void replay_register_char_driver(struct Chardev *chr) { } -void replay_chr_be_write(struct Chardev *s, uint8_t *buf, int len) +void replay_chr_be_write(struct Chardev *s, const uint8_t *buf, int len) { abort(); } From e0cf7f230778efbb560dc7774258fd9e88f4e1ff Mon Sep 17 00:00:00 2001 From: Arwed Meyer Date: Sun, 11 Sep 2022 20:18:38 +0200 Subject: [PATCH 0751/1020] msmouse: Use fifo8 instead of array MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make use of fifo8 functions instead of implementing own fifo code. This makes the code more readable and reduces risk of bugs. Signed-off-by: Arwed Meyer Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220911181840.8933-4-arwed.meyer@gmx.de> --- chardev/msmouse.c | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) diff --git a/chardev/msmouse.c b/chardev/msmouse.c index 95fa488339..5982c15df6 100644 --- a/chardev/msmouse.c +++ b/chardev/msmouse.c @@ -24,6 +24,7 @@ #include "qemu/osdep.h" #include "qemu/module.h" +#include "qemu/fifo8.h" #include "chardev/char.h" #include "chardev/char-serial.h" #include "ui/console.h" @@ -34,6 +35,12 @@ #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) #define MSMOUSE_PWR(cm) (cm & (CHR_TIOCM_RTS | CHR_TIOCM_DTR)) +/* Serial fifo size. */ +#define MSMOUSE_BUF_SZ 64 + +/* Mouse ID: Send "M3" cause we behave like a 3 button logitech mouse. */ +const uint8_t mouse_id[] = {'M', '3'}; + struct MouseChardev { Chardev parent; @@ -42,8 +49,7 @@ struct MouseChardev { int axis[INPUT_AXIS__MAX]; bool btns[INPUT_BUTTON__MAX]; bool btnc[INPUT_BUTTON__MAX]; - uint8_t outbuf[32]; - int outlen; + Fifo8 outbuf; }; typedef struct MouseChardev MouseChardev; @@ -54,20 +60,18 @@ DECLARE_INSTANCE_CHECKER(MouseChardev, MOUSE_CHARDEV, static void msmouse_chr_accept_input(Chardev *chr) { MouseChardev *mouse = MOUSE_CHARDEV(chr); - int len; + uint32_t len, avail; len = qemu_chr_be_can_write(chr); - if (len > mouse->outlen) { - len = mouse->outlen; - } - if (!len) { - return; - } + avail = fifo8_num_used(&mouse->outbuf); + while (len > 0 && avail > 0) { + const uint8_t *buf; + uint32_t size; - qemu_chr_be_write(chr, mouse->outbuf, len); - mouse->outlen -= len; - if (mouse->outlen) { - memmove(mouse->outbuf, mouse->outbuf + len, mouse->outlen); + buf = fifo8_pop_buf(&mouse->outbuf, MIN(len, avail), &size); + qemu_chr_be_write(chr, buf, size); + len = qemu_chr_be_can_write(chr); + avail -= size; } } @@ -94,12 +98,11 @@ static void msmouse_queue_event(MouseChardev *mouse) mouse->btnc[INPUT_BUTTON_MIDDLE]) { bytes[3] |= (mouse->btns[INPUT_BUTTON_MIDDLE] ? 0x20 : 0x00); mouse->btnc[INPUT_BUTTON_MIDDLE] = false; - count = 4; + count++; } - if (mouse->outlen <= sizeof(mouse->outbuf) - count) { - memcpy(mouse->outbuf + mouse->outlen, bytes, count); - mouse->outlen += count; + if (fifo8_num_free(&mouse->outbuf) >= count) { + fifo8_push_all(&mouse->outbuf, bytes, count); } else { /* queue full -> drop event */ } @@ -172,9 +175,7 @@ static int msmouse_ioctl(Chardev *chr, int cmd, void *arg) * cause we behave like a 3 button logitech * mouse. */ - mouse->outbuf[0] = 'M'; - mouse->outbuf[1] = '3'; - mouse->outlen = 2; + fifo8_push_all(&mouse->outbuf, mouse_id, sizeof(mouse_id)); /* Start sending data to serial. */ msmouse_chr_accept_input(chr); } @@ -184,7 +185,7 @@ static int msmouse_ioctl(Chardev *chr, int cmd, void *arg) * Reset mouse buffers on power down. * Mouse won't send anything without power. */ - mouse->outlen = 0; + fifo8_reset(&mouse->outbuf); memset(mouse->axis, 0, sizeof(mouse->axis)); memset(mouse->btns, false, sizeof(mouse->btns)); memset(mouse->btnc, false, sizeof(mouse->btns)); @@ -204,6 +205,7 @@ static void char_msmouse_finalize(Object *obj) MouseChardev *mouse = MOUSE_CHARDEV(obj); qemu_input_handler_unregister(mouse->hs); + fifo8_destroy(&mouse->outbuf); } static QemuInputHandler msmouse_handler = { @@ -224,6 +226,7 @@ static void msmouse_chr_open(Chardev *chr, mouse->hs = qemu_input_handler_register((DeviceState *)mouse, &msmouse_handler); mouse->tiocm = 0; + fifo8_create(&mouse->outbuf, MSMOUSE_BUF_SZ); } static void char_msmouse_class_init(ObjectClass *oc, void *data) From 50d03d485251d63931a69b3ad7004f3bb6ac8eee Mon Sep 17 00:00:00 2001 From: Arwed Meyer Date: Sun, 11 Sep 2022 20:18:39 +0200 Subject: [PATCH 0752/1020] msmouse: Add pnp data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make msmouse send serial pnp data. Enables you to see nice qemu device name in Win9x. Signed-off-by: Arwed Meyer Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220911181840.8933-5-arwed.meyer@gmx.de> --- chardev/msmouse.c | 58 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 47 insertions(+), 11 deletions(-) diff --git a/chardev/msmouse.c b/chardev/msmouse.c index 5982c15df6..9006703023 100644 --- a/chardev/msmouse.c +++ b/chardev/msmouse.c @@ -35,11 +35,24 @@ #define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6) #define MSMOUSE_PWR(cm) (cm & (CHR_TIOCM_RTS | CHR_TIOCM_DTR)) +/* Serial PnP for 6 bit devices/mice sends all ASCII chars - 0x20 */ +#define M(c) (c - 0x20) /* Serial fifo size. */ #define MSMOUSE_BUF_SZ 64 /* Mouse ID: Send "M3" cause we behave like a 3 button logitech mouse. */ const uint8_t mouse_id[] = {'M', '3'}; +/* + * PnP start "(", PnP version (1.0), vendor ID, product ID, '\\', + * serial ID (omitted), '\\', MS class name, '\\', driver ID (omitted), '\\', + * product description, checksum, ")" + * Missing parts are inserted later. + */ +const uint8_t pnp_data[] = {M('('), 1, '$', M('Q'), M('M'), M('U'), + M('0'), M('0'), M('0'), M('1'), + M('\\'), M('\\'), + M('M'), M('O'), M('U'), M('S'), M('E'), + M('\\'), M('\\')}; struct MouseChardev { Chardev parent; @@ -158,11 +171,22 @@ static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len) return len; } +static QemuInputHandler msmouse_handler = { + .name = "QEMU Microsoft Mouse", + .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, + .event = msmouse_input_event, + .sync = msmouse_input_sync, +}; + static int msmouse_ioctl(Chardev *chr, int cmd, void *arg) { MouseChardev *mouse = MOUSE_CHARDEV(chr); - int c; + int c, i, j; + uint8_t bytes[MSMOUSE_BUF_SZ / 2]; int *targ = (int *)arg; + const uint8_t hexchr[16] = {M('0'), M('1'), M('2'), M('3'), M('4'), M('5'), + M('6'), M('7'), M('8'), M('9'), M('A'), M('B'), + M('C'), M('D'), M('E'), M('F')}; switch (cmd) { case CHR_IOCTL_SERIAL_SET_TIOCM: @@ -171,11 +195,30 @@ static int msmouse_ioctl(Chardev *chr, int cmd, void *arg) if (MSMOUSE_PWR(mouse->tiocm)) { if (!MSMOUSE_PWR(c)) { /* - * Power on after reset: send "M3" - * cause we behave like a 3 button logitech - * mouse. + * Power on after reset: Send ID and PnP data + * No need to check fifo space as it is empty at this point. */ fifo8_push_all(&mouse->outbuf, mouse_id, sizeof(mouse_id)); + /* Add PnP data: */ + fifo8_push_all(&mouse->outbuf, pnp_data, sizeof(pnp_data)); + /* + * Add device description from qemu handler name. + * Make sure this all fits into the queue beforehand! + */ + c = M(')'); + for (i = 0; msmouse_handler.name[i]; i++) { + bytes[i] = M(msmouse_handler.name[i]); + c += bytes[i]; + } + /* Calc more of checksum */ + for (j = 0; j < sizeof(pnp_data); j++) { + c += pnp_data[j]; + } + c &= 0xff; + bytes[i++] = hexchr[c >> 4]; + bytes[i++] = hexchr[c & 0x0f]; + bytes[i++] = M(')'); + fifo8_push_all(&mouse->outbuf, bytes, i); /* Start sending data to serial. */ msmouse_chr_accept_input(chr); } @@ -208,13 +251,6 @@ static void char_msmouse_finalize(Object *obj) fifo8_destroy(&mouse->outbuf); } -static QemuInputHandler msmouse_handler = { - .name = "QEMU Microsoft Mouse", - .mask = INPUT_EVENT_MASK_BTN | INPUT_EVENT_MASK_REL, - .event = msmouse_input_event, - .sync = msmouse_input_sync, -}; - static void msmouse_chr_open(Chardev *chr, ChardevBackend *backend, bool *be_opened, From 769a726ccb9a8ab9b2a05bca648c79b3f80ab8de Mon Sep 17 00:00:00 2001 From: Arwed Meyer Date: Sun, 11 Sep 2022 20:18:40 +0200 Subject: [PATCH 0753/1020] serial: Allow unaligned i/o access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unaligned i/o access on serial UART works on real PCs. This is used for example by FreeDOS CTMouse driver. Without this it can't reset and detect serial mice. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/77 Signed-off-by: Arwed Meyer Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220911181840.8933-6-arwed.meyer@gmx.de> --- hw/char/serial.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/hw/char/serial.c b/hw/char/serial.c index 7061aacbce..41b5e61977 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -961,6 +961,9 @@ void serial_set_frequency(SerialState *s, uint32_t frequency) const MemoryRegionOps serial_io_ops = { .read = serial_ioport_read, .write = serial_ioport_write, + .valid = { + .unaligned = 1, + }, .impl = { .min_access_size = 1, .max_access_size = 1, From fc0c128531ed55f058bfbad4f1348ebd9a0187f2 Mon Sep 17 00:00:00 2001 From: Maksim Davydov Date: Thu, 25 Aug 2022 19:52:47 +0300 Subject: [PATCH 0754/1020] chardev: fix segfault in finalize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If finalize chardev-msmouse or chardev-wctable is called immediately after init it cases QEMU to crash with segfault. This happens because of QTAILQ_REMOVE in qemu_input_handler_unregister tries to dereference NULL pointer. For instance, this error can be reproduced via `qom-list-properties` command. Signed-off-by: Maksim Davydov Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220825165247.33704-1-davydov-max@yandex-team.ru> --- chardev/msmouse.c | 4 +++- chardev/wctablet.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/chardev/msmouse.c b/chardev/msmouse.c index 9006703023..ab8fe981d6 100644 --- a/chardev/msmouse.c +++ b/chardev/msmouse.c @@ -247,7 +247,9 @@ static void char_msmouse_finalize(Object *obj) { MouseChardev *mouse = MOUSE_CHARDEV(obj); - qemu_input_handler_unregister(mouse->hs); + if (mouse->hs) { + qemu_input_handler_unregister(mouse->hs); + } fifo8_destroy(&mouse->outbuf); } diff --git a/chardev/wctablet.c b/chardev/wctablet.c index e8b292c43c..43bdf6b608 100644 --- a/chardev/wctablet.c +++ b/chardev/wctablet.c @@ -319,7 +319,9 @@ static void wctablet_chr_finalize(Object *obj) { TabletChardev *tablet = WCTABLET_CHARDEV(obj); - qemu_input_handler_unregister(tablet->hs); + if (tablet->hs) { + qemu_input_handler_unregister(tablet->hs); + } } static void wctablet_chr_open(Chardev *chr, From 3c63b4e94a16db730a8185278479b592f7de8b7f Mon Sep 17 00:00:00 2001 From: Guoyi Tu Date: Tue, 23 Aug 2022 15:50:39 +0800 Subject: [PATCH 0755/1020] oslib-posix: Introduce qemu_socketpair() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qemu_socketpair() will create a pair of connected sockets with FD_CLOEXEC set Signed-off-by: Guoyi Tu Reviewed-by: Christian Schoenebeck Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <17fa1eff729eeabd9a001f4639abccb127ceec81.1661240709.git.tugy@chinatelecom.cn> --- include/qemu/sockets.h | 18 ++++++++++++++++++ util/oslib-posix.c | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/include/qemu/sockets.h b/include/qemu/sockets.h index 038faa157f..036745e586 100644 --- a/include/qemu/sockets.h +++ b/include/qemu/sockets.h @@ -14,6 +14,24 @@ int inet_aton(const char *cp, struct in_addr *ia); /* misc helpers */ bool fd_is_socket(int fd); int qemu_socket(int domain, int type, int protocol); + +#ifndef WIN32 +/** + * qemu_socketpair: + * @domain: specifies a communication domain, such as PF_UNIX + * @type: specifies the socket type. + * @protocol: specifies a particular protocol to be used with the socket + * @sv: an array to store the pair of socket created + * + * Creates an unnamed pair of connected sockets in the specified domain, + * of the specified type, and using the optionally specified protocol. + * And automatically set the close-on-exec flags on the returned sockets + * + * Return 0 on success. + */ +int qemu_socketpair(int domain, int type, int protocol, int sv[2]); +#endif + int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen); int socket_set_cork(int fd, int v); int socket_set_nodelay(int fd); diff --git a/util/oslib-posix.c b/util/oslib-posix.c index d55af69c11..827a7aadba 100644 --- a/util/oslib-posix.c +++ b/util/oslib-posix.c @@ -253,6 +253,25 @@ void qemu_set_cloexec(int fd) assert(f != -1); } +int qemu_socketpair(int domain, int type, int protocol, int sv[2]) +{ + int ret; + +#ifdef SOCK_CLOEXEC + ret = socketpair(domain, type | SOCK_CLOEXEC, protocol, sv); + if (ret != -1 || errno != EINVAL) { + return ret; + } +#endif + ret = socketpair(domain, type, protocol, sv);; + if (ret == 0) { + qemu_set_cloexec(sv[0]); + qemu_set_cloexec(sv[1]); + } + + return ret; +} + char * qemu_get_local_state_dir(void) { From 9cbda7b354389e536d546cc2091365bc402b3206 Mon Sep 17 00:00:00 2001 From: Guoyi Tu Date: Tue, 23 Aug 2022 15:50:40 +0800 Subject: [PATCH 0756/1020] vhost-user: Call qemu_socketpair() instead of socketpair() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As the close-on-exec flags is not set on the file descriptors returned by socketpair() at default, the fds will survive across exec' function. In the case that exec' function get invoked, such as the live-update feature which is been developing, it will cause fd leaks. To address this problem, we should call qemu_socketpair() to create an pair of connected sockets with the close-on-exec flag set. Signed-off-by: Guoyi Tu Reviewed-by: Christian Schoenebeck Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <7002b12a5fb0a30cd878e14e07da61c36da72913.1661240709.git.tugy@chinatelecom.cn> --- hw/display/vhost-user-gpu.c | 3 ++- hw/virtio/vhost-user.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/display/vhost-user-gpu.c b/hw/display/vhost-user-gpu.c index 3340ef9e5f..19c0e20103 100644 --- a/hw/display/vhost-user-gpu.c +++ b/hw/display/vhost-user-gpu.c @@ -11,6 +11,7 @@ */ #include "qemu/osdep.h" +#include "qemu/sockets.h" #include "hw/qdev-properties.h" #include "hw/virtio/virtio-gpu.h" #include "chardev/char-fe.h" @@ -375,7 +376,7 @@ vhost_user_gpu_do_set_socket(VhostUserGPU *g, Error **errp) Chardev *chr; int sv[2]; - if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { + if (qemu_socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { error_setg_errno(errp, errno, "socketpair() failed"); return false; } diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index bd24741be8..70748e61e0 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -1726,7 +1726,7 @@ static int vhost_setup_slave_channel(struct vhost_dev *dev) return 0; } - if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { + if (qemu_socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { int saved_errno = errno; error_report("socketpair() failed"); return -saved_errno; From 0e902f59c1f24f5779850d4ff6001c88bed2527c Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 27 Jul 2022 12:19:03 +0200 Subject: [PATCH 0757/1020] ui: fix path to dbus-display1.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the source directory is always included in the include path, the corresponding directory in the build tree is not. Therefore, custom_targets (e.g. ui/dbus-display1.h) must be referred to using the full path. This avoids a build failure when ui/dbus-chardev.c is not built as a module: In file included from ../ui/dbus-chardev.c:32: ../ui/dbus.h:34:10: fatal error: dbus-display1.h: No such file or directory 34 | #include "dbus-display1.h" | ^~~~~~~~~~~~~~~~~ Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Paolo Bonzini --- tests/qtest/dbus-display-test.c | 2 +- ui/dbus.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/qtest/dbus-display-test.c b/tests/qtest/dbus-display-test.c index 8be5974763..cb1b62d1d1 100644 --- a/tests/qtest/dbus-display-test.c +++ b/tests/qtest/dbus-display-test.c @@ -3,7 +3,7 @@ #include #include #include "libqtest.h" -#include "dbus-display1.h" +#include "ui/dbus-display1.h" static GDBusConnection* test_dbus_p2p_from_fd(int fd) diff --git a/ui/dbus.h b/ui/dbus.h index c001c11f70..9c149e7b41 100644 --- a/ui/dbus.h +++ b/ui/dbus.h @@ -31,7 +31,7 @@ #include "ui/console.h" #include "ui/clipboard.h" -#include "dbus-display1.h" +#include "ui/dbus-display1.h" typedef struct DBusClipboardRequest { GDBusMethodInvocation *invocation; From 7f4fbfb5dc08fe3fb6829bde8e4072d6cb214931 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 23 Sep 2022 13:34:10 +0100 Subject: [PATCH 0758/1020] target/arm: Mark registers which call pmu_op_start() as ARM_CP_IO In commit 01765386a888 we made some system register write functions call pmu_op_start()/pmu_op_finish(). This means that they now touch timers, so for icount to work these registers must have the ARM_CP_IO flag set. This fixes a bug where when icount is enabled a guest that touches MDCR_EL3, MDCR_EL2, PMCNTENSET_EL0 or PMCNTENCLR_EL0 would cause QEMU to print an error message and exit, for example: [ 2.495971] TCP: Hash tables configured (established 1024 bind 1024) [ 2.496213] UDP hash table entries: 256 (order: 1, 8192 bytes) [ 2.496386] UDP-Lite hash table entries: 256 (order: 1, 8192 bytes) [ 2.496917] NET: Registered protocol family 1 qemu-system-aarch64: Bad icount read Reported-by: Thomas Huth Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220923123412.1214041-2-peter.maydell@linaro.org --- target/arm/helper.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index b5dac651e7..fadeed0b6b 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1927,12 +1927,12 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { * or PL0_RO as appropriate and then check PMUSERENR in the helper fn. */ { .name = "PMCNTENSET", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 1, - .access = PL0_RW, .type = ARM_CP_ALIAS, + .access = PL0_RW, .type = ARM_CP_ALIAS | ARM_CP_IO, .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcnten), .writefn = pmcntenset_write, .accessfn = pmreg_access, .raw_writefn = raw_write }, - { .name = "PMCNTENSET_EL0", .state = ARM_CP_STATE_AA64, + { .name = "PMCNTENSET_EL0", .state = ARM_CP_STATE_AA64, .type = ARM_CP_IO, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 1, .access = PL0_RW, .accessfn = pmreg_access, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten), .resetvalue = 0, @@ -1942,11 +1942,11 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .fieldoffset = offsetoflow32(CPUARMState, cp15.c9_pmcnten), .accessfn = pmreg_access, .writefn = pmcntenclr_write, - .type = ARM_CP_ALIAS }, + .type = ARM_CP_ALIAS | ARM_CP_IO }, { .name = "PMCNTENCLR_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 9, .crm = 12, .opc2 = 2, .access = PL0_RW, .accessfn = pmreg_access, - .type = ARM_CP_ALIAS, + .type = ARM_CP_ALIAS | ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c9_pmcnten), .writefn = pmcntenclr_write }, { .name = "PMOVSR", .cp = 15, .crn = 9, .crm = 12, .opc1 = 0, .opc2 = 3, @@ -5125,7 +5125,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 3, .opc2 = 1, .resetvalue = 0, .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) }, - { .name = "SDCR", .type = ARM_CP_ALIAS, + { .name = "SDCR", .type = ARM_CP_ALIAS | ARM_CP_IO, .cp = 15, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 1, .access = PL1_RW, .accessfn = access_trap_aa32s_el1, .writefn = sdcr_write, @@ -7832,7 +7832,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) * value is MDCR_EL2.HPMN which should reset to the value of PMCR_EL0.N. */ ARMCPRegInfo mdcr_el2 = { - .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH, + .name = "MDCR_EL2", .state = ARM_CP_STATE_BOTH, .type = ARM_CP_IO, .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 1, .writefn = mdcr_el2_write, .access = PL2_RW, .resetvalue = pmu_num_counters(env), From 80d2b43b2ff367f38ae4c9616b1ed261ecf801b6 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 23 Sep 2022 13:34:11 +0100 Subject: [PATCH 0759/1020] target/arm: Make writes to MDCR_EL3 use PMU start/finish calls In commit 01765386a88868 we fixed a bug where we weren't correctly bracketing changes to some registers with pmu_op_start() and pmu_op_finish() calls for changes which affect whether the PMU counters might be enabled. However, we missed the case of writes to the AArch64 MDCR_EL3 register, because (unlike its AArch32 counterpart) they are currently done directly to the CPU state struct without going through the sdcr_write() function. Give MDCR_EL3 a writefn which handles the PMU start/finish calls. The SDCR writefn then simplfies to "call the MDCR_EL3 writefn after masking off the bits which don't exist in the AArch32 register". Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220923123412.1214041-3-peter.maydell@linaro.org --- target/arm/helper.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index fadeed0b6b..24c592ffef 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -4756,8 +4756,8 @@ static void sctlr_write(CPUARMState *env, const ARMCPRegInfo *ri, } } -static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri, - uint64_t value) +static void mdcr_el3_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) { /* * Some MDCR_EL3 bits affect whether PMU counters are running: @@ -4769,12 +4769,19 @@ static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri, if (pmu_op) { pmu_op_start(env); } - env->cp15.mdcr_el3 = value & SDCR_VALID_MASK; + env->cp15.mdcr_el3 = value; if (pmu_op) { pmu_op_finish(env); } } +static void sdcr_write(CPUARMState *env, const ARMCPRegInfo *ri, + uint64_t value) +{ + /* Not all bits defined for MDCR_EL3 exist in the AArch32 SDCR */ + mdcr_el3_write(env, ri, value & SDCR_VALID_MASK); +} + static void mdcr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { @@ -5122,9 +5129,12 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_FIQ]) }, { .name = "MDCR_EL3", .state = ARM_CP_STATE_AA64, + .type = ARM_CP_IO, .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 3, .opc2 = 1, .resetvalue = 0, - .access = PL3_RW, .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) }, + .access = PL3_RW, + .writefn = mdcr_el3_write, + .fieldoffset = offsetof(CPUARMState, cp15.mdcr_el3) }, { .name = "SDCR", .type = ARM_CP_ALIAS | ARM_CP_IO, .cp = 15, .opc1 = 0, .crn = 1, .crm = 3, .opc2 = 1, .access = PL1_RW, .accessfn = access_trap_aa32s_el1, From f190bd1da1c291bb1dac9a715e02ef2521698d16 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 23 Sep 2022 13:34:12 +0100 Subject: [PATCH 0760/1020] target/arm: Update SDCR_VALID_MASK to include SCCD Our SDCR_VALID_MASK doesn't include all of the bits which are defined by the current architecture. In particular in commit 0b42f4fab9d3 we forgot to add SCCD, which meant that an AArch32 guest couldn't actually use the SCCD bit to disable counting in Secure state. Add all the currently defined bits; we don't implement all of them, but this makes them be reads-as-written, which is architecturally valid and matches how we currently handle most of the others in the mask. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20220923123412.1214041-4-peter.maydell@linaro.org --- target/arm/cpu.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 33cdbc0143..429ed42eec 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1334,11 +1334,15 @@ FIELD(CPTR_EL3, TTA, 20, 1) FIELD(CPTR_EL3, TAM, 30, 1) FIELD(CPTR_EL3, TCPAC, 31, 1) +#define MDCR_MTPME (1U << 28) +#define MDCR_TDCC (1U << 27) #define MDCR_HLP (1U << 26) /* MDCR_EL2 */ #define MDCR_SCCD (1U << 23) /* MDCR_EL3 */ #define MDCR_HCCD (1U << 23) /* MDCR_EL2 */ #define MDCR_EPMAD (1U << 21) #define MDCR_EDAD (1U << 20) +#define MDCR_TTRF (1U << 19) +#define MDCR_STE (1U << 18) /* MDCR_EL3 */ #define MDCR_SPME (1U << 17) /* MDCR_EL3 */ #define MDCR_HPMD (1U << 17) /* MDCR_EL2 */ #define MDCR_SDD (1U << 16) @@ -1353,7 +1357,9 @@ FIELD(CPTR_EL3, TCPAC, 31, 1) #define MDCR_HPMN (0x1fU) /* Not all of the MDCR_EL3 bits are present in the 32-bit SDCR */ -#define SDCR_VALID_MASK (MDCR_EPMAD | MDCR_EDAD | MDCR_SPME | MDCR_SPD) +#define SDCR_VALID_MASK (MDCR_MTPME | MDCR_TDCC | MDCR_SCCD | \ + MDCR_EPMAD | MDCR_EDAD | MDCR_TTRF | \ + MDCR_STE | MDCR_SPME | MDCR_SPD) #define CPSR_M (0x1fU) #define CPSR_T (1U << 5) From 042e85d14c0f7cf3adf9ce67dd45b311378e67fa Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 12 Aug 2022 18:41:56 +0100 Subject: [PATCH 0761/1020] target/arm: Rearrange cpu64.c so all the CPU initfns are together MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cpu64.c has ended up in a slightly odd order -- it starts with the initfns for most of the models-real-hardware CPUs; after that comes a bunch of support code for SVE, SME, pauth and LPA2 properties. Then come the initfns for the 'host' and 'max' CPU types, and then after that one more models-real-hardware CPU initfn, for a64fx. (This ordering is partly historical and partly required because a64fx needs the SVE properties.) Reorder the file into: * CPU property support functions * initfns for real hardware CPUs * initfns for host and max * class boilerplate Signed-off-by: Peter Maydell Reviewed-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson --- target/arm/cpu64.c | 712 ++++++++++++++++++++++----------------------- 1 file changed, 356 insertions(+), 356 deletions(-) diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c index e6314e86d2..85e0d1daf1 100644 --- a/target/arm/cpu64.c +++ b/target/arm/cpu64.c @@ -116,313 +116,6 @@ static void aarch64_a35_initfn(Object *obj) define_cortex_a72_a57_a53_cp_reginfo(cpu); } -static void aarch64_a57_initfn(Object *obj) -{ - ARMCPU *cpu = ARM_CPU(obj); - - cpu->dtb_compatible = "arm,cortex-a57"; - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_NEON); - set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); - set_feature(&cpu->env, ARM_FEATURE_AARCH64); - set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); - set_feature(&cpu->env, ARM_FEATURE_EL2); - set_feature(&cpu->env, ARM_FEATURE_EL3); - set_feature(&cpu->env, ARM_FEATURE_PMU); - cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57; - cpu->midr = 0x411fd070; - cpu->revidr = 0x00000000; - cpu->reset_fpsid = 0x41034070; - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x12111111; - cpu->isar.mvfr2 = 0x00000043; - cpu->ctr = 0x8444c004; - cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10101105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_isar6 = 0; - cpu->isar.id_aa64pfr0 = 0x00002222; - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; - cpu->isar.dbgdidr = 0x3516d000; - cpu->isar.dbgdevid = 0x01110f13; - cpu->isar.dbgdevid1 = 0x2; - cpu->isar.reset_pmcr_el0 = 0x41013000; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ - cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */ - cpu->dcz_blocksize = 4; /* 64 bytes */ - cpu->gic_num_lrs = 4; - cpu->gic_vpribits = 5; - cpu->gic_vprebits = 5; - cpu->gic_pribits = 5; - define_cortex_a72_a57_a53_cp_reginfo(cpu); -} - -static void aarch64_a53_initfn(Object *obj) -{ - ARMCPU *cpu = ARM_CPU(obj); - - cpu->dtb_compatible = "arm,cortex-a53"; - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_NEON); - set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); - set_feature(&cpu->env, ARM_FEATURE_AARCH64); - set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); - set_feature(&cpu->env, ARM_FEATURE_EL2); - set_feature(&cpu->env, ARM_FEATURE_EL3); - set_feature(&cpu->env, ARM_FEATURE_PMU); - cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A53; - cpu->midr = 0x410fd034; - cpu->revidr = 0x00000000; - cpu->reset_fpsid = 0x41034070; - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x12111111; - cpu->isar.mvfr2 = 0x00000043; - cpu->ctr = 0x84448004; /* L1Ip = VIPT */ - cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10101105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_isar6 = 0; - cpu->isar.id_aa64pfr0 = 0x00002222; - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ - cpu->isar.dbgdidr = 0x3516d000; - cpu->isar.dbgdevid = 0x00110f13; - cpu->isar.dbgdevid1 = 0x1; - cpu->isar.reset_pmcr_el0 = 0x41033000; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ - cpu->ccsidr[2] = 0x707fe07a; /* 1024KB L2 cache */ - cpu->dcz_blocksize = 4; /* 64 bytes */ - cpu->gic_num_lrs = 4; - cpu->gic_vpribits = 5; - cpu->gic_vprebits = 5; - cpu->gic_pribits = 5; - define_cortex_a72_a57_a53_cp_reginfo(cpu); -} - -static void aarch64_a72_initfn(Object *obj) -{ - ARMCPU *cpu = ARM_CPU(obj); - - cpu->dtb_compatible = "arm,cortex-a72"; - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_NEON); - set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); - set_feature(&cpu->env, ARM_FEATURE_AARCH64); - set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); - set_feature(&cpu->env, ARM_FEATURE_EL2); - set_feature(&cpu->env, ARM_FEATURE_EL3); - set_feature(&cpu->env, ARM_FEATURE_PMU); - cpu->midr = 0x410fd083; - cpu->revidr = 0x00000000; - cpu->reset_fpsid = 0x41034080; - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x12111111; - cpu->isar.mvfr2 = 0x00000043; - cpu->ctr = 0x8444c004; - cpu->reset_sctlr = 0x00c50838; - cpu->isar.id_pfr0 = 0x00000131; - cpu->isar.id_pfr1 = 0x00011011; - cpu->isar.id_dfr0 = 0x03010066; - cpu->id_afr0 = 0x00000000; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02102211; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00011142; - cpu->isar.id_isar5 = 0x00011121; - cpu->isar.id_aa64pfr0 = 0x00002222; - cpu->isar.id_aa64dfr0 = 0x10305106; - cpu->isar.id_aa64isar0 = 0x00011120; - cpu->isar.id_aa64mmfr0 = 0x00001124; - cpu->isar.dbgdidr = 0x3516d000; - cpu->isar.dbgdevid = 0x01110f13; - cpu->isar.dbgdevid1 = 0x2; - cpu->isar.reset_pmcr_el0 = 0x41023000; - cpu->clidr = 0x0a200023; - cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ - cpu->ccsidr[2] = 0x707fe07a; /* 1MB L2 cache */ - cpu->dcz_blocksize = 4; /* 64 bytes */ - cpu->gic_num_lrs = 4; - cpu->gic_vpribits = 5; - cpu->gic_vprebits = 5; - cpu->gic_pribits = 5; - define_cortex_a72_a57_a53_cp_reginfo(cpu); -} - -static void aarch64_a76_initfn(Object *obj) -{ - ARMCPU *cpu = ARM_CPU(obj); - - cpu->dtb_compatible = "arm,cortex-a76"; - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_NEON); - set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); - set_feature(&cpu->env, ARM_FEATURE_AARCH64); - set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); - set_feature(&cpu->env, ARM_FEATURE_EL2); - set_feature(&cpu->env, ARM_FEATURE_EL3); - set_feature(&cpu->env, ARM_FEATURE_PMU); - - /* Ordered by B2.4 AArch64 registers by functional group */ - cpu->clidr = 0x82000023; - cpu->ctr = 0x8444C004; - cpu->dcz_blocksize = 4; - cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; - cpu->isar.id_aa64isar0 = 0x0000100010211120ull; - cpu->isar.id_aa64isar1 = 0x0000000000100001ull; - cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; - cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; - cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; - cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ - cpu->isar.id_aa64pfr1 = 0x0000000000000010ull; - cpu->id_afr0 = 0x00000000; - cpu->isar.id_dfr0 = 0x04010088; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00010142; - cpu->isar.id_isar5 = 0x01011121; - cpu->isar.id_isar6 = 0x00000010; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02122211; - cpu->isar.id_mmfr4 = 0x00021110; - cpu->isar.id_pfr0 = 0x10010131; - cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ - cpu->isar.id_pfr2 = 0x00000011; - cpu->midr = 0x414fd0b1; /* r4p1 */ - cpu->revidr = 0; - - /* From B2.18 CCSIDR_EL1 */ - cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */ - cpu->ccsidr[2] = 0x707fe03a; /* 512KB L2 cache */ - - /* From B2.93 SCTLR_EL3 */ - cpu->reset_sctlr = 0x30c50838; - - /* From B4.23 ICH_VTR_EL2 */ - cpu->gic_num_lrs = 4; - cpu->gic_vpribits = 5; - cpu->gic_vprebits = 5; - cpu->gic_pribits = 5; - - /* From B5.1 AdvSIMD AArch64 register summary */ - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x13211111; - cpu->isar.mvfr2 = 0x00000043; - - /* From D5.1 AArch64 PMU register summary */ - cpu->isar.reset_pmcr_el0 = 0x410b3000; -} - -static void aarch64_neoverse_n1_initfn(Object *obj) -{ - ARMCPU *cpu = ARM_CPU(obj); - - cpu->dtb_compatible = "arm,neoverse-n1"; - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_NEON); - set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); - set_feature(&cpu->env, ARM_FEATURE_AARCH64); - set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); - set_feature(&cpu->env, ARM_FEATURE_EL2); - set_feature(&cpu->env, ARM_FEATURE_EL3); - set_feature(&cpu->env, ARM_FEATURE_PMU); - - /* Ordered by B2.4 AArch64 registers by functional group */ - cpu->clidr = 0x82000023; - cpu->ctr = 0x8444c004; - cpu->dcz_blocksize = 4; - cpu->isar.id_aa64dfr0 = 0x0000000110305408ull; - cpu->isar.id_aa64isar0 = 0x0000100010211120ull; - cpu->isar.id_aa64isar1 = 0x0000000000100001ull; - cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; - cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; - cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; - cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ - cpu->isar.id_aa64pfr1 = 0x0000000000000020ull; - cpu->id_afr0 = 0x00000000; - cpu->isar.id_dfr0 = 0x04010088; - cpu->isar.id_isar0 = 0x02101110; - cpu->isar.id_isar1 = 0x13112111; - cpu->isar.id_isar2 = 0x21232042; - cpu->isar.id_isar3 = 0x01112131; - cpu->isar.id_isar4 = 0x00010142; - cpu->isar.id_isar5 = 0x01011121; - cpu->isar.id_isar6 = 0x00000010; - cpu->isar.id_mmfr0 = 0x10201105; - cpu->isar.id_mmfr1 = 0x40000000; - cpu->isar.id_mmfr2 = 0x01260000; - cpu->isar.id_mmfr3 = 0x02122211; - cpu->isar.id_mmfr4 = 0x00021110; - cpu->isar.id_pfr0 = 0x10010131; - cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ - cpu->isar.id_pfr2 = 0x00000011; - cpu->midr = 0x414fd0c1; /* r4p1 */ - cpu->revidr = 0; - - /* From B2.23 CCSIDR_EL1 */ - cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */ - cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */ - cpu->ccsidr[2] = 0x70ffe03a; /* 1MB L2 cache */ - - /* From B2.98 SCTLR_EL3 */ - cpu->reset_sctlr = 0x30c50838; - - /* From B4.23 ICH_VTR_EL2 */ - cpu->gic_num_lrs = 4; - cpu->gic_vpribits = 5; - cpu->gic_vprebits = 5; - cpu->gic_pribits = 5; - - /* From B5.1 AdvSIMD AArch64 register summary */ - cpu->isar.mvfr0 = 0x10110222; - cpu->isar.mvfr1 = 0x13211111; - cpu->isar.mvfr2 = 0x00000043; - - /* From D5.1 AArch64 PMU register summary */ - cpu->isar.reset_pmcr_el0 = 0x410c3000; -} - void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp) { /* @@ -985,6 +678,362 @@ void arm_cpu_lpa2_finalize(ARMCPU *cpu, Error **errp) cpu->isar.id_aa64mmfr0 = t; } +static void aarch64_a57_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + cpu->dtb_compatible = "arm,cortex-a57"; + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); + set_feature(&cpu->env, ARM_FEATURE_EL2); + set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); + cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A57; + cpu->midr = 0x411fd070; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034070; + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x12111111; + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; + cpu->isar.id_isar0 = 0x02101110; + cpu->isar.id_isar1 = 0x13112111; + cpu->isar.id_isar2 = 0x21232042; + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_isar6 = 0; + cpu->isar.id_aa64pfr0 = 0x00002222; + cpu->isar.id_aa64dfr0 = 0x10305106; + cpu->isar.id_aa64isar0 = 0x00011120; + cpu->isar.id_aa64mmfr0 = 0x00001124; + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x01110f13; + cpu->isar.dbgdevid1 = 0x2; + cpu->isar.reset_pmcr_el0 = 0x41013000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ + cpu->ccsidr[2] = 0x70ffe07a; /* 2048KB L2 cache */ + cpu->dcz_blocksize = 4; /* 64 bytes */ + cpu->gic_num_lrs = 4; + cpu->gic_vpribits = 5; + cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; + define_cortex_a72_a57_a53_cp_reginfo(cpu); +} + +static void aarch64_a53_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + cpu->dtb_compatible = "arm,cortex-a53"; + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); + set_feature(&cpu->env, ARM_FEATURE_EL2); + set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); + cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A53; + cpu->midr = 0x410fd034; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034070; + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x12111111; + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x84448004; /* L1Ip = VIPT */ + cpu->reset_sctlr = 0x00c50838; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10101105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; + cpu->isar.id_isar0 = 0x02101110; + cpu->isar.id_isar1 = 0x13112111; + cpu->isar.id_isar2 = 0x21232042; + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_isar6 = 0; + cpu->isar.id_aa64pfr0 = 0x00002222; + cpu->isar.id_aa64dfr0 = 0x10305106; + cpu->isar.id_aa64isar0 = 0x00011120; + cpu->isar.id_aa64mmfr0 = 0x00001122; /* 40 bit physical addr */ + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x00110f13; + cpu->isar.dbgdevid1 = 0x1; + cpu->isar.reset_pmcr_el0 = 0x41033000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x700fe01a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe00a; /* 32KB L1 icache */ + cpu->ccsidr[2] = 0x707fe07a; /* 1024KB L2 cache */ + cpu->dcz_blocksize = 4; /* 64 bytes */ + cpu->gic_num_lrs = 4; + cpu->gic_vpribits = 5; + cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; + define_cortex_a72_a57_a53_cp_reginfo(cpu); +} + +static void aarch64_a72_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + cpu->dtb_compatible = "arm,cortex-a72"; + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); + set_feature(&cpu->env, ARM_FEATURE_EL2); + set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); + cpu->midr = 0x410fd083; + cpu->revidr = 0x00000000; + cpu->reset_fpsid = 0x41034080; + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x12111111; + cpu->isar.mvfr2 = 0x00000043; + cpu->ctr = 0x8444c004; + cpu->reset_sctlr = 0x00c50838; + cpu->isar.id_pfr0 = 0x00000131; + cpu->isar.id_pfr1 = 0x00011011; + cpu->isar.id_dfr0 = 0x03010066; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02102211; + cpu->isar.id_isar0 = 0x02101110; + cpu->isar.id_isar1 = 0x13112111; + cpu->isar.id_isar2 = 0x21232042; + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00011142; + cpu->isar.id_isar5 = 0x00011121; + cpu->isar.id_aa64pfr0 = 0x00002222; + cpu->isar.id_aa64dfr0 = 0x10305106; + cpu->isar.id_aa64isar0 = 0x00011120; + cpu->isar.id_aa64mmfr0 = 0x00001124; + cpu->isar.dbgdidr = 0x3516d000; + cpu->isar.dbgdevid = 0x01110f13; + cpu->isar.dbgdevid1 = 0x2; + cpu->isar.reset_pmcr_el0 = 0x41023000; + cpu->clidr = 0x0a200023; + cpu->ccsidr[0] = 0x701fe00a; /* 32KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe012; /* 48KB L1 icache */ + cpu->ccsidr[2] = 0x707fe07a; /* 1MB L2 cache */ + cpu->dcz_blocksize = 4; /* 64 bytes */ + cpu->gic_num_lrs = 4; + cpu->gic_vpribits = 5; + cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; + define_cortex_a72_a57_a53_cp_reginfo(cpu); +} + +static void aarch64_a76_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + cpu->dtb_compatible = "arm,cortex-a76"; + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); + set_feature(&cpu->env, ARM_FEATURE_EL2); + set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); + + /* Ordered by B2.4 AArch64 registers by functional group */ + cpu->clidr = 0x82000023; + cpu->ctr = 0x8444C004; + cpu->dcz_blocksize = 4; + cpu->isar.id_aa64dfr0 = 0x0000000010305408ull; + cpu->isar.id_aa64isar0 = 0x0000100010211120ull; + cpu->isar.id_aa64isar1 = 0x0000000000100001ull; + cpu->isar.id_aa64mmfr0 = 0x0000000000101122ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; + cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ + cpu->isar.id_aa64pfr1 = 0x0000000000000010ull; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x04010088; + cpu->isar.id_isar0 = 0x02101110; + cpu->isar.id_isar1 = 0x13112111; + cpu->isar.id_isar2 = 0x21232042; + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00010142; + cpu->isar.id_isar5 = 0x01011121; + cpu->isar.id_isar6 = 0x00000010; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; + cpu->isar.id_mmfr4 = 0x00021110; + cpu->isar.id_pfr0 = 0x10010131; + cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ + cpu->isar.id_pfr2 = 0x00000011; + cpu->midr = 0x414fd0b1; /* r4p1 */ + cpu->revidr = 0; + + /* From B2.18 CCSIDR_EL1 */ + cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */ + cpu->ccsidr[2] = 0x707fe03a; /* 512KB L2 cache */ + + /* From B2.93 SCTLR_EL3 */ + cpu->reset_sctlr = 0x30c50838; + + /* From B4.23 ICH_VTR_EL2 */ + cpu->gic_num_lrs = 4; + cpu->gic_vpribits = 5; + cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; + + /* From B5.1 AdvSIMD AArch64 register summary */ + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; + + /* From D5.1 AArch64 PMU register summary */ + cpu->isar.reset_pmcr_el0 = 0x410b3000; +} + +static void aarch64_a64fx_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + cpu->dtb_compatible = "arm,a64fx"; + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_EL2); + set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); + cpu->midr = 0x461f0010; + cpu->revidr = 0x00000000; + cpu->ctr = 0x86668006; + cpu->reset_sctlr = 0x30000180; + cpu->isar.id_aa64pfr0 = 0x0000000101111111; /* No RAS Extensions */ + cpu->isar.id_aa64pfr1 = 0x0000000000000000; + cpu->isar.id_aa64dfr0 = 0x0000000010305408; + cpu->isar.id_aa64dfr1 = 0x0000000000000000; + cpu->id_aa64afr0 = 0x0000000000000000; + cpu->id_aa64afr1 = 0x0000000000000000; + cpu->isar.id_aa64mmfr0 = 0x0000000000001122; + cpu->isar.id_aa64mmfr1 = 0x0000000011212100; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011; + cpu->isar.id_aa64isar0 = 0x0000000010211120; + cpu->isar.id_aa64isar1 = 0x0000000000010001; + cpu->isar.id_aa64zfr0 = 0x0000000000000000; + cpu->clidr = 0x0000000080000023; + cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ + cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */ + cpu->ccsidr[2] = 0x70ffe07c; /* 8MB L2 cache */ + cpu->dcz_blocksize = 6; /* 256 bytes */ + cpu->gic_num_lrs = 4; + cpu->gic_vpribits = 5; + cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; + + /* The A64FX supports only 128, 256 and 512 bit vector lengths */ + aarch64_add_sve_properties(obj); + cpu->sve_vq.supported = (1 << 0) /* 128bit */ + | (1 << 1) /* 256bit */ + | (1 << 3); /* 512bit */ + + cpu->isar.reset_pmcr_el0 = 0x46014040; + + /* TODO: Add A64FX specific HPC extension registers */ +} + +static void aarch64_neoverse_n1_initfn(Object *obj) +{ + ARMCPU *cpu = ARM_CPU(obj); + + cpu->dtb_compatible = "arm,neoverse-n1"; + set_feature(&cpu->env, ARM_FEATURE_V8); + set_feature(&cpu->env, ARM_FEATURE_NEON); + set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); + set_feature(&cpu->env, ARM_FEATURE_AARCH64); + set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); + set_feature(&cpu->env, ARM_FEATURE_EL2); + set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); + + /* Ordered by B2.4 AArch64 registers by functional group */ + cpu->clidr = 0x82000023; + cpu->ctr = 0x8444c004; + cpu->dcz_blocksize = 4; + cpu->isar.id_aa64dfr0 = 0x0000000110305408ull; + cpu->isar.id_aa64isar0 = 0x0000100010211120ull; + cpu->isar.id_aa64isar1 = 0x0000000000100001ull; + cpu->isar.id_aa64mmfr0 = 0x0000000000101125ull; + cpu->isar.id_aa64mmfr1 = 0x0000000010212122ull; + cpu->isar.id_aa64mmfr2 = 0x0000000000001011ull; + cpu->isar.id_aa64pfr0 = 0x1100000010111112ull; /* GIC filled in later */ + cpu->isar.id_aa64pfr1 = 0x0000000000000020ull; + cpu->id_afr0 = 0x00000000; + cpu->isar.id_dfr0 = 0x04010088; + cpu->isar.id_isar0 = 0x02101110; + cpu->isar.id_isar1 = 0x13112111; + cpu->isar.id_isar2 = 0x21232042; + cpu->isar.id_isar3 = 0x01112131; + cpu->isar.id_isar4 = 0x00010142; + cpu->isar.id_isar5 = 0x01011121; + cpu->isar.id_isar6 = 0x00000010; + cpu->isar.id_mmfr0 = 0x10201105; + cpu->isar.id_mmfr1 = 0x40000000; + cpu->isar.id_mmfr2 = 0x01260000; + cpu->isar.id_mmfr3 = 0x02122211; + cpu->isar.id_mmfr4 = 0x00021110; + cpu->isar.id_pfr0 = 0x10010131; + cpu->isar.id_pfr1 = 0x00010000; /* GIC filled in later */ + cpu->isar.id_pfr2 = 0x00000011; + cpu->midr = 0x414fd0c1; /* r4p1 */ + cpu->revidr = 0; + + /* From B2.23 CCSIDR_EL1 */ + cpu->ccsidr[0] = 0x701fe01a; /* 64KB L1 dcache */ + cpu->ccsidr[1] = 0x201fe01a; /* 64KB L1 icache */ + cpu->ccsidr[2] = 0x70ffe03a; /* 1MB L2 cache */ + + /* From B2.98 SCTLR_EL3 */ + cpu->reset_sctlr = 0x30c50838; + + /* From B4.23 ICH_VTR_EL2 */ + cpu->gic_num_lrs = 4; + cpu->gic_vpribits = 5; + cpu->gic_vprebits = 5; + cpu->gic_pribits = 5; + + /* From B5.1 AdvSIMD AArch64 register summary */ + cpu->isar.mvfr0 = 0x10110222; + cpu->isar.mvfr1 = 0x13211111; + cpu->isar.mvfr2 = 0x00000043; + + /* From D5.1 AArch64 PMU register summary */ + cpu->isar.reset_pmcr_el0 = 0x410c3000; +} + static void aarch64_host_initfn(Object *obj) { #if defined(CONFIG_KVM) @@ -1188,55 +1237,6 @@ static void aarch64_max_initfn(Object *obj) qdev_property_add_static(DEVICE(obj), &arm_cpu_lpa2_property); } -static void aarch64_a64fx_initfn(Object *obj) -{ - ARMCPU *cpu = ARM_CPU(obj); - - cpu->dtb_compatible = "arm,a64fx"; - set_feature(&cpu->env, ARM_FEATURE_V8); - set_feature(&cpu->env, ARM_FEATURE_NEON); - set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER); - set_feature(&cpu->env, ARM_FEATURE_AARCH64); - set_feature(&cpu->env, ARM_FEATURE_EL2); - set_feature(&cpu->env, ARM_FEATURE_EL3); - set_feature(&cpu->env, ARM_FEATURE_PMU); - cpu->midr = 0x461f0010; - cpu->revidr = 0x00000000; - cpu->ctr = 0x86668006; - cpu->reset_sctlr = 0x30000180; - cpu->isar.id_aa64pfr0 = 0x0000000101111111; /* No RAS Extensions */ - cpu->isar.id_aa64pfr1 = 0x0000000000000000; - cpu->isar.id_aa64dfr0 = 0x0000000010305408; - cpu->isar.id_aa64dfr1 = 0x0000000000000000; - cpu->id_aa64afr0 = 0x0000000000000000; - cpu->id_aa64afr1 = 0x0000000000000000; - cpu->isar.id_aa64mmfr0 = 0x0000000000001122; - cpu->isar.id_aa64mmfr1 = 0x0000000011212100; - cpu->isar.id_aa64mmfr2 = 0x0000000000001011; - cpu->isar.id_aa64isar0 = 0x0000000010211120; - cpu->isar.id_aa64isar1 = 0x0000000000010001; - cpu->isar.id_aa64zfr0 = 0x0000000000000000; - cpu->clidr = 0x0000000080000023; - cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */ - cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */ - cpu->ccsidr[2] = 0x70ffe07c; /* 8MB L2 cache */ - cpu->dcz_blocksize = 6; /* 256 bytes */ - cpu->gic_num_lrs = 4; - cpu->gic_vpribits = 5; - cpu->gic_vprebits = 5; - cpu->gic_pribits = 5; - - /* The A64FX supports only 128, 256 and 512 bit vector lengths */ - aarch64_add_sve_properties(obj); - cpu->sve_vq.supported = (1 << 0) /* 128bit */ - | (1 << 1) /* 256bit */ - | (1 << 3); /* 512bit */ - - cpu->isar.reset_pmcr_el0 = 0x46014040; - - /* TODO: Add A64FX specific HPC extension registers */ -} - static const ARMCPUInfo aarch64_cpus[] = { { .name = "cortex-a35", .initfn = aarch64_a35_initfn }, { .name = "cortex-a57", .initfn = aarch64_a57_initfn }, From acc0b8b05af518586d86c1fab96d88cbbe77b2ec Mon Sep 17 00:00:00 2001 From: Francisco Iglesias Date: Tue, 20 Sep 2022 10:15:17 +0200 Subject: [PATCH 0762/1020] hw/arm/xlnx-zynqmp: Connect ZynqMP's USB controllers Connect ZynqMP's USB controllers. Signed-off-by: Francisco Iglesias Acked-by: Alistair Francis Message-id: 20220920081517.25401-1-frasse.iglesias@gmail.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/xlnx-zynqmp.c | 36 ++++++++++++++++++++++++++++++++++++ include/hw/arm/xlnx-zynqmp.h | 3 +++ 2 files changed, 39 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index 383e177a00..335cfc417d 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -143,6 +143,14 @@ static const int adma_ch_intr[XLNX_ZYNQMP_NUM_ADMA_CH] = { 77, 78, 79, 80, 81, 82, 83, 84 }; +static const uint64_t usb_addr[XLNX_ZYNQMP_NUM_USB] = { + 0xFE200000, 0xFE300000 +}; + +static const int usb_intr[XLNX_ZYNQMP_NUM_USB] = { + 65, 70 +}; + typedef struct XlnxZynqMPGICRegion { int region_index; uint32_t address; @@ -428,6 +436,10 @@ static void xlnx_zynqmp_init(Object *obj) object_initialize_child(obj, "qspi-dma", &s->qspi_dma, TYPE_XLNX_CSU_DMA); object_initialize_child(obj, "qspi-irq-orgate", &s->qspi_irq_orgate, TYPE_OR_IRQ); + + for (i = 0; i < XLNX_ZYNQMP_NUM_USB; i++) { + object_initialize_child(obj, "usb[*]", &s->usb[i], TYPE_USB_DWC3); + } } static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) @@ -814,6 +826,30 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) object_property_add_alias(OBJECT(s), bus_name, OBJECT(&s->qspi), target_bus); } + + for (i = 0; i < XLNX_ZYNQMP_NUM_USB; i++) { + if (!object_property_set_link(OBJECT(&s->usb[i].sysbus_xhci), "dma", + OBJECT(system_memory), errp)) { + return; + } + + qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "intrs", 4); + qdev_prop_set_uint32(DEVICE(&s->usb[i].sysbus_xhci), "slots", 2); + + if (!sysbus_realize(SYS_BUS_DEVICE(&s->usb[i]), errp)) { + return; + } + + sysbus_mmio_map(SYS_BUS_DEVICE(&s->usb[i]), 0, usb_addr[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 0, + gic_spi[usb_intr[i]]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 1, + gic_spi[usb_intr[i] + 1]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 2, + gic_spi[usb_intr[i] + 2]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb[i].sysbus_xhci), 3, + gic_spi[usb_intr[i] + 3]); + } } static Property xlnx_zynqmp_props[] = { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 85fd9f53da..20bdf894aa 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -42,6 +42,7 @@ #include "hw/misc/xlnx-zynqmp-apu-ctrl.h" #include "hw/misc/xlnx-zynqmp-crf.h" #include "hw/timer/cadence_ttc.h" +#include "hw/usb/hcd-dwc3.h" #define TYPE_XLNX_ZYNQMP "xlnx-zynqmp" OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) @@ -56,6 +57,7 @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP) #define XLNX_ZYNQMP_NUM_SPIS 2 #define XLNX_ZYNQMP_NUM_GDMA_CH 8 #define XLNX_ZYNQMP_NUM_ADMA_CH 8 +#define XLNX_ZYNQMP_NUM_USB 2 #define XLNX_ZYNQMP_NUM_QSPI_BUS 2 #define XLNX_ZYNQMP_NUM_QSPI_BUS_CS 2 @@ -132,6 +134,7 @@ struct XlnxZynqMPState { XlnxZynqMPAPUCtrl apu_ctrl; XlnxZynqMPCRF crf; CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC]; + USBDWC3 usb[XLNX_ZYNQMP_NUM_USB]; char *boot_cpu; ARMCPU *boot_cpu_ptr; From 5f1d731c08d86528bafce1d7bfe8b359bcbaeabf Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Tue, 27 Sep 2022 11:03:42 +0100 Subject: [PATCH 0763/1020] hw/arm/virt: Fix devicetree warning about the root node The devicetree specification requires a 'model' property in the root node. Fix the corresponding dt-validate warning: /: 'model' is a required property From schema: dtschema/schemas/root-node.yaml Use the same name for model as for compatible. The specification recommends that 'compatible' follows the format 'manufacturer,model' and 'model' follows the format 'manufacturer,model-number'. Since our 'compatible' doesn't observe this, 'model' doesn't really need to either. Signed-off-by: Jean-Philippe Brucker Reviewed-by: Peter Maydell Reviewed-by: Eric Auger Message-id: 20220927100347.176606-2-jean-philippe@linaro.org Signed-off-by: Peter Maydell --- hw/arm/virt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 0961e053e5..f4ee71cda1 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -253,6 +253,7 @@ static void create_fdt(VirtMachineState *vms) qemu_fdt_setprop_string(fdt, "/", "compatible", "linux,dummy-virt"); qemu_fdt_setprop_cell(fdt, "/", "#address-cells", 0x2); qemu_fdt_setprop_cell(fdt, "/", "#size-cells", 0x2); + qemu_fdt_setprop_string(fdt, "/", "model", "linux,dummy-virt"); /* /chosen must exist for load_dtb to fill in necessary properties later */ qemu_fdt_add_subnode(fdt, "/chosen"); From a312a530076cb24414f193d3e6279b882a8288ff Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Tue, 27 Sep 2022 11:03:43 +0100 Subject: [PATCH 0764/1020] hw/arm/virt: Fix devicetree warning about the GIC node The GICv3 bindings requires a #msi-cells property for the ITS node. Fix the corresponding dt-validate warning: interrupt-controller@8000000: msi-controller@8080000: '#msi-cells' is a required property From schema: linux/Documentation/devicetree/bindings/interrupt-controller/arm,gic-v3.yaml Signed-off-by: Jean-Philippe Brucker Reviewed-by: Peter Maydell Reviewed-by: Eric Auger Message-id: 20220927100347.176606-3-jean-philippe@linaro.org Signed-off-by: Peter Maydell --- hw/arm/virt.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index f4ee71cda1..41b88dd144 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -488,6 +488,7 @@ static void fdt_add_its_gic_node(VirtMachineState *vms) qemu_fdt_setprop_string(ms->fdt, nodename, "compatible", "arm,gic-v3-its"); qemu_fdt_setprop(ms->fdt, nodename, "msi-controller", NULL, 0); + qemu_fdt_setprop_cell(ms->fdt, nodename, "#msi-cells", 1); qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", 2, vms->memmap[VIRT_GIC_ITS].base, 2, vms->memmap[VIRT_GIC_ITS].size); From 6b2f3ac945b75f548ab7ca37ac239dc981f7dfc3 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Tue, 27 Sep 2022 11:03:44 +0100 Subject: [PATCH 0765/1020] hw/arm/virt: Use "msi-map" devicetree property for PCI The "msi-parent" property can be used on the PCI node when MSIs do not contain sideband data (device IDs) [1]. In QEMU, MSI transactions contain the requester ID, so the PCI node should use the "msi-map" property instead of "msi-parent". In our case the property describes an identity map between requester ID and sideband data. This fixes a warning when passing the DTB generated by QEMU to dtc, following a recent change to the GICv3 node: Warning (msi_parent_property): /pcie@10000000:msi-parent: property size (4) too small for cell size 1 [1] linux/Documentation/devicetree/bindings/pci/pci-msi.txt Signed-off-by: Jean-Philippe Brucker Reviewed-by: Peter Maydell Reviewed-by: Eric Auger Message-id: 20220927100347.176606-4-jean-philippe@linaro.org Signed-off-by: Peter Maydell --- hw/arm/virt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 41b88dd144..b67ba0f2a1 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1490,8 +1490,8 @@ static void create_pcie(VirtMachineState *vms) qemu_fdt_setprop(ms->fdt, nodename, "dma-coherent", NULL, 0); if (vms->msi_phandle) { - qemu_fdt_setprop_cells(ms->fdt, nodename, "msi-parent", - vms->msi_phandle); + qemu_fdt_setprop_cells(ms->fdt, nodename, "msi-map", + 0, vms->msi_phandle, 0, 0x10000); } qemu_fdt_setprop_sized_cells(ms->fdt, nodename, "reg", From 6ebbf2f9d120db04e3bea1f874d8a506ffb62fb3 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Brucker Date: Tue, 27 Sep 2022 11:03:47 +0100 Subject: [PATCH 0766/1020] hw/arm/virt: Fix devicetree warning about the SMMU node The SMMUv3 node isn't expected to have clock properties (unlike the SMMUv2). Fix the corresponding dt-validate warning: smmuv3@9050000: 'clock-names', 'clocks' do not match any of the regexes: 'pinctrl-[0-9]+' From schema: linux/Documentation/devicetree/bindings/iommu/arm,smmu-v3.yaml Signed-off-by: Jean-Philippe Brucker Reviewed-by: Peter Maydell [PMM: tweaked commit message as suggested by Eric] Reviewed-by: Eric Auger Message-id: 20220927100347.176606-7-jean-philippe@linaro.org Signed-off-by: Peter Maydell --- hw/arm/virt.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index b67ba0f2a1..cda9defe8f 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -1361,8 +1361,6 @@ static void create_smmu(const VirtMachineState *vms, qemu_fdt_setprop(ms->fdt, node, "interrupt-names", irq_names, sizeof(irq_names)); - qemu_fdt_setprop_cell(ms->fdt, node, "clocks", vms->clock_phandle); - qemu_fdt_setprop_string(ms->fdt, node, "clock-names", "apb_pclk"); qemu_fdt_setprop(ms->fdt, node, "dma-coherent", NULL, 0); qemu_fdt_setprop_cell(ms->fdt, node, "#iommu-cells", 1); From beeec926d24aac28f95cc7694ef3837d7a4cd3bb Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Tue, 27 Sep 2022 14:00:58 +0200 Subject: [PATCH 0767/1020] target/arm: mark SP_EL1 with ARM_CP_EL3_NO_EL2_KEEP SP_EL1 must be kept when EL3 is present but EL2 is not. Therefore mark it with ARM_CP_EL3_NO_EL2_KEEP. Cc: qemu-stable@nongnu.org Fixes: 696ba3771894 ("target/arm: Handle cpreg registration for missing EL") Signed-off-by: Jerome Forissier Reviewed-by: Richard Henderson Message-id: 20220927120058.670901-1-jerome.forissier@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 24c592ffef..db3b1ea72d 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -5088,7 +5088,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = { .fieldoffset = offsetof(CPUARMState, sp_el[0]) }, { .name = "SP_EL1", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 4, .crn = 4, .crm = 1, .opc2 = 0, - .access = PL2_RW, .type = ARM_CP_ALIAS, + .access = PL2_RW, .type = ARM_CP_ALIAS | ARM_CP_EL3_NO_EL2_KEEP, .fieldoffset = offsetof(CPUARMState, sp_el[1]) }, { .name = "SPSel", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 0, From ad9f958db5c48b9501905002a19e80b221dc7186 Mon Sep 17 00:00:00 2001 From: Bernhard Beschow Date: Sat, 10 Sep 2022 17:11:17 +0200 Subject: [PATCH 0768/1020] hw/virtio/vhost-shadow-virtqueue: Silence GCC error "maybe-uninitialized" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC issues a false positive warning, resulting in build failure with -Werror: In file included from /usr/include/glib-2.0/glib.h:114, from src/include/glib-compat.h:32, from src/include/qemu/osdep.h:144, from ../src/hw/virtio/vhost-shadow-virtqueue.c:10: In function ‘g_autoptr_cleanup_generic_gfree’, inlined from ‘vhost_handle_guest_kick’ at ../src/hw/virtio/vhost-shadow-virtqueue.c:292:42: /usr/include/glib-2.0/glib/glib-autocleanups.h:28:3: error: ‘elem’ may be used uninitialized [-Werror=maybe-uninitialized] 28 | g_free (*pp); | ^~~~~~~~~~~~ ../src/hw/virtio/vhost-shadow-virtqueue.c: In function ‘vhost_handle_guest_kick’: ../src/hw/virtio/vhost-shadow-virtqueue.c:292:42: note: ‘elem’ was declared here 292 | g_autofree VirtQueueElement *elem; | ^~~~ cc1: all warnings being treated as errors There is actually no problem since "elem" is initialized in both branches. Silence the warning by initializig it with "NULL". $ gcc --version gcc (GCC) 12.2.0 Fixes: 9c2ab2f1ec333be8614cc12272d4b91960704dbe ("vhost: stop transfer elem ownership in vhost_handle_guest_kick") Signed-off-by: Bernhard Beschow Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220910151117.6665-1-shentey@gmail.com> Signed-off-by: Laurent Vivier --- hw/virtio/vhost-shadow-virtqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c index e8e5bbc368..596d4434d2 100644 --- a/hw/virtio/vhost-shadow-virtqueue.c +++ b/hw/virtio/vhost-shadow-virtqueue.c @@ -289,7 +289,7 @@ static void vhost_handle_guest_kick(VhostShadowVirtqueue *svq) virtio_queue_set_notification(svq->vq, false); while (true) { - g_autofree VirtQueueElement *elem; + g_autofree VirtQueueElement *elem = NULL; int r; if (svq->next_guest_avail_elem) { From fcf5813cba7079d94eccc8804fb80c4b05e48a86 Mon Sep 17 00:00:00 2001 From: "Wang, Lei" Date: Wed, 7 Sep 2022 23:00:10 +0800 Subject: [PATCH 0769/1020] .gitignore: add .cache/ to .gitignore $PROJECT/.cache/clangd/index is the intended location for project index data when using clangd as the language server. Ignore this directory to keep the git status clean. Signed-off-by: Wang, Lei Message-Id: <20220907150010.2047037-1-lei4.wang@intel.com> Signed-off-by: Laurent Vivier --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 9726a778b3..8aab671265 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ /GNUmakefile /build/ +/.cache/ *.pyc .sdk .stgit-* From c6cc866c0eaab1deddea21bf0b386730ed71bb97 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Thu, 15 Sep 2022 17:59:04 +0000 Subject: [PATCH 0770/1020] mem/cxl_type3: fix GPF DVSEC The structure is for device dvsec not port dvsec. Change type to fix this issue. Signed-off-by: Tong Zhang Acked-by: Jonathan Cameron Message-Id: <20220915175853.2902-1-t.zhang2@samsung.com> Signed-off-by: Laurent Vivier --- hw/mem/cxl_type3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index 3bf2869573..ada2108fac 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -49,7 +49,7 @@ static void build_dvsecs(CXLType3Dev *ct3d) .phase2_power = 0x33, /* 0x33 miliwatts */ }; cxl_component_create_dvsec(cxl_cstate, CXL2_TYPE3_DEVICE, - GPF_DEVICE_DVSEC_LENGTH, GPF_PORT_DVSEC, + GPF_DEVICE_DVSEC_LENGTH, GPF_DEVICE_DVSEC, GPF_DEVICE_DVSEC_REVID, dvsec); } From 321b0ca353a2cb568ed7807ff6b64ad97101ee1e Mon Sep 17 00:00:00 2001 From: Matheus Tavares Bernardino Date: Tue, 20 Sep 2022 10:42:28 -0300 Subject: [PATCH 0771/1020] checkpatch: ignore target/hexagon/imported/* files These files come from an external project (the hexagon archlib), so they deliberately do not follow QEMU's coding style. To avoid false positives from checkpatch.pl, let's disable the checking for those. Signed-off-by: Matheus Tavares Bernardino Message-Id: Signed-off-by: Laurent Vivier --- scripts/checkpatch.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index d900d18048..e3e3b43076 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1667,6 +1667,7 @@ sub process { # some scripts we imported from other projects. next if ($realfile =~ /\.(s|S)$/); next if ($realfile =~ /(checkpatch|get_maintainer)\.pl$/); + next if ($realfile =~ /^target\/hexagon\/imported\/*/); if ($rawline =~ /^\+.*\t/) { my $herevet = "$here\n" . cat_vet($rawline) . "\n"; From 38f034e728e5a60c27c3ac43ed2bc4ae7a6659b0 Mon Sep 17 00:00:00 2001 From: lu zhipeng Date: Wed, 21 Sep 2022 22:45:15 +0800 Subject: [PATCH 0772/1020] qcow2: fix memory leak in qcow2_read_extensions Free feature_table if it is failed in bdrv_pread. Signed-off-by: lu zhipeng Message-Id: <20220921144515.1166-1-luzhipeng@cestc.cn> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/qcow2.c | 1 + 1 file changed, 1 insertion(+) diff --git a/block/qcow2.c b/block/qcow2.c index c6c6692fb7..c8fc3a6160 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -275,6 +275,7 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset, if (ret < 0) { error_setg_errno(errp, -ret, "ERROR: ext_feature_table: " "Could not read table"); + g_free(feature_table); return ret; } From 8485563aa6b0e32f8509184b202d285fce2169bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 19 Sep 2022 20:27:55 +0200 Subject: [PATCH 0773/1020] block/qcow2-bitmap: Add missing cast to silent GCC error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit d1258dd0c8 ("qcow2: autoloading dirty bitmaps") added the set_readonly_helper() GFunc handler, correctly casting the gpointer user_data in both the g_slist_foreach() caller and the handler. Few commits later (commit 1b6b0562db), the handler is reused in qcow2_reopen_bitmaps_rw() but missing the gpointer cast, resulting in the following error when using Homebrew GCC 12.2.0: [2/658] Compiling C object libblock.fa.p/block_qcow2-bitmap.c.o ../../block/qcow2-bitmap.c: In function 'qcow2_reopen_bitmaps_rw': ../../block/qcow2-bitmap.c:1211:60: error: incompatible type for argument 3 of 'g_slist_foreach' 1211 | g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, false); | ^~~~~ | | | _Bool In file included from /opt/homebrew/Cellar/glib/2.72.3_1/include/glib-2.0/glib/gmain.h:26, from /opt/homebrew/Cellar/glib/2.72.3_1/include/glib-2.0/glib/giochannel.h:33, from /opt/homebrew/Cellar/glib/2.72.3_1/include/glib-2.0/glib.h:54, from /Users/philmd/source/qemu/include/glib-compat.h:32, from /Users/philmd/source/qemu/include/qemu/osdep.h:144, from ../../block/qcow2-bitmap.c:28: /opt/homebrew/Cellar/glib/2.72.3_1/include/glib-2.0/glib/gslist.h:127:61: note: expected 'gpointer' {aka 'void *'} but argument is of type '_Bool' 127 | gpointer user_data); | ~~~~~~~~~~~~~~~~~~^~~~~~~~~ At top level: FAILED: libblock.fa.p/block_qcow2-bitmap.c.o Fix by adding the missing gpointer cast. Fixes: 1b6b0562db ("qcow2: support .bdrv_reopen_bitmaps_rw") Signed-off-by: Philippe Mathieu-DaudĂ© Message-Id: <20220919182755.51967-1-f4bug@amsat.org> Reviewed-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block/qcow2-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index ff3309846c..7197754843 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -1208,7 +1208,7 @@ int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp) } } - g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, false); + g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, (gpointer)false); ret = 0; out: From 7f118b433a2e8c98fe5a8d73f0dd529aada327d1 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 8 Sep 2022 15:08:42 +0200 Subject: [PATCH 0774/1020] qemu-img: Wean documentation and help output off '?' for help '?' for help is deprecated since commit c8057f951d "Support 'help' as a synonym for '?' in command line options", v1.2.0. We neglected to update output of qemu-img --help and the manual. Do that now. Signed-off-by: Markus Armbruster Message-Id: <20220908130842.641410-1-armbru@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- docs/tools/qemu-img.rst | 2 +- qemu-img.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst index 85a6e05b35..15aeddc6d8 100644 --- a/docs/tools/qemu-img.rst +++ b/docs/tools/qemu-img.rst @@ -57,7 +57,7 @@ cases. See below for a description of the supported disk formats. *OUTPUT_FMT* is the destination format. *OPTIONS* is a comma separated list of format specific options in a -name=value format. Use ``-o ?`` for an overview of the options supported +name=value format. Use ``-o help`` for an overview of the options supported by the used format or see the format descriptions below for details. *SNAPSHOT_PARAM* is param used for internal snapshot, format is diff --git a/qemu-img.c b/qemu-img.c index 7d4b33b3da..cab9776f42 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -164,8 +164,8 @@ void help(void) " 'output_filename' is the destination disk image filename\n" " 'output_fmt' is the destination format\n" " 'options' is a comma separated list of format specific options in a\n" - " name=value format. Use -o ? for an overview of the options supported by the\n" - " used format\n" + " name=value format. Use -o help for an overview of the options supported by\n" + " the used format\n" " 'snapshot_param' is param used for internal snapshot, format\n" " is 'snapshot.id=[ID],snapshot.name=[NAME]', or\n" " '[ID_OR_NAME]'\n" From b2aaf354773417f034fdc1a56cdb76ad79de6e19 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Wed, 24 Aug 2022 11:50:43 +0200 Subject: [PATCH 0775/1020] block: pass OnOffAuto instead of bool to block_acct_setup() We would have one more place for block_acct_setup() calling, which should not corrupt original value. Signed-off-by: Denis V. Lunev Reviewed-by: Vladimir Sementsov-Ogievskiy CC: Peter Krempa CC: Markus Armbruster CC: John Snow CC: Kevin Wolf CC: Hanna Reitz Message-Id: <20220824095044.166009-2-den@openvz.org> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/accounting.c | 22 ++++++++++++++++++---- blockdev.c | 17 ++++++++++++++--- include/block/accounting.h | 6 +++--- 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/block/accounting.c b/block/accounting.c index 2030851d79..6b300c5129 100644 --- a/block/accounting.c +++ b/block/accounting.c @@ -40,11 +40,25 @@ void block_acct_init(BlockAcctStats *stats) } } -void block_acct_setup(BlockAcctStats *stats, bool account_invalid, - bool account_failed) +static bool bool_from_onoffauto(OnOffAuto val, bool def) { - stats->account_invalid = account_invalid; - stats->account_failed = account_failed; + switch (val) { + case ON_OFF_AUTO_AUTO: + return def; + case ON_OFF_AUTO_ON: + return true; + case ON_OFF_AUTO_OFF: + return false; + default: + abort(); + } +} + +void block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid, + enum OnOffAuto account_failed) +{ + stats->account_invalid = bool_from_onoffauto(account_invalid, true); + stats->account_failed = bool_from_onoffauto(account_failed, true); } void block_acct_cleanup(BlockAcctStats *stats) diff --git a/blockdev.c b/blockdev.c index 9230888e34..392d9476e6 100644 --- a/blockdev.c +++ b/blockdev.c @@ -455,6 +455,17 @@ static void extract_common_blockdev_options(QemuOpts *opts, int *bdrv_flags, } } +static OnOffAuto account_get_opt(QemuOpts *opts, const char *name) +{ + if (!qemu_opt_find(opts, name)) { + return ON_OFF_AUTO_AUTO; + } + if (qemu_opt_get_bool(opts, name, true)) { + return ON_OFF_AUTO_ON; + } + return ON_OFF_AUTO_OFF; +} + /* Takes the ownership of bs_opts */ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, Error **errp) @@ -462,7 +473,7 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, const char *buf; int bdrv_flags = 0; int on_read_error, on_write_error; - bool account_invalid, account_failed; + OnOffAuto account_invalid, account_failed; bool writethrough, read_only; BlockBackend *blk; BlockDriverState *bs; @@ -496,8 +507,8 @@ static BlockBackend *blockdev_init(const char *file, QDict *bs_opts, /* extract parameters */ snapshot = qemu_opt_get_bool(opts, "snapshot", 0); - account_invalid = qemu_opt_get_bool(opts, "stats-account-invalid", true); - account_failed = qemu_opt_get_bool(opts, "stats-account-failed", true); + account_invalid = account_get_opt(opts, "stats-account-invalid"); + account_failed = account_get_opt(opts, "stats-account-failed"); writethrough = !qemu_opt_get_bool(opts, BDRV_OPT_CACHE_WB, true); diff --git a/include/block/accounting.h b/include/block/accounting.h index 878b4c3581..b9caad60d5 100644 --- a/include/block/accounting.h +++ b/include/block/accounting.h @@ -27,7 +27,7 @@ #include "qemu/timed-average.h" #include "qemu/thread.h" -#include "qapi/qapi-builtin-types.h" +#include "qapi/qapi-types-common.h" typedef struct BlockAcctTimedStats BlockAcctTimedStats; typedef struct BlockAcctStats BlockAcctStats; @@ -100,8 +100,8 @@ typedef struct BlockAcctCookie { } BlockAcctCookie; void block_acct_init(BlockAcctStats *stats); -void block_acct_setup(BlockAcctStats *stats, bool account_invalid, - bool account_failed); +void block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid, + enum OnOffAuto account_failed); void block_acct_cleanup(BlockAcctStats *stats); void block_acct_add_interval(BlockAcctStats *stats, unsigned interval_length); BlockAcctTimedStats *block_acct_interval_next(BlockAcctStats *stats, From 62a6c300f18a9f6994baf6d767985425d48de427 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Wed, 24 Aug 2022 11:50:44 +0200 Subject: [PATCH 0776/1020] block: add missed block_acct_setup with new block device init procedure Commit 5f76a7aac156ca75680dad5df4a385fd0b58f6b1 is looking harmless from the first glance, but it has changed things a lot. 'libvirt' uses it to detect that it should follow new initialization way and this changes things considerably. With this procedure followed, blockdev_init() is not called anymore and thus block_acct_setup() helper is not called. This means in particular that defaults for block accounting statistics are changed and account_invalid/account_failed are actually initialized as false instead of true originally. This commit changes things to match original world. There are the following constraints: * new default value in block_acct_init() is set to true * block_acct_setup() inside blockdev_init() is called before blkconf_apply_backend_options() * thus newly created option in block device properties has precedence if specified Signed-off-by: Denis V. Lunev Reviewed-by: Vladimir Sementsov-Ogievskiy CC: Peter Krempa CC: Markus Armbruster CC: John Snow CC: Kevin Wolf CC: Hanna Reitz Message-Id: <20220824095044.166009-3-den@openvz.org> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/accounting.c | 8 +++- hw/block/block.c | 2 + include/hw/block/block.h | 7 +++- tests/qemu-iotests/172.out | 76 ++++++++++++++++++++++++++++++++++++++ tests/qemu-iotests/227.out | 4 +- 5 files changed, 92 insertions(+), 5 deletions(-) diff --git a/block/accounting.c b/block/accounting.c index 6b300c5129..2829745377 100644 --- a/block/accounting.c +++ b/block/accounting.c @@ -38,6 +38,8 @@ void block_acct_init(BlockAcctStats *stats) if (qtest_enabled()) { clock_type = QEMU_CLOCK_VIRTUAL; } + stats->account_invalid = true; + stats->account_failed = true; } static bool bool_from_onoffauto(OnOffAuto val, bool def) @@ -57,8 +59,10 @@ static bool bool_from_onoffauto(OnOffAuto val, bool def) void block_acct_setup(BlockAcctStats *stats, enum OnOffAuto account_invalid, enum OnOffAuto account_failed) { - stats->account_invalid = bool_from_onoffauto(account_invalid, true); - stats->account_failed = bool_from_onoffauto(account_failed, true); + stats->account_invalid = bool_from_onoffauto(account_invalid, + stats->account_invalid); + stats->account_failed = bool_from_onoffauto(account_failed, + stats->account_failed); } void block_acct_cleanup(BlockAcctStats *stats) diff --git a/hw/block/block.c b/hw/block/block.c index 04279166ee..f9c4fe6767 100644 --- a/hw/block/block.c +++ b/hw/block/block.c @@ -205,6 +205,8 @@ bool blkconf_apply_backend_options(BlockConf *conf, bool readonly, blk_set_enable_write_cache(blk, wce); blk_set_on_error(blk, rerror, werror); + block_acct_setup(blk_get_stats(blk), conf->account_invalid, + conf->account_failed); return true; } diff --git a/include/hw/block/block.h b/include/hw/block/block.h index 5902c0440a..15fff66435 100644 --- a/include/hw/block/block.h +++ b/include/hw/block/block.h @@ -31,6 +31,7 @@ typedef struct BlockConf { uint32_t lcyls, lheads, lsecs; OnOffAuto wce; bool share_rw; + OnOffAuto account_invalid, account_failed; BlockdevOnError rerror; BlockdevOnError werror; } BlockConf; @@ -61,7 +62,11 @@ static inline unsigned int get_physical_block_exp(BlockConf *conf) _conf.discard_granularity, -1), \ DEFINE_PROP_ON_OFF_AUTO("write-cache", _state, _conf.wce, \ ON_OFF_AUTO_AUTO), \ - DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false) + DEFINE_PROP_BOOL("share-rw", _state, _conf.share_rw, false), \ + DEFINE_PROP_ON_OFF_AUTO("account-invalid", _state, \ + _conf.account_invalid, ON_OFF_AUTO_AUTO), \ + DEFINE_PROP_ON_OFF_AUTO("account-failed", _state, \ + _conf.account_failed, ON_OFF_AUTO_AUTO) #define DEFINE_BLOCK_PROPERTIES(_state, _conf) \ DEFINE_PROP_DRIVE("drive", _state, _conf.blk), \ diff --git a/tests/qemu-iotests/172.out b/tests/qemu-iotests/172.out index 9479b92185..07eebf3583 100644 --- a/tests/qemu-iotests/172.out +++ b/tests/qemu-iotests/172.out @@ -28,6 +28,8 @@ Testing: discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "288" @@ -55,6 +57,8 @@ Testing: -fda TEST_DIR/t.qcow2 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -92,6 +96,8 @@ Testing: -fdb TEST_DIR/t.qcow2 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -104,6 +110,8 @@ Testing: -fdb TEST_DIR/t.qcow2 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "288" floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -145,6 +153,8 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -157,6 +167,8 @@ Testing: -fda TEST_DIR/t.qcow2 -fdb TEST_DIR/t.qcow2.2 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -199,6 +211,8 @@ Testing: -fdb discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "288" dev: floppy, id "" unit = 0 (0x0) @@ -211,6 +225,8 @@ Testing: -fdb discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "288" @@ -238,6 +254,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -275,6 +293,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -287,6 +307,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2,index=1 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "288" floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -328,6 +350,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -340,6 +364,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=floppy,file=TEST_DIR/t discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -385,6 +411,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/peripheral-anon/device[N] @@ -422,6 +450,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,unit=1 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/peripheral-anon/device[N] @@ -459,6 +489,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -471,6 +503,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qco discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/peripheral-anon/device[N] @@ -522,6 +556,8 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -534,6 +570,8 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -576,6 +614,8 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -588,6 +628,8 @@ Testing: -fda TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -630,6 +672,8 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 1 (0x1) @@ -642,6 +686,8 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -684,6 +730,8 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 1 (0x1) @@ -696,6 +744,8 @@ Testing: -fdb TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.qcow2.2 -device fl discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy1 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -747,6 +797,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -759,6 +811,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -801,6 +855,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" dev: floppy, id "" unit = 0 (0x0) @@ -813,6 +869,8 @@ Testing: -drive if=floppy,file=TEST_DIR/t.qcow2 -drive if=none,file=TEST_DIR/t.q discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" floppy0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/unattached/device[N] @@ -861,6 +919,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -global floppy.drive=none0 -device discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/peripheral-anon/device[N] @@ -928,6 +988,8 @@ Testing: -device floppy discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "288" Testing: -device floppy,drive-type=120 @@ -952,6 +1014,8 @@ Testing: -device floppy,drive-type=120 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "120" Testing: -device floppy,drive-type=144 @@ -976,6 +1040,8 @@ Testing: -device floppy,drive-type=144 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" Testing: -device floppy,drive-type=288 @@ -1000,6 +1066,8 @@ Testing: -device floppy,drive-type=288 discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "288" @@ -1027,6 +1095,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "120" none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/peripheral-anon/device[N] @@ -1064,6 +1134,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,drive-t discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "288" none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/peripheral-anon/device[N] @@ -1104,6 +1176,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,logical discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/peripheral-anon/device[N] @@ -1141,6 +1215,8 @@ Testing: -drive if=none,file=TEST_DIR/t.qcow2 -device floppy,drive=none0,physica discard_granularity = 4294967295 (4 GiB) write-cache = "auto" share-rw = false + account-invalid = "auto" + account-failed = "auto" drive-type = "144" none0 (NODE_NAME): TEST_DIR/t.qcow2 (qcow2) Attached to: /machine/peripheral-anon/device[N] diff --git a/tests/qemu-iotests/227.out b/tests/qemu-iotests/227.out index 9c09ee3917..378c1b8fb1 100644 --- a/tests/qemu-iotests/227.out +++ b/tests/qemu-iotests/227.out @@ -188,7 +188,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b ], "failed_unmap_operations": 0, "failed_flush_operations": 0, - "account_invalid": false, + "account_invalid": true, "rd_total_time_ns": 0, "invalid_unmap_operations": 0, "flush_operations": 0, @@ -198,7 +198,7 @@ Testing: -blockdev driver=null-co,read-zeroes=on,node-name=null -device virtio-b "rd_bytes": 0, "unmap_total_time_ns": 0, "invalid_flush_operations": 0, - "account_failed": false, + "account_failed": true, "rd_operations": 0, "invalid_wr_operations": 0, "invalid_rd_operations": 0 From 006e1962449f8ea9f0822b838d9fdf13c98eb147 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Wed, 17 Aug 2022 10:37:35 +0200 Subject: [PATCH 0777/1020] block: use bdrv_is_sg() helper instead of raw bs->sg reading I believe that if the helper exists, it must be used always for reading of the value. It breaks expectations in the other case. Signed-off-by: Denis V. Lunev CC: Kevin Wolf CC: Hanna Reitz CC: Stefan Hajnoczi CC: Fam Zheng CC: Ronnie Sahlberg CC: Paolo Bonzini CC: Peter Lieven CC: Vladimir Sementsov-Ogievskiy Message-Id: <20220817083736.40981-2-den@openvz.org> Reviewed-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block/file-posix.c | 2 +- block/iscsi.c | 2 +- block/raw-format.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index 48cd096624..256de1f456 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -1295,7 +1295,7 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp) } #endif - if (bs->sg || S_ISBLK(st.st_mode)) { + if (bdrv_is_sg(bs) || S_ISBLK(st.st_mode)) { int ret = hdev_get_max_hw_transfer(s->fd, &st); if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) { diff --git a/block/iscsi.c b/block/iscsi.c index d707d0b354..612de127e5 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -2065,7 +2065,7 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp) uint64_t max_xfer_len = iscsilun->use_16_for_rw ? 0xffffffff : 0xffff; unsigned int block_size = MAX(BDRV_SECTOR_SIZE, iscsilun->block_size); - assert(iscsilun->block_size >= BDRV_SECTOR_SIZE || bs->sg); + assert(iscsilun->block_size >= BDRV_SECTOR_SIZE || bdrv_is_sg(bs)); bs->bl.request_alignment = block_size; diff --git a/block/raw-format.c b/block/raw-format.c index 69fd650eaf..c7278e348e 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -463,7 +463,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, return -EINVAL; } - bs->sg = bs->file->bs->sg; + bs->sg = bdrv_is_sg(bs->file->bs); bs->supported_write_flags = BDRV_REQ_WRITE_UNCHANGED | (BDRV_REQ_FUA & bs->file->bs->supported_write_flags); bs->supported_zero_flags = BDRV_REQ_WRITE_UNCHANGED | @@ -489,7 +489,7 @@ static int raw_open(BlockDriverState *bs, QDict *options, int flags, return ret; } - if (bs->sg && (s->offset || s->has_size)) { + if (bdrv_is_sg(bs) && (s->offset || s->has_size)) { error_setg(errp, "Cannot use offset/size with SCSI generic devices"); return -EINVAL; } From 131498f775ea18852992dc56441eba33de3fcde5 Mon Sep 17 00:00:00 2001 From: "Denis V. Lunev" Date: Wed, 17 Aug 2022 10:37:36 +0200 Subject: [PATCH 0778/1020] block: make serializing requests functions 'void' Return codes of the following functions are never used in the code: * bdrv_wait_serialising_requests_locked * bdrv_wait_serialising_requests * bdrv_make_request_serialising Signed-off-by: Denis V. Lunev CC: Kevin Wolf CC: Hanna Reitz CC: Stefan Hajnoczi CC: Fam Zheng CC: Ronnie Sahlberg CC: Paolo Bonzini CC: Peter Lieven CC: Vladimir Sementsov-Ogievskiy Message-Id: <20220817083736.40981-3-den@openvz.org> Reviewed-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block/io.c | 23 +++++++---------------- include/block/block_int-io.h | 2 +- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/block/io.c b/block/io.c index 0a8cbefe86..51d8f943a4 100644 --- a/block/io.c +++ b/block/io.c @@ -828,20 +828,16 @@ bdrv_find_conflicting_request(BdrvTrackedRequest *self) } /* Called with self->bs->reqs_lock held */ -static bool coroutine_fn +static void coroutine_fn bdrv_wait_serialising_requests_locked(BdrvTrackedRequest *self) { BdrvTrackedRequest *req; - bool waited = false; while ((req = bdrv_find_conflicting_request(self))) { self->waiting_for = req; qemu_co_queue_wait(&req->wait_queue, &self->bs->reqs_lock); self->waiting_for = NULL; - waited = true; } - - return waited; } /* Called with req->bs->reqs_lock held */ @@ -934,36 +930,31 @@ void bdrv_dec_in_flight(BlockDriverState *bs) bdrv_wakeup(bs); } -static bool coroutine_fn bdrv_wait_serialising_requests(BdrvTrackedRequest *self) +static void coroutine_fn +bdrv_wait_serialising_requests(BdrvTrackedRequest *self) { BlockDriverState *bs = self->bs; - bool waited = false; if (!qatomic_read(&bs->serialising_in_flight)) { - return false; + return; } qemu_co_mutex_lock(&bs->reqs_lock); - waited = bdrv_wait_serialising_requests_locked(self); + bdrv_wait_serialising_requests_locked(self); qemu_co_mutex_unlock(&bs->reqs_lock); - - return waited; } -bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req, +void coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req, uint64_t align) { - bool waited; IO_CODE(); qemu_co_mutex_lock(&req->bs->reqs_lock); tracked_request_set_serialising(req, align); - waited = bdrv_wait_serialising_requests_locked(req); + bdrv_wait_serialising_requests_locked(req); qemu_co_mutex_unlock(&req->bs->reqs_lock); - - return waited; } int bdrv_check_qiov_request(int64_t offset, int64_t bytes, diff --git a/include/block/block_int-io.h b/include/block/block_int-io.h index 91cdd61692..4b0b3e17ef 100644 --- a/include/block/block_int-io.h +++ b/include/block/block_int-io.h @@ -73,7 +73,7 @@ static inline int coroutine_fn bdrv_co_pwrite(BdrvChild *child, return bdrv_co_pwritev(child, offset, bytes, &qiov, flags); } -bool coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req, +void coroutine_fn bdrv_make_request_serialising(BdrvTrackedRequest *req, uint64_t align); BdrvTrackedRequest *coroutine_fn bdrv_co_get_self_request(BlockDriverState *bs); From 9a891a91a19a9b999fec00ce6e27bc71c93273ec Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 11 Aug 2022 12:49:05 -0400 Subject: [PATCH 0779/1020] gluster: stop using .bdrv_needs_filename The gluster protocol driver used to parse URIs (filenames) but was extended with a richer JSON syntax in commit 6c7189bb29de ("block/gluster: add support for multiple gluster servers"). The gluster drivers that have JSON parsing set .bdrv_needs_filename to false. The gluster+unix and gluster+rdma drivers still to require a filename even though the JSON parser is equipped to parse the same volume/path/sockaddr details as the URI parser. Let's allow JSON parsing for these drivers too. Note that the gluster+rdma driver actually uses TCP because RDMA support is not available, so the JSON server.type field must be "inet". Drop .bdrv_needs_filename since both the filename and the JSON parsers can handle gluster+unix and gluster+rdma. This change is in preparation for eventually removing .bdrv_needs_filename across the entire codebase. Cc: Prasanna Kumar Kalever Signed-off-by: Stefan Hajnoczi Message-Id: <20220811164905.430834-1-stefanha@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/gluster.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/block/gluster.c b/block/gluster.c index b60213ab80..bb1144cf6a 100644 --- a/block/gluster.c +++ b/block/gluster.c @@ -1555,7 +1555,6 @@ static BlockDriver bdrv_gluster = { .format_name = "gluster", .protocol_name = "gluster", .instance_size = sizeof(BDRVGlusterState), - .bdrv_needs_filename = false, .bdrv_file_open = qemu_gluster_open, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_commit = qemu_gluster_reopen_commit, @@ -1585,7 +1584,6 @@ static BlockDriver bdrv_gluster_tcp = { .format_name = "gluster", .protocol_name = "gluster+tcp", .instance_size = sizeof(BDRVGlusterState), - .bdrv_needs_filename = false, .bdrv_file_open = qemu_gluster_open, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_commit = qemu_gluster_reopen_commit, @@ -1615,7 +1613,6 @@ static BlockDriver bdrv_gluster_unix = { .format_name = "gluster", .protocol_name = "gluster+unix", .instance_size = sizeof(BDRVGlusterState), - .bdrv_needs_filename = true, .bdrv_file_open = qemu_gluster_open, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_commit = qemu_gluster_reopen_commit, @@ -1651,7 +1648,6 @@ static BlockDriver bdrv_gluster_rdma = { .format_name = "gluster", .protocol_name = "gluster+rdma", .instance_size = sizeof(BDRVGlusterState), - .bdrv_needs_filename = true, .bdrv_file_open = qemu_gluster_open, .bdrv_reopen_prepare = qemu_gluster_reopen_prepare, .bdrv_reopen_commit = qemu_gluster_reopen_commit, From ec64b1ca08138b5f57d270a5756a9138f897ee5a Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Wed, 3 Aug 2022 16:44:44 +0200 Subject: [PATCH 0780/1020] block/qcow2: Keep auto_backing_file if possible qcow2_do_open() is used by qcow2_co_invalidate_cache(), i.e. may be run on an image that has been opened before. When reading the backing file string from the image header, compare it against the existing bs->backing_file, and update bs->auto_backing_file only if they differ. auto_backing_file should ideally contain the filename the backing BDS will actually have after opening, i.e. a post-bdrv_refresh_filename() version of what is in the image header. So for example, if the image header reports the following backing file string: json:{"driver": "qcow2", "file": { "driver": "file", "filename": "/tmp/backing.qcow2" }} Then auto_backing_file should contain simply "/tmp/backing.qcow2". Because bdrv_refresh_filename() only works on existing BDSs, though, the way how we get this auto_backing_file value is to have the format driver set it to whatever is in the image header, and when the backing BDS is opened based on that, we update it with the filename the backing BDS actually got. However, qcow2's qcow2_co_invalidate_cache() implementation breaks this because it just resets auto_backing_file to whatever is in the image file without opening a BDS based on it, so we never get auto_backing_file back to the "refreshed" version, and in the example above, it would stay "json:{...}". Then, bs->backing->bs->filename will differ from bs->auto_backing_file, making bdrv_backing_overridden(bs) return true, which will lead bdrv_refresh_filename(bs) to generate a json:{} filename for bs, even though that may not have been necessary. This is reported in the issue linked below. Therefore, skip updating auto_backing_file if nothing has changed in the image header since we last read it. Fixes: https://gitlab.com/qemu-project/qemu/-/issues/1117 Signed-off-by: Hanna Reitz Message-Id: <20220803144446.20723-2-hreitz@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/qcow2.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/block/qcow2.c b/block/qcow2.c index c8fc3a6160..6c8c8b2b5a 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -1697,16 +1697,27 @@ static int coroutine_fn qcow2_do_open(BlockDriverState *bs, QDict *options, ret = -EINVAL; goto fail; } + + s->image_backing_file = g_malloc(len + 1); ret = bdrv_pread(bs->file, header.backing_file_offset, len, - bs->auto_backing_file, 0); + s->image_backing_file, 0); if (ret < 0) { error_setg_errno(errp, -ret, "Could not read backing file name"); goto fail; } - bs->auto_backing_file[len] = '\0'; - pstrcpy(bs->backing_file, sizeof(bs->backing_file), - bs->auto_backing_file); - s->image_backing_file = g_strdup(bs->auto_backing_file); + s->image_backing_file[len] = '\0'; + + /* + * Update only when something has changed. This function is called by + * qcow2_co_invalidate_cache(), and we do not want to reset + * auto_backing_file unless necessary. + */ + if (!g_str_equal(s->image_backing_file, bs->backing_file)) { + pstrcpy(bs->backing_file, sizeof(bs->backing_file), + s->image_backing_file); + pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file), + s->image_backing_file); + } } /* From dc70638ff616ef0a1a6e4f61ce1f3f5282d2c942 Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Wed, 3 Aug 2022 16:44:45 +0200 Subject: [PATCH 0781/1020] block/qed: Keep auto_backing_file if possible Just like qcow2, qed invokes its open function in its .bdrv_co_invalidate_cache() implementation. Therefore, just like done for qcow2 in HEAD^, update auto_backing_file only if the backing file string in the image header differs from the one we have read before. Signed-off-by: Hanna Reitz Message-Id: <20220803144446.20723-3-hreitz@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/qed.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/block/qed.c b/block/qed.c index 40943e679b..324ca0e95a 100644 --- a/block/qed.c +++ b/block/qed.c @@ -445,6 +445,8 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options, } if ((s->header.features & QED_F_BACKING_FILE)) { + g_autofree char *backing_file_str = NULL; + if ((uint64_t)s->header.backing_filename_offset + s->header.backing_filename_size > s->header.cluster_size * s->header.header_size) { @@ -452,16 +454,21 @@ static int coroutine_fn bdrv_qed_do_open(BlockDriverState *bs, QDict *options, return -EINVAL; } + backing_file_str = g_malloc(sizeof(bs->backing_file)); ret = qed_read_string(bs->file, s->header.backing_filename_offset, s->header.backing_filename_size, - bs->auto_backing_file, - sizeof(bs->auto_backing_file)); + backing_file_str, sizeof(bs->backing_file)); if (ret < 0) { error_setg(errp, "Failed to read backing filename"); return ret; } - pstrcpy(bs->backing_file, sizeof(bs->backing_file), - bs->auto_backing_file); + + if (!g_str_equal(backing_file_str, bs->backing_file)) { + pstrcpy(bs->backing_file, sizeof(bs->backing_file), + backing_file_str); + pstrcpy(bs->auto_backing_file, sizeof(bs->auto_backing_file), + backing_file_str); + } if (s->header.features & QED_F_BACKING_FORMAT_NO_PROBE) { pstrcpy(bs->backing_format, sizeof(bs->backing_format), "raw"); From 283153f10ab474cb2f14cc2b3f272edcf13aedaf Mon Sep 17 00:00:00 2001 From: Hanna Reitz Date: Wed, 3 Aug 2022 16:44:46 +0200 Subject: [PATCH 0782/1020] iotests/backing-file-invalidation: Add new test Add a new test to see what happens when you migrate a VM with a backing chain that has json:{} backing file strings, which, when opened, will be resolved to plain filenames. Signed-off-by: Hanna Reitz Message-Id: <20220803144446.20723-4-hreitz@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- .../tests/backing-file-invalidation | 152 ++++++++++++++++++ .../tests/backing-file-invalidation.out | 5 + 2 files changed, 157 insertions(+) create mode 100755 tests/qemu-iotests/tests/backing-file-invalidation create mode 100644 tests/qemu-iotests/tests/backing-file-invalidation.out diff --git a/tests/qemu-iotests/tests/backing-file-invalidation b/tests/qemu-iotests/tests/backing-file-invalidation new file mode 100755 index 0000000000..4eccc80153 --- /dev/null +++ b/tests/qemu-iotests/tests/backing-file-invalidation @@ -0,0 +1,152 @@ +#!/usr/bin/env python3 +# group: rw migration +# +# Migrate a VM with a BDS with backing nodes, which runs +# bdrv_invalidate_cache(), which for qcow2 and qed triggers reading the +# backing file string from the image header. Check whether this +# interferes with bdrv_backing_overridden(). +# +# Copyright (C) 2022 Red Hat, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import json +import os +from typing import Optional + +import iotests +from iotests import qemu_img_create, qemu_img_info + + +image_size = 1 * 1024 * 1024 +imgs = [os.path.join(iotests.test_dir, f'{i}.img') for i in range(0, 4)] + +mig_sock = os.path.join(iotests.sock_dir, 'mig.sock') + + +class TestPostMigrateFilename(iotests.QMPTestCase): + vm_s: Optional[iotests.VM] = None + vm_d: Optional[iotests.VM] = None + + def setUp(self) -> None: + # Create backing chain of three images, where the backing file strings + # are json:{} filenames + qemu_img_create('-f', iotests.imgfmt, imgs[0], str(image_size)) + for i in range(1, 3): + backing = { + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': imgs[i - 1] + } + } + qemu_img_create('-f', iotests.imgfmt, '-F', iotests.imgfmt, + '-b', 'json:' + json.dumps(backing), + imgs[i], str(image_size)) + + def tearDown(self) -> None: + if self.vm_s is not None: + self.vm_s.shutdown() + if self.vm_d is not None: + self.vm_d.shutdown() + + for img in imgs: + try: + os.remove(img) + except OSError: + pass + try: + os.remove(mig_sock) + except OSError: + pass + + def test_migration(self) -> None: + """ + Migrate a VM with the backing chain created in setUp() attached. At + the end of the migration process, the destination will run + bdrv_invalidate_cache(), which for some image formats (qcow2 and qed) + means the backing file string is re-read from the image header. If + this overwrites bs->auto_backing_file, doing so may cause + bdrv_backing_overridden() to become true: The image header reports a + json:{} filename, but when opening it, bdrv_refresh_filename() will + simplify it to a plain simple filename; and when bs->auto_backing_file + and bs->backing->bs->filename differ, bdrv_backing_overridden() becomes + true. + If bdrv_backing_overridden() is true, the BDS will be forced to get a + json:{} filename, which in general is not the end of the world, but not + great. Check whether that happens, i.e. whether migration changes the + node's filename. + """ + + blockdev = { + 'node-name': 'node0', + 'driver': iotests.imgfmt, + 'file': { + 'driver': 'file', + 'filename': imgs[2] + } + } + + self.vm_s = iotests.VM(path_suffix='a') \ + .add_blockdev(json.dumps(blockdev)) + self.vm_d = iotests.VM(path_suffix='b') \ + .add_blockdev(json.dumps(blockdev)) \ + .add_incoming(f'unix:{mig_sock}') + + assert self.vm_s is not None + assert self.vm_d is not None + + self.vm_s.launch() + self.vm_d.launch() + + pre_mig_filename = self.vm_s.node_info('node0')['file'] + + self.vm_s.qmp('migrate', uri=f'unix:{mig_sock}') + + # Wait for migration to be done + self.vm_s.event_wait('STOP') + self.vm_d.event_wait('RESUME') + + post_mig_filename = self.vm_d.node_info('node0')['file'] + + # Verify that the filename hasn't changed from before the migration + self.assertEqual(pre_mig_filename, post_mig_filename) + + self.vm_s.shutdown() + self.vm_s = None + + # For good measure, try creating an overlay and check its backing + # chain below. This is how the issue was originally found. + result = self.vm_d.qmp('blockdev-snapshot-sync', + format=iotests.imgfmt, + snapshot_file=imgs[3], + node_name='node0', + snapshot_node_name='node0-overlay') + self.assert_qmp(result, 'return', {}) + + self.vm_d.shutdown() + self.vm_d = None + + # Check the newly created overlay's backing chain + chain = qemu_img_info('--backing-chain', imgs[3]) + for index, image in enumerate(chain): + self.assertEqual(image['filename'], imgs[3 - index]) + + +if __name__ == '__main__': + # These are the image formats that run their open() function from their + # .bdrv_co_invaliate_cache() implementations, so test them + iotests.main(supported_fmts=['qcow2', 'qed'], + supported_protocols=['file']) diff --git a/tests/qemu-iotests/tests/backing-file-invalidation.out b/tests/qemu-iotests/tests/backing-file-invalidation.out new file mode 100644 index 0000000000..ae1213e6f8 --- /dev/null +++ b/tests/qemu-iotests/tests/backing-file-invalidation.out @@ -0,0 +1,5 @@ +. +---------------------------------------------------------------------- +Ran 1 tests + +OK From a7c5f67a78569f8c275ea4ea9962e9c79b9d03cb Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Thu, 29 Sep 2022 13:05:22 -0700 Subject: [PATCH 0783/1020] block: move bdrv_qiov_is_aligned to file-posix There is only user of bdrv_qiov_is_aligned(), so move the alignment function to there and make it static. Signed-off-by: Keith Busch Message-Id: <20220929200523.3218710-2-kbusch@meta.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/file-posix.c | 21 +++++++++++++++++++++ block/io.c | 21 --------------------- include/block/block-io.h | 1 - 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index 256de1f456..989dfc4586 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -2061,6 +2061,27 @@ static int coroutine_fn raw_thread_pool_submit(BlockDriverState *bs, return thread_pool_submit_co(pool, func, arg); } +/* + * Check if all memory in this vector is sector aligned. + */ +static bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov) +{ + int i; + size_t alignment = bdrv_min_mem_align(bs); + IO_CODE(); + + for (i = 0; i < qiov->niov; i++) { + if ((uintptr_t) qiov->iov[i].iov_base % alignment) { + return false; + } + if (qiov->iov[i].iov_len % alignment) { + return false; + } + } + + return true; +} + static int coroutine_fn raw_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes, QEMUIOVector *qiov, int type) { diff --git a/block/io.c b/block/io.c index 51d8f943a4..c3200bcdff 100644 --- a/block/io.c +++ b/block/io.c @@ -3227,27 +3227,6 @@ void *qemu_try_blockalign0(BlockDriverState *bs, size_t size) return mem; } -/* - * Check if all memory in this vector is sector aligned. - */ -bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov) -{ - int i; - size_t alignment = bdrv_min_mem_align(bs); - IO_CODE(); - - for (i = 0; i < qiov->niov; i++) { - if ((uintptr_t) qiov->iov[i].iov_base % alignment) { - return false; - } - if (qiov->iov[i].iov_len % alignment) { - return false; - } - } - - return true; -} - void bdrv_io_plug(BlockDriverState *bs) { BdrvChild *child; diff --git a/include/block/block-io.h b/include/block/block-io.h index fd25ffa9be..492f95fc05 100644 --- a/include/block/block-io.h +++ b/include/block/block-io.h @@ -150,7 +150,6 @@ void *qemu_blockalign(BlockDriverState *bs, size_t size); void *qemu_blockalign0(BlockDriverState *bs, size_t size); void *qemu_try_blockalign(BlockDriverState *bs, size_t size); void *qemu_try_blockalign0(BlockDriverState *bs, size_t size); -bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov); void bdrv_enable_copy_on_read(BlockDriverState *bs); void bdrv_disable_copy_on_read(BlockDriverState *bs); From 25474d90aa50bd32e0de395a33d8de42dd6f2aef Mon Sep 17 00:00:00 2001 From: Keith Busch Date: Thu, 29 Sep 2022 13:05:23 -0700 Subject: [PATCH 0784/1020] block: use the request length for iov alignment An iov length needs to be aligned to the logical block size, which may be larger than the memory alignment. Tested-by: Jens Axboe Signed-off-by: Keith Busch Message-Id: <20220929200523.3218710-3-kbusch@meta.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/file-posix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/file-posix.c b/block/file-posix.c index 989dfc4586..66fdb07820 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -2068,13 +2068,14 @@ static bool bdrv_qiov_is_aligned(BlockDriverState *bs, QEMUIOVector *qiov) { int i; size_t alignment = bdrv_min_mem_align(bs); + size_t len = bs->bl.request_alignment; IO_CODE(); for (i = 0; i < qiov->niov; i++) { if ((uintptr_t) qiov->iov[i].iov_base % alignment) { return false; } - if (qiov->iov[i].iov_len % alignment) { + if (qiov->iov[i].iov_len % len) { return false; } } From 4851a986b205ac8fb133164cd15d9bb983d8502d Mon Sep 17 00:00:00 2001 From: Lev Kujawski Date: Thu, 7 Jul 2022 03:11:34 +0000 Subject: [PATCH 0785/1020] piix_ide_reset: Use pci_set_* functions instead of direct access Eliminate the remaining TODOs in hw/ide/piix.c by: * Using pci_set_{size} functions to write the PIIX PCI configuration space instead of manipulating it directly as an array; and * Documenting the default register values by reference to the controlling specification. Signed-off-by: Lev Kujawski Message-Id: <20220707031140.158958-1-lkujaw@member.fsf.org> Signed-off-by: Kevin Wolf --- hw/ide/piix.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/hw/ide/piix.c b/hw/ide/piix.c index 9a9b28078e..de1f4f0efb 100644 --- a/hw/ide/piix.c +++ b/hw/ide/piix.c @@ -21,6 +21,10 @@ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. + * + * References: + * [1] 82371FB (PIIX) AND 82371SB (PIIX3) PCI ISA IDE XCELERATOR, + * 290550-002, Intel Corporation, April 1997. */ #include "qemu/osdep.h" @@ -114,14 +118,11 @@ static void piix_ide_reset(DeviceState *dev) ide_bus_reset(&d->bus[i]); } - /* TODO: this is the default. do not override. */ - pci_conf[PCI_COMMAND] = 0x00; - /* TODO: this is the default. do not override. */ - pci_conf[PCI_COMMAND + 1] = 0x00; - /* TODO: use pci_set_word */ - pci_conf[PCI_STATUS] = PCI_STATUS_FAST_BACK; - pci_conf[PCI_STATUS + 1] = PCI_STATUS_DEVSEL_MEDIUM >> 8; - pci_conf[0x20] = 0x01; /* BMIBA: 20-23h */ + /* PCI command register default value (0000h) per [1, p.48]. */ + pci_set_word(pci_conf + PCI_COMMAND, 0x0000); + pci_set_word(pci_conf + PCI_STATUS, + PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_FAST_BACK); + pci_set_byte(pci_conf + 0x20, 0x01); /* BMIBA: 20-23h */ } static int pci_piix_init_ports(PCIIDEState *d) From ecfcf71314bc1548f387a035e1061296ec8f4ec3 Mon Sep 17 00:00:00 2001 From: Lev Kujawski Date: Thu, 7 Jul 2022 03:11:35 +0000 Subject: [PATCH 0786/1020] tests/qtest/ide-test.c: Create disk image for use as a secondary Change 'tmp_path' into an array of two members to accommodate another disk image of size TEST_IMAGE_SIZE. This facilitates testing ATA protocol aspects peculiar to secondary devices on the same controller. Signed-off-by: Lev Kujawski Message-Id: <20220707031140.158958-2-lkujaw@member.fsf.org> Signed-off-by: Kevin Wolf --- tests/qtest/ide-test.c | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c index 4ea89c26c9..93b4416023 100644 --- a/tests/qtest/ide-test.c +++ b/tests/qtest/ide-test.c @@ -121,7 +121,7 @@ enum { static QPCIBus *pcibus = NULL; static QGuestAllocator guest_malloc; -static char *tmp_path; +static char *tmp_path[2]; static char *debug_path; static QTestState *ide_test_start(const char *cmdline_fmt, ...) @@ -310,7 +310,7 @@ static QTestState *test_bmdma_setup(void) qts = ide_test_start( "-drive file=%s,if=ide,cache=writeback,format=raw " "-global ide-hd.serial=%s -global ide-hd.ver=%s", - tmp_path, "testdisk", "version"); + tmp_path[0], "testdisk", "version"); qtest_irq_intercept_in(qts, "ioapic"); return qts; @@ -574,7 +574,7 @@ static void test_identify(void) qts = ide_test_start( "-drive file=%s,if=ide,cache=writeback,format=raw " "-global ide-hd.serial=%s -global ide-hd.ver=%s", - tmp_path, "testdisk", "version"); + tmp_path[0], "testdisk", "version"); dev = get_pci_device(qts, &bmdma_bar, &ide_bar); @@ -662,7 +662,7 @@ static void test_flush(void) qts = ide_test_start( "-drive file=blkdebug::%s,if=ide,cache=writeback,format=raw", - tmp_path); + tmp_path[0]); dev = get_pci_device(qts, &bmdma_bar, &ide_bar); @@ -713,7 +713,7 @@ static void test_pci_retry_flush(void) qts = ide_test_start( "-drive file=blkdebug:%s:%s,if=ide,cache=writeback,format=raw," "rerror=stop,werror=stop", - debug_path, tmp_path); + debug_path, tmp_path[0]); dev = get_pci_device(qts, &bmdma_bar, &ide_bar); @@ -892,14 +892,14 @@ static void cdrom_pio_impl(int nblocks) /* Prepopulate the CDROM with an interesting pattern */ generate_pattern(pattern, patt_len, ATAPI_BLOCK_SIZE); - fh = fopen(tmp_path, "wb+"); + fh = fopen(tmp_path[0], "wb+"); ret = fwrite(pattern, ATAPI_BLOCK_SIZE, patt_blocks, fh); g_assert_cmpint(ret, ==, patt_blocks); fclose(fh); qts = ide_test_start( "-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 " - "-device ide-cd,drive=sr0,bus=ide.0", tmp_path); + "-device ide-cd,drive=sr0,bus=ide.0", tmp_path[0]); dev = get_pci_device(qts, &bmdma_bar, &ide_bar); qtest_irq_intercept_in(qts, "ioapic"); @@ -985,7 +985,7 @@ static void test_cdrom_dma(void) qts = ide_test_start( "-drive if=none,file=%s,media=cdrom,format=raw,id=sr0,index=0 " - "-device ide-cd,drive=sr0,bus=ide.0", tmp_path); + "-device ide-cd,drive=sr0,bus=ide.0", tmp_path[0]); qtest_irq_intercept_in(qts, "ioapic"); guest_buf = guest_alloc(&guest_malloc, len); @@ -993,7 +993,7 @@ static void test_cdrom_dma(void) prdt[0].size = cpu_to_le32(len | PRDT_EOT); generate_pattern(pattern, ATAPI_BLOCK_SIZE * 16, ATAPI_BLOCK_SIZE); - fh = fopen(tmp_path, "wb+"); + fh = fopen(tmp_path[0], "wb+"); ret = fwrite(pattern, ATAPI_BLOCK_SIZE, 16, fh); g_assert_cmpint(ret, ==, 16); fclose(fh); @@ -1012,6 +1012,7 @@ static void test_cdrom_dma(void) int main(int argc, char **argv) { const char *base; + int i; int fd; int ret; @@ -1035,12 +1036,14 @@ int main(int argc, char **argv) close(fd); /* Create a temporary raw image */ - tmp_path = g_strdup_printf("%s/qtest.XXXXXX", base); - fd = g_mkstemp(tmp_path); - g_assert(fd >= 0); - ret = ftruncate(fd, TEST_IMAGE_SIZE); - g_assert(ret == 0); - close(fd); + for (i = 0; i < 2; ++i) { + tmp_path[i] = g_strdup_printf("%s/qtest.XXXXXX", base); + fd = g_mkstemp(tmp_path[i]); + g_assert(fd >= 0); + ret = ftruncate(fd, TEST_IMAGE_SIZE); + g_assert(ret == 0); + close(fd); + } /* Run the tests */ g_test_init(&argc, &argv, NULL); @@ -1064,8 +1067,10 @@ int main(int argc, char **argv) ret = g_test_run(); /* Cleanup */ - unlink(tmp_path); - g_free(tmp_path); + for (i = 0; i < 2; ++i) { + unlink(tmp_path[i]); + g_free(tmp_path[i]); + } unlink(debug_path); g_free(debug_path); From 3195c9e6abe96b367a671474e850ae3f89781880 Mon Sep 17 00:00:00 2001 From: Lev Kujawski Date: Thu, 7 Jul 2022 03:11:36 +0000 Subject: [PATCH 0787/1020] hw/ide/core: Clear LBA and drive bits for EXECUTE DEVICE DIAGNOSTIC Prior to this patch, cmd_exec_dev_diagnostic relied upon ide_set_signature to clear the device register. While the preservation of the drive bit by ide_set_signature is necessary for the DEVICE RESET, IDENTIFY DEVICE, and READ SECTOR commands, ATA/ATAPI-6 specifies that "DEV shall be cleared to zero" for EXECUTE DEVICE DIAGNOSTIC. This deviation was uncovered by the ATACT Device Testing Program written by Hale Landis. Signed-off-by: Lev Kujawski Message-Id: <20220707031140.158958-3-lkujaw@member.fsf.org> Signed-off-by: Kevin Wolf --- hw/ide/core.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/hw/ide/core.c b/hw/ide/core.c index 7cbc0a54a7..b747191ebf 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -1704,8 +1704,14 @@ static bool cmd_identify_packet(IDEState *s, uint8_t cmd) return false; } +/* EXECUTE DEVICE DIAGNOSTIC */ static bool cmd_exec_dev_diagnostic(IDEState *s, uint8_t cmd) { + /* + * Clear the device register per the ATA (v6) specification, + * because ide_set_signature does not clear LBA or drive bits. + */ + s->select = (ATA_DEV_ALWAYS_ON); ide_set_signature(s); if (s->drive_kind == IDE_CD) { From 2cc38a02e61e0f4d858df2cfa5388f72bddcd634 Mon Sep 17 00:00:00 2001 From: Lev Kujawski Date: Thu, 7 Jul 2022 03:11:37 +0000 Subject: [PATCH 0788/1020] tests/qtest/ide-test: Verify that DIAGNOSTIC clears DEV to zero Verify correction of EXECUTE DEVICE DIAGNOSTIC introduced in commit 72423831c3 (hw/ide/core: Clear LBA and drive bits for EXECUTE DEVICE DIAGNOSTIC, 2022-05-28). Signed-off-by: Lev Kujawski Message-Id: <20220707031140.158958-4-lkujaw@member.fsf.org> Signed-off-by: Kevin Wolf --- tests/qtest/ide-test.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/tests/qtest/ide-test.c b/tests/qtest/ide-test.c index 93b4416023..dbe1563b23 100644 --- a/tests/qtest/ide-test.c +++ b/tests/qtest/ide-test.c @@ -90,6 +90,7 @@ enum { enum { CMD_DSM = 0x06, + CMD_DIAGNOSE = 0x90, CMD_READ_DMA = 0xc8, CMD_WRITE_DMA = 0xca, CMD_FLUSH_CACHE = 0xe7, @@ -614,6 +615,36 @@ static void test_identify(void) free_pci_device(dev); } +static void test_diagnostic(void) +{ + QTestState *qts; + QPCIDevice *dev; + QPCIBar bmdma_bar, ide_bar; + uint8_t data; + + qts = ide_test_start( + "-blockdev driver=file,node-name=hda,filename=%s " + "-blockdev driver=file,node-name=hdb,filename=%s " + "-device ide-hd,drive=hda,bus=ide.0,unit=0 " + "-device ide-hd,drive=hdb,bus=ide.0,unit=1 ", + tmp_path[0], tmp_path[1]); + + dev = get_pci_device(qts, &bmdma_bar, &ide_bar); + + /* DIAGNOSE command on device 1 */ + qpci_io_writeb(dev, ide_bar, reg_device, DEV); + data = qpci_io_readb(dev, ide_bar, reg_device); + g_assert_cmphex(data & DEV, ==, DEV); + qpci_io_writeb(dev, ide_bar, reg_command, CMD_DIAGNOSE); + + /* Verify that DEVICE is now 0 */ + data = qpci_io_readb(dev, ide_bar, reg_device); + g_assert_cmphex(data & DEV, ==, 0); + + ide_test_quit(qts); + free_pci_device(dev); +} + /* * Write sector 1 with random data to make IDE storage dirty * Needed for flush tests so that flushes actually go though the block layer @@ -1050,6 +1081,8 @@ int main(int argc, char **argv) qtest_add_func("/ide/identify", test_identify); + qtest_add_func("/ide/diagnostic", test_diagnostic); + qtest_add_func("/ide/bmdma/simple_rw", test_bmdma_simple_rw); qtest_add_func("/ide/bmdma/trim", test_bmdma_trim); qtest_add_func("/ide/bmdma/various_prdts", test_bmdma_various_prdts); From 176e4961bb33d559da1af441fb0ee2e0cb8245ae Mon Sep 17 00:00:00 2001 From: Lev Kujawski Date: Thu, 7 Jul 2022 03:11:40 +0000 Subject: [PATCH 0789/1020] hw/ide/core.c: Implement ATA INITIALIZE_DEVICE_PARAMETERS command CHS-based disk utilities and operating systems may adjust the logical geometry of a hard drive to cope with the expectations or limitations of software using the ATA INITIALIZE_DEVICE_PARAMETERS command. Prior to this patch, INITIALIZE_DEVICE_PARAMETERS was a nop that always returned success, raising the possibility of data loss or corruption if the CHS<->LBA translation redirected a write to the wrong sector. * hw/ide/core.c ide_reset(): Reset the logical CHS geometry of the hard disk when the power-on defaults feature is enabled. cmd_specify(): a) New function implementing INITIALIZE_DEVICE_PARAMETERS. b) Ignore calls for empty or ATAPI devices. cmd_set_features(): Implement the power-on defaults enable and disable features. struct ide_cmd_table: Switch WIN_SPECIFY from cmd_nop() to cmd_specify(). ide_init_drive(): Set new fields 'drive_heads' and 'drive_sectors' based upon the actual disk geometry. * include/hw/ide/internal.h struct IDEState: a) Store the actual drive CHS values within the new fields 'drive_heads' and 'drive_sectors.' b) Track whether a soft IDE reset should also reset the logical CHS geometry of the hard disk within the new field 'reset_reverts'. Signed-off-by: Lev Kujawski Message-Id: <20220707031140.158958-7-lkujaw@member.fsf.org> Signed-off-by: Kevin Wolf --- hw/ide/core.c | 29 ++++++++++++++++++++++++++--- include/hw/ide/internal.h | 3 +++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/hw/ide/core.c b/hw/ide/core.c index b747191ebf..39afdc0006 100644 --- a/hw/ide/core.c +++ b/hw/ide/core.c @@ -1340,6 +1340,11 @@ static void ide_reset(IDEState *s) s->pio_aiocb = NULL; } + if (s->reset_reverts) { + s->reset_reverts = false; + s->heads = s->drive_heads; + s->sectors = s->drive_sectors; + } if (s->drive_kind == IDE_CFATA) s->mult_sectors = 0; else @@ -1618,6 +1623,20 @@ static bool cmd_check_power_mode(IDEState *s, uint8_t cmd) return true; } +/* INITIALIZE DEVICE PARAMETERS */ +static bool cmd_specify(IDEState *s, uint8_t cmd) +{ + if (s->blk && s->drive_kind != IDE_CD) { + s->heads = (s->select & (ATA_DEV_HS)) + 1; + s->sectors = s->nsector; + ide_set_irq(s->bus); + } else { + ide_abort_command(s); + } + + return true; +} + static bool cmd_set_features(IDEState *s, uint8_t cmd) { uint16_t *identify_data; @@ -1641,7 +1660,11 @@ static bool cmd_set_features(IDEState *s, uint8_t cmd) ide_flush_cache(s); return false; case 0xcc: /* reverting to power-on defaults enable */ + s->reset_reverts = true; + return true; case 0x66: /* reverting to power-on defaults disable */ + s->reset_reverts = false; + return true; case 0xaa: /* read look-ahead enable */ case 0x55: /* read look-ahead disable */ case 0x05: /* set advanced power management mode */ @@ -2051,7 +2074,7 @@ static const struct { [WIN_SEEK] = { cmd_seek, HD_CFA_OK | SET_DSC }, [CFA_TRANSLATE_SECTOR] = { cmd_cfa_translate_sector, CFA_OK }, [WIN_DIAGNOSE] = { cmd_exec_dev_diagnostic, ALL_OK }, - [WIN_SPECIFY] = { cmd_nop, HD_CFA_OK | SET_DSC }, + [WIN_SPECIFY] = { cmd_specify, HD_CFA_OK | SET_DSC }, [WIN_STANDBYNOW2] = { cmd_nop, HD_CFA_OK }, [WIN_IDLEIMMEDIATE2] = { cmd_nop, HD_CFA_OK }, [WIN_STANDBY2] = { cmd_nop, HD_CFA_OK }, @@ -2541,8 +2564,8 @@ int ide_init_drive(IDEState *s, BlockBackend *blk, IDEDriveKind kind, blk_get_geometry(blk, &nb_sectors); s->cylinders = cylinders; - s->heads = heads; - s->sectors = secs; + s->heads = s->drive_heads = heads; + s->sectors = s->drive_sectors = secs; s->chs_trans = chs_trans; s->nb_sectors = nb_sectors; s->wwn = wwn; diff --git a/include/hw/ide/internal.h b/include/hw/ide/internal.h index 97e7e59dc5..b17f36df95 100644 --- a/include/hw/ide/internal.h +++ b/include/hw/ide/internal.h @@ -375,6 +375,7 @@ struct IDEState { uint8_t unit; /* ide config */ IDEDriveKind drive_kind; + int drive_heads, drive_sectors; int cylinders, heads, sectors, chs_trans; int64_t nb_sectors; int mult_sectors; @@ -401,6 +402,8 @@ struct IDEState { uint8_t select; uint8_t status; + bool reset_reverts; + /* set for lba48 access */ uint8_t lba48; BlockBackend *blk; From b772528acbd4669a56c8bbc16d78f8f4335c1aa3 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Tue, 20 Sep 2022 01:07:44 -0700 Subject: [PATCH 0790/1020] Hexagon (target/hexagon) add instruction attributes from archlib The imported files from the architecture library have added some instruction attributes. Some of these will be used in a subsequent patch for determing the size of a store. Signed-off-by: Taylor Simpson Acked-by: Richard Henderson Message-Id: <20220920080746.26791-2-tsimpson@quicinc.com> --- target/hexagon/attribs_def.h.inc | 37 +++++++- target/hexagon/imported/ldst.idef | 122 +++++++++++++------------- target/hexagon/imported/subinsns.idef | 72 +++++++-------- 3 files changed, 133 insertions(+), 98 deletions(-) diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc index dc890a557f..222ad95fb0 100644 --- a/target/hexagon/attribs_def.h.inc +++ b/target/hexagon/attribs_def.h.inc @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,6 +38,16 @@ DEF_ATTRIB(SUBINSN, "sub-instruction", "", "") /* Load and Store attributes */ DEF_ATTRIB(LOAD, "Loads from memory", "", "") DEF_ATTRIB(STORE, "Stores to memory", "", "") +DEF_ATTRIB(STOREIMMED, "Stores immed to memory", "", "") +DEF_ATTRIB(MEMSIZE_0B, "Memory width is 0 byte", "", "") +DEF_ATTRIB(MEMSIZE_1B, "Memory width is 1 byte", "", "") +DEF_ATTRIB(MEMSIZE_2B, "Memory width is 2 bytes", "", "") +DEF_ATTRIB(MEMSIZE_4B, "Memory width is 4 bytes", "", "") +DEF_ATTRIB(MEMSIZE_8B, "Memory width is 8 bytes", "", "") +DEF_ATTRIB(REGWRSIZE_1B, "Memory width is 1 byte", "", "") +DEF_ATTRIB(REGWRSIZE_2B, "Memory width is 2 bytes", "", "") +DEF_ATTRIB(REGWRSIZE_4B, "Memory width is 4 bytes", "", "") +DEF_ATTRIB(REGWRSIZE_8B, "Memory width is 8 bytes", "", "") DEF_ATTRIB(MEMLIKE, "Memory-like instruction", "", "") DEF_ATTRIB(MEMLIKE_PACKET_RULES, "follows Memory-like packet rules", "", "") @@ -71,6 +81,11 @@ DEF_ATTRIB(COF, "Change-of-flow instruction", "", "") DEF_ATTRIB(CONDEXEC, "May be cancelled by a predicate", "", "") DEF_ATTRIB(DOTNEWVALUE, "Uses a register value generated in this pkt", "", "") DEF_ATTRIB(NEWCMPJUMP, "Compound compare and jump", "", "") +DEF_ATTRIB(NVSTORE, "New-value store", "", "") +DEF_ATTRIB(MEMOP, "memop", "", "") + +DEF_ATTRIB(ROPS_2, "Compound instruction worth 2 RISC-ops", "", "") +DEF_ATTRIB(ROPS_3, "Compound instruction worth 3 RISC-ops", "", "") /* access to implicit registers */ DEF_ATTRIB(IMPLICIT_WRITES_LR, "Writes the link register", "", "UREG.LR") @@ -87,6 +102,9 @@ DEF_ATTRIB(IMPLICIT_WRITES_P3, "May write Predicate 3", "", "UREG.P3") DEF_ATTRIB(IMPLICIT_READS_PC, "Reads the PC register", "", "") DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "") DEF_ATTRIB(WRITES_PRED_REG, "Writes a predicate register", "", "") +DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "") +DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "") +DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "") DEF_ATTRIB(CRSLOT23, "Can execute in slot 2 or slot 3 (CR)", "", "") DEF_ATTRIB(IT_NOP, "nop instruction", "", "") @@ -94,17 +112,21 @@ DEF_ATTRIB(IT_EXTENDER, "constant extender instruction", "", "") /* Restrictions to make note of */ +DEF_ATTRIB(RESTRICT_COF_MAX1, "One change-of-flow per packet", "", "") +DEF_ATTRIB(RESTRICT_NOPACKET, "Not allowed in a packet", "", "") DEF_ATTRIB(RESTRICT_SLOT0ONLY, "Must execute on slot0", "", "") DEF_ATTRIB(RESTRICT_SLOT1ONLY, "Must execute on slot1", "", "") DEF_ATTRIB(RESTRICT_SLOT2ONLY, "Must execute on slot2", "", "") DEF_ATTRIB(RESTRICT_SLOT3ONLY, "Must execute on slot3", "", "") DEF_ATTRIB(RESTRICT_NOSLOT1, "No slot 1 instruction in parallel", "", "") DEF_ATTRIB(RESTRICT_PREFERSLOT0, "Try to encode into slot 0", "", "") +DEF_ATTRIB(RESTRICT_PACKET_AXOK, "May exist with A-type or X-type", "", "") DEF_ATTRIB(ICOP, "Instruction cache op", "", "") DEF_ATTRIB(HWLOOP0_END, "Ends HW loop0", "", "") DEF_ATTRIB(HWLOOP1_END, "Ends HW loop1", "", "") +DEF_ATTRIB(RET_TYPE, "return type", "", "") DEF_ATTRIB(DCZEROA, "dczeroa type", "", "") DEF_ATTRIB(ICFLUSHOP, "icflush op type", "", "") DEF_ATTRIB(DCFLUSHOP, "dcflush op type", "", "") @@ -116,5 +138,18 @@ DEF_ATTRIB(L2FETCH, "Instruction is l2fetch type", "", "") DEF_ATTRIB(ICINVA, "icinva", "", "") DEF_ATTRIB(DCCLEANINVA, "dccleaninva", "", "") +/* Documentation Notes */ +DEF_ATTRIB(NOTE_CONDITIONAL, "can be conditionally executed", "", "") +DEF_ATTRIB(NOTE_NEWVAL_SLOT0, "New-value oprnd must execute on slot 0", "", "") +DEF_ATTRIB(NOTE_PRIV, "Monitor-level feature", "", "") +DEF_ATTRIB(NOTE_NOPACKET, "solo instruction", "", "") +DEF_ATTRIB(NOTE_AXOK, "May only be grouped with ALU32 or non-FP XTYPE.", "", "") +DEF_ATTRIB(NOTE_LATEPRED, "The predicate can not be used as a .new", "", "") +DEF_ATTRIB(NOTE_NVSLOT0, "Can execute only in slot 0 (ST)", "", "") + +/* Restrictions to make note of */ +DEF_ATTRIB(RESTRICT_NOSLOT1_STORE, "Packet must not have slot 1 store", "", "") +DEF_ATTRIB(RESTRICT_LATEPRED, "Predicate can not be used as a .new.", "", "") + /* Keep this as the last attribute: */ DEF_ATTRIB(ZZ_LASTATTRIB, "Last attribute in the file", "", "") diff --git a/target/hexagon/imported/ldst.idef b/target/hexagon/imported/ldst.idef index 359d3b744e..237634bdd9 100644 --- a/target/hexagon/imported/ldst.idef +++ b/target/hexagon/imported/ldst.idef @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -31,12 +31,12 @@ Q6INSN(L2_##TAG##_pci, OPER"(Rx32++#s4:"SHFT":circ(Mu2))",ATTRIB,DESCR,{fEA_REG( Q6INSN(L2_##TAG##_pcr, OPER"(Rx32++I:circ(Mu2))", ATTRIB,DESCR,{fEA_REG(RxV); fPM_CIRR(RxV,fREAD_IREG(MuV)< Date: Tue, 20 Sep 2022 01:07:46 -0700 Subject: [PATCH 0791/1020] Hexagon (target/hexagon) Change decision to set pkt_has_store_s[01] We have found cases where pkt_has_store_s[01] is set incorrectly. This leads to generating an unnecessary store that is left over from a previous packet. Add an attribute to determine if an instruction is a scalar store The attribute is attached to the fSTORE macro (hex_common.py) Update the logic in decode.c that sets pkt_has_store_s[01] Signed-off-by: Taylor Simpson Reviewed-by: Richard Henderson Message-Id: <20220920080746.26791-4-tsimpson@quicinc.com> --- target/hexagon/attribs_def.h.inc | 1 + target/hexagon/decode.c | 13 ++++++++----- target/hexagon/hex_common.py | 3 ++- target/hexagon/translate.c | 10 ++++++---- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc index 222ad95fb0..5d2a102c18 100644 --- a/target/hexagon/attribs_def.h.inc +++ b/target/hexagon/attribs_def.h.inc @@ -44,6 +44,7 @@ DEF_ATTRIB(MEMSIZE_1B, "Memory width is 1 byte", "", "") DEF_ATTRIB(MEMSIZE_2B, "Memory width is 2 bytes", "", "") DEF_ATTRIB(MEMSIZE_4B, "Memory width is 4 bytes", "", "") DEF_ATTRIB(MEMSIZE_8B, "Memory width is 8 bytes", "", "") +DEF_ATTRIB(SCALAR_STORE, "Store is scalar", "", "") DEF_ATTRIB(REGWRSIZE_1B, "Memory width is 1 byte", "", "") DEF_ATTRIB(REGWRSIZE_2B, "Memory width is 2 bytes", "", "") DEF_ATTRIB(REGWRSIZE_4B, "Memory width is 4 bytes", "", "") diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c index 6f0f27b4ba..6b73b5c60c 100644 --- a/target/hexagon/decode.c +++ b/target/hexagon/decode.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -402,10 +402,13 @@ static void decode_set_insn_attr_fields(Packet *pkt) } if (GET_ATTRIB(opcode, A_STORE)) { - if (pkt->insn[i].slot == 0) { - pkt->pkt_has_store_s0 = true; - } else { - pkt->pkt_has_store_s1 = true; + if (GET_ATTRIB(opcode, A_SCALAR_STORE) && + !GET_ATTRIB(opcode, A_MEMSIZE_0B)) { + if (pkt->insn[i].slot == 0) { + pkt->pkt_has_store_s0 = true; + } else { + pkt->pkt_has_store_s1 = true; + } } } diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py index c81aca8d2a..d9ba7df786 100755 --- a/target/hexagon/hex_common.py +++ b/target/hexagon/hex_common.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 ## -## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. +## Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by @@ -75,6 +75,7 @@ def calculate_attribs(): add_qemu_macro_attrib('fWRITE_P3', 'A_WRITES_PRED_REG') add_qemu_macro_attrib('fSET_OVERFLOW', 'A_IMPLICIT_WRITES_USR') add_qemu_macro_attrib('fSET_LPCFG', 'A_IMPLICIT_WRITES_USR') + add_qemu_macro_attrib('fSTORE', 'A_SCALAR_STORE') # Recurse down macros, find attributes from sub-macros macroValues = list(macros.values()) diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index 0e8a0772f7..b6b834b4ee 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved. + * Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -499,10 +499,12 @@ static void process_store_log(DisasContext *ctx, Packet *pkt) * slot 1 and then slot 0. This will be important when * the memory accesses overlap. */ - if (pkt->pkt_has_store_s1 && !pkt->pkt_has_dczeroa) { + if (pkt->pkt_has_store_s1) { + g_assert(!pkt->pkt_has_dczeroa); process_store(ctx, pkt, 1); } - if (pkt->pkt_has_store_s0 && !pkt->pkt_has_dczeroa) { + if (pkt->pkt_has_store_s0) { + g_assert(!pkt->pkt_has_dczeroa); process_store(ctx, pkt, 0); } } @@ -665,7 +667,7 @@ static void gen_commit_packet(CPUHexagonState *env, DisasContext *ctx, * The dczeroa will be the store in slot 0, check that we don't have * a store in slot 1 or an HVX store. */ - g_assert(has_store_s0 && !has_store_s1 && !has_hvx_store); + g_assert(!has_store_s1 && !has_hvx_store); process_dczeroa(ctx, pkt); } else if (has_hvx_store) { TCGv mem_idx = tcg_constant_tl(ctx->mem_idx); From 661ad999c554d1cc99ff96b3baf3ff4acbe2ecee Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Tue, 20 Sep 2022 01:07:45 -0700 Subject: [PATCH 0792/1020] Hexagon (target/hexagon) move store size tracking to translation The store width is needed for packet commit, so it is stored in ctx->store_width. Currently, it is set when a store has a TCG override instead of a QEMU helper. In the QEMU helper case, the ctx->store_width is not set, we invoke a helper during packet commit that uses the runtime store width. This patch ensures ctx->store_width is set for all store instructions, so performance is improved because packet commit can generate the proper TCG store rather than the generic helper. We do this by - Use the attributes from the instructions during translation to set ctx->store_width - Remove setting of ctx->store_width from genptr.c Signed-off-by: Taylor Simpson Reviewed-by: Richard Henderson Message-Id: <20220920080746.26791-3-tsimpson@quicinc.com> --- target/hexagon/genptr.c | 36 ++++++++++++------------------------ target/hexagon/macros.h | 8 ++++---- target/hexagon/translate.c | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 28 deletions(-) diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index 8a334ba07b..806d0974ff 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -401,62 +401,50 @@ static inline void gen_store32(TCGv vaddr, TCGv src, int width, int slot) tcg_gen_mov_tl(hex_store_val32[slot], src); } -static inline void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, - DisasContext *ctx, int slot) +static inline void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, int slot) { gen_store32(vaddr, src, 1, slot); - ctx->store_width[slot] = 1; } -static inline void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, - DisasContext *ctx, int slot) +static inline void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, int slot) { TCGv tmp = tcg_constant_tl(src); - gen_store1(cpu_env, vaddr, tmp, ctx, slot); + gen_store1(cpu_env, vaddr, tmp, slot); } -static inline void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, - DisasContext *ctx, int slot) +static inline void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, int slot) { gen_store32(vaddr, src, 2, slot); - ctx->store_width[slot] = 2; } -static inline void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, - DisasContext *ctx, int slot) +static inline void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, int slot) { TCGv tmp = tcg_constant_tl(src); - gen_store2(cpu_env, vaddr, tmp, ctx, slot); + gen_store2(cpu_env, vaddr, tmp, slot); } -static inline void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, - DisasContext *ctx, int slot) +static inline void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, int slot) { gen_store32(vaddr, src, 4, slot); - ctx->store_width[slot] = 4; } -static inline void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, - DisasContext *ctx, int slot) +static inline void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, int slot) { TCGv tmp = tcg_constant_tl(src); - gen_store4(cpu_env, vaddr, tmp, ctx, slot); + gen_store4(cpu_env, vaddr, tmp, slot); } -static inline void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, - DisasContext *ctx, int slot) +static inline void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, int slot) { tcg_gen_mov_tl(hex_store_addr[slot], vaddr); tcg_gen_movi_tl(hex_store_width[slot], 8); tcg_gen_mov_i64(hex_store_val64[slot], src); - ctx->store_width[slot] = 8; } -static inline void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, - DisasContext *ctx, int slot) +static inline void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, int slot) { TCGv_i64 tmp = tcg_constant_i64(src); - gen_store8(cpu_env, vaddr, tmp, ctx, slot); + gen_store8(cpu_env, vaddr, tmp, slot); } static TCGv gen_8bitsof(TCGv result, TCGv value) diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h index 92eb8bbf05..c8805bdaeb 100644 --- a/target/hexagon/macros.h +++ b/target/hexagon/macros.h @@ -156,7 +156,7 @@ __builtin_choose_expr(TYPE_TCGV(X), \ gen_store1, (void)0)) #define MEM_STORE1(VA, DATA, SLOT) \ - MEM_STORE1_FUNC(DATA)(cpu_env, VA, DATA, ctx, SLOT) + MEM_STORE1_FUNC(DATA)(cpu_env, VA, DATA, SLOT) #define MEM_STORE2_FUNC(X) \ __builtin_choose_expr(TYPE_INT(X), \ @@ -164,7 +164,7 @@ __builtin_choose_expr(TYPE_TCGV(X), \ gen_store2, (void)0)) #define MEM_STORE2(VA, DATA, SLOT) \ - MEM_STORE2_FUNC(DATA)(cpu_env, VA, DATA, ctx, SLOT) + MEM_STORE2_FUNC(DATA)(cpu_env, VA, DATA, SLOT) #define MEM_STORE4_FUNC(X) \ __builtin_choose_expr(TYPE_INT(X), \ @@ -172,7 +172,7 @@ __builtin_choose_expr(TYPE_TCGV(X), \ gen_store4, (void)0)) #define MEM_STORE4(VA, DATA, SLOT) \ - MEM_STORE4_FUNC(DATA)(cpu_env, VA, DATA, ctx, SLOT) + MEM_STORE4_FUNC(DATA)(cpu_env, VA, DATA, SLOT) #define MEM_STORE8_FUNC(X) \ __builtin_choose_expr(TYPE_INT(X), \ @@ -180,7 +180,7 @@ __builtin_choose_expr(TYPE_TCGV_I64(X), \ gen_store8, (void)0)) #define MEM_STORE8(VA, DATA, SLOT) \ - MEM_STORE8_FUNC(DATA)(cpu_env, VA, DATA, ctx, SLOT) + MEM_STORE8_FUNC(DATA)(cpu_env, VA, DATA, SLOT) #else #define MEM_LOAD1s(VA) ((int8_t)mem_load1(env, slot, VA)) #define MEM_LOAD1u(VA) ((uint8_t)mem_load1(env, slot, VA)) diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c index b6b834b4ee..2329177537 100644 --- a/target/hexagon/translate.c +++ b/target/hexagon/translate.c @@ -327,6 +327,30 @@ static void mark_implicit_pred_writes(DisasContext *ctx, Insn *insn) mark_implicit_pred_write(ctx, insn, A_IMPLICIT_WRITES_P3, 3); } +static void mark_store_width(DisasContext *ctx, Insn *insn) +{ + uint16_t opcode = insn->opcode; + uint32_t slot = insn->slot; + uint8_t width = 0; + + if (GET_ATTRIB(opcode, A_SCALAR_STORE)) { + if (GET_ATTRIB(opcode, A_MEMSIZE_1B)) { + width |= 1; + } + if (GET_ATTRIB(opcode, A_MEMSIZE_2B)) { + width |= 2; + } + if (GET_ATTRIB(opcode, A_MEMSIZE_4B)) { + width |= 4; + } + if (GET_ATTRIB(opcode, A_MEMSIZE_8B)) { + width |= 8; + } + tcg_debug_assert(is_power_of_2(width)); + ctx->store_width[slot] = width; + } +} + static void gen_insn(CPUHexagonState *env, DisasContext *ctx, Insn *insn, Packet *pkt) { @@ -334,6 +358,7 @@ static void gen_insn(CPUHexagonState *env, DisasContext *ctx, mark_implicit_reg_writes(ctx, insn); insn->generate(env, ctx, insn, pkt); mark_implicit_pred_writes(ctx, insn); + mark_store_width(ctx, insn); } else { gen_exception_end_tb(ctx, HEX_EXCP_INVALID_OPCODE); } From bb2dc4b73a30613216c048fe2a6551e011d1c963 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 30 Sep 2022 09:53:02 +0200 Subject: [PATCH 0793/1020] meson: -display dbus and CFI are incompatible The generated skeletons for DBus call the finalize method of the parent type using code like G_OBJECT_CLASS (qemu_dbus_display1_chardev_skeleton_parent_class)->finalize (object); However, the finalize method is defined in a shared library that is not compiled with CFI. Do not enable anything that uses gdbus-codegen if --enable-cfi was specified. Signed-off-by: Paolo Bonzini --- meson.build | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 3885fc1076..ca47ecbffe 100644 --- a/meson.build +++ b/meson.build @@ -487,6 +487,7 @@ meson.override_dependency('glib-2.0', glib) gio = not_found gdbus_codegen = not_found +gdbus_codegen_error = '@0@ requires gdbus-codegen, please install libgio' if not get_option('gio').auto() or have_system gio = dependency('gio-2.0', required: get_option('gio'), method: 'pkg-config', kwargs: static_kwargs) @@ -511,6 +512,10 @@ if not get_option('gio').auto() or have_system version: gio.version()) endif endif +if gdbus_codegen.found() and get_option('cfi') + gdbus_codegen = not_found + gdbus_codegen_error = '@0@ uses gdbus-codegen, which does not support control flow integrity' +endif lttng = not_found if 'ust' in get_option('trace_backends') @@ -1676,7 +1681,7 @@ dbus_display = get_option('dbus_display') \ .require(enable_modules, error_message: '-display dbus requires --enable-modules') \ .require(gdbus_codegen.found(), - error_message: '-display dbus requires gdbus-codegen') \ + error_message: gdbus_codegen_error.format('-display dbus')) \ .require(opengl.found() and gbm.found(), error_message: '-display dbus requires epoxy/egl and gbm') \ .allowed() From 8a29c20597f98e20c7390300b63fa6ac7d3ad6dd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 23 Dec 2021 15:29:56 +0100 Subject: [PATCH 0794/1020] meson: require 0.61.3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes the dependency of dbus-display on --enable-modules. It also allows cleanups in modinfo collection and allows moving C++ compiler detection to meson.build. Because it is now deprecated to use install_subdir to create an empty directory, replace it with install_emptydir. Updating the Meson submodule to 0.61.5 also removes the message WARNING: Broken python installation detected. Python files installed by Meson might not be found by python interpreter. unless using system meson is forced with --meson. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/873 Resolves: https://gitlab.com/qemu-project/qemu/-/issues/848 Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Paolo Bonzini --- configure | 2 +- meson | 2 +- meson.build | 5 +---- qga/meson.build | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/configure b/configure index 894e37310f..c5069775db 100755 --- a/configure +++ b/configure @@ -1114,7 +1114,7 @@ fi python="$python -B" if test -z "$meson"; then - if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.59.3; then + if test "$explicit_python" = no && has meson && version_ge "$(meson --version)" 0.61.5; then meson=meson elif test "$git_submodules_action" != 'ignore' ; then meson=git diff --git a/meson b/meson index 12f9f04ba0..3a9b285a55 160000 --- a/meson +++ b/meson @@ -1 +1 @@ -Subproject commit 12f9f04ba0decfda425dbbf9a501084c153a2d18 +Subproject commit 3a9b285a55b91b53b2acda987192274352ecb5be diff --git a/meson.build b/meson.build index ca47ecbffe..077441fe88 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('qemu', ['c'], meson_version: '>=0.59.3', +project('qemu', ['c'], meson_version: '>=0.61.3', default_options: ['warning_level=1', 'c_std=gnu11', 'cpp_std=gnu++11', 'b_colorout=auto', 'b_staticpic=false', 'stdsplit=false', 'optimization=2', 'b_pie=true'], version: files('VERSION')) @@ -1674,12 +1674,9 @@ endif have_host_block_device = (targetos != 'darwin' or cc.has_header('IOKit/storage/IOMedia.h')) -# FIXME enable_modules shouldn't be necessary, but: https://github.com/mesonbuild/meson/issues/8333 dbus_display = get_option('dbus_display') \ .require(gio.version().version_compare('>=2.64'), error_message: '-display dbus requires glib>=2.64') \ - .require(enable_modules, - error_message: '-display dbus requires --enable-modules') \ .require(gdbus_codegen.found(), error_message: gdbus_codegen_error.format('-display dbus')) \ .require(opengl.found() and gbm.found(), diff --git a/qga/meson.build b/qga/meson.build index 65c1e93846..a0ffd6d268 100644 --- a/qga/meson.build +++ b/qga/meson.build @@ -138,7 +138,7 @@ else if get_option('guest_agent_msi').enabled() error('MSI guest agent package is available only for MinGW Windows cross-compilation') endif - install_subdir('run', install_dir: get_option('localstatedir')) + install_emptydir(get_option('localstatedir') / 'run') endif alias_target('qemu-ga', all_qga) From 6d3226357fb848499aacf609bf628932bca781ea Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Sun, 27 Mar 2022 16:05:58 +0200 Subject: [PATCH 0795/1020] meson: multiple names can be passed to dependency() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is new in Meson 0.60.0. Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Paolo Bonzini --- meson.build | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/meson.build b/meson.build index 077441fe88..780654b00c 100644 --- a/meson.build +++ b/meson.build @@ -830,14 +830,10 @@ if have_system and get_option('curses').allowed() }''' curses_dep_list = targetos == 'windows' ? ['ncurses', 'ncursesw'] : ['ncursesw'] - foreach curses_dep : curses_dep_list - if not curses.found() - curses = dependency(curses_dep, - required: false, - method: 'pkg-config', - kwargs: static_kwargs) - endif - endforeach + curses = dependency(curses_dep_list, + required: false, + method: 'pkg-config', + kwargs: static_kwargs) msg = get_option('curses').enabled() ? 'curses library not found' : '' curses_compile_args = ['-DNCURSES_WIDECHAR=1'] if curses.found() From b485458e00dae4af5e2b7b1c17521e2885180544 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 8 Nov 2021 12:31:52 +0100 Subject: [PATCH 0796/1020] configure, meson: move C++ compiler detection to meson.build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test is slightly weaker than before, because it does not call an extern "C" function from a C source file. However, in practice what we seek to detect is ABI compatibility of the various sanitizer flags, and for that it is enough to compile anything with CC and link it with CXX. Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Paolo Bonzini --- configure | 57 -------------------------------------------------- meson.build | 37 ++++++++++++++++++++++---------- scripts/main.c | 1 + 3 files changed, 27 insertions(+), 68 deletions(-) create mode 100644 scripts/main.c diff --git a/configure b/configure index c5069775db..3e3c0f36c9 100755 --- a/configure +++ b/configure @@ -75,7 +75,6 @@ fi TMPB="qemu-conf" TMPC="${TMPDIR1}/${TMPB}.c" TMPO="${TMPDIR1}/${TMPB}.o" -TMPCXX="${TMPDIR1}/${TMPB}.cxx" TMPM="${TMPDIR1}/${TMPB}.m" TMPE="${TMPDIR1}/${TMPB}.exe" @@ -158,10 +157,6 @@ do_cc() { do_compiler_werror "$cc" $CPU_CFLAGS "$@" } -do_cxx() { - do_compiler_werror "$cxx" $CPU_CFLAGS "$@" -} - do_objc() { do_compiler_werror "$objcc" $CPU_CFLAGS "$@" } @@ -171,24 +166,6 @@ add_to() { eval $1=\${$1:+\"\$$1 \"}\$2 } -update_cxxflags() { - # Set QEMU_CXXFLAGS from QEMU_CFLAGS by filtering out those - # options which some versions of GCC's C++ compiler complain about - # because they only make sense for C programs. - QEMU_CXXFLAGS="-D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS" - CONFIGURE_CXXFLAGS=$(echo "$CONFIGURE_CFLAGS" | sed s/-std=gnu11/-std=gnu++11/) - for arg in $QEMU_CFLAGS; do - case $arg in - -Wstrict-prototypes|-Wmissing-prototypes|-Wnested-externs|\ - -Wold-style-declaration|-Wold-style-definition|-Wredundant-decls) - ;; - *) - QEMU_CXXFLAGS=${QEMU_CXXFLAGS:+$QEMU_CXXFLAGS }$arg - ;; - esac - done -} - compile_object() { local_cflags="$1" do_cc $CFLAGS $EXTRA_CFLAGS $CONFIGURE_CFLAGS $QEMU_CFLAGS $local_cflags -c -o $TMPO $TMPC @@ -2362,38 +2339,6 @@ fi ####################################### # generate config-host.mak -# Check that the C++ compiler exists and works with the C compiler. -# All the QEMU_CXXFLAGS are based on QEMU_CFLAGS. Keep this at the end to don't miss any other that could be added. -if has $cxx; then - cat > $TMPC < $TMPCXX <> $config_host_mak echo "NINJA=$ninja" >> $config_host_mak echo "CC=$cc" >> $config_host_mak echo "QEMU_CFLAGS=$QEMU_CFLAGS" >> $config_host_mak -echo "QEMU_CXXFLAGS=$QEMU_CXXFLAGS" >> $config_host_mak echo "QEMU_OBJCFLAGS=$QEMU_OBJCFLAGS" >> $config_host_mak echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak echo "GLIB_LIBS=$glib_libs" >> $config_host_mak @@ -2665,7 +2609,6 @@ if test "$skip_meson" = no; then echo "${a}-softmmu = '$c'" >> $cross done - test -z "$cxx" && echo "link_language = 'c'" >> $cross echo "[built-in options]" >> $cross echo "c_args = [$(meson_quote $CFLAGS $EXTRA_CFLAGS)]" >> $cross echo "cpp_args = [$(meson_quote $CXXFLAGS $EXTRA_CXXFLAGS)]" >> $cross diff --git a/meson.build b/meson.build index 780654b00c..9c57ebdfb9 100644 --- a/meson.build +++ b/meson.build @@ -180,7 +180,6 @@ endif ################## qemu_cflags = config_host['QEMU_CFLAGS'].split() -qemu_cxxflags = config_host['QEMU_CXXFLAGS'].split() qemu_objcflags = config_host['QEMU_OBJCFLAGS'].split() qemu_ldflags = config_host['QEMU_LDFLAGS'].split() @@ -194,7 +193,6 @@ endif if get_option('gprof') qemu_cflags += ['-p'] - qemu_cxxflags += ['-p'] qemu_objcflags += ['-p'] qemu_ldflags += ['-p'] endif @@ -240,8 +238,33 @@ if get_option('fuzzing') endif add_global_arguments(qemu_cflags, native: false, language: ['c']) -add_global_arguments(qemu_cxxflags, native: false, language: ['cpp']) add_global_arguments(qemu_objcflags, native: false, language: ['objc']) + +# Check that the C++ compiler exists and works with the C compiler. +link_language = 'c' +linker = cc +qemu_cxxflags = [] +if add_languages('cpp', required: false, native: false) + cxx = meson.get_compiler('cpp') + add_global_arguments(['-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS'], + native: false, language: 'cpp') + foreach k: qemu_cflags + if k not in ['-Wstrict-prototypes', '-Wmissing-prototypes', '-Wnested-externs', + '-Wold-style-declaration', '-Wold-style-definition', '-Wredundant-decls'] + qemu_cxxflags += [k] + endif + endforeach + add_global_arguments(qemu_cxxflags, native: false, language: 'cpp') + + if cxx.links(files('scripts/main.c'), args: qemu_cflags) + link_language = 'cpp' + linker = cxx + else + message('C++ compiler does not work with C compiler') + message('Disabling C++-specific optional code') + endif +endif + add_global_link_arguments(qemu_ldflags, native: false, language: ['c', 'cpp', 'objc']) if targetos == 'linux' @@ -255,14 +278,6 @@ add_project_arguments('-iquote', '.', '-iquote', meson.current_source_dir() / 'include', language: ['c', 'cpp', 'objc']) -link_language = meson.get_external_property('link_language', 'cpp') -if link_language == 'cpp' - add_languages('cpp', required: true, native: false) - cxx = meson.get_compiler('cpp') - linker = cxx -else - linker = cc -endif if host_machine.system() == 'darwin' add_languages('objc', required: false, native: false) endif diff --git a/scripts/main.c b/scripts/main.c new file mode 100644 index 0000000000..b552c8e4ed --- /dev/null +++ b/scripts/main.c @@ -0,0 +1 @@ +int main(void) {} From e4333d14c574631029e2d9d00bcb94b81a8df800 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 15 Mar 2022 15:57:15 +0100 Subject: [PATCH 0797/1020] configure, meson: move linker flag detection to meson MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Marc-AndrĂ© Lureau Signed-off-by: Paolo Bonzini --- configure | 16 ---------------- meson.build | 13 +++++++++++++ 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/configure b/configure index 3e3c0f36c9..e032bd0a08 100755 --- a/configure +++ b/configure @@ -1342,12 +1342,10 @@ EOF if test "$static" = "yes"; then if test "$pie" != "no" && compile_prog "-Werror -fPIE -DPIE" "-static-pie"; then CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS" - QEMU_LDFLAGS="-static-pie $QEMU_LDFLAGS" pie="yes" elif test "$pie" = "yes"; then error_exit "-static-pie not available due to missing toolchain support" else - QEMU_LDFLAGS="-static $QEMU_LDFLAGS" pie="no" fi elif test "$pie" = "no"; then @@ -1369,12 +1367,6 @@ else pie="no" fi -# Detect support for PT_GNU_RELRO + DT_BIND_NOW. -# The combination is known as "full relro", because .got.plt is read-only too. -if compile_prog "" "-Wl,-z,relro -Wl,-z,now" ; then - QEMU_LDFLAGS="-Wl,-z,relro -Wl,-z,now $QEMU_LDFLAGS" -fi - ########################################## # __sync_fetch_and_and requires at least -march=i486. Many toolchains # use i686 as default anyway, but for those that don't, an explicit @@ -2242,14 +2234,6 @@ if test "$have_ubsan" = "yes"; then fi ########################################## - -# Exclude --warn-common with TSan to suppress warnings from the TSan libraries. -if test "$solaris" = "no" && test "$tsan" = "no"; then - if $ld --version 2>/dev/null | grep "GNU ld" >/dev/null 2>/dev/null ; then - QEMU_LDFLAGS="-Wl,--warn-common $QEMU_LDFLAGS" - fi -fi - # Guest agent Windows MSI package if test "$QEMU_GA_MANUFACTURER" = ""; then diff --git a/meson.build b/meson.build index 9c57ebdfb9..e9b0125b41 100644 --- a/meson.build +++ b/meson.build @@ -183,6 +183,14 @@ qemu_cflags = config_host['QEMU_CFLAGS'].split() qemu_objcflags = config_host['QEMU_OBJCFLAGS'].split() qemu_ldflags = config_host['QEMU_LDFLAGS'].split() +if enable_static + qemu_ldflags += get_option('b_pie') ? '-static-pie' : '-static' +endif + +# Detect support for PT_GNU_RELRO + DT_BIND_NOW. +# The combination is known as "full relro", because .got.plt is read-only too. +qemu_ldflags += cc.get_supported_link_arguments('-Wl,-z,relro', '-Wl,-z,now') + if targetos == 'windows' qemu_ldflags += cc.get_supported_link_arguments('-Wl,--no-seh', '-Wl,--nxcompat') # Disable ASLR for debug builds to allow debugging with gdb @@ -265,6 +273,11 @@ if add_languages('cpp', required: false, native: false) endif endif +# Exclude --warn-common with TSan to suppress warnings from the TSan libraries. +if targetos != 'sunos' and not config_host.has_key('CONFIG_TSAN') + qemu_ldflags += linker.get_supported_link_arguments('-Wl,--warn-common') +endif + add_global_link_arguments(qemu_ldflags, native: false, language: ['c', 'cpp', 'objc']) if targetos == 'linux' From c4ef867f2949bf2a2ae18a4e27cf1a34bbc8aecb Mon Sep 17 00:00:00 2001 From: Ray Zhang Date: Thu, 22 Sep 2022 18:05:23 +0800 Subject: [PATCH 0798/1020] target/i386/kvm: fix kvmclock_current_nsec: Assertion `time.tsc_timestamp <= migration_tsc' failed New KVM_CLOCK flags were added in the kernel.(c68dc1b577eabd5605c6c7c08f3e07ae18d30d5d) ``` + #define KVM_CLOCK_VALID_FLAGS \ + (KVM_CLOCK_TSC_STABLE | KVM_CLOCK_REALTIME | KVM_CLOCK_HOST_TSC) case KVM_CAP_ADJUST_CLOCK: - r = KVM_CLOCK_TSC_STABLE; + r = KVM_CLOCK_VALID_FLAGS; ``` kvm_has_adjust_clock_stable needs to handle additional flags, so that s->clock_is_reliable can be true and kvmclock_current_nsec doesn't need to be called. Signed-off-by: Ray Zhang Message-Id: <20220922100523.2362205-1-zhanglei002@gmail.com> Signed-off-by: Paolo Bonzini --- target/i386/kvm/kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index a1fd1f5379..9eeee91c2f 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -157,7 +157,7 @@ bool kvm_has_adjust_clock_stable(void) { int ret = kvm_check_extension(kvm_state, KVM_CAP_ADJUST_CLOCK); - return (ret == KVM_CLOCK_TSC_STABLE); + return (ret & KVM_CLOCK_TSC_STABLE); } bool kvm_has_adjust_clock(void) From cc63374a5a7c240b7d3be734ef589dabbefc7527 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Thu, 22 Sep 2022 17:28:47 +0200 Subject: [PATCH 0799/1020] x86: re-initialize RNG seed when selecting kernel We don't want it to be possible to re-read the RNG seed after ingesting it, because this ruins forward secrecy. Currently, however, the setup data section can just be re-read. Since the kernel is always read after the setup data, use the selection of the kernel as a trigger to re-initialize the RNG seed, just like we do on reboot, to preserve forward secrecy. Cc: Paolo Bonzini Signed-off-by: Jason A. Donenfeld Message-Id: <20220922152847.3670513-1-Jason@zx2c4.com> Signed-off-by: Paolo Bonzini --- hw/i386/x86.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/hw/i386/x86.c b/hw/i386/x86.c index f9a4ddaa4a..1148f70c03 100644 --- a/hw/i386/x86.c +++ b/hw/i386/x86.c @@ -1112,11 +1112,14 @@ void x86_load_linux(X86MachineState *x86ms, setup_data->len = cpu_to_le32(RNG_SEED_LENGTH); qemu_guest_getrandom_nofail(setup_data->data, RNG_SEED_LENGTH); qemu_register_reset(reset_rng_seed, setup_data); + fw_cfg_add_bytes_callback(fw_cfg, FW_CFG_KERNEL_DATA, reset_rng_seed, NULL, + setup_data, kernel, kernel_size, true); + } else { + fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size); } fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, prot_addr); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); - fw_cfg_add_bytes(fw_cfg, FW_CFG_KERNEL_DATA, kernel, kernel_size); sev_load_ctx.kernel_data = (char *)kernel; sev_load_ctx.kernel_size = kernel_size; From 772b3eb4b4fe15f0595bd95923778a5a0f3558cc Mon Sep 17 00:00:00 2001 From: Matheus Tavares Bernardino Date: Fri, 30 Sep 2022 17:08:23 -0300 Subject: [PATCH 0800/1020] Hexagon (gen_tcg_funcs.py): avoid duplicated tcg code on A_CVI_NEW MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hexagon instructions with the A_CVI_NEW attribute produce a vector value that can be used in the same packet. The python function responsible for generating code for such instructions has a typo ("if" instead of "elif"), which makes genptr_dst_write_ext() be executed twice, thus also generating the same tcg code twice. Fortunately, this doesn't cause any problems for correctness, but it is less efficient than it could be. Fix it by using an "elif" and avoiding the unnecessary extra code gen. Signed-off-by: Matheus Tavares Bernardino Signed-off-by: Taylor Simpson Reviewed-by: Philippe Mathieu-DaudĂ© Reviewed-by: Richard Henderson Reviewed-by: Taylor Simpson Message-Id: --- target/hexagon/gen_tcg_funcs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py index d72c689ad7..6dea02b0b9 100755 --- a/target/hexagon/gen_tcg_funcs.py +++ b/target/hexagon/gen_tcg_funcs.py @@ -548,7 +548,7 @@ def genptr_dst_write_opn(f,regtype, regid, tag): if (hex_common.is_hvx_reg(regtype)): if (hex_common.is_new_result(tag)): genptr_dst_write_ext(f, tag, regtype, regid, "EXT_NEW") - if (hex_common.is_tmp_result(tag)): + elif (hex_common.is_tmp_result(tag)): genptr_dst_write_ext(f, tag, regtype, regid, "EXT_TMP") else: genptr_dst_write_ext(f, tag, regtype, regid, "EXT_DFL") From 90dc46d31495ec5825dc35e6984c38149261538f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Mon, 19 Sep 2022 20:27:55 +0200 Subject: [PATCH 0801/1020] block/qcow2-bitmap: Add missing cast to silent GCC error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit d1258dd0c8 ("qcow2: autoloading dirty bitmaps") added the set_readonly_helper() GFunc handler, correctly casting the gpointer user_data in both the g_slist_foreach() caller and the handler. Few commits later (commit 1b6b0562db), the handler is reused in qcow2_reopen_bitmaps_rw() but missing the gpointer cast, resulting in the following error when using Homebrew GCC 12.2.0: [2/658] Compiling C object libblock.fa.p/block_qcow2-bitmap.c.o ../../block/qcow2-bitmap.c: In function 'qcow2_reopen_bitmaps_rw': ../../block/qcow2-bitmap.c:1211:60: error: incompatible type for argument 3 of 'g_slist_foreach' 1211 | g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, false); | ^~~~~ | | | _Bool In file included from /opt/homebrew/Cellar/glib/2.72.3_1/include/glib-2.0/glib/gmain.h:26, from /opt/homebrew/Cellar/glib/2.72.3_1/include/glib-2.0/glib/giochannel.h:33, from /opt/homebrew/Cellar/glib/2.72.3_1/include/glib-2.0/glib.h:54, from /Users/philmd/source/qemu/include/glib-compat.h:32, from /Users/philmd/source/qemu/include/qemu/osdep.h:144, from ../../block/qcow2-bitmap.c:28: /opt/homebrew/Cellar/glib/2.72.3_1/include/glib-2.0/glib/gslist.h:127:61: note: expected 'gpointer' {aka 'void *'} but argument is of type '_Bool' 127 | gpointer user_data); | ~~~~~~~~~~~~~~~~~~^~~~~~~~~ At top level: FAILED: libblock.fa.p/block_qcow2-bitmap.c.o Fix by adding the missing gpointer cast. Fixes: 1b6b0562db ("qcow2: support .bdrv_reopen_bitmaps_rw") Signed-off-by: Philippe Mathieu-DaudĂ© Reviewed-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220919182755.51967-1-f4bug@amsat.org> Signed-off-by: Laurent Vivier --- block/qcow2-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/qcow2-bitmap.c b/block/qcow2-bitmap.c index ff3309846c..7197754843 100644 --- a/block/qcow2-bitmap.c +++ b/block/qcow2-bitmap.c @@ -1208,7 +1208,7 @@ int qcow2_reopen_bitmaps_rw(BlockDriverState *bs, Error **errp) } } - g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, false); + g_slist_foreach(ro_dirty_bitmaps, set_readonly_helper, (gpointer)false); ret = 0; out: From 76eb88b12baf2bd9a1729ded33bd58b7da5d7ec3 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 23 Sep 2022 11:04:28 +0200 Subject: [PATCH 0802/1020] Drop superfluous conditionals around g_free() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is no need to guard g_free(P) with if (P): g_free(NULL) is safe. Signed-off-by: Markus Armbruster Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220923090428.93529-1-armbru@redhat.com> Signed-off-by: Laurent Vivier --- replay/replay.c | 6 ++---- target/i386/kvm/kvm.c | 12 ++++-------- target/i386/whpx/whpx-all.c | 14 ++++++-------- 3 files changed, 12 insertions(+), 20 deletions(-) diff --git a/replay/replay.c b/replay/replay.c index 4c396bb376..9a0dc1cf44 100644 --- a/replay/replay.c +++ b/replay/replay.c @@ -366,10 +366,8 @@ void replay_finish(void) fclose(replay_file); replay_file = NULL; } - if (replay_filename) { - g_free(replay_filename); - replay_filename = NULL; - } + g_free(replay_filename); + replay_filename = NULL; g_free(replay_snapshot); replay_snapshot = NULL; diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c index a1fd1f5379..9603bf265a 100644 --- a/target/i386/kvm/kvm.c +++ b/target/i386/kvm/kvm.c @@ -2176,15 +2176,11 @@ int kvm_arch_destroy_vcpu(CPUState *cs) g_free(env->xsave_buf); - if (cpu->kvm_msr_buf) { - g_free(cpu->kvm_msr_buf); - cpu->kvm_msr_buf = NULL; - } + g_free(cpu->kvm_msr_buf); + cpu->kvm_msr_buf = NULL; - if (env->nested_state) { - g_free(env->nested_state); - env->nested_state = NULL; - } + g_free(env->nested_state); + env->nested_state = NULL; qemu_del_vm_change_state_handler(cpu->vmsentry); diff --git a/target/i386/whpx/whpx-all.c b/target/i386/whpx/whpx-all.c index b22a3314b4..8e4969edeb 100644 --- a/target/i386/whpx/whpx-all.c +++ b/target/i386/whpx/whpx-all.c @@ -1225,14 +1225,12 @@ static void whpx_translate_cpu_breakpoints( } } - if (breakpoints->breakpoints) { - /* - * Free the previous breakpoint list. This can be optimized by keeping - * it as shadow buffer for the next computation instead of freeing - * it immediately. - */ - g_free(breakpoints->breakpoints); - } + /* + * Free the previous breakpoint list. This can be optimized by keeping + * it as shadow buffer for the next computation instead of freeing + * it immediately. + */ + g_free(breakpoints->breakpoints); breakpoints->breakpoints = new_breakpoints; } From c5e8d51824fe725d0693cd9f50171d34297c5cc0 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 23 Sep 2022 10:42:54 +0200 Subject: [PATCH 0803/1020] Use g_new() & friends where that makes obvious sense g_new(T, n) is neater than g_malloc(sizeof(T) * n). It's also safer, for two reasons. One, it catches multiplication overflowing size_t. Two, it returns T * rather than void *, which lets the compiler catch more type errors. This commit only touches allocations with size arguments of the form sizeof(T). Patch created mechanically with: $ spatch --in-place --sp-file scripts/coccinelle/use-g_new-etc.cocci \ --macro-file scripts/cocci-macro-file.h FILES... The previous iteration was commit a95942b50c. Signed-off-by: Markus Armbruster Reviewed-by: Michael S. Tsirkin Message-Id: <20220923084254.4173111-1-armbru@redhat.com> Signed-off-by: Laurent Vivier --- hw/remote/iommu.c | 2 +- hw/virtio/virtio-crypto.c | 2 +- migration/dirtyrate.c | 4 ++-- softmmu/dirtylimit.c | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/remote/iommu.c b/hw/remote/iommu.c index fd723d91f3..1391dd712c 100644 --- a/hw/remote/iommu.c +++ b/hw/remote/iommu.c @@ -47,7 +47,7 @@ static AddressSpace *remote_iommu_find_add_as(PCIBus *pci_bus, elem = g_hash_table_lookup(iommu->elem_by_devfn, INT2VOIDP(devfn)); if (!elem) { - elem = g_malloc0(sizeof(RemoteIommuElem)); + elem = g_new0(RemoteIommuElem, 1); g_hash_table_insert(iommu->elem_by_devfn, INT2VOIDP(devfn), elem); } diff --git a/hw/virtio/virtio-crypto.c b/hw/virtio/virtio-crypto.c index c1243c3f93..df4bde210b 100644 --- a/hw/virtio/virtio-crypto.c +++ b/hw/virtio/virtio-crypto.c @@ -710,7 +710,7 @@ virtio_crypto_handle_asym_req(VirtIOCrypto *vcrypto, uint8_t *src = NULL; uint8_t *dst = NULL; - asym_op_info = g_malloc0(sizeof(CryptoDevBackendAsymOpInfo)); + asym_op_info = g_new0(CryptoDevBackendAsymOpInfo, 1); src_len = ldl_le_p(&req->para.src_data_len); dst_len = ldl_le_p(&req->para.dst_data_len); diff --git a/migration/dirtyrate.c b/migration/dirtyrate.c index 795fab5c37..d6f1e01a70 100644 --- a/migration/dirtyrate.c +++ b/migration/dirtyrate.c @@ -119,9 +119,9 @@ static DirtyPageRecord *vcpu_dirty_stat_alloc(VcpuStat *stat) } stat->nvcpu = nvcpu; - stat->rates = g_malloc0(sizeof(DirtyRateVcpu) * nvcpu); + stat->rates = g_new0(DirtyRateVcpu, nvcpu); - records = g_malloc0(sizeof(DirtyPageRecord) * nvcpu); + records = g_new0(DirtyPageRecord, nvcpu); return records; } diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c index 8d98cb7f2c..12668555f2 100644 --- a/softmmu/dirtylimit.c +++ b/softmmu/dirtylimit.c @@ -154,7 +154,7 @@ void vcpu_dirty_rate_stat_initialize(void) vcpu_dirty_rate_stat->stat.nvcpu = max_cpus; vcpu_dirty_rate_stat->stat.rates = - g_malloc0(sizeof(DirtyRateVcpu) * max_cpus); + g_new0(DirtyRateVcpu, max_cpus); vcpu_dirty_rate_stat->running = false; } @@ -198,7 +198,7 @@ void dirtylimit_state_initialize(void) dirtylimit_state = g_malloc0(sizeof(*dirtylimit_state)); dirtylimit_state->states = - g_malloc0(sizeof(VcpuDirtyLimitState) * max_cpus); + g_new0(VcpuDirtyLimitState, max_cpus); for (i = 0; i < max_cpus; i++) { dirtylimit_state->states[i].cpu_index = i; From 4a4a74bf439910e957db42405a3abefdf867516a Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Tue, 27 Sep 2022 08:21:46 -0400 Subject: [PATCH 0804/1020] docs: Update TPM documentation for usage of a TPM 2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the TPM documentation for usage of a TPM 2 rather than a TPM 1.2. Adjust the command lines and expected outputs inside the VM accordingly. Update the command line to start a TPM 2 with swtpm. Signed-off-by: Stefan Berger Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220927122146.2787854-1-stefanb@linux.ibm.com> Signed-off-by: Laurent Vivier --- docs/specs/tpm.rst | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/docs/specs/tpm.rst b/docs/specs/tpm.rst index 3be190343a..535912a92b 100644 --- a/docs/specs/tpm.rst +++ b/docs/specs/tpm.rst @@ -250,24 +250,25 @@ hardware TPM ``/dev/tpm0``: The following commands should result in similar output inside the VM with a Linux kernel that either has the TPM TIS driver built-in or -available as a module: +available as a module (assuming a TPM 2 is passed through): .. code-block:: console # dmesg | grep -i tpm - [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) - - # dmesg | grep TCPA - [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ - BXPCTCPA 0000001 BXPC 00000001) + [ 0.012560] ACPI: TPM2 0x000000000BFFD1900 00004C (v04 BOCHS \ + BXPC 0000001 BXPC 00000001) # ls -l /dev/tpm* - crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 + crw-rw----. 1 tss root 10, 224 Sep 6 12:36 /dev/tpm0 + crw-rw----. 1 tss rss 253, 65536 Sep 6 12:36 /dev/tpmrm0 - # find /sys/devices/ | grep pcrs$ | xargs cat - PCR-00: 35 4E 3B CE 23 9F 38 59 ... + Starting with Linux 5.12 there are PCR entries for TPM 2 in sysfs: + # find /sys/devices/ -type f | grep pcr-sha + ... + /sys/devices/LNXSYSTEM:00/LNXSYBUS:00/MSFT0101:00/tpm/tpm0/pcr-sha256/1 + ... + /sys/devices/LNXSYSTEM:00/LNXSYBUS:00/MSFT0101:00/tpm/tpm0/pcr-sha256/9 ... - PCR-23: 00 00 00 00 00 00 00 00 ... The QEMU TPM emulator device ---------------------------- @@ -304,6 +305,7 @@ a socket interface. They do not need to be run as root. mkdir /tmp/mytpm1 swtpm socket --tpmstate dir=/tmp/mytpm1 \ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ + --tpm2 \ --log level=20 Command line to start QEMU with the TPM emulator device communicating @@ -365,19 +367,20 @@ available as a module: .. code-block:: console # dmesg | grep -i tpm - [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) - - # dmesg | grep TCPA - [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ - BXPCTCPA 0000001 BXPC 00000001) + [ 0.012560] ACPI: TPM2 0x000000000BFFD1900 00004C (v04 BOCHS \ + BXPC 0000001 BXPC 00000001) # ls -l /dev/tpm* - crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 + crw-rw----. 1 tss root 10, 224 Sep 6 12:36 /dev/tpm0 + crw-rw----. 1 tss rss 253, 65536 Sep 6 12:36 /dev/tpmrm0 - # find /sys/devices/ | grep pcrs$ | xargs cat - PCR-00: 35 4E 3B CE 23 9F 38 59 ... + Starting with Linux 5.12 there are PCR entries for TPM 2 in sysfs: + # find /sys/devices/ -type f | grep pcr-sha + ... + /sys/devices/LNXSYSTEM:00/LNXSYBUS:00/MSFT0101:00/tpm/tpm0/pcr-sha256/1 + ... + /sys/devices/LNXSYSTEM:00/LNXSYBUS:00/MSFT0101:00/tpm/tpm0/pcr-sha256/9 ... - PCR-23: 00 00 00 00 00 00 00 00 ... Migration with the TPM emulator =============================== @@ -398,7 +401,8 @@ In a 1st terminal start an instance of a swtpm using the following command: mkdir /tmp/mytpm1 swtpm socket --tpmstate dir=/tmp/mytpm1 \ --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ - --log level=20 --tpm2 + --tpm2 \ + --log level=20 In a 2nd terminal start the VM: From 6fbdff870620705042a5b2d87491659487b3f4e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 23 Sep 2022 10:47:59 +0200 Subject: [PATCH 0805/1020] cpu: cache CPUClass in CPUState for hot code paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The class cast checkers are quite expensive and always on (unlike the dynamic case who's checks are gated by CONFIG_QOM_CAST_DEBUG). To avoid the overhead of repeatedly checking something which should never change we cache the CPUClass reference for use in the hot code paths. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220811151413.3350684-3-alex.bennee@linaro.org> Signed-off-by: CĂ©dric Le Goater Message-Id: <20220923084803.498337-3-clg@kaod.org> Signed-off-by: Richard Henderson --- cpu.c | 9 ++++----- include/hw/core/cpu.h | 9 +++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/cpu.c b/cpu.c index 584ac78baf..14365e36f3 100644 --- a/cpu.c +++ b/cpu.c @@ -131,9 +131,8 @@ const VMStateDescription vmstate_cpu_common = { void cpu_exec_realizefn(CPUState *cpu, Error **errp) { -#ifndef CONFIG_USER_ONLY - CPUClass *cc = CPU_GET_CLASS(cpu); -#endif + /* cache the cpu class for the hotpath */ + cpu->cc = CPU_GET_CLASS(cpu); cpu_list_add(cpu); if (!accel_cpu_realizefn(cpu, errp)) { @@ -151,8 +150,8 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp) if (qdev_get_vmsd(DEVICE(cpu)) == NULL) { vmstate_register(NULL, cpu->cpu_index, &vmstate_cpu_common, cpu); } - if (cc->sysemu_ops->legacy_vmsd != NULL) { - vmstate_register(NULL, cpu->cpu_index, cc->sysemu_ops->legacy_vmsd, cpu); + if (cpu->cc->sysemu_ops->legacy_vmsd != NULL) { + vmstate_register(NULL, cpu->cpu_index, cpu->cc->sysemu_ops->legacy_vmsd, cpu); } #endif /* CONFIG_USER_ONLY */ } diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 500503da13..1a7e1a9380 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -51,6 +51,13 @@ typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size, */ #define CPU(obj) ((CPUState *)(obj)) +/* + * The class checkers bring in CPU_GET_CLASS() which is potentially + * expensive given the eventual call to + * object_class_dynamic_cast_assert(). Because of this the CPUState + * has a cached value for the class in cs->cc which is set up in + * cpu_exec_realizefn() for use in hot code paths. + */ typedef struct CPUClass CPUClass; DECLARE_CLASS_CHECKERS(CPUClass, CPU, TYPE_CPU) @@ -317,6 +324,8 @@ struct qemu_work_item; struct CPUState { /*< private >*/ DeviceState parent_obj; + /* cache to avoid expensive CPU_GET_CLASS */ + CPUClass *cc; /*< public >*/ int nr_cores; From b404ca370e4ee60e98effec5cdf942d15b61c507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 23 Sep 2022 10:48:00 +0200 Subject: [PATCH 0806/1020] hw/core/cpu-sysemu: used cached class in cpu_asidx_from_attrs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is a heavily used function so lets avoid the cost of CPU_GET_CLASS. On the romulus-bmc run it has a modest effect: Before: 36.812 s ± 0.506 s After: 35.912 s ± 0.168 s Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220811151413.3350684-4-alex.bennee@linaro.org> Signed-off-by: CĂ©dric Le Goater Message-Id: <20220923084803.498337-4-clg@kaod.org> Signed-off-by: Richard Henderson --- hw/core/cpu-sysemu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/core/cpu-sysemu.c b/hw/core/cpu-sysemu.c index 00253f8929..5eaf2e79e6 100644 --- a/hw/core/cpu-sysemu.c +++ b/hw/core/cpu-sysemu.c @@ -69,11 +69,10 @@ hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr) int cpu_asidx_from_attrs(CPUState *cpu, MemTxAttrs attrs) { - CPUClass *cc = CPU_GET_CLASS(cpu); int ret = 0; - if (cc->sysemu_ops->asidx_from_attrs) { - ret = cc->sysemu_ops->asidx_from_attrs(cpu, attrs); + if (cpu->cc->sysemu_ops->asidx_from_attrs) { + ret = cpu->cc->sysemu_ops->asidx_from_attrs(cpu, attrs); assert(ret < cpu->num_ases && ret >= 0); } return ret; From 8810ee2ac0899356013f56db6ea5f3e5023fbef6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Fri, 23 Sep 2022 10:48:01 +0200 Subject: [PATCH 0807/1020] cputlb: used cached CPUClass in our hot-paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before: 35.912 s ± 0.168 s After: 35.565 s ± 0.087 s Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220811151413.3350684-5-alex.bennee@linaro.org> Signed-off-by: CĂ©dric Le Goater Message-Id: <20220923084803.498337-5-clg@kaod.org> Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 8fad2d9b83..193bfc1cfc 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1291,15 +1291,14 @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr, static void tlb_fill(CPUState *cpu, target_ulong addr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { - CPUClass *cc = CPU_GET_CLASS(cpu); bool ok; /* * This is not a probe, so only valid return is success; failure * should result in exception + longjmp to the cpu loop. */ - ok = cc->tcg_ops->tlb_fill(cpu, addr, size, - access_type, mmu_idx, false, retaddr); + ok = cpu->cc->tcg_ops->tlb_fill(cpu, addr, size, + access_type, mmu_idx, false, retaddr); assert(ok); } @@ -1307,9 +1306,8 @@ static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { - CPUClass *cc = CPU_GET_CLASS(cpu); - - cc->tcg_ops->do_unaligned_access(cpu, addr, access_type, mmu_idx, retaddr); + cpu->cc->tcg_ops->do_unaligned_access(cpu, addr, access_type, + mmu_idx, retaddr); } static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr, @@ -1539,10 +1537,9 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr, if (!tlb_hit_page(tlb_addr, page_addr)) { if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page_addr)) { CPUState *cs = env_cpu(env); - CPUClass *cc = CPU_GET_CLASS(cs); - if (!cc->tcg_ops->tlb_fill(cs, addr, fault_size, access_type, - mmu_idx, nonfault, retaddr)) { + if (!cs->cc->tcg_ops->tlb_fill(cs, addr, fault_size, access_type, + mmu_idx, nonfault, retaddr)) { /* Non-faulting page table read failed. */ *phost = NULL; return TLB_INVALID_MASK; From 25d3ec5831e08ed3e72a5db654d7c281feb559c7 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 19 Aug 2022 14:20:37 -0700 Subject: [PATCH 0808/1020] accel/tcg: Rename CPUIOTLBEntry to CPUTLBEntryFull MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This structure will shortly contain more than just data for accessing MMIO. Rename the 'addr' member to 'xlat_section' to more clearly indicate its purpose. Reviewed-by: Alex BennĂ©e Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 102 +++++++++++++++++++------------------ include/exec/cpu-defs.h | 22 ++++---- target/arm/mte_helper.c | 14 ++--- target/arm/sve_helper.c | 4 +- target/arm/translate-a64.c | 2 +- 5 files changed, 73 insertions(+), 71 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 193bfc1cfc..aa22f578cb 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -200,13 +200,13 @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast, } g_free(fast->table); - g_free(desc->iotlb); + g_free(desc->fulltlb); tlb_window_reset(desc, now, 0); /* desc->n_used_entries is cleared by the caller */ fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS; fast->table = g_try_new(CPUTLBEntry, new_size); - desc->iotlb = g_try_new(CPUIOTLBEntry, new_size); + desc->fulltlb = g_try_new(CPUTLBEntryFull, new_size); /* * If the allocations fail, try smaller sizes. We just freed some @@ -215,7 +215,7 @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast, * allocations to fail though, so we progressively reduce the allocation * size, aborting if we cannot even allocate the smallest TLB we support. */ - while (fast->table == NULL || desc->iotlb == NULL) { + while (fast->table == NULL || desc->fulltlb == NULL) { if (new_size == (1 << CPU_TLB_DYN_MIN_BITS)) { error_report("%s: %s", __func__, strerror(errno)); abort(); @@ -224,9 +224,9 @@ static void tlb_mmu_resize_locked(CPUTLBDesc *desc, CPUTLBDescFast *fast, fast->mask = (new_size - 1) << CPU_TLB_ENTRY_BITS; g_free(fast->table); - g_free(desc->iotlb); + g_free(desc->fulltlb); fast->table = g_try_new(CPUTLBEntry, new_size); - desc->iotlb = g_try_new(CPUIOTLBEntry, new_size); + desc->fulltlb = g_try_new(CPUTLBEntryFull, new_size); } } @@ -258,7 +258,7 @@ static void tlb_mmu_init(CPUTLBDesc *desc, CPUTLBDescFast *fast, int64_t now) desc->n_used_entries = 0; fast->mask = (n_entries - 1) << CPU_TLB_ENTRY_BITS; fast->table = g_new(CPUTLBEntry, n_entries); - desc->iotlb = g_new(CPUIOTLBEntry, n_entries); + desc->fulltlb = g_new(CPUTLBEntryFull, n_entries); tlb_mmu_flush_locked(desc, fast); } @@ -299,7 +299,7 @@ void tlb_destroy(CPUState *cpu) CPUTLBDescFast *fast = &env_tlb(env)->f[i]; g_free(fast->table); - g_free(desc->iotlb); + g_free(desc->fulltlb); } } @@ -1219,7 +1219,7 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, /* Evict the old entry into the victim tlb. */ copy_tlb_helper_locked(tv, te); - desc->viotlb[vidx] = desc->iotlb[index]; + desc->vfulltlb[vidx] = desc->fulltlb[index]; tlb_n_used_entries_dec(env, mmu_idx); } @@ -1236,8 +1236,8 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, * subtract here is that of the page base, and not the same as the * vaddr we add back in io_readx()/io_writex()/get_page_addr_code(). */ - desc->iotlb[index].addr = iotlb - vaddr_page; - desc->iotlb[index].attrs = attrs; + desc->fulltlb[index].xlat_section = iotlb - vaddr_page; + desc->fulltlb[index].attrs = attrs; /* Now calculate the new entry */ tn.addend = addend - vaddr_page; @@ -1327,7 +1327,7 @@ static inline void cpu_transaction_failed(CPUState *cpu, hwaddr physaddr, } } -static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, +static uint64_t io_readx(CPUArchState *env, CPUTLBEntryFull *full, int mmu_idx, target_ulong addr, uintptr_t retaddr, MMUAccessType access_type, MemOp op) { @@ -1339,9 +1339,9 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, bool locked = false; MemTxResult r; - section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs); + section = iotlb_to_section(cpu, full->xlat_section, full->attrs); mr = section->mr; - mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr; + mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr; cpu->mem_io_pc = retaddr; if (!cpu->can_do_io) { cpu_io_recompile(cpu, retaddr); @@ -1351,14 +1351,14 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, qemu_mutex_lock_iothread(); locked = true; } - r = memory_region_dispatch_read(mr, mr_offset, &val, op, iotlbentry->attrs); + r = memory_region_dispatch_read(mr, mr_offset, &val, op, full->attrs); if (r != MEMTX_OK) { hwaddr physaddr = mr_offset + section->offset_within_address_space - section->offset_within_region; cpu_transaction_failed(cpu, physaddr, addr, memop_size(op), access_type, - mmu_idx, iotlbentry->attrs, r, retaddr); + mmu_idx, full->attrs, r, retaddr); } if (locked) { qemu_mutex_unlock_iothread(); @@ -1368,8 +1368,8 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry, } /* - * Save a potentially trashed IOTLB entry for later lookup by plugin. - * This is read by tlb_plugin_lookup if the iotlb entry doesn't match + * Save a potentially trashed CPUTLBEntryFull for later lookup by plugin. + * This is read by tlb_plugin_lookup if the fulltlb entry doesn't match * because of the side effect of io_writex changing memory layout. */ static void save_iotlb_data(CPUState *cs, hwaddr addr, @@ -1383,7 +1383,7 @@ static void save_iotlb_data(CPUState *cs, hwaddr addr, #endif } -static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, +static void io_writex(CPUArchState *env, CPUTLBEntryFull *full, int mmu_idx, uint64_t val, target_ulong addr, uintptr_t retaddr, MemOp op) { @@ -1394,9 +1394,9 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, bool locked = false; MemTxResult r; - section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs); + section = iotlb_to_section(cpu, full->xlat_section, full->attrs); mr = section->mr; - mr_offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr; + mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr; if (!cpu->can_do_io) { cpu_io_recompile(cpu, retaddr); } @@ -1406,20 +1406,20 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry, * The memory_region_dispatch may trigger a flush/resize * so for plugins we save the iotlb_data just in case. */ - save_iotlb_data(cpu, iotlbentry->addr, section, mr_offset); + save_iotlb_data(cpu, full->xlat_section, section, mr_offset); if (!qemu_mutex_iothread_locked()) { qemu_mutex_lock_iothread(); locked = true; } - r = memory_region_dispatch_write(mr, mr_offset, val, op, iotlbentry->attrs); + r = memory_region_dispatch_write(mr, mr_offset, val, op, full->attrs); if (r != MEMTX_OK) { hwaddr physaddr = mr_offset + section->offset_within_address_space - section->offset_within_region; cpu_transaction_failed(cpu, physaddr, addr, memop_size(op), - MMU_DATA_STORE, mmu_idx, iotlbentry->attrs, r, + MMU_DATA_STORE, mmu_idx, full->attrs, r, retaddr); } if (locked) { @@ -1466,9 +1466,10 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index, copy_tlb_helper_locked(vtlb, &tmptlb); qemu_spin_unlock(&env_tlb(env)->c.lock); - CPUIOTLBEntry tmpio, *io = &env_tlb(env)->d[mmu_idx].iotlb[index]; - CPUIOTLBEntry *vio = &env_tlb(env)->d[mmu_idx].viotlb[vidx]; - tmpio = *io; *io = *vio; *vio = tmpio; + CPUTLBEntryFull *f1 = &env_tlb(env)->d[mmu_idx].fulltlb[index]; + CPUTLBEntryFull *f2 = &env_tlb(env)->d[mmu_idx].vfulltlb[vidx]; + CPUTLBEntryFull tmpf; + tmpf = *f1; *f1 = *f2; *f2 = tmpf; return true; } } @@ -1481,9 +1482,9 @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index, (ADDR) & TARGET_PAGE_MASK) static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size, - CPUIOTLBEntry *iotlbentry, uintptr_t retaddr) + CPUTLBEntryFull *full, uintptr_t retaddr) { - ram_addr_t ram_addr = mem_vaddr + iotlbentry->addr; + ram_addr_t ram_addr = mem_vaddr + full->xlat_section; trace_memory_notdirty_write_access(mem_vaddr, ram_addr, size); @@ -1575,9 +1576,9 @@ int probe_access_flags(CPUArchState *env, target_ulong addr, /* Handle clean RAM pages. */ if (unlikely(flags & TLB_NOTDIRTY)) { uintptr_t index = tlb_index(env, mmu_idx, addr); - CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index]; + CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index]; - notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr); + notdirty_write(env_cpu(env), addr, 1, full, retaddr); flags &= ~TLB_NOTDIRTY; } @@ -1602,19 +1603,19 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size, if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) { uintptr_t index = tlb_index(env, mmu_idx, addr); - CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index]; + CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index]; /* Handle watchpoints. */ if (flags & TLB_WATCHPOINT) { int wp_access = (access_type == MMU_DATA_STORE ? BP_MEM_WRITE : BP_MEM_READ); cpu_check_watchpoint(env_cpu(env), addr, size, - iotlbentry->attrs, wp_access, retaddr); + full->attrs, wp_access, retaddr); } /* Handle clean RAM pages. */ if (flags & TLB_NOTDIRTY) { - notdirty_write(env_cpu(env), addr, 1, iotlbentry, retaddr); + notdirty_write(env_cpu(env), addr, 1, full, retaddr); } } @@ -1671,7 +1672,7 @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, * should have just filled the TLB. The one corner case is io_writex * which can cause TLB flushes and potential resizing of the TLBs * losing the information we need. In those cases we need to recover - * data from a copy of the iotlbentry. As long as this always occurs + * data from a copy of the CPUTLBEntryFull. As long as this always occurs * from the same thread (which a mem callback will be) this is safe. */ @@ -1686,11 +1687,12 @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx, if (likely(tlb_hit(tlb_addr, addr))) { /* We must have an iotlb entry for MMIO */ if (tlb_addr & TLB_MMIO) { - CPUIOTLBEntry *iotlbentry; - iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index]; + CPUTLBEntryFull *full; + full = &env_tlb(env)->d[mmu_idx].fulltlb[index]; data->is_io = true; - data->v.io.section = iotlb_to_section(cpu, iotlbentry->addr, iotlbentry->attrs); - data->v.io.offset = (iotlbentry->addr & TARGET_PAGE_MASK) + addr; + data->v.io.section = + iotlb_to_section(cpu, full->xlat_section, full->attrs); + data->v.io.offset = (full->xlat_section & TARGET_PAGE_MASK) + addr; } else { data->is_io = false; data->v.ram.hostaddr = (void *)((uintptr_t)addr + tlbe->addend); @@ -1798,7 +1800,7 @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr, if (unlikely(tlb_addr & TLB_NOTDIRTY)) { notdirty_write(env_cpu(env), addr, size, - &env_tlb(env)->d[mmu_idx].iotlb[index], retaddr); + &env_tlb(env)->d[mmu_idx].fulltlb[index], retaddr); } return hostaddr; @@ -1906,7 +1908,7 @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi, /* Handle anything that isn't just a straight memory access. */ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { - CPUIOTLBEntry *iotlbentry; + CPUTLBEntryFull *full; bool need_swap; /* For anything that is unaligned, recurse through full_load. */ @@ -1914,20 +1916,20 @@ load_helper(CPUArchState *env, target_ulong addr, MemOpIdx oi, goto do_unaligned_access; } - iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index]; + full = &env_tlb(env)->d[mmu_idx].fulltlb[index]; /* Handle watchpoints. */ if (unlikely(tlb_addr & TLB_WATCHPOINT)) { /* On watchpoint hit, this will longjmp out. */ cpu_check_watchpoint(env_cpu(env), addr, size, - iotlbentry->attrs, BP_MEM_READ, retaddr); + full->attrs, BP_MEM_READ, retaddr); } need_swap = size > 1 && (tlb_addr & TLB_BSWAP); /* Handle I/O access. */ if (likely(tlb_addr & TLB_MMIO)) { - return io_readx(env, iotlbentry, mmu_idx, addr, retaddr, + return io_readx(env, full, mmu_idx, addr, retaddr, access_type, op ^ (need_swap * MO_BSWAP)); } @@ -2242,12 +2244,12 @@ store_helper_unaligned(CPUArchState *env, target_ulong addr, uint64_t val, */ if (unlikely(tlb_addr & TLB_WATCHPOINT)) { cpu_check_watchpoint(env_cpu(env), addr, size - size2, - env_tlb(env)->d[mmu_idx].iotlb[index].attrs, + env_tlb(env)->d[mmu_idx].fulltlb[index].attrs, BP_MEM_WRITE, retaddr); } if (unlikely(tlb_addr2 & TLB_WATCHPOINT)) { cpu_check_watchpoint(env_cpu(env), page2, size2, - env_tlb(env)->d[mmu_idx].iotlb[index2].attrs, + env_tlb(env)->d[mmu_idx].fulltlb[index2].attrs, BP_MEM_WRITE, retaddr); } @@ -2311,7 +2313,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, /* Handle anything that isn't just a straight memory access. */ if (unlikely(tlb_addr & ~TARGET_PAGE_MASK)) { - CPUIOTLBEntry *iotlbentry; + CPUTLBEntryFull *full; bool need_swap; /* For anything that is unaligned, recurse through byte stores. */ @@ -2319,20 +2321,20 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, goto do_unaligned_access; } - iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index]; + full = &env_tlb(env)->d[mmu_idx].fulltlb[index]; /* Handle watchpoints. */ if (unlikely(tlb_addr & TLB_WATCHPOINT)) { /* On watchpoint hit, this will longjmp out. */ cpu_check_watchpoint(env_cpu(env), addr, size, - iotlbentry->attrs, BP_MEM_WRITE, retaddr); + full->attrs, BP_MEM_WRITE, retaddr); } need_swap = size > 1 && (tlb_addr & TLB_BSWAP); /* Handle I/O access. */ if (tlb_addr & TLB_MMIO) { - io_writex(env, iotlbentry, mmu_idx, val, addr, retaddr, + io_writex(env, full, mmu_idx, val, addr, retaddr, op ^ (need_swap * MO_BSWAP)); return; } @@ -2344,7 +2346,7 @@ store_helper(CPUArchState *env, target_ulong addr, uint64_t val, /* Handle clean RAM pages. */ if (tlb_addr & TLB_NOTDIRTY) { - notdirty_write(env_cpu(env), addr, size, iotlbentry, retaddr); + notdirty_write(env_cpu(env), addr, size, full, retaddr); } haddr = (void *)((uintptr_t)addr + entry->addend); diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index ba3cd32a1e..f70f54d850 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -108,6 +108,7 @@ typedef uint64_t target_ulong; # endif # endif +/* Minimalized TLB entry for use by TCG fast path. */ typedef struct CPUTLBEntry { /* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not @@ -131,14 +132,14 @@ typedef struct CPUTLBEntry { QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS)); -/* The IOTLB is not accessed directly inline by generated TCG code, - * so the CPUIOTLBEntry layout is not as critical as that of the - * CPUTLBEntry. (This is also why we don't want to combine the two - * structs into one.) +/* + * The full TLB entry, which is not accessed by generated TCG code, + * so the layout is not as critical as that of CPUTLBEntry. This is + * also why we don't want to combine the two structs. */ -typedef struct CPUIOTLBEntry { +typedef struct CPUTLBEntryFull { /* - * @addr contains: + * @xlat_section contains: * - in the lower TARGET_PAGE_BITS, a physical section number * - with the lower TARGET_PAGE_BITS masked off, an offset which * must be added to the virtual address to obtain: @@ -146,9 +147,9 @@ typedef struct CPUIOTLBEntry { * number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM) * + the offset within the target MemoryRegion (otherwise) */ - hwaddr addr; + hwaddr xlat_section; MemTxAttrs attrs; -} CPUIOTLBEntry; +} CPUTLBEntryFull; /* * Data elements that are per MMU mode, minus the bits accessed by @@ -172,9 +173,8 @@ typedef struct CPUTLBDesc { size_t vindex; /* The tlb victim table, in two parts. */ CPUTLBEntry vtable[CPU_VTLB_SIZE]; - CPUIOTLBEntry viotlb[CPU_VTLB_SIZE]; - /* The iotlb. */ - CPUIOTLBEntry *iotlb; + CPUTLBEntryFull vfulltlb[CPU_VTLB_SIZE]; + CPUTLBEntryFull *fulltlb; } CPUTLBDesc; /* diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c index d11a8c70d0..fdd23ab3f8 100644 --- a/target/arm/mte_helper.c +++ b/target/arm/mte_helper.c @@ -106,7 +106,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, return tags + index; #else uintptr_t index; - CPUIOTLBEntry *iotlbentry; + CPUTLBEntryFull *full; int in_page, flags; ram_addr_t ptr_ra; hwaddr ptr_paddr, tag_paddr, xlat; @@ -129,7 +129,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, assert(!(flags & TLB_INVALID_MASK)); /* - * Find the iotlbentry for ptr. This *must* be present in the TLB + * Find the CPUTLBEntryFull for ptr. This *must* be present in the TLB * because we just found the mapping. * TODO: Perhaps there should be a cputlb helper that returns a * matching tlb entry + iotlb entry. @@ -144,10 +144,10 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, g_assert(tlb_hit(comparator, ptr)); } # endif - iotlbentry = &env_tlb(env)->d[ptr_mmu_idx].iotlb[index]; + full = &env_tlb(env)->d[ptr_mmu_idx].fulltlb[index]; /* If the virtual page MemAttr != Tagged, access unchecked. */ - if (!arm_tlb_mte_tagged(&iotlbentry->attrs)) { + if (!arm_tlb_mte_tagged(&full->attrs)) { return NULL; } @@ -181,7 +181,7 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE; assert(ra != 0); cpu_check_watchpoint(env_cpu(env), ptr, ptr_size, - iotlbentry->attrs, wp, ra); + full->attrs, wp, ra); } /* @@ -202,11 +202,11 @@ static uint8_t *allocation_tag_mem(CPUARMState *env, int ptr_mmu_idx, tag_paddr = ptr_paddr >> (LOG2_TAG_GRANULE + 1); /* Look up the address in tag space. */ - tag_asi = iotlbentry->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS; + tag_asi = full->attrs.secure ? ARMASIdx_TagS : ARMASIdx_TagNS; tag_as = cpu_get_address_space(env_cpu(env), tag_asi); mr = address_space_translate(tag_as, tag_paddr, &xlat, NULL, tag_access == MMU_DATA_STORE, - iotlbentry->attrs); + full->attrs); /* * Note that @mr will never be NULL. If there is nothing in the address diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c index d6f7ef94fe..9cae8fd352 100644 --- a/target/arm/sve_helper.c +++ b/target/arm/sve_helper.c @@ -5384,8 +5384,8 @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env, g_assert(tlb_hit(comparator, addr)); # endif - CPUIOTLBEntry *iotlbentry = &env_tlb(env)->d[mmu_idx].iotlb[index]; - info->attrs = iotlbentry->attrs; + CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index]; + info->attrs = full->attrs; } #endif diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 9bed336b47..78b2d91ed4 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -14624,7 +14624,7 @@ static bool is_guarded_page(CPUARMState *env, DisasContext *s) * table entry even for that case. */ return (tlb_hit(entry->addr_code, addr) && - arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].iotlb[index].attrs)); + arm_tlb_bti_gp(&env_tlb(env)->d[mmu_idx].fulltlb[index].attrs)); #endif } From 37523ff734721a699d338f918e95b1697cb0880c Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 19 Aug 2022 14:24:34 -0700 Subject: [PATCH 0809/1020] accel/tcg: Drop addr member from SavedIOTLB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This field is only written, not read; remove it. Reviewed-by: Alex BennĂ©e Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 7 +++---- include/hw/core/cpu.h | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index aa22f578cb..d06ff44ce9 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1372,12 +1372,11 @@ static uint64_t io_readx(CPUArchState *env, CPUTLBEntryFull *full, * This is read by tlb_plugin_lookup if the fulltlb entry doesn't match * because of the side effect of io_writex changing memory layout. */ -static void save_iotlb_data(CPUState *cs, hwaddr addr, - MemoryRegionSection *section, hwaddr mr_offset) +static void save_iotlb_data(CPUState *cs, MemoryRegionSection *section, + hwaddr mr_offset) { #ifdef CONFIG_PLUGIN SavedIOTLB *saved = &cs->saved_iotlb; - saved->addr = addr; saved->section = section; saved->mr_offset = mr_offset; #endif @@ -1406,7 +1405,7 @@ static void io_writex(CPUArchState *env, CPUTLBEntryFull *full, * The memory_region_dispatch may trigger a flush/resize * so for plugins we save the iotlb_data just in case. */ - save_iotlb_data(cpu, full->xlat_section, section, mr_offset); + save_iotlb_data(cpu, section, mr_offset); if (!qemu_mutex_iothread_locked()) { qemu_mutex_lock_iothread(); diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 1a7e1a9380..009dc0d336 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -225,7 +225,6 @@ struct CPUWatchpoint { * the memory regions get moved around by io_writex. */ typedef struct SavedIOTLB { - hwaddr addr; MemoryRegionSection *section; hwaddr mr_offset; } SavedIOTLB; From c3c8bf579b431b6b305dce12d67ff6fe86bc79e8 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 19 Aug 2022 15:28:05 -0700 Subject: [PATCH 0810/1020] accel/tcg: Suppress auto-invalidate in probe_access_internal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When PAGE_WRITE_INV is set when calling tlb_set_page, we immediately set TLB_INVALID_MASK in order to force tlb_fill to be called on the next lookup. Here in probe_access_internal, we have just called tlb_fill and eliminated true misses, thus the lookup must be valid. This allows us to remove a warning comment from s390x. There doesn't seem to be a reason to change the code though. Reviewed-by: Alex BennĂ©e Reviewed-by: David Hildenbrand Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 10 +++++++++- target/s390x/tcg/mem_helper.c | 4 ---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index d06ff44ce9..264f84a248 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1533,6 +1533,7 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr, } tlb_addr = tlb_read_ofs(entry, elt_ofs); + flags = TLB_FLAGS_MASK; page_addr = addr & TARGET_PAGE_MASK; if (!tlb_hit_page(tlb_addr, page_addr)) { if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, page_addr)) { @@ -1547,10 +1548,17 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr, /* TLB resize via tlb_fill may have moved the entry. */ entry = tlb_entry(env, mmu_idx, addr); + + /* + * With PAGE_WRITE_INV, we set TLB_INVALID_MASK immediately, + * to force the next access through tlb_fill. We've just + * called tlb_fill, so we know that this entry *is* valid. + */ + flags &= ~TLB_INVALID_MASK; } tlb_addr = tlb_read_ofs(entry, elt_ofs); } - flags = tlb_addr & TLB_FLAGS_MASK; + flags &= tlb_addr; /* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */ if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) { diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index fc52aa128b..3758b9e688 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -148,10 +148,6 @@ static int s390_probe_access(CPUArchState *env, target_ulong addr, int size, #else int flags; - /* - * For !CONFIG_USER_ONLY, we cannot rely on TLB_INVALID_MASK or haddr==NULL - * to detect if there was an exception during tlb_fill(). - */ env->tlb_fill_exc = 0; flags = probe_access_flags(env, addr, access_type, mmu_idx, nonfault, phost, ra); From af803a4fcb1c707a6a885b5736335baf794f7676 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 19 Aug 2022 15:49:41 -0700 Subject: [PATCH 0811/1020] accel/tcg: Introduce probe_access_full MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add an interface to return the CPUTLBEntryFull struct that goes with the lookup. The result is not intended to be valid across multiple lookups, so the user must use the results immediately. Reviewed-by: Alex BennĂ©e Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 47 +++++++++++++++++++++++++---------------- include/exec/exec-all.h | 15 +++++++++++++ include/qemu/typedefs.h | 1 + 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 264f84a248..e3ee4260bd 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1510,7 +1510,8 @@ static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size, static int probe_access_internal(CPUArchState *env, target_ulong addr, int fault_size, MMUAccessType access_type, int mmu_idx, bool nonfault, - void **phost, uintptr_t retaddr) + void **phost, CPUTLBEntryFull **pfull, + uintptr_t retaddr) { uintptr_t index = tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); @@ -1543,10 +1544,12 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr, mmu_idx, nonfault, retaddr)) { /* Non-faulting page table read failed. */ *phost = NULL; + *pfull = NULL; return TLB_INVALID_MASK; } /* TLB resize via tlb_fill may have moved the entry. */ + index = tlb_index(env, mmu_idx, addr); entry = tlb_entry(env, mmu_idx, addr); /* @@ -1560,6 +1563,8 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr, } flags &= tlb_addr; + *pfull = &env_tlb(env)->d[mmu_idx].fulltlb[index]; + /* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */ if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) { *phost = NULL; @@ -1571,37 +1576,44 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr, return flags; } -int probe_access_flags(CPUArchState *env, target_ulong addr, - MMUAccessType access_type, int mmu_idx, - bool nonfault, void **phost, uintptr_t retaddr) +int probe_access_full(CPUArchState *env, target_ulong addr, + MMUAccessType access_type, int mmu_idx, + bool nonfault, void **phost, CPUTLBEntryFull **pfull, + uintptr_t retaddr) { - int flags; - - flags = probe_access_internal(env, addr, 0, access_type, mmu_idx, - nonfault, phost, retaddr); + int flags = probe_access_internal(env, addr, 0, access_type, mmu_idx, + nonfault, phost, pfull, retaddr); /* Handle clean RAM pages. */ if (unlikely(flags & TLB_NOTDIRTY)) { - uintptr_t index = tlb_index(env, mmu_idx, addr); - CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index]; - - notdirty_write(env_cpu(env), addr, 1, full, retaddr); + notdirty_write(env_cpu(env), addr, 1, *pfull, retaddr); flags &= ~TLB_NOTDIRTY; } return flags; } +int probe_access_flags(CPUArchState *env, target_ulong addr, + MMUAccessType access_type, int mmu_idx, + bool nonfault, void **phost, uintptr_t retaddr) +{ + CPUTLBEntryFull *full; + + return probe_access_full(env, addr, access_type, mmu_idx, + nonfault, phost, &full, retaddr); +} + void *probe_access(CPUArchState *env, target_ulong addr, int size, MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { + CPUTLBEntryFull *full; void *host; int flags; g_assert(-(addr | TARGET_PAGE_MASK) >= size); flags = probe_access_internal(env, addr, size, access_type, mmu_idx, - false, &host, retaddr); + false, &host, &full, retaddr); /* Per the interface, size == 0 merely faults the access. */ if (size == 0) { @@ -1609,9 +1621,6 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size, } if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) { - uintptr_t index = tlb_index(env, mmu_idx, addr); - CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index]; - /* Handle watchpoints. */ if (flags & TLB_WATCHPOINT) { int wp_access = (access_type == MMU_DATA_STORE @@ -1632,11 +1641,12 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size, void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, MMUAccessType access_type, int mmu_idx) { + CPUTLBEntryFull *full; void *host; int flags; flags = probe_access_internal(env, addr, 0, access_type, - mmu_idx, true, &host, 0); + mmu_idx, true, &host, &full, 0); /* No combination of flags are expected by the caller. */ return flags ? NULL : host; @@ -1655,10 +1665,11 @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr, void **hostp) { + CPUTLBEntryFull *full; void *p; (void)probe_access_internal(env, addr, 1, MMU_INST_FETCH, - cpu_mmu_index(env, true), false, &p, 0); + cpu_mmu_index(env, true), false, &p, &full, 0); if (p == NULL) { return -1; } diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index bcad607c4e..d255d69bc1 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -434,6 +434,21 @@ int probe_access_flags(CPUArchState *env, target_ulong addr, MMUAccessType access_type, int mmu_idx, bool nonfault, void **phost, uintptr_t retaddr); +#ifndef CONFIG_USER_ONLY +/** + * probe_access_full: + * Like probe_access_flags, except also return into @pfull. + * + * The CPUTLBEntryFull structure returned via @pfull is transient + * and must be consumed or copied immediately, before any further + * access or changes to TLB @mmu_idx. + */ +int probe_access_full(CPUArchState *env, target_ulong addr, + MMUAccessType access_type, int mmu_idx, + bool nonfault, void **phost, + CPUTLBEntryFull **pfull, uintptr_t retaddr); +#endif + #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ /* Estimated block size for TB allocation. */ diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 42f4ceb701..a4aee238c7 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -42,6 +42,7 @@ typedef struct ConfidentialGuestSupport ConfidentialGuestSupport; typedef struct CPUAddressSpace CPUAddressSpace; typedef struct CPUArchState CPUArchState; typedef struct CPUState CPUState; +typedef struct CPUTLBEntryFull CPUTLBEntryFull; typedef struct DeviceListener DeviceListener; typedef struct DeviceState DeviceState; typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot; From 4047368938f64e2b79103c6e6358b06570b237e5 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 19 Aug 2022 16:33:23 -0700 Subject: [PATCH 0812/1020] accel/tcg: Introduce tlb_set_page_full MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have collected all of the page data into CPUTLBEntryFull, provide an interface to record that all in one go, instead of using 4 arguments. This interface allows CPUTLBEntryFull to be extended without having to change the number of arguments. Reviewed-by: Alex BennĂ©e Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 51 ++++++++++++++++++++++++++--------------- include/exec/cpu-defs.h | 14 +++++++++++ include/exec/exec-all.h | 22 ++++++++++++++++++ 3 files changed, 69 insertions(+), 18 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index e3ee4260bd..361078471b 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1095,16 +1095,16 @@ static void tlb_add_large_page(CPUArchState *env, int mmu_idx, env_tlb(env)->d[mmu_idx].large_page_mask = lp_mask; } -/* Add a new TLB entry. At most one entry for a given virtual address +/* + * Add a new TLB entry. At most one entry for a given virtual address * is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the * supplied size is only used by tlb_flush_page. * * Called from TCG-generated code, which is under an RCU read-side * critical section. */ -void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, - hwaddr paddr, MemTxAttrs attrs, int prot, - int mmu_idx, target_ulong size) +void tlb_set_page_full(CPUState *cpu, int mmu_idx, + target_ulong vaddr, CPUTLBEntryFull *full) { CPUArchState *env = cpu->env_ptr; CPUTLB *tlb = env_tlb(env); @@ -1117,35 +1117,36 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, CPUTLBEntry *te, tn; hwaddr iotlb, xlat, sz, paddr_page; target_ulong vaddr_page; - int asidx = cpu_asidx_from_attrs(cpu, attrs); - int wp_flags; + int asidx, wp_flags, prot; bool is_ram, is_romd; assert_cpu_is_self(cpu); - if (size <= TARGET_PAGE_SIZE) { + if (full->lg_page_size <= TARGET_PAGE_BITS) { sz = TARGET_PAGE_SIZE; } else { - tlb_add_large_page(env, mmu_idx, vaddr, size); - sz = size; + sz = (hwaddr)1 << full->lg_page_size; + tlb_add_large_page(env, mmu_idx, vaddr, sz); } vaddr_page = vaddr & TARGET_PAGE_MASK; - paddr_page = paddr & TARGET_PAGE_MASK; + paddr_page = full->phys_addr & TARGET_PAGE_MASK; + prot = full->prot; + asidx = cpu_asidx_from_attrs(cpu, full->attrs); section = address_space_translate_for_iotlb(cpu, asidx, paddr_page, - &xlat, &sz, attrs, &prot); + &xlat, &sz, full->attrs, &prot); assert(sz >= TARGET_PAGE_SIZE); tlb_debug("vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx " prot=%x idx=%d\n", - vaddr, paddr, prot, mmu_idx); + vaddr, full->phys_addr, prot, mmu_idx); address = vaddr_page; - if (size < TARGET_PAGE_SIZE) { + if (full->lg_page_size < TARGET_PAGE_BITS) { /* Repeat the MMU check and TLB fill on every access. */ address |= TLB_INVALID_MASK; } - if (attrs.byte_swap) { + if (full->attrs.byte_swap) { address |= TLB_BSWAP; } @@ -1236,8 +1237,10 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, * subtract here is that of the page base, and not the same as the * vaddr we add back in io_readx()/io_writex()/get_page_addr_code(). */ + desc->fulltlb[index] = *full; desc->fulltlb[index].xlat_section = iotlb - vaddr_page; - desc->fulltlb[index].attrs = attrs; + desc->fulltlb[index].phys_addr = paddr_page; + desc->fulltlb[index].prot = prot; /* Now calculate the new entry */ tn.addend = addend - vaddr_page; @@ -1272,9 +1275,21 @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, qemu_spin_unlock(&tlb->c.lock); } -/* Add a new TLB entry, but without specifying the memory - * transaction attributes to be used. - */ +void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr, + hwaddr paddr, MemTxAttrs attrs, int prot, + int mmu_idx, target_ulong size) +{ + CPUTLBEntryFull full = { + .phys_addr = paddr, + .attrs = attrs, + .prot = prot, + .lg_page_size = ctz64(size) + }; + + assert(is_power_of_2(size)); + tlb_set_page_full(cpu, mmu_idx, vaddr, &full); +} + void tlb_set_page(CPUState *cpu, target_ulong vaddr, hwaddr paddr, int prot, int mmu_idx, target_ulong size) diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index f70f54d850..5e12cc1854 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -148,7 +148,21 @@ typedef struct CPUTLBEntryFull { * + the offset within the target MemoryRegion (otherwise) */ hwaddr xlat_section; + + /* + * @phys_addr contains the physical address in the address space + * given by cpu_asidx_from_attrs(cpu, @attrs). + */ + hwaddr phys_addr; + + /* @attrs contains the memory transaction attributes for the page. */ MemTxAttrs attrs; + + /* @prot contains the complete protections for the page. */ + uint8_t prot; + + /* @lg_page_size contains the log2 of the page size. */ + uint8_t lg_page_size; } CPUTLBEntryFull; /* diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index d255d69bc1..b1b920a713 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -257,6 +257,28 @@ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu, uint16_t idxmap, unsigned bits); +/** + * tlb_set_page_full: + * @cpu: CPU context + * @mmu_idx: mmu index of the tlb to modify + * @vaddr: virtual address of the entry to add + * @full: the details of the tlb entry + * + * Add an entry to @cpu tlb index @mmu_idx. All of the fields of + * @full must be filled, except for xlat_section, and constitute + * the complete description of the translated page. + * + * This is generally called by the target tlb_fill function after + * having performed a successful page table walk to find the physical + * address and attributes for the translation. + * + * At most one entry for a given virtual address is permitted. Only a + * single TARGET_PAGE_SIZE region is mapped; @full->lg_page_size is only + * used by tlb_flush_page. + */ +void tlb_set_page_full(CPUState *cpu, int mmu_idx, target_ulong vaddr, + CPUTLBEntryFull *full); + /** * tlb_set_page_with_attrs: * @cpu: CPU to add this TLB entry for From 8c6953cf034cec0998815961e5ec70c9de15da6e Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 19 Aug 2022 17:02:36 -0700 Subject: [PATCH 0813/1020] include/exec: Introduce TARGET_PAGE_ENTRY_EXTRA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow the target to cache items from the guest page tables. Reviewed-by: Alex BennĂ©e Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Richard Henderson --- include/exec/cpu-defs.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 5e12cc1854..67239b4e5e 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -163,6 +163,15 @@ typedef struct CPUTLBEntryFull { /* @lg_page_size contains the log2 of the page size. */ uint8_t lg_page_size; + + /* + * Allow target-specific additions to this structure. + * This may be used to cache items from the guest cpu + * page tables for later use by the implementation. + */ +#ifdef TARGET_PAGE_ENTRY_EXTRA + TARGET_PAGE_ENTRY_EXTRA +#endif } CPUTLBEntryFull; /* From 6981f7026af3507f0bac6a16ae3b098fae12beb2 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 22 Aug 2022 16:23:22 -0700 Subject: [PATCH 0814/1020] accel/tcg: Remove PageDesc code_bitmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This bitmap is created and discarded immediately. We gain nothing by its existence. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson Message-Id: <20220822232338.1727934-2-richard.henderson@linaro.org> --- accel/tcg/translate-all.c | 78 ++------------------------------------- 1 file changed, 4 insertions(+), 74 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index d71d04d338..59432dc558 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -102,21 +102,14 @@ #define assert_memory_lock() tcg_debug_assert(have_mmap_lock()) #endif -#define SMC_BITMAP_USE_THRESHOLD 10 - typedef struct PageDesc { /* list of TBs intersecting this ram page */ uintptr_t first_tb; -#ifdef CONFIG_SOFTMMU - /* in order to optimize self modifying code, we count the number - of lookups we do to a given page to use a bitmap */ - unsigned long *code_bitmap; - unsigned int code_write_count; -#else +#ifdef CONFIG_USER_ONLY unsigned long flags; void *target_data; #endif -#ifndef CONFIG_USER_ONLY +#ifdef CONFIG_SOFTMMU QemuSpin lock; #endif } PageDesc; @@ -907,17 +900,6 @@ void tb_htable_init(void) qht_init(&tb_ctx.htable, tb_cmp, CODE_GEN_HTABLE_SIZE, mode); } -/* call with @p->lock held */ -static inline void invalidate_page_bitmap(PageDesc *p) -{ - assert_page_locked(p); -#ifdef CONFIG_SOFTMMU - g_free(p->code_bitmap); - p->code_bitmap = NULL; - p->code_write_count = 0; -#endif -} - /* Set to NULL all the 'first_tb' fields in all PageDescs. */ static void page_flush_tb_1(int level, void **lp) { @@ -932,7 +914,6 @@ static void page_flush_tb_1(int level, void **lp) for (i = 0; i < V_L2_SIZE; ++i) { page_lock(&pd[i]); pd[i].first_tb = (uintptr_t)NULL; - invalidate_page_bitmap(pd + i); page_unlock(&pd[i]); } } else { @@ -1197,11 +1178,9 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) if (rm_from_page_list) { p = page_find(tb->page_addr[0] >> TARGET_PAGE_BITS); tb_page_remove(p, tb); - invalidate_page_bitmap(p); if (tb->page_addr[1] != -1) { p = page_find(tb->page_addr[1] >> TARGET_PAGE_BITS); tb_page_remove(p, tb); - invalidate_page_bitmap(p); } } @@ -1246,35 +1225,6 @@ void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr) } } -#ifdef CONFIG_SOFTMMU -/* call with @p->lock held */ -static void build_page_bitmap(PageDesc *p) -{ - int n, tb_start, tb_end; - TranslationBlock *tb; - - assert_page_locked(p); - p->code_bitmap = bitmap_new(TARGET_PAGE_SIZE); - - PAGE_FOR_EACH_TB(p, tb, n) { - /* NOTE: this is subtle as a TB may span two physical pages */ - if (n == 0) { - /* NOTE: tb_end may be after the end of the page, but - it is not a problem */ - tb_start = tb->pc & ~TARGET_PAGE_MASK; - tb_end = tb_start + tb->size; - if (tb_end > TARGET_PAGE_SIZE) { - tb_end = TARGET_PAGE_SIZE; - } - } else { - tb_start = 0; - tb_end = ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); - } - bitmap_set(p->code_bitmap, tb_start, tb_end - tb_start); - } -} -#endif - /* add the tb in the target page and protect it if necessary * * Called with mmap_lock held for user-mode emulation. @@ -1295,7 +1245,6 @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb, page_already_protected = p->first_tb != (uintptr_t)NULL; #endif p->first_tb = (uintptr_t)tb | n; - invalidate_page_bitmap(p); #if defined(CONFIG_USER_ONLY) /* translator_loop() must have made all TB pages non-writable */ @@ -1357,10 +1306,8 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, /* remove TB from the page(s) if we couldn't insert it */ if (unlikely(existing_tb)) { tb_page_remove(p, tb); - invalidate_page_bitmap(p); if (p2) { tb_page_remove(p2, tb); - invalidate_page_bitmap(p2); } tb = existing_tb; } @@ -1731,7 +1678,6 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, #if !defined(CONFIG_USER_ONLY) /* if no code remaining, no need to continue to use slow writes */ if (!p->first_tb) { - invalidate_page_bitmap(p); tlb_unprotect_code(start); } #endif @@ -1827,24 +1773,8 @@ void tb_invalidate_phys_page_fast(struct page_collection *pages, } assert_page_locked(p); - if (!p->code_bitmap && - ++p->code_write_count >= SMC_BITMAP_USE_THRESHOLD) { - build_page_bitmap(p); - } - if (p->code_bitmap) { - unsigned int nr; - unsigned long b; - - nr = start & ~TARGET_PAGE_MASK; - b = p->code_bitmap[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG - 1)); - if (b & ((1 << len) - 1)) { - goto do_invalidate; - } - } else { - do_invalidate: - tb_invalidate_phys_page_range__locked(pages, p, start, start + len, - retaddr); - } + tb_invalidate_phys_page_range__locked(pages, p, start, start + len, + retaddr); } #else /* Called with mmap_lock held. If pc is not 0 then it indicates the From f79542afa798e1a6f7056b82c9a7e933242dd81b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 10 Aug 2022 15:27:46 -0700 Subject: [PATCH 0815/1020] accel/tcg: Use bool for page_find_alloc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bool is more appropriate type for the alloc parameter. Reviewed-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Richard Henderson --- accel/tcg/translate-all.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 59432dc558..ca685f6ede 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -465,7 +465,7 @@ void page_init(void) #endif } -static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) +static PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc) { PageDesc *pd; void **lp; @@ -533,11 +533,11 @@ static PageDesc *page_find_alloc(tb_page_addr_t index, int alloc) static inline PageDesc *page_find(tb_page_addr_t index) { - return page_find_alloc(index, 0); + return page_find_alloc(index, false); } static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1, - PageDesc **ret_p2, tb_page_addr_t phys2, int alloc); + PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc); /* In user-mode page locks aren't used; mmap_lock is enough */ #ifdef CONFIG_USER_ONLY @@ -651,7 +651,7 @@ static inline void page_unlock(PageDesc *pd) /* lock the page(s) of a TB in the correct acquisition order */ static inline void page_lock_tb(const TranslationBlock *tb) { - page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], 0); + page_lock_pair(NULL, tb->page_addr[0], NULL, tb->page_addr[1], false); } static inline void page_unlock_tb(const TranslationBlock *tb) @@ -840,7 +840,7 @@ void page_collection_unlock(struct page_collection *set) #endif /* !CONFIG_USER_ONLY */ static void page_lock_pair(PageDesc **ret_p1, tb_page_addr_t phys1, - PageDesc **ret_p2, tb_page_addr_t phys2, int alloc) + PageDesc **ret_p2, tb_page_addr_t phys2, bool alloc) { PageDesc *p1, *p2; tb_page_addr_t page1; @@ -1290,7 +1290,7 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, * Note that inserting into the hash table first isn't an option, since * we can only insert TBs that are fully initialized. */ - page_lock_pair(&p, phys_pc, &p2, phys_page2, 1); + page_lock_pair(&p, phys_pc, &p2, phys_page2, true); tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK); if (p2) { tb_page_add(p2, tb, 1, phys_page2); @@ -2219,7 +2219,7 @@ void page_set_flags(target_ulong start, target_ulong end, int flags) for (addr = start, len = end - start; len != 0; len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) { - PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1); + PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, true); /* If the write protection bit is set, then we invalidate the code inside. */ From b21af662c15522b83a973bc2ffd51d0117c0e039 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 12 Aug 2022 09:15:15 -0700 Subject: [PATCH 0816/1020] accel/tcg: Use DisasContextBase in plugin_gen_tb_start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the pc coming from db->pc_first rather than the TB. Use the cached host_addr rather than re-computing for the first page. We still need a separate lookup for the second page because it won't be computed for DisasContextBase until the translator actually performs a read from the page. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson --- accel/tcg/plugin-gen.c | 22 +++++++++++----------- accel/tcg/translator.c | 2 +- include/exec/plugin-gen.h | 7 ++++--- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/accel/tcg/plugin-gen.c b/accel/tcg/plugin-gen.c index 3d0b101e34..80dff68934 100644 --- a/accel/tcg/plugin-gen.c +++ b/accel/tcg/plugin-gen.c @@ -852,7 +852,8 @@ static void plugin_gen_inject(const struct qemu_plugin_tb *plugin_tb) pr_ops(); } -bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_only) +bool plugin_gen_tb_start(CPUState *cpu, const DisasContextBase *db, + bool mem_only) { bool ret = false; @@ -870,9 +871,9 @@ bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool mem_onl ret = true; - ptb->vaddr = tb->pc; + ptb->vaddr = db->pc_first; ptb->vaddr2 = -1; - get_page_addr_code_hostp(cpu->env_ptr, tb->pc, &ptb->haddr1); + ptb->haddr1 = db->host_addr[0]; ptb->haddr2 = NULL; ptb->mem_only = mem_only; @@ -898,16 +899,15 @@ void plugin_gen_insn_start(CPUState *cpu, const DisasContextBase *db) * Note that we skip this when haddr1 == NULL, e.g. when we're * fetching instructions from a region not backed by RAM. */ - if (likely(ptb->haddr1 != NULL && ptb->vaddr2 == -1) && - unlikely((db->pc_next & TARGET_PAGE_MASK) != - (db->pc_first & TARGET_PAGE_MASK))) { - get_page_addr_code_hostp(cpu->env_ptr, db->pc_next, - &ptb->haddr2); - ptb->vaddr2 = db->pc_next; - } - if (likely(ptb->vaddr2 == -1)) { + if (ptb->haddr1 == NULL) { + pinsn->haddr = NULL; + } else if (is_same_page(db, db->pc_next)) { pinsn->haddr = ptb->haddr1 + pinsn->vaddr - ptb->vaddr; } else { + if (ptb->vaddr2 == -1) { + ptb->vaddr2 = TARGET_PAGE_ALIGN(db->pc_first); + get_page_addr_code_hostp(cpu->env_ptr, ptb->vaddr2, &ptb->haddr2); + } pinsn->haddr = ptb->haddr2 + pinsn->vaddr - ptb->vaddr2; } } diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c index ca8a5f2d83..8e78fd7a9c 100644 --- a/accel/tcg/translator.c +++ b/accel/tcg/translator.c @@ -75,7 +75,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns, ops->tb_start(db, cpu); tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */ - plugin_enabled = plugin_gen_tb_start(cpu, tb, cflags & CF_MEMI_ONLY); + plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY); while (true) { db->num_insns++; diff --git a/include/exec/plugin-gen.h b/include/exec/plugin-gen.h index f92f169739..5004728c61 100644 --- a/include/exec/plugin-gen.h +++ b/include/exec/plugin-gen.h @@ -19,7 +19,8 @@ struct DisasContextBase; #ifdef CONFIG_PLUGIN -bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool supress); +bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db, + bool supress); void plugin_gen_tb_end(CPUState *cpu); void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db); void plugin_gen_insn_end(void); @@ -48,8 +49,8 @@ static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size) #else /* !CONFIG_PLUGIN */ -static inline -bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool supress) +static inline bool +plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db, bool sup) { return false; } From 93b996161b54860ded173f54ed96257717bb9728 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 15 Aug 2022 15:00:57 -0500 Subject: [PATCH 0817/1020] accel/tcg: Do not align tb->page_addr[0] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let tb->page_addr[0] contain the address of the first byte of the translated block, rather than the address of the page containing the start of the translated block. We need to recover this value anyway at various points, and it is easier to discard a page offset when it is not needed, which happens naturally via the existing find_page shift. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson --- accel/tcg/cpu-exec.c | 16 ++++++++-------- accel/tcg/cputlb.c | 3 ++- accel/tcg/translate-all.c | 9 +++++---- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 5f43b9769a..dd58a144a8 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -174,7 +174,7 @@ struct tb_desc { target_ulong pc; target_ulong cs_base; CPUArchState *env; - tb_page_addr_t phys_page1; + tb_page_addr_t page_addr0; uint32_t flags; uint32_t cflags; uint32_t trace_vcpu_dstate; @@ -186,7 +186,7 @@ static bool tb_lookup_cmp(const void *p, const void *d) const struct tb_desc *desc = d; if (tb->pc == desc->pc && - tb->page_addr[0] == desc->phys_page1 && + tb->page_addr[0] == desc->page_addr0 && tb->cs_base == desc->cs_base && tb->flags == desc->flags && tb->trace_vcpu_dstate == desc->trace_vcpu_dstate && @@ -195,8 +195,8 @@ static bool tb_lookup_cmp(const void *p, const void *d) if (tb->page_addr[1] == -1) { return true; } else { - tb_page_addr_t phys_page2; - target_ulong virt_page2; + tb_page_addr_t phys_page1; + target_ulong virt_page1; /* * We know that the first page matched, and an otherwise valid TB @@ -207,9 +207,9 @@ static bool tb_lookup_cmp(const void *p, const void *d) * is different for the new TB. Therefore any exception raised * here by the faulting lookup is not premature. */ - virt_page2 = TARGET_PAGE_ALIGN(desc->pc); - phys_page2 = get_page_addr_code(desc->env, virt_page2); - if (tb->page_addr[1] == phys_page2) { + virt_page1 = TARGET_PAGE_ALIGN(desc->pc); + phys_page1 = get_page_addr_code(desc->env, virt_page1); + if (tb->page_addr[1] == phys_page1) { return true; } } @@ -235,7 +235,7 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, if (phys_pc == -1) { return NULL; } - desc.phys_page1 = phys_pc & TARGET_PAGE_MASK; + desc.page_addr0 = phys_pc; h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate); return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); } diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 361078471b..a0db2d32a8 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -951,7 +951,8 @@ void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu, can be detected */ void tlb_protect_code(ram_addr_t ram_addr) { - cpu_physical_memory_test_and_clear_dirty(ram_addr, TARGET_PAGE_SIZE, + cpu_physical_memory_test_and_clear_dirty(ram_addr & TARGET_PAGE_MASK, + TARGET_PAGE_SIZE, DIRTY_MEMORY_CODE); } diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index ca685f6ede..3a63113c41 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -1167,7 +1167,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) qemu_spin_unlock(&tb->jmp_lock); /* remove the TB from the hash list */ - phys_pc = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); + phys_pc = tb->page_addr[0]; h = tb_hash_func(phys_pc, tb->pc, tb->flags, orig_cflags, tb->trace_vcpu_dstate); if (!qht_remove(&tb_ctx.htable, tb, h)) { @@ -1291,7 +1291,7 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, * we can only insert TBs that are fully initialized. */ page_lock_pair(&p, phys_pc, &p2, phys_page2, true); - tb_page_add(p, tb, 0, phys_pc & TARGET_PAGE_MASK); + tb_page_add(p, tb, 0, phys_pc); if (p2) { tb_page_add(p2, tb, 1, phys_page2); } else { @@ -1644,11 +1644,12 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, if (n == 0) { /* NOTE: tb_end may be after the end of the page, but it is not a problem */ - tb_start = tb->page_addr[0] + (tb->pc & ~TARGET_PAGE_MASK); + tb_start = tb->page_addr[0]; tb_end = tb_start + tb->size; } else { tb_start = tb->page_addr[1]; - tb_end = tb_start + ((tb->pc + tb->size) & ~TARGET_PAGE_MASK); + tb_end = tb_start + ((tb->page_addr[0] + tb->size) + & ~TARGET_PAGE_MASK); } if (!(tb_end <= start || tb_start >= end)) { #ifdef TARGET_HAS_PRECISE_SMC From 1d41a79b3c7573c941723455149cfadfe7c2ab37 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 29 Sep 2022 10:51:21 -0700 Subject: [PATCH 0818/1020] accel/tcg: Inline tb_flush_jmp_cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function has two users, who use it incompatibly. In tlb_flush_page_by_mmuidx_async_0, when flushing a single page, we need to flush exactly two pages. In tlb_flush_range_by_mmuidx_async_0, when flushing a range of pages, we need to flush N+1 pages. This avoids double-flushing of jmp cache pages in a range. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson --- accel/tcg/cputlb.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index a0db2d32a8..c7909fb619 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -107,14 +107,6 @@ static void tb_jmp_cache_clear_page(CPUState *cpu, target_ulong page_addr) } } -static void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr) -{ - /* Discard jump cache entries for any tb which might potentially - overlap the flushed page. */ - tb_jmp_cache_clear_page(cpu, addr - TARGET_PAGE_SIZE); - tb_jmp_cache_clear_page(cpu, addr); -} - /** * tlb_mmu_resize_locked() - perform TLB resize bookkeeping; resize if necessary * @desc: The CPUTLBDesc portion of the TLB @@ -541,7 +533,12 @@ static void tlb_flush_page_by_mmuidx_async_0(CPUState *cpu, } qemu_spin_unlock(&env_tlb(env)->c.lock); - tb_flush_jmp_cache(cpu, addr); + /* + * Discard jump cache entries for any tb which might potentially + * overlap the flushed page, which includes the previous. + */ + tb_jmp_cache_clear_page(cpu, addr - TARGET_PAGE_SIZE); + tb_jmp_cache_clear_page(cpu, addr); } /** @@ -792,8 +789,14 @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu, return; } - for (target_ulong i = 0; i < d.len; i += TARGET_PAGE_SIZE) { - tb_flush_jmp_cache(cpu, d.addr + i); + /* + * Discard jump cache entries for any tb which might potentially + * overlap the flushed pages, which includes the previous. + */ + d.addr -= TARGET_PAGE_SIZE; + for (target_ulong i = 0, n = d.len / TARGET_PAGE_SIZE + 1; i < n; i++) { + tb_jmp_cache_clear_page(cpu, d.addr); + d.addr += TARGET_PAGE_SIZE; } } From a976a99a29755e8c7a275ac269db8a0a20d79e95 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 15 Aug 2022 15:13:05 -0500 Subject: [PATCH 0819/1020] include/hw/core: Create struct CPUJumpCache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wrap the bare TranslationBlock pointer into a structure. Reviewed-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Richard Henderson --- accel/stubs/tcg-stub.c | 4 ++++ accel/tcg/cpu-exec.c | 10 +++++++--- accel/tcg/cputlb.c | 9 +++++---- accel/tcg/tb-hash.h | 1 + accel/tcg/tb-jmp-cache.h | 24 ++++++++++++++++++++++++ accel/tcg/translate-all.c | 28 +++++++++++++++++++++++++--- hw/core/cpu-common.c | 3 +-- include/exec/cpu-common.h | 1 + include/hw/core/cpu.h | 15 +-------------- include/qemu/typedefs.h | 1 + plugins/core.c | 2 +- trace/control-target.c | 2 +- 12 files changed, 72 insertions(+), 28 deletions(-) create mode 100644 accel/tcg/tb-jmp-cache.h diff --git a/accel/stubs/tcg-stub.c b/accel/stubs/tcg-stub.c index 6ce8a34228..c1b05767c0 100644 --- a/accel/stubs/tcg-stub.c +++ b/accel/stubs/tcg-stub.c @@ -21,6 +21,10 @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr) { } +void tcg_flush_jmp_cache(CPUState *cpu) +{ +} + int probe_access_flags(CPUArchState *env, target_ulong addr, MMUAccessType access_type, int mmu_idx, bool nonfault, void **phost, uintptr_t retaddr) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index dd58a144a8..2d7e610ee2 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -42,6 +42,7 @@ #include "sysemu/replay.h" #include "sysemu/tcg.h" #include "exec/helper-proto.h" +#include "tb-jmp-cache.h" #include "tb-hash.h" #include "tb-context.h" #include "internal.h" @@ -252,7 +253,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, tcg_debug_assert(!(cflags & CF_INVALID)); hash = tb_jmp_cache_hash_func(pc); - tb = qatomic_rcu_read(&cpu->tb_jmp_cache[hash]); + tb = qatomic_rcu_read(&cpu->tb_jmp_cache->array[hash].tb); if (likely(tb && tb->pc == pc && @@ -266,7 +267,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, if (tb == NULL) { return NULL; } - qatomic_set(&cpu->tb_jmp_cache[hash], tb); + qatomic_set(&cpu->tb_jmp_cache->array[hash].tb, tb); return tb; } @@ -987,6 +988,8 @@ int cpu_exec(CPUState *cpu) tb = tb_lookup(cpu, pc, cs_base, flags, cflags); if (tb == NULL) { + uint32_t h; + mmap_lock(); tb = tb_gen_code(cpu, pc, cs_base, flags, cflags); mmap_unlock(); @@ -994,7 +997,8 @@ int cpu_exec(CPUState *cpu) * We add the TB in the virtual pc hash table * for the fast lookup */ - qatomic_set(&cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)], tb); + h = tb_jmp_cache_hash_func(pc); + qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb); } #ifndef CONFIG_USER_ONLY diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index c7909fb619..6f1c00682b 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -100,10 +100,11 @@ static void tlb_window_reset(CPUTLBDesc *desc, int64_t ns, static void tb_jmp_cache_clear_page(CPUState *cpu, target_ulong page_addr) { - unsigned int i, i0 = tb_jmp_cache_hash_page(page_addr); + int i, i0 = tb_jmp_cache_hash_page(page_addr); + CPUJumpCache *jc = cpu->tb_jmp_cache; for (i = 0; i < TB_JMP_PAGE_SIZE; i++) { - qatomic_set(&cpu->tb_jmp_cache[i0 + i], NULL); + qatomic_set(&jc->array[i0 + i].tb, NULL); } } @@ -356,7 +357,7 @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data) qemu_spin_unlock(&env_tlb(env)->c.lock); - cpu_tb_jmp_cache_clear(cpu); + tcg_flush_jmp_cache(cpu); if (to_clean == ALL_MMUIDX_BITS) { qatomic_set(&env_tlb(env)->c.full_flush_count, @@ -785,7 +786,7 @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu, * longer to clear each entry individually than it will to clear it all. */ if (d.len >= (TARGET_PAGE_SIZE * TB_JMP_CACHE_SIZE)) { - cpu_tb_jmp_cache_clear(cpu); + tcg_flush_jmp_cache(cpu); return; } diff --git a/accel/tcg/tb-hash.h b/accel/tcg/tb-hash.h index 0a273d9605..83dc610e4c 100644 --- a/accel/tcg/tb-hash.h +++ b/accel/tcg/tb-hash.h @@ -23,6 +23,7 @@ #include "exec/cpu-defs.h" #include "exec/exec-all.h" #include "qemu/xxhash.h" +#include "tb-jmp-cache.h" #ifdef CONFIG_SOFTMMU diff --git a/accel/tcg/tb-jmp-cache.h b/accel/tcg/tb-jmp-cache.h new file mode 100644 index 0000000000..2d8fbb1bfe --- /dev/null +++ b/accel/tcg/tb-jmp-cache.h @@ -0,0 +1,24 @@ +/* + * The per-CPU TranslationBlock jump cache. + * + * Copyright (c) 2003 Fabrice Bellard + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef ACCEL_TCG_TB_JMP_CACHE_H +#define ACCEL_TCG_TB_JMP_CACHE_H + +#define TB_JMP_CACHE_BITS 12 +#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) + +/* + * Accessed in parallel; all accesses to 'tb' must be atomic. + */ +struct CPUJumpCache { + struct { + TranslationBlock *tb; + } array[TB_JMP_CACHE_SIZE]; +}; + +#endif /* ACCEL_TCG_TB_JMP_CACHE_H */ diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 3a63113c41..63ecc15236 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -58,6 +58,7 @@ #include "sysemu/tcg.h" #include "qapi/error.h" #include "hw/core/tcg-cpu-ops.h" +#include "tb-jmp-cache.h" #include "tb-hash.h" #include "tb-context.h" #include "internal.h" @@ -967,7 +968,7 @@ static void do_tb_flush(CPUState *cpu, run_on_cpu_data tb_flush_count) } CPU_FOREACH(cpu) { - cpu_tb_jmp_cache_clear(cpu); + tcg_flush_jmp_cache(cpu); } qht_reset_size(&tb_ctx.htable, CODE_GEN_HTABLE_SIZE); @@ -1187,8 +1188,9 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) /* remove the TB from the hash list */ h = tb_jmp_cache_hash_func(tb->pc); CPU_FOREACH(cpu) { - if (qatomic_read(&cpu->tb_jmp_cache[h]) == tb) { - qatomic_set(&cpu->tb_jmp_cache[h], NULL); + CPUJumpCache *jc = cpu->tb_jmp_cache; + if (qatomic_read(&jc->array[h].tb) == tb) { + qatomic_set(&jc->array[h].tb, NULL); } } @@ -2443,6 +2445,26 @@ int page_unprotect(target_ulong address, uintptr_t pc) } #endif /* CONFIG_USER_ONLY */ +/* + * Called by generic code at e.g. cpu reset after cpu creation, + * therefore we must be prepared to allocate the jump cache. + */ +void tcg_flush_jmp_cache(CPUState *cpu) +{ + CPUJumpCache *jc = cpu->tb_jmp_cache; + + if (likely(jc)) { + for (int i = 0; i < TB_JMP_CACHE_SIZE; i++) { + qatomic_set(&jc->array[i].tb, NULL); + } + } else { + /* This should happen once during realize, and thus never race. */ + jc = g_new0(CPUJumpCache, 1); + jc = qatomic_xchg(&cpu->tb_jmp_cache, jc); + assert(jc == NULL); + } +} + /* This is a wrapper for common code that can not use CONFIG_SOFTMMU */ void tcg_flush_softmmu_tlb(CPUState *cs) { diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c index 9e3241b430..f9fdd46b9d 100644 --- a/hw/core/cpu-common.c +++ b/hw/core/cpu-common.c @@ -137,8 +137,7 @@ static void cpu_common_reset(DeviceState *dev) cpu->cflags_next_tb = -1; if (tcg_enabled()) { - cpu_tb_jmp_cache_clear(cpu); - + tcg_flush_jmp_cache(cpu); tcg_flush_softmmu_tlb(cpu); } } diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index d909429427..c493510ee9 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -38,6 +38,7 @@ void cpu_list_unlock(void); unsigned int cpu_list_generation_id_get(void); void tcg_flush_softmmu_tlb(CPUState *cs); +void tcg_flush_jmp_cache(CPUState *cs); void tcg_iommu_init_notifier_list(CPUState *cpu); void tcg_iommu_free_notifier_list(CPUState *cpu); diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 009dc0d336..18ca701b44 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -236,9 +236,6 @@ struct kvm_run; struct hax_vcpu_state; struct hvf_vcpu_state; -#define TB_JMP_CACHE_BITS 12 -#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) - /* work queue */ /* The union type allows passing of 64 bit target pointers on 32 bit @@ -369,8 +366,7 @@ struct CPUState { CPUArchState *env_ptr; IcountDecr *icount_decr_ptr; - /* Accessed in parallel; all accesses must be atomic */ - TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE]; + CPUJumpCache *tb_jmp_cache; struct GDBRegisterState *gdb_regs; int gdb_num_regs; @@ -456,15 +452,6 @@ extern CPUTailQ cpus; extern __thread CPUState *current_cpu; -static inline void cpu_tb_jmp_cache_clear(CPUState *cpu) -{ - unsigned int i; - - for (i = 0; i < TB_JMP_CACHE_SIZE; i++) { - qatomic_set(&cpu->tb_jmp_cache[i], NULL); - } -} - /** * qemu_tcg_mttcg_enabled: * Check whether we are running MultiThread TCG or not. diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index a4aee238c7..5f95169827 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -41,6 +41,7 @@ typedef struct CoMutex CoMutex; typedef struct ConfidentialGuestSupport ConfidentialGuestSupport; typedef struct CPUAddressSpace CPUAddressSpace; typedef struct CPUArchState CPUArchState; +typedef struct CPUJumpCache CPUJumpCache; typedef struct CPUState CPUState; typedef struct CPUTLBEntryFull CPUTLBEntryFull; typedef struct DeviceListener DeviceListener; diff --git a/plugins/core.c b/plugins/core.c index 792262da08..c3ae284994 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -56,7 +56,7 @@ struct qemu_plugin_ctx *plugin_id_to_ctx_locked(qemu_plugin_id_t id) static void plugin_cpu_update__async(CPUState *cpu, run_on_cpu_data data) { bitmap_copy(cpu->plugin_mask, &data.host_ulong, QEMU_PLUGIN_EV_MAX); - cpu_tb_jmp_cache_clear(cpu); + tcg_flush_jmp_cache(cpu); } static void plugin_cpu_update__locked(gpointer k, gpointer v, gpointer udata) diff --git a/trace/control-target.c b/trace/control-target.c index 8418673c18..232c97a4a1 100644 --- a/trace/control-target.c +++ b/trace/control-target.c @@ -65,7 +65,7 @@ static void trace_event_synchronize_vcpu_state_dynamic( { bitmap_copy(vcpu->trace_dstate, vcpu->trace_dstate_delayed, CPU_TRACE_DSTATE_MAX_EVENTS); - cpu_tb_jmp_cache_clear(vcpu); + tcg_flush_jmp_cache(vcpu); } void trace_event_set_vcpu_state_dynamic(CPUState *vcpu, From e4fdf9df5b1c2aa427de796bea973520027ddd15 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 30 Sep 2022 10:31:21 -0700 Subject: [PATCH 0820/1020] hw/core: Add CPUClass.get_pc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Populate this new method for all targets. Always match the result that would be given by cpu_get_tb_cpu_state, as we will want these values to correspond in the logs. Reviewed-by: Taylor Simpson Reviewed-by: Alex BennĂ©e Reviewed-by: Mark Cave-Ayland (target/sparc) Signed-off-by: Richard Henderson --- Cc: Eduardo Habkost (supporter:Machine core) Cc: Marcel Apfelbaum (supporter:Machine core) Cc: "Philippe Mathieu-DaudĂ©" (reviewer:Machine core) Cc: Yanan Wang (reviewer:Machine core) Cc: Michael Rolnik (maintainer:AVR TCG CPUs) Cc: "Edgar E. Iglesias" (maintainer:CRIS TCG CPUs) Cc: Taylor Simpson (supporter:Hexagon TCG CPUs) Cc: Song Gao (maintainer:LoongArch TCG CPUs) Cc: Xiaojuan Yang (maintainer:LoongArch TCG CPUs) Cc: Laurent Vivier (maintainer:M68K TCG CPUs) Cc: Jiaxun Yang (reviewer:MIPS TCG CPUs) Cc: Aleksandar Rikalo (reviewer:MIPS TCG CPUs) Cc: Chris Wulff (maintainer:NiosII TCG CPUs) Cc: Marek Vasut (maintainer:NiosII TCG CPUs) Cc: Stafford Horne (odd fixer:OpenRISC TCG CPUs) Cc: Yoshinori Sato (reviewer:RENESAS RX CPUs) Cc: Mark Cave-Ayland (maintainer:SPARC TCG CPUs) Cc: Bastian Koppelmann (maintainer:TriCore TCG CPUs) Cc: Max Filippov (maintainer:Xtensa TCG CPUs) Cc: qemu-arm@nongnu.org (open list:ARM TCG CPUs) Cc: qemu-ppc@nongnu.org (open list:PowerPC TCG CPUs) Cc: qemu-riscv@nongnu.org (open list:RISC-V TCG CPUs) Cc: qemu-s390x@nongnu.org (open list:S390 TCG CPUs) --- include/hw/core/cpu.h | 3 +++ target/alpha/cpu.c | 9 +++++++++ target/arm/cpu.c | 13 +++++++++++++ target/avr/cpu.c | 8 ++++++++ target/cris/cpu.c | 8 ++++++++ target/hexagon/cpu.c | 8 ++++++++ target/hppa/cpu.c | 8 ++++++++ target/i386/cpu.c | 9 +++++++++ target/loongarch/cpu.c | 9 +++++++++ target/m68k/cpu.c | 8 ++++++++ target/microblaze/cpu.c | 8 ++++++++ target/mips/cpu.c | 8 ++++++++ target/nios2/cpu.c | 9 +++++++++ target/openrisc/cpu.c | 8 ++++++++ target/ppc/cpu_init.c | 8 ++++++++ target/riscv/cpu.c | 13 +++++++++++++ target/rx/cpu.c | 8 ++++++++ target/s390x/cpu.c | 8 ++++++++ target/sh4/cpu.c | 8 ++++++++ target/sparc/cpu.c | 8 ++++++++ target/tricore/cpu.c | 9 +++++++++ target/xtensa/cpu.c | 8 ++++++++ 22 files changed, 186 insertions(+) diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index 18ca701b44..f9b58773f7 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -115,6 +115,8 @@ struct SysemuCPUOps; * If the target behaviour here is anything other than "set * the PC register to the value passed in" then the target must * also implement the synchronize_from_tb hook. + * @get_pc: Callback for getting the Program Counter register. + * As above, with the semantics of the target architecture. * @gdb_read_register: Callback for letting GDB read a register. * @gdb_write_register: Callback for letting GDB write a register. * @gdb_adjust_breakpoint: Callback for adjusting the address of a @@ -151,6 +153,7 @@ struct CPUClass { void (*dump_state)(CPUState *cpu, FILE *, int flags); int64_t (*get_arch_id)(CPUState *cpu); void (*set_pc)(CPUState *cpu, vaddr value); + vaddr (*get_pc)(CPUState *cpu); int (*gdb_read_register)(CPUState *cpu, GByteArray *buf, int reg); int (*gdb_write_register)(CPUState *cpu, uint8_t *buf, int reg); vaddr (*gdb_adjust_breakpoint)(CPUState *cpu, vaddr addr); diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c index a8990d401b..979a629d59 100644 --- a/target/alpha/cpu.c +++ b/target/alpha/cpu.c @@ -33,6 +33,14 @@ static void alpha_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.pc = value; } +static vaddr alpha_cpu_get_pc(CPUState *cs) +{ + AlphaCPU *cpu = ALPHA_CPU(cs); + + return cpu->env.pc; +} + + static bool alpha_cpu_has_work(CPUState *cs) { /* Here we are checking to see if the CPU should wake up from HALT. @@ -244,6 +252,7 @@ static void alpha_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = alpha_cpu_has_work; cc->dump_state = alpha_cpu_dump_state; cc->set_pc = alpha_cpu_set_pc; + cc->get_pc = alpha_cpu_get_pc; cc->gdb_read_register = alpha_cpu_gdb_read_register; cc->gdb_write_register = alpha_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 7ec3281da9..fa67ba6647 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -60,6 +60,18 @@ static void arm_cpu_set_pc(CPUState *cs, vaddr value) } } +static vaddr arm_cpu_get_pc(CPUState *cs) +{ + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + if (is_a64(env)) { + return env->pc; + } else { + return env->regs[15]; + } +} + #ifdef CONFIG_TCG void arm_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) @@ -2172,6 +2184,7 @@ static void arm_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = arm_cpu_has_work; cc->dump_state = arm_cpu_dump_state; cc->set_pc = arm_cpu_set_pc; + cc->get_pc = arm_cpu_get_pc; cc->gdb_read_register = arm_cpu_gdb_read_register; cc->gdb_write_register = arm_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/avr/cpu.c b/target/avr/cpu.c index 05b992ff73..6900444d03 100644 --- a/target/avr/cpu.c +++ b/target/avr/cpu.c @@ -32,6 +32,13 @@ static void avr_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.pc_w = value / 2; /* internally PC points to words */ } +static vaddr avr_cpu_get_pc(CPUState *cs) +{ + AVRCPU *cpu = AVR_CPU(cs); + + return cpu->env.pc_w * 2; +} + static bool avr_cpu_has_work(CPUState *cs) { AVRCPU *cpu = AVR_CPU(cs); @@ -214,6 +221,7 @@ static void avr_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = avr_cpu_has_work; cc->dump_state = avr_cpu_dump_state; cc->set_pc = avr_cpu_set_pc; + cc->get_pc = avr_cpu_get_pc; dc->vmsd = &vms_avr_cpu; cc->sysemu_ops = &avr_sysemu_ops; cc->disas_set_info = avr_cpu_disas_set_info; diff --git a/target/cris/cpu.c b/target/cris/cpu.c index ed6c781342..22f5c70f39 100644 --- a/target/cris/cpu.c +++ b/target/cris/cpu.c @@ -35,6 +35,13 @@ static void cris_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.pc = value; } +static vaddr cris_cpu_get_pc(CPUState *cs) +{ + CRISCPU *cpu = CRIS_CPU(cs); + + return cpu->env.pc; +} + static bool cris_cpu_has_work(CPUState *cs) { return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI); @@ -297,6 +304,7 @@ static void cris_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = cris_cpu_has_work; cc->dump_state = cris_cpu_dump_state; cc->set_pc = cris_cpu_set_pc; + cc->get_pc = cris_cpu_get_pc; cc->gdb_read_register = cris_cpu_gdb_read_register; cc->gdb_write_register = cris_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index fa9bd702d6..04a497db5e 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -251,6 +251,13 @@ static void hexagon_cpu_set_pc(CPUState *cs, vaddr value) env->gpr[HEX_REG_PC] = value; } +static vaddr hexagon_cpu_get_pc(CPUState *cs) +{ + HexagonCPU *cpu = HEXAGON_CPU(cs); + CPUHexagonState *env = &cpu->env; + return env->gpr[HEX_REG_PC]; +} + static void hexagon_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -337,6 +344,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data) cc->has_work = hexagon_cpu_has_work; cc->dump_state = hexagon_dump_state; cc->set_pc = hexagon_cpu_set_pc; + cc->get_pc = hexagon_cpu_get_pc; cc->gdb_read_register = hexagon_gdb_read_register; cc->gdb_write_register = hexagon_gdb_write_register; cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS; diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index a6f52caf14..e25d3db6d5 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -36,6 +36,13 @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.iaoq_b = value + 4; } +static vaddr hppa_cpu_get_pc(CPUState *cs) +{ + HPPACPU *cpu = HPPA_CPU(cs); + + return cpu->env.iaoq_f; +} + static void hppa_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -168,6 +175,7 @@ static void hppa_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = hppa_cpu_has_work; cc->dump_state = hppa_cpu_dump_state; cc->set_pc = hppa_cpu_set_pc; + cc->get_pc = hppa_cpu_get_pc; cc->gdb_read_register = hppa_cpu_gdb_read_register; cc->gdb_write_register = hppa_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 1db1278a59..ad623d91e4 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -6824,6 +6824,14 @@ static void x86_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.eip = value; } +static vaddr x86_cpu_get_pc(CPUState *cs) +{ + X86CPU *cpu = X86_CPU(cs); + + /* Match cpu_get_tb_cpu_state. */ + return cpu->env.eip + cpu->env.segs[R_CS].base; +} + int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request) { X86CPU *cpu = X86_CPU(cs); @@ -7106,6 +7114,7 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data) cc->has_work = x86_cpu_has_work; cc->dump_state = x86_cpu_dump_state; cc->set_pc = x86_cpu_set_pc; + cc->get_pc = x86_cpu_get_pc; cc->gdb_read_register = x86_cpu_gdb_read_register; cc->gdb_write_register = x86_cpu_gdb_write_register; cc->get_arch_id = x86_cpu_get_arch_id; diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 941e2772bc..20a92ea56c 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -82,6 +82,14 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value) env->pc = value; } +static vaddr loongarch_cpu_get_pc(CPUState *cs) +{ + LoongArchCPU *cpu = LOONGARCH_CPU(cs); + CPULoongArchState *env = &cpu->env; + + return env->pc; +} + #ifndef CONFIG_USER_ONLY #include "hw/loongarch/virt.h" @@ -680,6 +688,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data) cc->has_work = loongarch_cpu_has_work; cc->dump_state = loongarch_cpu_dump_state; cc->set_pc = loongarch_cpu_set_pc; + cc->get_pc = loongarch_cpu_get_pc; #ifndef CONFIG_USER_ONLY dc->vmsd = &vmstate_loongarch_cpu; cc->sysemu_ops = &loongarch_sysemu_ops; diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c index 25d610db21..1e902e1ef0 100644 --- a/target/m68k/cpu.c +++ b/target/m68k/cpu.c @@ -31,6 +31,13 @@ static void m68k_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.pc = value; } +static vaddr m68k_cpu_get_pc(CPUState *cs) +{ + M68kCPU *cpu = M68K_CPU(cs); + + return cpu->env.pc; +} + static bool m68k_cpu_has_work(CPUState *cs) { return cs->interrupt_request & CPU_INTERRUPT_HARD; @@ -540,6 +547,7 @@ static void m68k_cpu_class_init(ObjectClass *c, void *data) cc->has_work = m68k_cpu_has_work; cc->dump_state = m68k_cpu_dump_state; cc->set_pc = m68k_cpu_set_pc; + cc->get_pc = m68k_cpu_get_pc; cc->gdb_read_register = m68k_cpu_gdb_read_register; cc->gdb_write_register = m68k_cpu_gdb_write_register; #if defined(CONFIG_SOFTMMU) diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index aed200dcff..73af51769e 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -84,6 +84,13 @@ static void mb_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.iflags = 0; } +static vaddr mb_cpu_get_pc(CPUState *cs) +{ + MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); + + return cpu->env.pc; +} + static void mb_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -391,6 +398,7 @@ static void mb_cpu_class_init(ObjectClass *oc, void *data) cc->dump_state = mb_cpu_dump_state; cc->set_pc = mb_cpu_set_pc; + cc->get_pc = mb_cpu_get_pc; cc->gdb_read_register = mb_cpu_gdb_read_register; cc->gdb_write_register = mb_cpu_gdb_write_register; diff --git a/target/mips/cpu.c b/target/mips/cpu.c index c15c955367..da58eb8892 100644 --- a/target/mips/cpu.c +++ b/target/mips/cpu.c @@ -128,6 +128,13 @@ static void mips_cpu_set_pc(CPUState *cs, vaddr value) mips_env_set_pc(&cpu->env, value); } +static vaddr mips_cpu_get_pc(CPUState *cs) +{ + MIPSCPU *cpu = MIPS_CPU(cs); + + return cpu->env.active_tc.PC; +} + static bool mips_cpu_has_work(CPUState *cs) { MIPSCPU *cpu = MIPS_CPU(cs); @@ -557,6 +564,7 @@ static void mips_cpu_class_init(ObjectClass *c, void *data) cc->has_work = mips_cpu_has_work; cc->dump_state = mips_cpu_dump_state; cc->set_pc = mips_cpu_set_pc; + cc->get_pc = mips_cpu_get_pc; cc->gdb_read_register = mips_cpu_gdb_read_register; cc->gdb_write_register = mips_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/nios2/cpu.c b/target/nios2/cpu.c index 19b2409974..2b28429c08 100644 --- a/target/nios2/cpu.c +++ b/target/nios2/cpu.c @@ -34,6 +34,14 @@ static void nios2_cpu_set_pc(CPUState *cs, vaddr value) env->pc = value; } +static vaddr nios2_cpu_get_pc(CPUState *cs) +{ + Nios2CPU *cpu = NIOS2_CPU(cs); + CPUNios2State *env = &cpu->env; + + return env->pc; +} + static bool nios2_cpu_has_work(CPUState *cs) { return cs->interrupt_request & CPU_INTERRUPT_HARD; @@ -362,6 +370,7 @@ static void nios2_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = nios2_cpu_has_work; cc->dump_state = nios2_cpu_dump_state; cc->set_pc = nios2_cpu_set_pc; + cc->get_pc = nios2_cpu_get_pc; cc->disas_set_info = nios2_cpu_disas_set_info; #ifndef CONFIG_USER_ONLY cc->sysemu_ops = &nios2_sysemu_ops; diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index cb9f35f408..33cf717210 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -31,6 +31,13 @@ static void openrisc_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.dflag = 0; } +static vaddr openrisc_cpu_get_pc(CPUState *cs) +{ + OpenRISCCPU *cpu = OPENRISC_CPU(cs); + + return cpu->env.pc; +} + static void openrisc_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -218,6 +225,7 @@ static void openrisc_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = openrisc_cpu_has_work; cc->dump_state = openrisc_cpu_dump_state; cc->set_pc = openrisc_cpu_set_pc; + cc->get_pc = openrisc_cpu_get_pc; cc->gdb_read_register = openrisc_cpu_gdb_read_register; cc->gdb_write_register = openrisc_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c index 6e080ebda0..763a8431be 100644 --- a/target/ppc/cpu_init.c +++ b/target/ppc/cpu_init.c @@ -7214,6 +7214,13 @@ static void ppc_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.nip = value; } +static vaddr ppc_cpu_get_pc(CPUState *cs) +{ + PowerPCCPU *cpu = POWERPC_CPU(cs); + + return cpu->env.nip; +} + static bool ppc_cpu_has_work(CPUState *cs) { PowerPCCPU *cpu = POWERPC_CPU(cs); @@ -7472,6 +7479,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = ppc_cpu_has_work; cc->dump_state = ppc_cpu_dump_state; cc->set_pc = ppc_cpu_set_pc; + cc->get_pc = ppc_cpu_get_pc; cc->gdb_read_register = ppc_cpu_gdb_read_register; cc->gdb_write_register = ppc_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index b29c88b9f0..6ca05c6eaf 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -462,6 +462,18 @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value) } } +static vaddr riscv_cpu_get_pc(CPUState *cs) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + + /* Match cpu_get_tb_cpu_state. */ + if (env->xl == MXL_RV32) { + return env->pc & UINT32_MAX; + } + return env->pc; +} + static void riscv_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -1154,6 +1166,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) cc->has_work = riscv_cpu_has_work; cc->dump_state = riscv_cpu_dump_state; cc->set_pc = riscv_cpu_set_pc; + cc->get_pc = riscv_cpu_get_pc; cc->gdb_read_register = riscv_cpu_gdb_read_register; cc->gdb_write_register = riscv_cpu_gdb_write_register; cc->gdb_num_core_regs = 33; diff --git a/target/rx/cpu.c b/target/rx/cpu.c index fb30080ac4..134b4b6bb6 100644 --- a/target/rx/cpu.c +++ b/target/rx/cpu.c @@ -32,6 +32,13 @@ static void rx_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.pc = value; } +static vaddr rx_cpu_get_pc(CPUState *cs) +{ + RXCPU *cpu = RX_CPU(cs); + + return cpu->env.pc; +} + static void rx_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -208,6 +215,7 @@ static void rx_cpu_class_init(ObjectClass *klass, void *data) cc->has_work = rx_cpu_has_work; cc->dump_state = rx_cpu_dump_state; cc->set_pc = rx_cpu_set_pc; + cc->get_pc = rx_cpu_get_pc; #ifndef CONFIG_USER_ONLY cc->sysemu_ops = &rx_sysemu_ops; diff --git a/target/s390x/cpu.c b/target/s390x/cpu.c index c31bb2351f..df00040e95 100644 --- a/target/s390x/cpu.c +++ b/target/s390x/cpu.c @@ -88,6 +88,13 @@ static void s390_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.psw.addr = value; } +static vaddr s390_cpu_get_pc(CPUState *cs) +{ + S390CPU *cpu = S390_CPU(cs); + + return cpu->env.psw.addr; +} + static bool s390_cpu_has_work(CPUState *cs) { S390CPU *cpu = S390_CPU(cs); @@ -297,6 +304,7 @@ static void s390_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = s390_cpu_has_work; cc->dump_state = s390_cpu_dump_state; cc->set_pc = s390_cpu_set_pc; + cc->get_pc = s390_cpu_get_pc; cc->gdb_read_register = s390_cpu_gdb_read_register; cc->gdb_write_register = s390_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index 06b2691dc4..4bafbf8596 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -34,6 +34,13 @@ static void superh_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.pc = value; } +static vaddr superh_cpu_get_pc(CPUState *cs) +{ + SuperHCPU *cpu = SUPERH_CPU(cs); + + return cpu->env.pc; +} + static void superh_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -261,6 +268,7 @@ static void superh_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = superh_cpu_has_work; cc->dump_state = superh_cpu_dump_state; cc->set_pc = superh_cpu_set_pc; + cc->get_pc = superh_cpu_get_pc; cc->gdb_read_register = superh_cpu_gdb_read_register; cc->gdb_write_register = superh_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 55268ed2a1..1b2afb0cb8 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -693,6 +693,13 @@ static void sparc_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.npc = value + 4; } +static vaddr sparc_cpu_get_pc(CPUState *cs) +{ + SPARCCPU *cpu = SPARC_CPU(cs); + + return cpu->env.pc; +} + static void sparc_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -896,6 +903,7 @@ static void sparc_cpu_class_init(ObjectClass *oc, void *data) cc->memory_rw_debug = sparc_cpu_memory_rw_debug; #endif cc->set_pc = sparc_cpu_set_pc; + cc->get_pc = sparc_cpu_get_pc; cc->gdb_read_register = sparc_cpu_gdb_read_register; cc->gdb_write_register = sparc_cpu_gdb_write_register; #ifndef CONFIG_USER_ONLY diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c index b95682b7f0..91b16bdefc 100644 --- a/target/tricore/cpu.c +++ b/target/tricore/cpu.c @@ -41,6 +41,14 @@ static void tricore_cpu_set_pc(CPUState *cs, vaddr value) env->PC = value & ~(target_ulong)1; } +static vaddr tricore_cpu_get_pc(CPUState *cs) +{ + TriCoreCPU *cpu = TRICORE_CPU(cs); + CPUTriCoreState *env = &cpu->env; + + return env->PC; +} + static void tricore_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -176,6 +184,7 @@ static void tricore_cpu_class_init(ObjectClass *c, void *data) cc->dump_state = tricore_cpu_dump_state; cc->set_pc = tricore_cpu_set_pc; + cc->get_pc = tricore_cpu_get_pc; cc->sysemu_ops = &tricore_sysemu_ops; cc->tcg_ops = &tricore_tcg_ops; } diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c index fd553fdfb5..cbbe0e84a2 100644 --- a/target/xtensa/cpu.c +++ b/target/xtensa/cpu.c @@ -44,6 +44,13 @@ static void xtensa_cpu_set_pc(CPUState *cs, vaddr value) cpu->env.pc = value; } +static vaddr xtensa_cpu_get_pc(CPUState *cs) +{ + XtensaCPU *cpu = XTENSA_CPU(cs); + + return cpu->env.pc; +} + static bool xtensa_cpu_has_work(CPUState *cs) { #ifndef CONFIG_USER_ONLY @@ -233,6 +240,7 @@ static void xtensa_cpu_class_init(ObjectClass *oc, void *data) cc->has_work = xtensa_cpu_has_work; cc->dump_state = xtensa_cpu_dump_state; cc->set_pc = xtensa_cpu_set_pc; + cc->get_pc = xtensa_cpu_get_pc; cc->gdb_read_register = xtensa_cpu_gdb_read_register; cc->gdb_write_register = xtensa_cpu_gdb_write_register; cc->gdb_stop_before_watchpoint = true; From fbf59aad178d98afe193fa872a2d880266a75269 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Mon, 15 Aug 2022 15:16:06 -0500 Subject: [PATCH 0821/1020] accel/tcg: Introduce tb_pc and log_pc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The availability of tb->pc will shortly be conditional. Introduce accessor functions to minimize ifdefs. Pass around a known pc to places like tcg_gen_code, where the caller must already have the value. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson --- accel/tcg/cpu-exec.c | 46 ++++++++++++++----------- accel/tcg/internal.h | 6 ++++ accel/tcg/translate-all.c | 37 +++++++++++--------- include/exec/exec-all.h | 6 ++++ include/tcg/tcg.h | 2 +- target/arm/cpu.c | 4 +-- target/avr/cpu.c | 2 +- target/hexagon/cpu.c | 2 +- target/hppa/cpu.c | 4 +-- target/i386/tcg/tcg-cpu.c | 2 +- target/loongarch/cpu.c | 2 +- target/microblaze/cpu.c | 2 +- target/mips/tcg/exception.c | 2 +- target/mips/tcg/sysemu/special_helper.c | 2 +- target/openrisc/cpu.c | 2 +- target/riscv/cpu.c | 4 +-- target/rx/cpu.c | 2 +- target/sh4/cpu.c | 4 +-- target/sparc/cpu.c | 2 +- target/tricore/cpu.c | 2 +- tcg/tcg.c | 8 ++--- 21 files changed, 82 insertions(+), 61 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 2d7e610ee2..8b3f8435fb 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -186,7 +186,7 @@ static bool tb_lookup_cmp(const void *p, const void *d) const TranslationBlock *tb = p; const struct tb_desc *desc = d; - if (tb->pc == desc->pc && + if (tb_pc(tb) == desc->pc && tb->page_addr[0] == desc->page_addr0 && tb->cs_base == desc->cs_base && tb->flags == desc->flags && @@ -271,12 +271,10 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, return tb; } -static inline void log_cpu_exec(target_ulong pc, CPUState *cpu, - const TranslationBlock *tb) +static void log_cpu_exec(target_ulong pc, CPUState *cpu, + const TranslationBlock *tb) { - if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) - && qemu_log_in_addr_range(pc)) { - + if (qemu_log_in_addr_range(pc)) { qemu_log_mask(CPU_LOG_EXEC, "Trace %d: %p [" TARGET_FMT_lx "/" TARGET_FMT_lx "/%08x/%08x] %s\n", @@ -400,7 +398,9 @@ const void *HELPER(lookup_tb_ptr)(CPUArchState *env) return tcg_code_gen_epilogue; } - log_cpu_exec(pc, cpu, tb); + if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) { + log_cpu_exec(pc, cpu, tb); + } return tb->tc.ptr; } @@ -423,7 +423,9 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) TranslationBlock *last_tb; const void *tb_ptr = itb->tc.ptr; - log_cpu_exec(itb->pc, cpu, itb); + if (qemu_loglevel_mask(CPU_LOG_TB_CPU | CPU_LOG_EXEC)) { + log_cpu_exec(log_pc(cpu, itb), cpu, itb); + } qemu_thread_jit_execute(); ret = tcg_qemu_tb_exec(env, tb_ptr); @@ -447,16 +449,20 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) * of the start of the TB. */ CPUClass *cc = CPU_GET_CLASS(cpu); - qemu_log_mask_and_addr(CPU_LOG_EXEC, last_tb->pc, - "Stopped execution of TB chain before %p [" - TARGET_FMT_lx "] %s\n", - last_tb->tc.ptr, last_tb->pc, - lookup_symbol(last_tb->pc)); + if (cc->tcg_ops->synchronize_from_tb) { cc->tcg_ops->synchronize_from_tb(cpu, last_tb); } else { assert(cc->set_pc); - cc->set_pc(cpu, last_tb->pc); + cc->set_pc(cpu, tb_pc(last_tb)); + } + if (qemu_loglevel_mask(CPU_LOG_EXEC)) { + target_ulong pc = log_pc(cpu, last_tb); + if (qemu_log_in_addr_range(pc)) { + qemu_log("Stopped execution of TB chain before %p [" + TARGET_FMT_lx "] %s\n", + last_tb->tc.ptr, pc, lookup_symbol(pc)); + } } } @@ -598,11 +604,8 @@ static inline void tb_add_jump(TranslationBlock *tb, int n, qemu_spin_unlock(&tb_next->jmp_lock); - qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc, - "Linking TBs %p [" TARGET_FMT_lx - "] index %d -> %p [" TARGET_FMT_lx "]\n", - tb->tc.ptr, tb->pc, n, - tb_next->tc.ptr, tb_next->pc); + qemu_log_mask(CPU_LOG_EXEC, "Linking TBs %p index %d -> %p\n", + tb->tc.ptr, n, tb_next->tc.ptr); return; out_unlock_next: @@ -848,11 +851,12 @@ static inline bool cpu_handle_interrupt(CPUState *cpu, } static inline void cpu_loop_exec_tb(CPUState *cpu, TranslationBlock *tb, + target_ulong pc, TranslationBlock **last_tb, int *tb_exit) { int32_t insns_left; - trace_exec_tb(tb, tb->pc); + trace_exec_tb(tb, pc); tb = cpu_tb_exec(cpu, tb, tb_exit); if (*tb_exit != TB_EXIT_REQUESTED) { *last_tb = tb; @@ -1017,7 +1021,7 @@ int cpu_exec(CPUState *cpu) tb_add_jump(last_tb, tb_exit, tb); } - cpu_loop_exec_tb(cpu, tb, &last_tb, &tb_exit); + cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit); /* Try to align the host and virtual clocks if the guest is in advance */ diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h index 3092bfa964..a3875a3b5a 100644 --- a/accel/tcg/internal.h +++ b/accel/tcg/internal.h @@ -18,4 +18,10 @@ G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr); void page_init(void); void tb_htable_init(void); +/* Return the current PC from CPU, which may be cached in TB. */ +static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb) +{ + return tb_pc(tb); +} + #endif /* ACCEL_TCG_INTERNAL_H */ diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 63ecc15236..13c964dcd8 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -299,7 +299,7 @@ static int encode_search(TranslationBlock *tb, uint8_t *block) for (j = 0; j < TARGET_INSN_START_WORDS; ++j) { if (i == 0) { - prev = (j == 0 ? tb->pc : 0); + prev = (j == 0 ? tb_pc(tb) : 0); } else { prev = tcg_ctx->gen_insn_data[i - 1][j]; } @@ -327,7 +327,7 @@ static int encode_search(TranslationBlock *tb, uint8_t *block) static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, uintptr_t searched_pc, bool reset_icount) { - target_ulong data[TARGET_INSN_START_WORDS] = { tb->pc }; + target_ulong data[TARGET_INSN_START_WORDS] = { tb_pc(tb) }; uintptr_t host_pc = (uintptr_t)tb->tc.ptr; CPUArchState *env = cpu->env_ptr; const uint8_t *p = tb->tc.ptr + tb->tc.size; @@ -885,7 +885,7 @@ static bool tb_cmp(const void *ap, const void *bp) const TranslationBlock *a = ap; const TranslationBlock *b = bp; - return a->pc == b->pc && + return tb_pc(a) == tb_pc(b) && a->cs_base == b->cs_base && a->flags == b->flags && (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) && @@ -1013,9 +1013,10 @@ static void do_tb_invalidate_check(void *p, uint32_t hash, void *userp) TranslationBlock *tb = p; target_ulong addr = *(target_ulong *)userp; - if (!(addr + TARGET_PAGE_SIZE <= tb->pc || addr >= tb->pc + tb->size)) { + if (!(addr + TARGET_PAGE_SIZE <= tb_pc(tb) || + addr >= tb_pc(tb) + tb->size)) { printf("ERROR invalidate: address=" TARGET_FMT_lx - " PC=%08lx size=%04x\n", addr, (long)tb->pc, tb->size); + " PC=%08lx size=%04x\n", addr, (long)tb_pc(tb), tb->size); } } @@ -1034,11 +1035,11 @@ static void do_tb_page_check(void *p, uint32_t hash, void *userp) TranslationBlock *tb = p; int flags1, flags2; - flags1 = page_get_flags(tb->pc); - flags2 = page_get_flags(tb->pc + tb->size - 1); + flags1 = page_get_flags(tb_pc(tb)); + flags2 = page_get_flags(tb_pc(tb) + tb->size - 1); if ((flags1 & PAGE_WRITE) || (flags2 & PAGE_WRITE)) { printf("ERROR page flags: PC=%08lx size=%04x f1=%x f2=%x\n", - (long)tb->pc, tb->size, flags1, flags2); + (long)tb_pc(tb), tb->size, flags1, flags2); } } @@ -1169,7 +1170,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) /* remove the TB from the hash list */ phys_pc = tb->page_addr[0]; - h = tb_hash_func(phys_pc, tb->pc, tb->flags, orig_cflags, + h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, orig_cflags, tb->trace_vcpu_dstate); if (!qht_remove(&tb_ctx.htable, tb, h)) { return; @@ -1301,7 +1302,7 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, } /* add in the hash table */ - h = tb_hash_func(phys_pc, tb->pc, tb->flags, tb->cflags, + h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, tb->cflags, tb->trace_vcpu_dstate); qht_insert(&tb_ctx.htable, tb, h, &existing_tb); @@ -1401,7 +1402,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, tcg_ctx->cpu = NULL; max_insns = tb->icount; - trace_translate_block(tb, tb->pc, tb->tc.ptr); + trace_translate_block(tb, pc, tb->tc.ptr); /* generate machine code */ tb->jmp_reset_offset[0] = TB_JMP_RESET_OFFSET_INVALID; @@ -1422,7 +1423,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, ti = profile_getclock(); #endif - gen_code_size = tcg_gen_code(tcg_ctx, tb); + gen_code_size = tcg_gen_code(tcg_ctx, tb, pc); if (unlikely(gen_code_size < 0)) { error_return: switch (gen_code_size) { @@ -1478,7 +1479,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, #ifdef DEBUG_DISAS if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) && - qemu_log_in_addr_range(tb->pc)) { + qemu_log_in_addr_range(pc)) { FILE *logfile = qemu_log_trylock(); if (logfile) { int code_size, data_size; @@ -1918,9 +1919,13 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr) */ cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | CF_LAST_IO | n; - qemu_log_mask_and_addr(CPU_LOG_EXEC, tb->pc, - "cpu_io_recompile: rewound execution of TB to " - TARGET_FMT_lx "\n", tb->pc); + if (qemu_loglevel_mask(CPU_LOG_EXEC)) { + target_ulong pc = log_pc(cpu, tb); + if (qemu_log_in_addr_range(pc)) { + qemu_log("cpu_io_recompile: rewound execution of TB to " + TARGET_FMT_lx "\n", pc); + } + } cpu_loop_exit_noexc(cpu); } diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index b1b920a713..7ea6026ba9 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -570,6 +570,12 @@ struct TranslationBlock { uintptr_t jmp_dest[2]; }; +/* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */ +static inline target_ulong tb_pc(const TranslationBlock *tb) +{ + return tb->pc; +} + /* Hide the qatomic_read to make code a little easier on the eyes */ static inline uint32_t tb_cflags(const TranslationBlock *tb) { diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h index 26a70526f1..d84bae6e3f 100644 --- a/include/tcg/tcg.h +++ b/include/tcg/tcg.h @@ -840,7 +840,7 @@ void tcg_register_thread(void); void tcg_prologue_init(TCGContext *s); void tcg_func_start(TCGContext *s); -int tcg_gen_code(TCGContext *s, TranslationBlock *tb); +int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start); void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size); diff --git a/target/arm/cpu.c b/target/arm/cpu.c index fa67ba6647..94ca6f163f 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -84,9 +84,9 @@ void arm_cpu_synchronize_from_tb(CPUState *cs, * never possible for an AArch64 TB to chain to an AArch32 TB. */ if (is_a64(env)) { - env->pc = tb->pc; + env->pc = tb_pc(tb); } else { - env->regs[15] = tb->pc; + env->regs[15] = tb_pc(tb); } } #endif /* CONFIG_TCG */ diff --git a/target/avr/cpu.c b/target/avr/cpu.c index 6900444d03..0d2861179d 100644 --- a/target/avr/cpu.c +++ b/target/avr/cpu.c @@ -54,7 +54,7 @@ static void avr_cpu_synchronize_from_tb(CPUState *cs, AVRCPU *cpu = AVR_CPU(cs); CPUAVRState *env = &cpu->env; - env->pc_w = tb->pc / 2; /* internally PC points to words */ + env->pc_w = tb_pc(tb) / 2; /* internally PC points to words */ } static void avr_cpu_reset(DeviceState *ds) diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index 04a497db5e..fa6d722555 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -263,7 +263,7 @@ static void hexagon_cpu_synchronize_from_tb(CPUState *cs, { HexagonCPU *cpu = HEXAGON_CPU(cs); CPUHexagonState *env = &cpu->env; - env->gpr[HEX_REG_PC] = tb->pc; + env->gpr[HEX_REG_PC] = tb_pc(tb); } static bool hexagon_cpu_has_work(CPUState *cs) diff --git a/target/hppa/cpu.c b/target/hppa/cpu.c index e25d3db6d5..e677ca09d4 100644 --- a/target/hppa/cpu.c +++ b/target/hppa/cpu.c @@ -49,7 +49,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, HPPACPU *cpu = HPPA_CPU(cs); #ifdef CONFIG_USER_ONLY - cpu->env.iaoq_f = tb->pc; + cpu->env.iaoq_f = tb_pc(tb); cpu->env.iaoq_b = tb->cs_base; #else /* Recover the IAOQ values from the GVA + PRIV. */ @@ -59,7 +59,7 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs, int32_t diff = cs_base; cpu->env.iasq_f = iasq_f; - cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv; + cpu->env.iaoq_f = (tb_pc(tb) & ~iasq_f) + priv; if (diff) { cpu->env.iaoq_b = cpu->env.iaoq_f + diff; } diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c index d3c2b8fb49..6cf14c83ff 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -51,7 +51,7 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, { X86CPU *cpu = X86_CPU(cs); - cpu->env.eip = tb->pc - tb->cs_base; + cpu->env.eip = tb_pc(tb) - tb->cs_base; } #ifndef CONFIG_USER_ONLY diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 20a92ea56c..1722ed2a4d 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -317,7 +317,7 @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs, LoongArchCPU *cpu = LOONGARCH_CPU(cs); CPULoongArchState *env = &cpu->env; - env->pc = tb->pc; + env->pc = tb_pc(tb); } #endif /* CONFIG_TCG */ diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c index 73af51769e..c10b8ac029 100644 --- a/target/microblaze/cpu.c +++ b/target/microblaze/cpu.c @@ -96,7 +96,7 @@ static void mb_cpu_synchronize_from_tb(CPUState *cs, { MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs); - cpu->env.pc = tb->pc; + cpu->env.pc = tb_pc(tb); cpu->env.iflags = tb->flags & IFLAGS_TB_MASK; } diff --git a/target/mips/tcg/exception.c b/target/mips/tcg/exception.c index 2bd77a61de..96e61170e6 100644 --- a/target/mips/tcg/exception.c +++ b/target/mips/tcg/exception.c @@ -82,7 +82,7 @@ void mips_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) MIPSCPU *cpu = MIPS_CPU(cs); CPUMIPSState *env = &cpu->env; - env->active_tc.PC = tb->pc; + env->active_tc.PC = tb_pc(tb); env->hflags &= ~MIPS_HFLAG_BMASK; env->hflags |= tb->flags & MIPS_HFLAG_BMASK; } diff --git a/target/mips/tcg/sysemu/special_helper.c b/target/mips/tcg/sysemu/special_helper.c index f4f8fe8afc..3c5f35c759 100644 --- a/target/mips/tcg/sysemu/special_helper.c +++ b/target/mips/tcg/sysemu/special_helper.c @@ -94,7 +94,7 @@ bool mips_io_recompile_replay_branch(CPUState *cs, const TranslationBlock *tb) CPUMIPSState *env = &cpu->env; if ((env->hflags & MIPS_HFLAG_BMASK) != 0 - && env->active_tc.PC != tb->pc) { + && env->active_tc.PC != tb_pc(tb)) { env->active_tc.PC -= (env->hflags & MIPS_HFLAG_B16 ? 2 : 4); env->hflags &= ~MIPS_HFLAG_BMASK; return true; diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c index 33cf717210..f6fd437785 100644 --- a/target/openrisc/cpu.c +++ b/target/openrisc/cpu.c @@ -43,7 +43,7 @@ static void openrisc_cpu_synchronize_from_tb(CPUState *cs, { OpenRISCCPU *cpu = OPENRISC_CPU(cs); - cpu->env.pc = tb->pc; + cpu->env.pc = tb_pc(tb); } diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6ca05c6eaf..e6d9c706bb 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -482,9 +482,9 @@ static void riscv_cpu_synchronize_from_tb(CPUState *cs, RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL); if (xl == MXL_RV32) { - env->pc = (int32_t)tb->pc; + env->pc = (int32_t)tb_pc(tb); } else { - env->pc = tb->pc; + env->pc = tb_pc(tb); } } diff --git a/target/rx/cpu.c b/target/rx/cpu.c index 134b4b6bb6..2f28099723 100644 --- a/target/rx/cpu.c +++ b/target/rx/cpu.c @@ -44,7 +44,7 @@ static void rx_cpu_synchronize_from_tb(CPUState *cs, { RXCPU *cpu = RX_CPU(cs); - cpu->env.pc = tb->pc; + cpu->env.pc = tb_pc(tb); } static bool rx_cpu_has_work(CPUState *cs) diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index 4bafbf8596..a65a66de43 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -46,7 +46,7 @@ static void superh_cpu_synchronize_from_tb(CPUState *cs, { SuperHCPU *cpu = SUPERH_CPU(cs); - cpu->env.pc = tb->pc; + cpu->env.pc = tb_pc(tb); cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK; } @@ -58,7 +58,7 @@ static bool superh_io_recompile_replay_branch(CPUState *cs, CPUSH4State *env = &cpu->env; if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0 - && env->pc != tb->pc) { + && env->pc != tb_pc(tb)) { env->pc -= 2; env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); return true; diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c index 1b2afb0cb8..1f9ef7afd8 100644 --- a/target/sparc/cpu.c +++ b/target/sparc/cpu.c @@ -705,7 +705,7 @@ static void sparc_cpu_synchronize_from_tb(CPUState *cs, { SPARCCPU *cpu = SPARC_CPU(cs); - cpu->env.pc = tb->pc; + cpu->env.pc = tb_pc(tb); cpu->env.npc = tb->cs_base; } diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c index 91b16bdefc..ab7a1e3a6d 100644 --- a/target/tricore/cpu.c +++ b/target/tricore/cpu.c @@ -55,7 +55,7 @@ static void tricore_cpu_synchronize_from_tb(CPUState *cs, TriCoreCPU *cpu = TRICORE_CPU(cs); CPUTriCoreState *env = &cpu->env; - env->PC = tb->pc; + env->PC = tb_pc(tb); } static void tricore_cpu_reset(DeviceState *dev) diff --git a/tcg/tcg.c b/tcg/tcg.c index 0f9cfe96f2..612a12f58f 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -4188,7 +4188,7 @@ int64_t tcg_cpu_exec_time(void) #endif -int tcg_gen_code(TCGContext *s, TranslationBlock *tb) +int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start) { #ifdef CONFIG_PROFILER TCGProfile *prof = &s->prof; @@ -4218,7 +4218,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP) - && qemu_log_in_addr_range(tb->pc))) { + && qemu_log_in_addr_range(pc_start))) { FILE *logfile = qemu_log_trylock(); if (logfile) { fprintf(logfile, "OP:\n"); @@ -4265,7 +4265,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) if (s->nb_indirects > 0) { #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND) - && qemu_log_in_addr_range(tb->pc))) { + && qemu_log_in_addr_range(pc_start))) { FILE *logfile = qemu_log_trylock(); if (logfile) { fprintf(logfile, "OP before indirect lowering:\n"); @@ -4288,7 +4288,7 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb) #ifdef DEBUG_DISAS if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT) - && qemu_log_in_addr_range(tb->pc))) { + && qemu_log_in_addr_range(pc_start))) { FILE *logfile = qemu_log_trylock(); if (logfile) { fprintf(logfile, "OP after optimization and liveness analysis:\n"); From 8ed558ec0cbcc29ecf490e93c54dd65d276e8e69 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 12 Aug 2022 09:53:53 -0700 Subject: [PATCH 0822/1020] accel/tcg: Introduce TARGET_TB_PCREL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prepare for targets to be able to produce TBs that can run in more than one virtual context. Reviewed-by: Alex BennĂ©e Signed-off-by: Richard Henderson --- accel/tcg/cpu-exec.c | 16 ++++++---- accel/tcg/internal.h | 4 +++ accel/tcg/tb-jmp-cache.h | 41 +++++++++++++++++++++++++ accel/tcg/translate-all.c | 64 ++++++++++++++++++++++++++------------- include/exec/cpu-defs.h | 3 ++ include/exec/exec-all.h | 32 ++++++++++++++++++-- 6 files changed, 131 insertions(+), 29 deletions(-) diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 8b3f8435fb..f9e5cc9ba0 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -186,7 +186,7 @@ static bool tb_lookup_cmp(const void *p, const void *d) const TranslationBlock *tb = p; const struct tb_desc *desc = d; - if (tb_pc(tb) == desc->pc && + if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) && tb->page_addr[0] == desc->page_addr0 && tb->cs_base == desc->cs_base && tb->flags == desc->flags && @@ -237,7 +237,8 @@ static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc, return NULL; } desc.page_addr0 = phys_pc; - h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate); + h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : pc), + flags, cflags, *cpu->trace_dstate); return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp); } @@ -247,16 +248,18 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, uint32_t flags, uint32_t cflags) { TranslationBlock *tb; + CPUJumpCache *jc; uint32_t hash; /* we should never be trying to look up an INVALID tb */ tcg_debug_assert(!(cflags & CF_INVALID)); hash = tb_jmp_cache_hash_func(pc); - tb = qatomic_rcu_read(&cpu->tb_jmp_cache->array[hash].tb); + jc = cpu->tb_jmp_cache; + tb = tb_jmp_cache_get_tb(jc, hash); if (likely(tb && - tb->pc == pc && + tb_jmp_cache_get_pc(jc, hash, tb) == pc && tb->cs_base == cs_base && tb->flags == flags && tb->trace_vcpu_dstate == *cpu->trace_dstate && @@ -267,7 +270,7 @@ static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc, if (tb == NULL) { return NULL; } - qatomic_set(&cpu->tb_jmp_cache->array[hash].tb, tb); + tb_jmp_cache_set(jc, hash, tb, pc); return tb; } @@ -453,6 +456,7 @@ cpu_tb_exec(CPUState *cpu, TranslationBlock *itb, int *tb_exit) if (cc->tcg_ops->synchronize_from_tb) { cc->tcg_ops->synchronize_from_tb(cpu, last_tb); } else { + assert(!TARGET_TB_PCREL); assert(cc->set_pc); cc->set_pc(cpu, tb_pc(last_tb)); } @@ -1002,7 +1006,7 @@ int cpu_exec(CPUState *cpu) * for the fast lookup */ h = tb_jmp_cache_hash_func(pc); - qatomic_set(&cpu->tb_jmp_cache->array[h].tb, tb); + tb_jmp_cache_set(cpu->tb_jmp_cache, h, tb, pc); } #ifndef CONFIG_USER_ONLY diff --git a/accel/tcg/internal.h b/accel/tcg/internal.h index a3875a3b5a..dc800fd485 100644 --- a/accel/tcg/internal.h +++ b/accel/tcg/internal.h @@ -21,7 +21,11 @@ void tb_htable_init(void); /* Return the current PC from CPU, which may be cached in TB. */ static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb) { +#if TARGET_TB_PCREL + return cpu->cc->get_pc(cpu); +#else return tb_pc(tb); +#endif } #endif /* ACCEL_TCG_INTERNAL_H */ diff --git a/accel/tcg/tb-jmp-cache.h b/accel/tcg/tb-jmp-cache.h index 2d8fbb1bfe..ff5ffc8fc2 100644 --- a/accel/tcg/tb-jmp-cache.h +++ b/accel/tcg/tb-jmp-cache.h @@ -14,11 +14,52 @@ /* * Accessed in parallel; all accesses to 'tb' must be atomic. + * For TARGET_TB_PCREL, accesses to 'pc' must be protected by + * a load_acquire/store_release to 'tb'. */ struct CPUJumpCache { struct { TranslationBlock *tb; +#if TARGET_TB_PCREL + target_ulong pc; +#endif } array[TB_JMP_CACHE_SIZE]; }; +static inline TranslationBlock * +tb_jmp_cache_get_tb(CPUJumpCache *jc, uint32_t hash) +{ +#if TARGET_TB_PCREL + /* Use acquire to ensure current load of pc from jc. */ + return qatomic_load_acquire(&jc->array[hash].tb); +#else + /* Use rcu_read to ensure current load of pc from *tb. */ + return qatomic_rcu_read(&jc->array[hash].tb); +#endif +} + +static inline target_ulong +tb_jmp_cache_get_pc(CPUJumpCache *jc, uint32_t hash, TranslationBlock *tb) +{ +#if TARGET_TB_PCREL + return jc->array[hash].pc; +#else + return tb_pc(tb); +#endif +} + +static inline void +tb_jmp_cache_set(CPUJumpCache *jc, uint32_t hash, + TranslationBlock *tb, target_ulong pc) +{ +#if TARGET_TB_PCREL + jc->array[hash].pc = pc; + /* Use store_release on tb to ensure pc is written first. */ + qatomic_store_release(&jc->array[hash].tb, tb); +#else + /* Use the pc value already stored in tb->pc. */ + qatomic_set(&jc->array[hash].tb, tb); +#endif +} + #endif /* ACCEL_TCG_TB_JMP_CACHE_H */ diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index 13c964dcd8..4ed75a13e1 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -299,7 +299,7 @@ static int encode_search(TranslationBlock *tb, uint8_t *block) for (j = 0; j < TARGET_INSN_START_WORDS; ++j) { if (i == 0) { - prev = (j == 0 ? tb_pc(tb) : 0); + prev = (!TARGET_TB_PCREL && j == 0 ? tb_pc(tb) : 0); } else { prev = tcg_ctx->gen_insn_data[i - 1][j]; } @@ -327,7 +327,7 @@ static int encode_search(TranslationBlock *tb, uint8_t *block) static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, uintptr_t searched_pc, bool reset_icount) { - target_ulong data[TARGET_INSN_START_WORDS] = { tb_pc(tb) }; + target_ulong data[TARGET_INSN_START_WORDS]; uintptr_t host_pc = (uintptr_t)tb->tc.ptr; CPUArchState *env = cpu->env_ptr; const uint8_t *p = tb->tc.ptr + tb->tc.size; @@ -343,6 +343,11 @@ static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb, return -1; } + memset(data, 0, sizeof(data)); + if (!TARGET_TB_PCREL) { + data[0] = tb_pc(tb); + } + /* Reconstruct the stored insn data while looking for the point at which the end of the insn exceeds the searched_pc. */ for (i = 0; i < num_insns; ++i) { @@ -885,13 +890,13 @@ static bool tb_cmp(const void *ap, const void *bp) const TranslationBlock *a = ap; const TranslationBlock *b = bp; - return tb_pc(a) == tb_pc(b) && - a->cs_base == b->cs_base && - a->flags == b->flags && - (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) && - a->trace_vcpu_dstate == b->trace_vcpu_dstate && - a->page_addr[0] == b->page_addr[0] && - a->page_addr[1] == b->page_addr[1]; + return ((TARGET_TB_PCREL || tb_pc(a) == tb_pc(b)) && + a->cs_base == b->cs_base && + a->flags == b->flags && + (tb_cflags(a) & ~CF_INVALID) == (tb_cflags(b) & ~CF_INVALID) && + a->trace_vcpu_dstate == b->trace_vcpu_dstate && + a->page_addr[0] == b->page_addr[0] && + a->page_addr[1] == b->page_addr[1]); } void tb_htable_init(void) @@ -1148,6 +1153,28 @@ static inline void tb_jmp_unlink(TranslationBlock *dest) qemu_spin_unlock(&dest->jmp_lock); } +static void tb_jmp_cache_inval_tb(TranslationBlock *tb) +{ + CPUState *cpu; + + if (TARGET_TB_PCREL) { + /* A TB may be at any virtual address */ + CPU_FOREACH(cpu) { + tcg_flush_jmp_cache(cpu); + } + } else { + uint32_t h = tb_jmp_cache_hash_func(tb_pc(tb)); + + CPU_FOREACH(cpu) { + CPUJumpCache *jc = cpu->tb_jmp_cache; + + if (qatomic_read(&jc->array[h].tb) == tb) { + qatomic_set(&jc->array[h].tb, NULL); + } + } + } +} + /* * In user-mode, call with mmap_lock held. * In !user-mode, if @rm_from_page_list is set, call with the TB's pages' @@ -1155,7 +1182,6 @@ static inline void tb_jmp_unlink(TranslationBlock *dest) */ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) { - CPUState *cpu; PageDesc *p; uint32_t h; tb_page_addr_t phys_pc; @@ -1170,8 +1196,8 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) /* remove the TB from the hash list */ phys_pc = tb->page_addr[0]; - h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, orig_cflags, - tb->trace_vcpu_dstate); + h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)), + tb->flags, orig_cflags, tb->trace_vcpu_dstate); if (!qht_remove(&tb_ctx.htable, tb, h)) { return; } @@ -1187,13 +1213,7 @@ static void do_tb_phys_invalidate(TranslationBlock *tb, bool rm_from_page_list) } /* remove the TB from the hash list */ - h = tb_jmp_cache_hash_func(tb->pc); - CPU_FOREACH(cpu) { - CPUJumpCache *jc = cpu->tb_jmp_cache; - if (qatomic_read(&jc->array[h].tb) == tb) { - qatomic_set(&jc->array[h].tb, NULL); - } - } + tb_jmp_cache_inval_tb(tb); /* suppress this TB from the two jump lists */ tb_remove_from_jmp_list(tb, 0); @@ -1302,8 +1322,8 @@ tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc, } /* add in the hash table */ - h = tb_hash_func(phys_pc, tb_pc(tb), tb->flags, tb->cflags, - tb->trace_vcpu_dstate); + h = tb_hash_func(phys_pc, (TARGET_TB_PCREL ? 0 : tb_pc(tb)), + tb->flags, tb->cflags, tb->trace_vcpu_dstate); qht_insert(&tb_ctx.htable, tb, h, &existing_tb); /* remove TB from the page(s) if we couldn't insert it */ @@ -1373,7 +1393,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu, gen_code_buf = tcg_ctx->code_gen_ptr; tb->tc.ptr = tcg_splitwx_to_rx(gen_code_buf); +#if !TARGET_TB_PCREL tb->pc = pc; +#endif tb->cs_base = cs_base; tb->flags = flags; tb->cflags = cflags; diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index 67239b4e5e..21309cf567 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -54,6 +54,9 @@ # error TARGET_PAGE_BITS must be defined in cpu-param.h # endif #endif +#ifndef TARGET_TB_PCREL +# define TARGET_TB_PCREL 0 +#endif #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8) diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 7ea6026ba9..e5f8b224a5 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -496,8 +496,32 @@ struct tb_tc { }; struct TranslationBlock { - target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */ - target_ulong cs_base; /* CS base for this block */ +#if !TARGET_TB_PCREL + /* + * Guest PC corresponding to this block. This must be the true + * virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and + * targets like Arm, MIPS, HP-PA, which reuse low bits for ISA or + * privilege, must store those bits elsewhere. + * + * If TARGET_TB_PCREL, the opcodes for the TranslationBlock are + * written such that the TB is associated only with the physical + * page and may be run in any virtual address context. In this case, + * PC must always be taken from ENV in a target-specific manner. + * Unwind information is taken as offsets from the page, to be + * deposited into the "current" PC. + */ + target_ulong pc; +#endif + + /* + * Target-specific data associated with the TranslationBlock, e.g.: + * x86: the original user, the Code Segment virtual base, + * arm: an extension of tb->flags, + * s390x: instruction data for EXECUTE, + * sparc: the next pc of the instruction queue (for delay slots). + */ + target_ulong cs_base; + uint32_t flags; /* flags defining in which context the code was generated */ uint32_t cflags; /* compile flags */ @@ -573,7 +597,11 @@ struct TranslationBlock { /* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */ static inline target_ulong tb_pc(const TranslationBlock *tb) { +#if TARGET_TB_PCREL + qemu_build_not_reached(); +#else return tb->pc; +#endif } /* Hide the qatomic_read to make code a little easier on the eyes */ From 20add588296a8a24374004e9dbf6219f28665d34 Mon Sep 17 00:00:00 2001 From: Leandro Lupori Date: Mon, 19 Sep 2022 14:56:14 -0300 Subject: [PATCH 0823/1020] tcg/ppc: Optimize 26-bit jumps PowerPC64 processors handle direct branches better than indirect ones, resulting in less stalled cycles and branch misses. However, PPC's tb_target_set_jmp_target() was only using direct branches for 16-bit jumps, while PowerPC64's unconditional branch instructions are able to handle displacements of up to 26 bits. To take advantage of this, now jumps whose displacements fit in between 17 and 26 bits are also converted to direct branches. Reviewed-by: Richard Henderson Signed-off-by: Leandro Lupori [rth: Expanded some commentary.] Signed-off-by: Richard Henderson --- tcg/ppc/tcg-target.c.inc | 119 +++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 31 deletions(-) diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc index 1cbd047ab3..e3dba47697 100644 --- a/tcg/ppc/tcg-target.c.inc +++ b/tcg/ppc/tcg-target.c.inc @@ -1847,44 +1847,101 @@ static void tcg_out_mb(TCGContext *s, TCGArg a0) tcg_out32(s, insn); } +static inline uint64_t make_pair(tcg_insn_unit i1, tcg_insn_unit i2) +{ + if (HOST_BIG_ENDIAN) { + return (uint64_t)i1 << 32 | i2; + } + return (uint64_t)i2 << 32 | i1; +} + +static inline void ppc64_replace2(uintptr_t rx, uintptr_t rw, + tcg_insn_unit i0, tcg_insn_unit i1) +{ +#if TCG_TARGET_REG_BITS == 64 + qatomic_set((uint64_t *)rw, make_pair(i0, i1)); + flush_idcache_range(rx, rw, 8); +#else + qemu_build_not_reached(); +#endif +} + +static inline void ppc64_replace4(uintptr_t rx, uintptr_t rw, + tcg_insn_unit i0, tcg_insn_unit i1, + tcg_insn_unit i2, tcg_insn_unit i3) +{ + uint64_t p[2]; + + p[!HOST_BIG_ENDIAN] = make_pair(i0, i1); + p[HOST_BIG_ENDIAN] = make_pair(i2, i3); + + /* + * There's no convenient way to get the compiler to allocate a pair + * of registers at an even index, so copy into r6/r7 and clobber. + */ + asm("mr %%r6, %1\n\t" + "mr %%r7, %2\n\t" + "stq %%r6, %0" + : "=Q"(*(__int128 *)rw) : "r"(p[0]), "r"(p[1]) : "r6", "r7"); + flush_idcache_range(rx, rw, 16); +} + void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, uintptr_t jmp_rw, uintptr_t addr) { - if (TCG_TARGET_REG_BITS == 64) { - tcg_insn_unit i1, i2; - intptr_t tb_diff = addr - tc_ptr; - intptr_t br_diff = addr - (jmp_rx + 4); - uint64_t pair; + tcg_insn_unit i0, i1, i2, i3; + intptr_t tb_diff = addr - tc_ptr; + intptr_t br_diff = addr - (jmp_rx + 4); + intptr_t lo, hi; - /* This does not exercise the range of the branch, but we do - still need to be able to load the new value of TCG_REG_TB. - But this does still happen quite often. */ - if (tb_diff == (int16_t)tb_diff) { - i1 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, tb_diff); - i2 = B | (br_diff & 0x3fffffc); - } else { - intptr_t lo = (int16_t)tb_diff; - intptr_t hi = (int32_t)(tb_diff - lo); - assert(tb_diff == hi + lo); - i1 = ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, hi >> 16); - i2 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, lo); - } -#if HOST_BIG_ENDIAN - pair = (uint64_t)i1 << 32 | i2; -#else - pair = (uint64_t)i2 << 32 | i1; -#endif - - /* As per the enclosing if, this is ppc64. Avoid the _Static_assert - within qatomic_set that would fail to build a ppc32 host. */ - qatomic_set__nocheck((uint64_t *)jmp_rw, pair); - flush_idcache_range(jmp_rx, jmp_rw, 8); - } else { + if (TCG_TARGET_REG_BITS == 32) { intptr_t diff = addr - jmp_rx; tcg_debug_assert(in_range_b(diff)); qatomic_set((uint32_t *)jmp_rw, B | (diff & 0x3fffffc)); flush_idcache_range(jmp_rx, jmp_rw, 4); + return; } + + /* + * For 16-bit displacements, we can use a single add + branch. + * This happens quite often. + */ + if (tb_diff == (int16_t)tb_diff) { + i0 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, tb_diff); + i1 = B | (br_diff & 0x3fffffc); + ppc64_replace2(jmp_rx, jmp_rw, i0, i1); + return; + } + + lo = (int16_t)tb_diff; + hi = (int32_t)(tb_diff - lo); + assert(tb_diff == hi + lo); + i0 = ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, hi >> 16); + i1 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, lo); + + /* + * Without stq from 2.07, we can only update two insns, + * and those must be the ones that load the target address. + */ + if (!have_isa_2_07) { + ppc64_replace2(jmp_rx, jmp_rw, i0, i1); + return; + } + + /* + * For 26-bit displacements, we can use a direct branch. + * Otherwise we still need the indirect branch, which we + * must restore after a potential direct branch write. + */ + br_diff -= 4; + if (in_range_b(br_diff)) { + i2 = B | (br_diff & 0x3fffffc); + i3 = NOP; + } else { + i2 = MTSPR | RS(TCG_REG_TB) | CTR; + i3 = BCCTR | BO_ALWAYS; + } + ppc64_replace4(jmp_rx, jmp_rw, i0, i1, i2, i3); } static void tcg_out_call_int(TCGContext *s, int lk, @@ -2574,8 +2631,8 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, if (s->tb_jmp_insn_offset) { /* Direct jump. */ if (TCG_TARGET_REG_BITS == 64) { - /* Ensure the next insns are 8-byte aligned. */ - if ((uintptr_t)s->code_ptr & 7) { + /* Ensure the next insns are 8 or 16-byte aligned. */ + while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) { tcg_out32(s, NOP); } s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s); From ab419fd8a035a65942de4e63effcd55ccbf1a9fe Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 28 Aug 2022 18:58:20 -0700 Subject: [PATCH 0824/1020] target/sh4: Fix TB_FLAG_UNALIGN The value previously chosen overlaps GUSA_MASK. Rename all DELAY_SLOT_* and GUSA_* defines to emphasize that they are included in TB_FLAGs. Add aliases for the FPSCR and SR bits that are included in TB_FLAGS, so that we don't accidentally reassign those bits. Fixes: 4da06fb3062 ("target/sh4: Implement prctl_unalign_sigbus") Resolves: https://gitlab.com/qemu-project/qemu/-/issues/856 Reviewed-by: Yoshinori Sato Signed-off-by: Richard Henderson --- linux-user/sh4/signal.c | 6 +-- target/sh4/cpu.c | 6 +-- target/sh4/cpu.h | 56 +++++++++++++------------ target/sh4/helper.c | 6 +-- target/sh4/translate.c | 90 ++++++++++++++++++++++------------------- 5 files changed, 88 insertions(+), 76 deletions(-) diff --git a/linux-user/sh4/signal.c b/linux-user/sh4/signal.c index f6a18bc6b5..c4ba962708 100644 --- a/linux-user/sh4/signal.c +++ b/linux-user/sh4/signal.c @@ -161,7 +161,7 @@ static void restore_sigcontext(CPUSH4State *regs, struct target_sigcontext *sc) __get_user(regs->fpul, &sc->sc_fpul); regs->tra = -1; /* disable syscall checks */ - regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK); + regs->flags = 0; } void setup_frame(int sig, struct target_sigaction *ka, @@ -199,7 +199,7 @@ void setup_frame(int sig, struct target_sigaction *ka, regs->gregs[5] = 0; regs->gregs[6] = frame_addr += offsetof(typeof(*frame), sc); regs->pc = (unsigned long) ka->_sa_handler; - regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK); + regs->flags &= ~(TB_FLAG_DELAY_SLOT_MASK | TB_FLAG_GUSA_MASK); unlock_user_struct(frame, frame_addr, 1); return; @@ -251,7 +251,7 @@ void setup_rt_frame(int sig, struct target_sigaction *ka, regs->gregs[5] = frame_addr + offsetof(typeof(*frame), info); regs->gregs[6] = frame_addr + offsetof(typeof(*frame), uc); regs->pc = (unsigned long) ka->_sa_handler; - regs->flags &= ~(DELAY_SLOT_MASK | GUSA_MASK); + regs->flags &= ~(TB_FLAG_DELAY_SLOT_MASK | TB_FLAG_GUSA_MASK); unlock_user_struct(frame, frame_addr, 1); return; diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c index a65a66de43..56c50530da 100644 --- a/target/sh4/cpu.c +++ b/target/sh4/cpu.c @@ -47,7 +47,7 @@ static void superh_cpu_synchronize_from_tb(CPUState *cs, SuperHCPU *cpu = SUPERH_CPU(cs); cpu->env.pc = tb_pc(tb); - cpu->env.flags = tb->flags & TB_FLAG_ENVFLAGS_MASK; + cpu->env.flags = tb->flags; } #ifndef CONFIG_USER_ONLY @@ -57,10 +57,10 @@ static bool superh_io_recompile_replay_branch(CPUState *cs, SuperHCPU *cpu = SUPERH_CPU(cs); CPUSH4State *env = &cpu->env; - if ((env->flags & ((DELAY_SLOT | DELAY_SLOT_CONDITIONAL))) != 0 + if ((env->flags & (TB_FLAG_DELAY_SLOT | TB_FLAG_DELAY_SLOT_COND)) && env->pc != tb_pc(tb)) { env->pc -= 2; - env->flags &= ~(DELAY_SLOT | DELAY_SLOT_CONDITIONAL); + env->flags &= ~(TB_FLAG_DELAY_SLOT | TB_FLAG_DELAY_SLOT_COND); return true; } return false; diff --git a/target/sh4/cpu.h b/target/sh4/cpu.h index 9f15ef913c..727b829598 100644 --- a/target/sh4/cpu.h +++ b/target/sh4/cpu.h @@ -78,26 +78,33 @@ #define FPSCR_RM_NEAREST (0 << 0) #define FPSCR_RM_ZERO (1 << 0) -#define DELAY_SLOT_MASK 0x7 -#define DELAY_SLOT (1 << 0) -#define DELAY_SLOT_CONDITIONAL (1 << 1) -#define DELAY_SLOT_RTE (1 << 2) +#define TB_FLAG_DELAY_SLOT (1 << 0) +#define TB_FLAG_DELAY_SLOT_COND (1 << 1) +#define TB_FLAG_DELAY_SLOT_RTE (1 << 2) +#define TB_FLAG_PENDING_MOVCA (1 << 3) +#define TB_FLAG_GUSA_SHIFT 4 /* [11:4] */ +#define TB_FLAG_GUSA_EXCLUSIVE (1 << 12) +#define TB_FLAG_UNALIGN (1 << 13) +#define TB_FLAG_SR_FD (1 << SR_FD) /* 15 */ +#define TB_FLAG_FPSCR_PR FPSCR_PR /* 19 */ +#define TB_FLAG_FPSCR_SZ FPSCR_SZ /* 20 */ +#define TB_FLAG_FPSCR_FR FPSCR_FR /* 21 */ +#define TB_FLAG_SR_RB (1 << SR_RB) /* 29 */ +#define TB_FLAG_SR_MD (1 << SR_MD) /* 30 */ -#define TB_FLAG_PENDING_MOVCA (1 << 3) -#define TB_FLAG_UNALIGN (1 << 4) - -#define GUSA_SHIFT 4 -#ifdef CONFIG_USER_ONLY -#define GUSA_EXCLUSIVE (1 << 12) -#define GUSA_MASK ((0xff << GUSA_SHIFT) | GUSA_EXCLUSIVE) -#else -/* Provide dummy versions of the above to allow tests against tbflags - to be elided while avoiding ifdefs. */ -#define GUSA_EXCLUSIVE 0 -#define GUSA_MASK 0 -#endif - -#define TB_FLAG_ENVFLAGS_MASK (DELAY_SLOT_MASK | GUSA_MASK) +#define TB_FLAG_DELAY_SLOT_MASK (TB_FLAG_DELAY_SLOT | \ + TB_FLAG_DELAY_SLOT_COND | \ + TB_FLAG_DELAY_SLOT_RTE) +#define TB_FLAG_GUSA_MASK ((0xff << TB_FLAG_GUSA_SHIFT) | \ + TB_FLAG_GUSA_EXCLUSIVE) +#define TB_FLAG_FPSCR_MASK (TB_FLAG_FPSCR_PR | \ + TB_FLAG_FPSCR_SZ | \ + TB_FLAG_FPSCR_FR) +#define TB_FLAG_SR_MASK (TB_FLAG_SR_FD | \ + TB_FLAG_SR_RB | \ + TB_FLAG_SR_MD) +#define TB_FLAG_ENVFLAGS_MASK (TB_FLAG_DELAY_SLOT_MASK | \ + TB_FLAG_GUSA_MASK) typedef struct tlb_t { uint32_t vpn; /* virtual page number */ @@ -258,7 +265,7 @@ static inline int cpu_mmu_index (CPUSH4State *env, bool ifetch) { /* The instruction in a RTE delay slot is fetched in privileged mode, but executed in user mode. */ - if (ifetch && (env->flags & DELAY_SLOT_RTE)) { + if (ifetch && (env->flags & TB_FLAG_DELAY_SLOT_RTE)) { return 0; } else { return (env->sr & (1u << SR_MD)) == 0 ? 1 : 0; @@ -366,11 +373,10 @@ static inline void cpu_get_tb_cpu_state(CPUSH4State *env, target_ulong *pc, { *pc = env->pc; /* For a gUSA region, notice the end of the region. */ - *cs_base = env->flags & GUSA_MASK ? env->gregs[0] : 0; - *flags = env->flags /* TB_FLAG_ENVFLAGS_MASK: bits 0-2, 4-12 */ - | (env->fpscr & (FPSCR_FR | FPSCR_SZ | FPSCR_PR)) /* Bits 19-21 */ - | (env->sr & ((1u << SR_MD) | (1u << SR_RB))) /* Bits 29-30 */ - | (env->sr & (1u << SR_FD)) /* Bit 15 */ + *cs_base = env->flags & TB_FLAG_GUSA_MASK ? env->gregs[0] : 0; + *flags = env->flags + | (env->fpscr & TB_FLAG_FPSCR_MASK) + | (env->sr & TB_FLAG_SR_MASK) | (env->movcal_backup ? TB_FLAG_PENDING_MOVCA : 0); /* Bit 3 */ #ifdef CONFIG_USER_ONLY *flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus; diff --git a/target/sh4/helper.c b/target/sh4/helper.c index 6a620e36fc..e02e7af607 100644 --- a/target/sh4/helper.c +++ b/target/sh4/helper.c @@ -147,11 +147,11 @@ void superh_cpu_do_interrupt(CPUState *cs) env->sr |= (1u << SR_BL) | (1u << SR_MD) | (1u << SR_RB); env->lock_addr = -1; - if (env->flags & DELAY_SLOT_MASK) { + if (env->flags & TB_FLAG_DELAY_SLOT_MASK) { /* Branch instruction should be executed again before delay slot. */ env->spc -= 2; /* Clear flags for exception/interrupt routine. */ - env->flags &= ~DELAY_SLOT_MASK; + env->flags &= ~TB_FLAG_DELAY_SLOT_MASK; } if (do_exp) { @@ -786,7 +786,7 @@ bool superh_cpu_exec_interrupt(CPUState *cs, int interrupt_request) CPUSH4State *env = &cpu->env; /* Delay slots are indivisible, ignore interrupts */ - if (env->flags & DELAY_SLOT_MASK) { + if (env->flags & TB_FLAG_DELAY_SLOT_MASK) { return false; } else { superh_cpu_do_interrupt(cs); diff --git a/target/sh4/translate.c b/target/sh4/translate.c index 01056571c3..26231b2a5a 100644 --- a/target/sh4/translate.c +++ b/target/sh4/translate.c @@ -175,13 +175,13 @@ void superh_cpu_dump_state(CPUState *cs, FILE *f, int flags) i, env->gregs[i], i + 1, env->gregs[i + 1], i + 2, env->gregs[i + 2], i + 3, env->gregs[i + 3]); } - if (env->flags & DELAY_SLOT) { + if (env->flags & TB_FLAG_DELAY_SLOT) { qemu_printf("in delay slot (delayed_pc=0x%08x)\n", env->delayed_pc); - } else if (env->flags & DELAY_SLOT_CONDITIONAL) { + } else if (env->flags & TB_FLAG_DELAY_SLOT_COND) { qemu_printf("in conditional delay slot (delayed_pc=0x%08x)\n", env->delayed_pc); - } else if (env->flags & DELAY_SLOT_RTE) { + } else if (env->flags & TB_FLAG_DELAY_SLOT_RTE) { qemu_fprintf(f, "in rte delay slot (delayed_pc=0x%08x)\n", env->delayed_pc); } @@ -223,7 +223,7 @@ static inline void gen_save_cpu_state(DisasContext *ctx, bool save_pc) static inline bool use_exit_tb(DisasContext *ctx) { - return (ctx->tbflags & GUSA_EXCLUSIVE) != 0; + return (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) != 0; } static bool use_goto_tb(DisasContext *ctx, target_ulong dest) @@ -276,12 +276,12 @@ static void gen_conditional_jump(DisasContext *ctx, target_ulong dest, TCGLabel *l1 = gen_new_label(); TCGCond cond_not_taken = jump_if_true ? TCG_COND_EQ : TCG_COND_NE; - if (ctx->tbflags & GUSA_EXCLUSIVE) { + if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) { /* When in an exclusive region, we must continue to the end. Therefore, exit the region on a taken branch, but otherwise fall through to the next instruction. */ tcg_gen_brcondi_i32(cond_not_taken, cpu_sr_t, 0, l1); - tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK); + tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK); /* Note that this won't actually use a goto_tb opcode because we disallow it in use_goto_tb, but it handles exit + singlestep. */ gen_goto_tb(ctx, 0, dest); @@ -307,14 +307,14 @@ static void gen_delayed_conditional_jump(DisasContext * ctx) tcg_gen_mov_i32(ds, cpu_delayed_cond); tcg_gen_discard_i32(cpu_delayed_cond); - if (ctx->tbflags & GUSA_EXCLUSIVE) { + if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) { /* When in an exclusive region, we must continue to the end. Therefore, exit the region on a taken branch, but otherwise fall through to the next instruction. */ tcg_gen_brcondi_i32(TCG_COND_EQ, ds, 0, l1); /* Leave the gUSA region. */ - tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~GUSA_MASK); + tcg_gen_movi_i32(cpu_flags, ctx->envflags & ~TB_FLAG_GUSA_MASK); gen_jump(ctx); gen_set_label(l1); @@ -361,8 +361,8 @@ static inline void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg) #define XHACK(x) ((((x) & 1 ) << 4) | ((x) & 0xe)) #define CHECK_NOT_DELAY_SLOT \ - if (ctx->envflags & DELAY_SLOT_MASK) { \ - goto do_illegal_slot; \ + if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { \ + goto do_illegal_slot; \ } #define CHECK_PRIVILEGED \ @@ -436,7 +436,7 @@ static void _decode_opc(DisasContext * ctx) case 0x000b: /* rts */ CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_delayed_pc, cpu_pr); - ctx->envflags |= DELAY_SLOT; + ctx->envflags |= TB_FLAG_DELAY_SLOT; ctx->delayed_pc = (uint32_t) - 1; return; case 0x0028: /* clrmac */ @@ -458,7 +458,7 @@ static void _decode_opc(DisasContext * ctx) CHECK_NOT_DELAY_SLOT gen_write_sr(cpu_ssr); tcg_gen_mov_i32(cpu_delayed_pc, cpu_spc); - ctx->envflags |= DELAY_SLOT_RTE; + ctx->envflags |= TB_FLAG_DELAY_SLOT_RTE; ctx->delayed_pc = (uint32_t) - 1; ctx->base.is_jmp = DISAS_STOP; return; @@ -513,12 +513,15 @@ static void _decode_opc(DisasContext * ctx) return; case 0xe000: /* mov #imm,Rn */ #ifdef CONFIG_USER_ONLY - /* Detect the start of a gUSA region. If so, update envflags - and end the TB. This will allow us to see the end of the - region (stored in R0) in the next TB. */ + /* + * Detect the start of a gUSA region (mov #-n, r15). + * If so, update envflags and end the TB. This will allow us + * to see the end of the region (stored in R0) in the next TB. + */ if (B11_8 == 15 && B7_0s < 0 && (tb_cflags(ctx->base.tb) & CF_PARALLEL)) { - ctx->envflags = deposit32(ctx->envflags, GUSA_SHIFT, 8, B7_0s); + ctx->envflags = + deposit32(ctx->envflags, TB_FLAG_GUSA_SHIFT, 8, B7_0s); ctx->base.is_jmp = DISAS_STOP; } #endif @@ -544,13 +547,13 @@ static void _decode_opc(DisasContext * ctx) case 0xa000: /* bra disp */ CHECK_NOT_DELAY_SLOT ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2; - ctx->envflags |= DELAY_SLOT; + ctx->envflags |= TB_FLAG_DELAY_SLOT; return; case 0xb000: /* bsr disp */ CHECK_NOT_DELAY_SLOT tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); ctx->delayed_pc = ctx->base.pc_next + 4 + B11_0s * 2; - ctx->envflags |= DELAY_SLOT; + ctx->envflags |= TB_FLAG_DELAY_SLOT; return; } @@ -1194,7 +1197,7 @@ static void _decode_opc(DisasContext * ctx) CHECK_NOT_DELAY_SLOT tcg_gen_xori_i32(cpu_delayed_cond, cpu_sr_t, 1); ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2; - ctx->envflags |= DELAY_SLOT_CONDITIONAL; + ctx->envflags |= TB_FLAG_DELAY_SLOT_COND; return; case 0x8900: /* bt label */ CHECK_NOT_DELAY_SLOT @@ -1204,7 +1207,7 @@ static void _decode_opc(DisasContext * ctx) CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_delayed_cond, cpu_sr_t); ctx->delayed_pc = ctx->base.pc_next + 4 + B7_0s * 2; - ctx->envflags |= DELAY_SLOT_CONDITIONAL; + ctx->envflags |= TB_FLAG_DELAY_SLOT_COND; return; case 0x8800: /* cmp/eq #imm,R0 */ tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_sr_t, REG(0), B7_0s); @@ -1388,14 +1391,14 @@ static void _decode_opc(DisasContext * ctx) case 0x0023: /* braf Rn */ CHECK_NOT_DELAY_SLOT tcg_gen_addi_i32(cpu_delayed_pc, REG(B11_8), ctx->base.pc_next + 4); - ctx->envflags |= DELAY_SLOT; + ctx->envflags |= TB_FLAG_DELAY_SLOT; ctx->delayed_pc = (uint32_t) - 1; return; case 0x0003: /* bsrf Rn */ CHECK_NOT_DELAY_SLOT tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); tcg_gen_add_i32(cpu_delayed_pc, REG(B11_8), cpu_pr); - ctx->envflags |= DELAY_SLOT; + ctx->envflags |= TB_FLAG_DELAY_SLOT; ctx->delayed_pc = (uint32_t) - 1; return; case 0x4015: /* cmp/pl Rn */ @@ -1411,14 +1414,14 @@ static void _decode_opc(DisasContext * ctx) case 0x402b: /* jmp @Rn */ CHECK_NOT_DELAY_SLOT tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); - ctx->envflags |= DELAY_SLOT; + ctx->envflags |= TB_FLAG_DELAY_SLOT; ctx->delayed_pc = (uint32_t) - 1; return; case 0x400b: /* jsr @Rn */ CHECK_NOT_DELAY_SLOT tcg_gen_movi_i32(cpu_pr, ctx->base.pc_next + 4); tcg_gen_mov_i32(cpu_delayed_pc, REG(B11_8)); - ctx->envflags |= DELAY_SLOT; + ctx->envflags |= TB_FLAG_DELAY_SLOT; ctx->delayed_pc = (uint32_t) - 1; return; case 0x400e: /* ldc Rm,SR */ @@ -1839,7 +1842,7 @@ static void _decode_opc(DisasContext * ctx) fflush(stderr); #endif do_illegal: - if (ctx->envflags & DELAY_SLOT_MASK) { + if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { do_illegal_slot: gen_save_cpu_state(ctx, true); gen_helper_raise_slot_illegal_instruction(cpu_env); @@ -1852,7 +1855,7 @@ static void _decode_opc(DisasContext * ctx) do_fpu_disabled: gen_save_cpu_state(ctx, true); - if (ctx->envflags & DELAY_SLOT_MASK) { + if (ctx->envflags & TB_FLAG_DELAY_SLOT_MASK) { gen_helper_raise_slot_fpu_disable(cpu_env); } else { gen_helper_raise_fpu_disable(cpu_env); @@ -1867,23 +1870,23 @@ static void decode_opc(DisasContext * ctx) _decode_opc(ctx); - if (old_flags & DELAY_SLOT_MASK) { + if (old_flags & TB_FLAG_DELAY_SLOT_MASK) { /* go out of the delay slot */ - ctx->envflags &= ~DELAY_SLOT_MASK; + ctx->envflags &= ~TB_FLAG_DELAY_SLOT_MASK; /* When in an exclusive region, we must continue to the end for conditional branches. */ - if (ctx->tbflags & GUSA_EXCLUSIVE - && old_flags & DELAY_SLOT_CONDITIONAL) { + if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE + && old_flags & TB_FLAG_DELAY_SLOT_COND) { gen_delayed_conditional_jump(ctx); return; } /* Otherwise this is probably an invalid gUSA region. Drop the GUSA bits so the next TB doesn't see them. */ - ctx->envflags &= ~GUSA_MASK; + ctx->envflags &= ~TB_FLAG_GUSA_MASK; tcg_gen_movi_i32(cpu_flags, ctx->envflags); - if (old_flags & DELAY_SLOT_CONDITIONAL) { + if (old_flags & TB_FLAG_DELAY_SLOT_COND) { gen_delayed_conditional_jump(ctx); } else { gen_jump(ctx); @@ -2223,7 +2226,7 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env) } /* The entire region has been translated. */ - ctx->envflags &= ~GUSA_MASK; + ctx->envflags &= ~TB_FLAG_GUSA_MASK; ctx->base.pc_next = pc_end; ctx->base.num_insns += max_insns - 1; return; @@ -2234,7 +2237,7 @@ static void decode_gusa(DisasContext *ctx, CPUSH4State *env) /* Restart with the EXCLUSIVE bit set, within a TB run via cpu_exec_step_atomic holding the exclusive lock. */ - ctx->envflags |= GUSA_EXCLUSIVE; + ctx->envflags |= TB_FLAG_GUSA_EXCLUSIVE; gen_save_cpu_state(ctx, false); gen_helper_exclusive(cpu_env); ctx->base.is_jmp = DISAS_NORETURN; @@ -2267,17 +2270,19 @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) (tbflags & (1 << SR_RB))) * 0x10; ctx->fbank = tbflags & FPSCR_FR ? 0x10 : 0; - if (tbflags & GUSA_MASK) { +#ifdef CONFIG_USER_ONLY + if (tbflags & TB_FLAG_GUSA_MASK) { + /* In gUSA exclusive region. */ uint32_t pc = ctx->base.pc_next; uint32_t pc_end = ctx->base.tb->cs_base; - int backup = sextract32(ctx->tbflags, GUSA_SHIFT, 8); + int backup = sextract32(ctx->tbflags, TB_FLAG_GUSA_SHIFT, 8); int max_insns = (pc_end - pc) / 2; if (pc != pc_end + backup || max_insns < 2) { /* This is a malformed gUSA region. Don't do anything special, since the interpreter is likely to get confused. */ - ctx->envflags &= ~GUSA_MASK; - } else if (tbflags & GUSA_EXCLUSIVE) { + ctx->envflags &= ~TB_FLAG_GUSA_MASK; + } else if (tbflags & TB_FLAG_GUSA_EXCLUSIVE) { /* Regardless of single-stepping or the end of the page, we must complete execution of the gUSA region while holding the exclusive lock. */ @@ -2285,6 +2290,7 @@ static void sh4_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) return; } } +#endif /* Since the ISA is fixed-width, we can bound by the number of instructions remaining on the page. */ @@ -2309,8 +2315,8 @@ static void sh4_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) DisasContext *ctx = container_of(dcbase, DisasContext, base); #ifdef CONFIG_USER_ONLY - if (unlikely(ctx->envflags & GUSA_MASK) - && !(ctx->envflags & GUSA_EXCLUSIVE)) { + if (unlikely(ctx->envflags & TB_FLAG_GUSA_MASK) + && !(ctx->envflags & TB_FLAG_GUSA_EXCLUSIVE)) { /* We're in an gUSA region, and we have not already fallen back on using an exclusive region. Attempt to parse the region into a single supported atomic operation. Failure @@ -2330,9 +2336,9 @@ static void sh4_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) { DisasContext *ctx = container_of(dcbase, DisasContext, base); - if (ctx->tbflags & GUSA_EXCLUSIVE) { + if (ctx->tbflags & TB_FLAG_GUSA_EXCLUSIVE) { /* Ending the region of exclusivity. Clear the bits. */ - ctx->envflags &= ~GUSA_MASK; + ctx->envflags &= ~TB_FLAG_GUSA_MASK; } switch (ctx->base.is_jmp) { From 0f900baec7680fb9b50fbd23eab44c897ed3ea2c Mon Sep 17 00:00:00 2001 From: "Lucas Mateus Castro (alqotel)" Date: Thu, 29 Sep 2022 12:41:41 +0100 Subject: [PATCH 0825/1020] scripts/ci/setup: ninja missing from build-environment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ninja-build is missing from the RHEL environment, so a system prepared with that script would still fail to compile QEMU. Tested on a Fedora 36 Signed-off-by: Lucas Mateus Castro (alqotel) Message-Id: <20220922135516.33627-2-lucas.araujo@eldorado.org.br> Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-2-alex.bennee@linaro.org> --- scripts/ci/setup/build-environment.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ci/setup/build-environment.yml b/scripts/ci/setup/build-environment.yml index 232525b91d..b5acaf9118 100644 --- a/scripts/ci/setup/build-environment.yml +++ b/scripts/ci/setup/build-environment.yml @@ -153,6 +153,7 @@ - make - mesa-libEGL-devel - nettle-devel + - ninja-build - nmap-ncat - perl-Test-Harness - pixman-devel From 561612f9c20d4c76d23c3051fa7b47bb13123c74 Mon Sep 17 00:00:00 2001 From: "Lucas Mateus Castro (alqotel)" Date: Thu, 29 Sep 2022 12:41:42 +0100 Subject: [PATCH 0826/1020] scripts/ci/setup: Fix libxen requirements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XEN hypervisor is only available in ARM and x86, but the yaml only checked if the architecture is different from s390x, changed it to a more accurate test. Tested this change on a Ubuntu 20.04 ppc64le. Signed-off-by: Lucas Mateus Castro (alqotel) Reviewed-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220922135516.33627-3-lucas.araujo@eldorado.org.br> Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-3-alex.bennee@linaro.org> --- scripts/ci/setup/build-environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/setup/build-environment.yml b/scripts/ci/setup/build-environment.yml index b5acaf9118..49292715d3 100644 --- a/scripts/ci/setup/build-environment.yml +++ b/scripts/ci/setup/build-environment.yml @@ -97,7 +97,7 @@ state: present when: - ansible_facts['distribution'] == 'Ubuntu' - - ansible_facts['architecture'] != 's390x' + - ansible_facts['architecture'] == 'aarch64' or ansible_facts['architecture'] == 'x86_64' - name: Install basic packages to build QEMU on Ubuntu 20.04 package: From 556ede028d5b1dba6d88dc0cd34ab9b96fa59288 Mon Sep 17 00:00:00 2001 From: "Lucas Mateus Castro (alqotel)" Date: Thu, 29 Sep 2022 12:41:43 +0100 Subject: [PATCH 0827/1020] scripts/ci/setup: spice-server only on x86 aarch64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changed build-environment.yml to only install spice-server on x86_64 and aarch64 as this package is only available on those architectures. Signed-off-by: Lucas Mateus Castro (alqotel) Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220922135516.33627-4-lucas.araujo@eldorado.org.br> Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-4-alex.bennee@linaro.org> --- scripts/ci/setup/build-environment.yml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/ci/setup/build-environment.yml b/scripts/ci/setup/build-environment.yml index 49292715d3..b04c2b7cee 100644 --- a/scripts/ci/setup/build-environment.yml +++ b/scripts/ci/setup/build-environment.yml @@ -160,7 +160,6 @@ - python36 - rdma-core-devel - spice-glib-devel - - spice-server - systemtap-sdt-devel - tar - zlib-devel @@ -168,3 +167,14 @@ when: - ansible_facts['distribution_file_variety'] == 'RedHat' - ansible_facts['distribution_version'] == '8' + + - name: Install packages only available on x86 and aarch64 + dnf: + # Spice server not available in ppc64le + name: + - spice-server + state: present + when: + - ansible_facts['distribution_file_variety'] == 'RedHat' + - ansible_facts['distribution_version'] == '8' + - ansible_facts['architecture'] == 'aarch64' or ansible_facts['architecture'] == 'x86_64' From f0c67a79ef7acce9305092f685da5d15c03502b4 Mon Sep 17 00:00:00 2001 From: "Lucas Mateus Castro (alqotel)" Date: Thu, 29 Sep 2022 12:41:44 +0100 Subject: [PATCH 0828/1020] tests/docker: run script use realpath instead of readlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The alpine docker image only comes with busybox, which doesn't have the '-e' option on its readlink, so change it to 'realpath' to avoid that problem. Suggested-by: Daniel P. BerrangĂ© Signed-off-by: Lucas Mateus Castro (alqotel) Message-Id: <20220922135516.33627-5-lucas.araujo@eldorado.org.br> Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-5-alex.bennee@linaro.org> --- tests/docker/run | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/docker/run b/tests/docker/run index 421393046b..9eb96129da 100755 --- a/tests/docker/run +++ b/tests/docker/run @@ -15,7 +15,7 @@ if test -n "$V"; then set -x fi -BASE="$(dirname $(readlink -e $0))" +BASE="$(dirname $(realpath $0))" # Prepare the environment export PATH=/usr/lib/ccache:/usr/lib64/ccache:$PATH From 48543dd727e2751356731e0a3aa6e86929652f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:41:45 +0100 Subject: [PATCH 0829/1020] configure: move detected gdb to TCG's config-host.mak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When tests/tcg gained it's own config-host.mak we forgot to move the GDB detection. Fixes: 544f4a2578 (tests/tcg: isolate from QEMU's config-host.mak) Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-6-alex.bennee@linaro.org> --- configure | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure b/configure index 78e7982b44..7ae448d16e 100755 --- a/configure +++ b/configure @@ -2370,6 +2370,8 @@ if test -n "$gdb_bin"; then gdb_version=$($gdb_bin --version | head -n 1) if version_ge ${gdb_version##* } 9.1; then echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak + else + gdb_bin="" fi fi @@ -2453,6 +2455,11 @@ echo "# Automatically generated by configure - do not modify" > $config_host_mak echo "SRC_PATH=$source_path" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak +# versioned checked in the main config_host.mak above +if test -n "$gdb_bin"; then + echo "HAVE_GDB_BIN=$gdb_bin" >> $config_host_mak +fi + tcg_tests_targets= for target in $target_list; do arch=${target%%-*} From 94378d4eb6d75322665d8a6d1577736fcc4ba97b Mon Sep 17 00:00:00 2001 From: Anton Johansson Date: Thu, 29 Sep 2022 12:41:46 +0100 Subject: [PATCH 0830/1020] target/hexagon: add flex/bison/glib2 to qemu.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note, the glib2-native mapping exists separately from the normal glib2 mapping. The latter uses a `foreign` cross-policy-default, and libvirt-ci is not able to support package mappings for multiple cross-compilation policies. This will probably change in the future. Signed-off-by: Alessandro Di Federico Signed-off-by: Paolo Montesel Signed-off-by: Anton Johansson Signed-off-by: Alex BennĂ©e Message-Id: <20220804115548.13024-9-anjo@rev.ng> Message-Id: <20220929114231.583801-7-alex.bennee@linaro.org> --- tests/lcitool/projects/qemu.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/lcitool/projects/qemu.yml b/tests/lcitool/projects/qemu.yml index d9f826f8eb..0d92819249 100644 --- a/tests/lcitool/projects/qemu.yml +++ b/tests/lcitool/projects/qemu.yml @@ -3,6 +3,7 @@ packages: - alsa - bash - bc + - bison - brlapi - bzip2 - bzip2-libs @@ -19,6 +20,7 @@ packages: - diffutils - dtrace - findutils + - flex - fuse3 - g++ - gcc @@ -26,6 +28,7 @@ packages: - gettext - genisoimage - glib2 + - glib2-native - glib2-static - glusterfs - gnutls From 8fae3910e2370691b098d51b918600b9ad905df5 Mon Sep 17 00:00:00 2001 From: Anton Johansson Date: Thu, 29 Sep 2022 12:41:47 +0100 Subject: [PATCH 0831/1020] target/hexagon: regenerate docker/cirrus files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch updates the docker and cirrus files with the new packages by running tests/lcitool/refresh Signed-off-by: Anton Johansson Signed-off-by: Alex BennĂ©e Message-Id: <20220804115548.13024-10-anjo@rev.ng> Message-Id: <20220929114231.583801-8-alex.bennee@linaro.org> --- .gitlab-ci.d/cirrus/freebsd-12.vars | 2 +- .gitlab-ci.d/cirrus/freebsd-13.vars | 2 +- .gitlab-ci.d/cirrus/macos-11.vars | 2 +- tests/docker/dockerfiles/alpine.docker | 2 ++ tests/docker/dockerfiles/centos8.docker | 2 ++ tests/docker/dockerfiles/debian-amd64-cross.docker | 3 +++ tests/docker/dockerfiles/debian-amd64.docker | 2 ++ tests/docker/dockerfiles/debian-arm64-cross.docker | 3 +++ tests/docker/dockerfiles/debian-armel-cross.docker | 3 +++ tests/docker/dockerfiles/debian-armhf-cross.docker | 3 +++ tests/docker/dockerfiles/debian-mips64el-cross.docker | 3 +++ tests/docker/dockerfiles/debian-mipsel-cross.docker | 3 +++ tests/docker/dockerfiles/debian-ppc64el-cross.docker | 3 +++ tests/docker/dockerfiles/debian-s390x-cross.docker | 3 +++ tests/docker/dockerfiles/fedora.docker | 2 ++ tests/docker/dockerfiles/opensuse-leap.docker | 2 ++ tests/docker/dockerfiles/ubuntu2004.docker | 2 ++ 17 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.d/cirrus/freebsd-12.vars b/.gitlab-ci.d/cirrus/freebsd-12.vars index 1a5959810f..c3db1d7d30 100644 --- a/.gitlab-ci.d/cirrus/freebsd-12.vars +++ b/.gitlab-ci.d/cirrus/freebsd-12.vars @@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' PYPI_PKGS='' PYTHON='/usr/local/bin/python3' diff --git a/.gitlab-ci.d/cirrus/freebsd-13.vars b/.gitlab-ci.d/cirrus/freebsd-13.vars index 5e5aafd7e5..d31faa787f 100644 --- a/.gitlab-ci.d/cirrus/freebsd-13.vars +++ b/.gitlab-ci.d/cirrus/freebsd-13.vars @@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='pkg' PIP3='/usr/local/bin/pip-3.8' -PKGS='alsa-lib bash bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' +PKGS='alsa-lib bash bison bzip2 ca_root_nss capstone4 ccache cdrkit-genisoimage cmocka ctags curl cyrus-sasl dbus diffutils dtc flex fusefs-libs3 gettext git glib gmake gnutls gsed gtk3 json-c libepoxy libffi libgcrypt libjpeg-turbo libnfs libslirp libspice-server libssh libtasn1 llvm lzo2 meson ncurses nettle ninja opencv perl5 pixman pkgconf png py39-numpy py39-pillow py39-pip py39-sphinx py39-sphinx_rtd_theme py39-yaml python3 rpm2cpio sdl2 sdl2_image snappy spice-protocol tesseract texinfo usbredir virglrenderer vte3 zstd' PYPI_PKGS='' PYTHON='/usr/local/bin/python3' diff --git a/.gitlab-ci.d/cirrus/macos-11.vars b/.gitlab-ci.d/cirrus/macos-11.vars index bec6e862d4..aee9f50de6 100644 --- a/.gitlab-ci.d/cirrus/macos-11.vars +++ b/.gitlab-ci.d/cirrus/macos-11.vars @@ -11,6 +11,6 @@ MAKE='/usr/local/bin/gmake' NINJA='/usr/local/bin/ninja' PACKAGING_COMMAND='brew' PIP3='/usr/local/bin/pip3' -PKGS='bash bc bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd' +PKGS='bash bc bison bzip2 capstone ccache cmocka ctags curl dbus diffutils dtc flex gcovr gettext git glib gnu-sed gnutls gtk+3 jemalloc jpeg-turbo json-c libepoxy libffi libgcrypt libiscsi libnfs libpng libslirp libssh libtasn1 libusb llvm lzo make meson ncurses nettle ninja perl pixman pkg-config python3 rpm2cpio sdl2 sdl2_image snappy sparse spice-protocol tesseract texinfo usbredir vde vte3 zlib zstd' PYPI_PKGS='PyYAML numpy pillow sphinx sphinx-rtd-theme' PYTHON='/usr/local/bin/python3' diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index 806cb19f17..7d6e95275a 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -13,6 +13,7 @@ RUN apk update && \ attr-dev \ bash \ bc \ + bison \ bzip2 \ bzip2-dev \ ca-certificates \ @@ -30,6 +31,7 @@ RUN apk update && \ dtc-dev \ eudev-dev \ findutils \ + flex \ fuse3-dev \ g++ \ gcc \ diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos8.docker index 3c29883332..d89113c0df 100644 --- a/tests/docker/dockerfiles/centos8.docker +++ b/tests/docker/dockerfiles/centos8.docker @@ -17,6 +17,7 @@ RUN dnf distro-sync -y && \ alsa-lib-devel \ bash \ bc \ + bison \ brlapi-devel \ bzip2 \ bzip2-devel \ @@ -31,6 +32,7 @@ RUN dnf distro-sync -y && \ device-mapper-multipath-devel \ diffutils \ findutils \ + flex \ fuse3-devel \ gcc \ gcc-c++ \ diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker index 7d2feb7bf7..9047759e76 100644 --- a/tests/docker/dockerfiles/debian-amd64-cross.docker +++ b/tests/docker/dockerfiles/debian-amd64-cross.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -22,11 +23,13 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ gcovr \ genisoimage \ gettext \ git \ hostname \ + libglib2.0-dev \ libpcre2-dev \ libspice-protocol-dev \ llvm \ diff --git a/tests/docker/dockerfiles/debian-amd64.docker b/tests/docker/dockerfiles/debian-amd64.docker index 8d78ba2484..a8b728ca64 100644 --- a/tests/docker/dockerfiles/debian-amd64.docker +++ b/tests/docker/dockerfiles/debian-amd64.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -23,6 +24,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ g++ \ gcc \ gcovr \ diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker index b7ba2c527f..17a5709245 100644 --- a/tests/docker/dockerfiles/debian-arm64-cross.docker +++ b/tests/docker/dockerfiles/debian-arm64-cross.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -22,11 +23,13 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ gcovr \ genisoimage \ gettext \ git \ hostname \ + libglib2.0-dev \ libpcre2-dev \ libspice-protocol-dev \ llvm \ diff --git a/tests/docker/dockerfiles/debian-armel-cross.docker b/tests/docker/dockerfiles/debian-armel-cross.docker index 9b1778261e..701fc70db0 100644 --- a/tests/docker/dockerfiles/debian-armel-cross.docker +++ b/tests/docker/dockerfiles/debian-armel-cross.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -22,11 +23,13 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ gcovr \ genisoimage \ gettext \ git \ hostname \ + libglib2.0-dev \ libpcre2-dev \ libspice-protocol-dev \ llvm \ diff --git a/tests/docker/dockerfiles/debian-armhf-cross.docker b/tests/docker/dockerfiles/debian-armhf-cross.docker index addbc9a793..5a11fe3900 100644 --- a/tests/docker/dockerfiles/debian-armhf-cross.docker +++ b/tests/docker/dockerfiles/debian-armhf-cross.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -22,11 +23,13 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ gcovr \ genisoimage \ gettext \ git \ hostname \ + libglib2.0-dev \ libpcre2-dev \ libspice-protocol-dev \ llvm \ diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker index 1bb7d8e184..9b90a4d6ff 100644 --- a/tests/docker/dockerfiles/debian-mips64el-cross.docker +++ b/tests/docker/dockerfiles/debian-mips64el-cross.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -22,11 +23,13 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ gcovr \ genisoimage \ gettext \ git \ hostname \ + libglib2.0-dev \ libpcre2-dev \ libspice-protocol-dev \ llvm \ diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker index a94b459b23..02feaf26cb 100644 --- a/tests/docker/dockerfiles/debian-mipsel-cross.docker +++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -22,11 +23,13 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ gcovr \ genisoimage \ gettext \ git \ hostname \ + libglib2.0-dev \ libpcre2-dev \ libspice-protocol-dev \ llvm \ diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker index c641fd5d0e..97d3872ee2 100644 --- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker +++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -22,11 +23,13 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ gcovr \ genisoimage \ gettext \ git \ hostname \ + libglib2.0-dev \ libpcre2-dev \ libspice-protocol-dev \ llvm \ diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker index c0cbe09e66..95585e9e56 100644 --- a/tests/docker/dockerfiles/debian-s390x-cross.docker +++ b/tests/docker/dockerfiles/debian-s390x-cross.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdextrautils \ bzip2 \ ca-certificates \ @@ -22,11 +23,13 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ gcovr \ genisoimage \ gettext \ git \ hostname \ + libglib2.0-dev \ libpcre2-dev \ libspice-protocol-dev \ llvm \ diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker index b39d311bbc..fe84166ca1 100644 --- a/tests/docker/dockerfiles/fedora.docker +++ b/tests/docker/dockerfiles/fedora.docker @@ -23,6 +23,7 @@ exec "$@"' > /usr/bin/nosync && \ alsa-lib-devel \ bash \ bc \ + bison \ brlapi-devel \ bzip2 \ bzip2-devel \ @@ -37,6 +38,7 @@ exec "$@"' > /usr/bin/nosync && \ device-mapper-multipath-devel \ diffutils \ findutils \ + flex \ fuse3-devel \ gcc \ gcc-c++ \ diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker index 041cf9c1ff..d80064756f 100644 --- a/tests/docker/dockerfiles/opensuse-leap.docker +++ b/tests/docker/dockerfiles/opensuse-leap.docker @@ -12,6 +12,7 @@ RUN zypper update -y && \ alsa-lib-devel \ bash \ bc \ + bison \ brlapi-devel \ bzip2 \ ca-certificates \ @@ -22,6 +23,7 @@ RUN zypper update -y && \ dbus-1 \ diffutils \ findutils \ + flex \ fuse3-devel \ gcc \ gcc-c++ \ diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker index e1f4ed7c80..24594afc15 100644 --- a/tests/docker/dockerfiles/ubuntu2004.docker +++ b/tests/docker/dockerfiles/ubuntu2004.docker @@ -13,6 +13,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ eatmydata apt-get install --no-install-recommends -y \ bash \ bc \ + bison \ bsdmainutils \ bzip2 \ ca-certificates \ @@ -23,6 +24,7 @@ RUN export DEBIAN_FRONTEND=noninteractive && \ diffutils \ exuberant-ctags \ findutils \ + flex \ g++ \ gcc \ gcovr \ From 3de61b9856f59bab7739bf213936ac63d8ef3584 Mon Sep 17 00:00:00 2001 From: Anton Johansson Date: Thu, 29 Sep 2022 12:41:48 +0100 Subject: [PATCH 0832/1020] target/hexagon: manually add flex/bison/glib2 to remaining containers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds our build-time dependencies to containers which build qemu-hexagon, but aren't covered by libvirt-ci. Signed-off-by: Anton Johansson Signed-off-by: Alex BennĂ©e Message-Id: <20220804115548.13024-11-anjo@rev.ng> Message-Id: <20220929114231.583801-9-alex.bennee@linaro.org> --- .gitlab-ci.d/windows.yml | 6 ++++-- tests/docker/dockerfiles/debian-riscv64-cross.docker | 3 +++ tests/docker/dockerfiles/fedora-i386-cross.docker | 2 ++ tests/docker/dockerfiles/fedora-win32-cross.docker | 3 +++ tests/docker/dockerfiles/fedora-win64-cross.docker | 3 +++ 5 files changed, 15 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.d/windows.yml b/.gitlab-ci.d/windows.yml index ba59844d12..a3e7a37022 100644 --- a/.gitlab-ci.d/windows.yml +++ b/.gitlab-ci.d/windows.yml @@ -33,7 +33,8 @@ msys2-64bit: extends: .shared_msys2_builder script: - .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed - diffutils git grep make sed + bison diffutils flex + git grep make sed mingw-w64-x86_64-capstone mingw-w64-x86_64-curl mingw-w64-x86_64-cyrus-sasl @@ -67,7 +68,8 @@ msys2-32bit: extends: .shared_msys2_builder script: - .\msys64\usr\bin\bash -lc "pacman -Sy --noconfirm --needed - diffutils git grep make sed + bison diffutils flex + git grep make sed mingw-w64-i686-capstone mingw-w64-i686-curl mingw-w64-i686-cyrus-sasl diff --git a/tests/docker/dockerfiles/debian-riscv64-cross.docker b/tests/docker/dockerfiles/debian-riscv64-cross.docker index 594d97982c..9715791e0b 100644 --- a/tests/docker/dockerfiles/debian-riscv64-cross.docker +++ b/tests/docker/dockerfiles/debian-riscv64-cross.docker @@ -16,13 +16,16 @@ RUN apt update && \ # Install common build utilities RUN DEBIAN_FRONTEND=noninteractive eatmydata apt install -yy \ + bison \ bc \ build-essential \ ca-certificates \ debian-ports-archive-keyring \ dpkg-dev \ + flex \ gettext \ git \ + libglib2.0-dev \ ninja-build \ pkg-config \ python3 diff --git a/tests/docker/dockerfiles/fedora-i386-cross.docker b/tests/docker/dockerfiles/fedora-i386-cross.docker index 0a3ec346e6..7eec648d2d 100644 --- a/tests/docker/dockerfiles/fedora-i386-cross.docker +++ b/tests/docker/dockerfiles/fedora-i386-cross.docker @@ -1,9 +1,11 @@ FROM registry.fedoraproject.org/fedora:34 ENV PACKAGES \ + bison \ bzip2 \ ccache \ diffutils \ + flex \ findutils \ gcc \ git \ diff --git a/tests/docker/dockerfiles/fedora-win32-cross.docker b/tests/docker/dockerfiles/fedora-win32-cross.docker index a06bd29e8e..aca37aabc4 100644 --- a/tests/docker/dockerfiles/fedora-win32-cross.docker +++ b/tests/docker/dockerfiles/fedora-win32-cross.docker @@ -3,13 +3,16 @@ FROM registry.fedoraproject.org/fedora:35 # Please keep this list sorted alphabetically ENV PACKAGES \ bc \ + bison \ bzip2 \ ccache \ diffutils \ findutils \ + flex \ gcc \ gettext \ git \ + glib2-devel \ hostname \ make \ meson \ diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/docker/dockerfiles/fedora-win64-cross.docker index b71624330f..3642766479 100644 --- a/tests/docker/dockerfiles/fedora-win64-cross.docker +++ b/tests/docker/dockerfiles/fedora-win64-cross.docker @@ -3,13 +3,16 @@ FROM registry.fedoraproject.org/fedora:35 # Please keep this list sorted alphabetically ENV PACKAGES \ bc \ + bison \ bzip2 \ ccache \ diffutils \ findutils \ + flex \ gcc \ gettext \ git \ + glib2-devel \ hostname \ make \ meson \ From 81844654156af97294657c0b4e793206afcc68ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:41:50 +0100 Subject: [PATCH 0833/1020] tests/docker: move alpine from edge to tagged release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tracking alpine-edge like debian-sid is a moving target. Usually such rolling releases are marked as "allow_failure: true" in our CI. However as alpine presents a musl based distro and provides useful extra coverage lets track a release branch instead to avoid random breakages. Signed-off-by: Alex BennĂ©e Reviewed-by: Thomas Huth Message-Id: <20220929114231.583801-11-alex.bennee@linaro.org> --- tests/docker/dockerfiles/alpine.docker | 4 ++-- tests/lcitool/refresh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker index 7d6e95275a..9b7541261a 100644 --- a/tests/docker/dockerfiles/alpine.docker +++ b/tests/docker/dockerfiles/alpine.docker @@ -1,10 +1,10 @@ # THIS FILE WAS AUTO-GENERATED # -# $ lcitool dockerfile --layers all alpine-edge qemu +# $ lcitool dockerfile --layers all alpine-316 qemu # # https://gitlab.com/libvirt/libvirt-ci -FROM docker.io/library/alpine:edge +FROM docker.io/library/alpine:3.16 RUN apk update && \ apk upgrade && \ diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh index fc604d8a21..e45c99adbe 100755 --- a/tests/lcitool/refresh +++ b/tests/lcitool/refresh @@ -107,7 +107,7 @@ try: # # Standard native builds # - generate_dockerfile("alpine", "alpine-edge") + generate_dockerfile("alpine", "alpine-316") generate_dockerfile("centos8", "centos-stream-8") generate_dockerfile("debian-amd64", "debian-11", trailer="".join(debian11_extras)) From 100c459f1948b9367cea44c76d5c633b0d23f23b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:41:51 +0100 Subject: [PATCH 0834/1020] tests/qtest: bump up QOS_PATH_MAX_ELEMENT_SIZE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems the depth of stack we need to support can vary depending on the order of the init constructors getting called. It seems --enable-lto shuffles things around just enough to push you over the limit. Signed-off-by: Alex BennĂ©e Fixes: https://gitlab.com/qemu-project/qemu/-/issues/1186 Acked-by: Thomas Huth Acked-by: Paolo Bonzini Message-Id: <20220929114231.583801-12-alex.bennee@linaro.org> --- tests/qtest/libqos/qgraph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/libqos/qgraph.h b/tests/qtest/libqos/qgraph.h index 6e94824d09..5c0046e989 100644 --- a/tests/qtest/libqos/qgraph.h +++ b/tests/qtest/libqos/qgraph.h @@ -24,7 +24,7 @@ #include "libqos-malloc.h" /* maximum path length */ -#define QOS_PATH_MAX_ELEMENT_SIZE 50 +#define QOS_PATH_MAX_ELEMENT_SIZE 64 typedef struct QOSGraphObject QOSGraphObject; typedef struct QOSGraphNode QOSGraphNode; From 66c9f20f5b63bac2249996e20a16de4dc212251e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:41:53 +0100 Subject: [PATCH 0835/1020] pc-bios/optionrom: detect CC options just once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for adding Docker container support, detect compiler options just once rather than once per Make run; container startup overhead is substantial and doing the detection just once makes things faster. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-14-alex.bennee@linaro.org> --- pc-bios/optionrom/Makefile | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index 3e06c11dea..f514e4f84b 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -8,23 +8,33 @@ all: multiboot.bin multiboot_dma.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bi CFLAGS = -O2 -g +NULL := +SPACE := $(NULL) # +TARGET_PREFIX := $(patsubst %/,%:$(SPACE),$(TARGET_DIR)) + +quiet-@ = $(if $(V),,@) quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1)) -cc-option = $(if $(shell $(CC) $1 -c -o /dev/null -xc /dev/null >/dev/null 2>&1 && echo OK), $1, $2) - -override CFLAGS += -march=i486 -Wall $(EXTRA_CFLAGS) -m16 - -# If -fcf-protection is enabled in flags or compiler defaults that will -# conflict with -march=i486 -override CFLAGS += $(call cc-option, -fcf-protection=none) # Flags for dependency generation override CPPFLAGS += -MMD -MP -MT $@ -MF $(@D)/$(*F).d -override CFLAGS += $(call cc-option, -fno-pie) -override CFLAGS += $(call cc-option, -no-pie) +override CFLAGS += -march=i486 -Wall $(EXTRA_CFLAGS) -m16 override CFLAGS += -ffreestanding -I$(TOPSRC_DIR)/include -override CFLAGS += $(call cc-option, -fno-stack-protector) -override CFLAGS += $(call cc-option, -Wno-array-bounds) + +cc-test = $(CC) -Werror $1 -c -o /dev/null -xc /dev/null >/dev/null 2>/dev/null +cc-option = if $(call cc-test, $1); then \ + echo "$(TARGET_PREFIX)$1 detected" && echo "override CFLAGS += $1" >&3; else \ + echo "$(TARGET_PREFIX)$1 not detected" $(if $2,&& echo "override CFLAGS += $2" >&3); fi + +# If -fcf-protection is enabled in flags or compiler defaults that will +# conflict with -march=i486 +config-cc.mak: Makefile + $(quiet-@)($(call cc-option,-fcf-protection=none); \ + $(call cc-option,-fno-pie); \ + $(call cc-option,-no-pie); \ + $(call cc-option,-fno-stack-protector); \ + $(call cc-option,-Wno-array-bounds)) 3> config-cc.mak +-include config-cc.mak override LDFLAGS = -nostdlib -Wl,-T,$(SRC_DIR)/flat.lds @@ -50,7 +60,10 @@ include $(wildcard *.d) clean: rm -f *.o *.d *.raw *.img *.bin *~ +distclean: + rm -f config-cc.mak + # suppress auto-removal of intermediate files .SECONDARY: -.PHONY: all clean +.PHONY: all clean distclean From ebc1d8213cb7807069f42191dcbfc05b6f9ebb0e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:41:54 +0100 Subject: [PATCH 0836/1020] pc-bios/s390-ccw: detect CC options just once MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for adding Docker container support, detect compiler options just once rather than once per Make run; container startup overhead is substantial and doing the detection just once makes things faster. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-15-alex.bennee@linaro.org> --- pc-bios/s390-ccw/Makefile | 33 +++++++++++++++++++++++++-------- pc-bios/s390-ccw/netboot.mak | 7 ++----- 2 files changed, 27 insertions(+), 13 deletions(-) diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile index c8784c2a08..965e633f43 100644 --- a/pc-bios/s390-ccw/Makefile +++ b/pc-bios/s390-ccw/Makefile @@ -6,9 +6,12 @@ include config-host.mak CFLAGS = -O2 -g MAKEFLAGS += -rR +NULL := +SPACE := $(NULL) # +TARGET_PREFIX := $(patsubst %/,%:$(SPACE),$(TARGET_DIR)) + +quiet-@ = $(if $(V),,@) quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1)) -cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \ - >/dev/null 2>&1 && echo OK),$2,$3) VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.sh %.rc Kconfig% %.json.in set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) @@ -25,22 +28,33 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d $(call quiet-command,$(CCAS) $(EXTRA_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) \ -c -o $@ $<,"CCAS","$(TARGET_DIR)$@") -.PHONY : all clean build-all +.PHONY : all clean build-all distclean OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o -EXTRA_CFLAGS := $(EXTRA_CFLAGS) -Wall -EXTRA_CFLAGS += $(call cc-option,-Werror $(EXTRA_CFLAGS),-Wno-stringop-overflow) +EXTRA_CFLAGS += -Wall EXTRA_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -fno-common -fPIE EXTRA_CFLAGS += -fwrapv -fno-strict-aliasing -fno-asynchronous-unwind-tables -EXTRA_CFLAGS += $(call cc-option, $(EXTRA_CFLAGS), -fno-stack-protector) -EXTRA_CFLAGS += $(call cc-option, $(EXTRA_CFLAGS), -Wno-array-bounds) EXTRA_CFLAGS += -msoft-float -EXTRA_CFLAGS += $(call cc-option, $(EXTRA_CFLAGS),-march=z900,-march=z10) EXTRA_CFLAGS += -std=gnu99 LDFLAGS += -Wl,-pie -nostdlib +cc-test = $(CC) -Werror $1 -c -o /dev/null -xc /dev/null >/dev/null 2>/dev/null +cc-option = if $(call cc-test, $1); then \ + echo "$(TARGET_PREFIX)$1 detected" && echo "EXTRA_CFLAGS += $1" >&3; else \ + echo "$(TARGET_PREFIX)$1 not detected" $(if $2,&& echo "EXTRA_CFLAGS += $2" >&3); fi + +config-cc.mak: Makefile + $(quiet-@)($(call cc-option,-Wno-stringop-overflow); \ + $(call cc-option,-fno-stack-protector); \ + $(call cc-option,-Wno-array-bounds); \ + $(call cc-option,-Wno-gnu); \ + $(call cc-option,-march=z900,-march=z10)) 3> config-cc.mak +-include config-cc.mak + +LDFLAGS += -Wl,-pie -nostdlib + build-all: s390-ccw.img s390-netboot.img s390-ccw.elf: $(OBJECTS) @@ -63,3 +77,6 @@ ALL_OBJS = $(sort $(OBJECTS) $(NETOBJS) $(LIBCOBJS) $(LIBNETOBJS)) clean: rm -f *.o *.d *.img *.elf *~ *.a + +distclean: + rm -f config-cc.mak diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak index 7639da194c..ee59a5f4de 100644 --- a/pc-bios/s390-ccw/netboot.mak +++ b/pc-bios/s390-ccw/netboot.mak @@ -16,12 +16,9 @@ s390-netboot.elf: $(NETOBJS) libnet.a libc.a s390-netboot.img: s390-netboot.elf $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@") -# SLOF is GCC-only, so ignore warnings about GNU extensions with Clang here -NO_GNU_WARN := $(call cc-option,-Werror $(QEMU_CFLAGS),-Wno-gnu) - # libc files: -LIBC_CFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(NO_GNU_WARN) $(LIBC_INC) $(LIBNET_INC) \ +LIBC_CFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ -MMD -MP -MT $@ -MF $(@:%.o=%.d) CTYPE_OBJS = isdigit.o isxdigit.o toupper.o @@ -55,7 +52,7 @@ libc.a: $(LIBCOBJS) LIBNETOBJS := args.o dhcp.o dns.o icmpv6.o ipv6.o tcp.o udp.o bootp.o \ dhcpv6.o ethernet.o ipv4.o ndp.o tftp.o pxelinux.o -LIBNETCFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(NO_GNU_WARN) $(LIBC_INC) $(LIBNET_INC) \ +LIBNETCFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ -DDHCPARCH=0x1F -MMD -MP -MT $@ -MF $(@:%.o=%.d) %.o : $(SLOF_DIR)/lib/libnet/%.c From ff0102f67ff859daebbbac7c5c7752fba97e3bfd Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:41:55 +0100 Subject: [PATCH 0837/1020] vof: add distclean target MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini [AJB: add clean dep to distclean] Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-16-alex.bennee@linaro.org> --- pc-bios/vof/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pc-bios/vof/Makefile b/pc-bios/vof/Makefile index 8809c82768..4e59009e67 100644 --- a/pc-bios/vof/Makefile +++ b/pc-bios/vof/Makefile @@ -19,4 +19,6 @@ vof.elf: entry.o main.o ci.o bootmem.o libc.o clean: rm -f *.o vof.bin vof.elf *~ -.PHONY: all clean +distclean: clean + +.PHONY: all clean distclean From 4a3447e5b393d11e3b7aaf50602cbc28a7deeb88 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:41:56 +0100 Subject: [PATCH 0838/1020] build: add recursive distclean rules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-17-alex.bennee@linaro.org> --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b576cba5a8..0fcde48bec 100644 --- a/Makefile +++ b/Makefile @@ -186,7 +186,7 @@ include $(SRC_PATH)/tests/Makefile.include all: recurse-all -ROMS_RULES=$(foreach t, all clean, $(addsuffix /$(t), $(ROMS))) +ROMS_RULES=$(foreach t, all clean distclean, $(addsuffix /$(t), $(ROMS))) .PHONY: $(ROMS_RULES) $(ROMS_RULES): $(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" TARGET_DIR="$(dir $@)" $(notdir $@),) @@ -194,6 +194,7 @@ $(ROMS_RULES): .PHONY: recurse-all recurse-clean recurse-all: $(addsuffix /all, $(ROMS)) recurse-clean: $(addsuffix /clean, $(ROMS)) +recurse-distclean: $(addsuffix /distclean, $(ROMS)) ###################################################################### @@ -214,7 +215,7 @@ dist: qemu-$(VERSION).tar.bz2 qemu-%.tar.bz2: $(SRC_PATH)/scripts/make-release "$(SRC_PATH)" "$(patsubst qemu-%.tar.bz2,%,$@)" -distclean: clean +distclean: clean recurse-distclean -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : rm -f config-host.mak qemu-bundle rm -f tests/tcg/config-*.mak From 61cbb35677896ef2de8aa907e91024a9e69edde8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:41:57 +0100 Subject: [PATCH 0839/1020] configure: return status code from probe_target_compiler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For now, return 1 for container-based compilers. This will change as soon as ROMs will be buildable with them. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-18-alex.bennee@linaro.org> --- configure | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/configure b/configure index 7ae448d16e..a62a833d83 100755 --- a/configure +++ b/configure @@ -2116,6 +2116,7 @@ probe_target_compiler() { target_ranlib= target_strip= fi + test -n "$target_cc" } write_target_makefile() { @@ -2255,10 +2256,9 @@ done # Mac OS X ships with a broken assembler roms= -probe_target_compiler i386-softmmu -if test -n "$target_cc" && - test "$targetos" != "darwin" && test "$targetos" != "sunos" && \ - test "$targetos" != "haiku" && test "$softmmu" = yes ; then +if test "$targetos" != "darwin" && test "$targetos" != "sunos" && \ + test "$targetos" != "haiku" && test "$softmmu" = yes && \ + probe_target_compiler i386-softmmu; then roms="pc-bios/optionrom" config_mak=pc-bios/optionrom/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak @@ -2266,8 +2266,7 @@ if test -n "$target_cc" && write_target_makefile >> $config_mak fi -probe_target_compiler ppc-softmmu -if test -n "$target_cc" && test "$softmmu" = yes; then +if test "$softmmu" = yes && probe_target_compiler ppc-softmmu; then roms="$roms pc-bios/vof" config_mak=pc-bios/vof/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak @@ -2277,8 +2276,7 @@ fi # Only build s390-ccw bios if the compiler has -march=z900 or -march=z10 # (which is the lowest architecture level that Clang supports) -probe_target_compiler s390x-softmmu -if test -n "$target_cc" && test "$softmmu" = yes; then +if test "$softmmu" = yes && probe_target_compiler s390x-softmmu; then write_c_skeleton do_compiler "$target_cc" $target_cc_cflags -march=z900 -o $TMPO -c $TMPC has_z900=$? From c4575b59155e2e0065c29d56496dbf3e6ffd035b Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:41:58 +0100 Subject: [PATCH 0840/1020] configure: store container engine in config-host.mak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In preparation for removing $(DOCKER_SCRIPT) from the tests/tcg configuration files, have Make use the same container engine that had been probed at configure time. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-19-alex.bennee@linaro.org> --- configure | 11 ++++++++--- tests/docker/Makefile.include | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/configure b/configure index a62a833d83..15033a4935 100755 --- a/configure +++ b/configure @@ -1779,9 +1779,11 @@ fi container="no" if test $use_containers = "yes"; then - if has "docker" || has "podman"; then - container=$($python "$source_path"/tests/docker/docker.py probe) - fi + case $($python "$source_path"/tests/docker/docker.py probe) in + *docker) container=docker ;; + podman) container=podman ;; + no) container=no ;; + esac fi # cross compilers defaults, can be overridden with --cross-cc-ARCH @@ -2373,6 +2375,9 @@ if test -n "$gdb_bin"; then fi fi +if test "$container" != no; then + echo "ENGINE=$container" >> $config_host_mak +fi echo "ROMS=$roms" >> $config_host_mak echo "MAKE=$make" >> $config_host_mak echo "PYTHON=$python" >> $config_host_mak diff --git a/tests/docker/Makefile.include b/tests/docker/Makefile.include index 270e99786e..c87f14477a 100644 --- a/tests/docker/Makefile.include +++ b/tests/docker/Makefile.include @@ -14,7 +14,7 @@ DOCKER_DEFAULT_REGISTRY := registry.gitlab.com/qemu-project/qemu endif DOCKER_REGISTRY := $(if $(REGISTRY),$(REGISTRY),$(DOCKER_DEFAULT_REGISTRY)) -ENGINE := auto +ENGINE ?= auto DOCKER_SCRIPT=$(SRC_PATH)/tests/docker/docker.py --engine $(ENGINE) CUR_TIME := $(shell date +%Y-%m-%d-%H.%M.%S.$$$$) From a3e28f81fd886a79502d56ac3614d30bdf4a6dad Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:41:59 +0100 Subject: [PATCH 0841/1020] tests: simplify Makefile invocation for tests/tcg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the DOCKER_SCRIPT and TARGET variable from the Makefile invocation for tests/tcg. For DOCKER_SCRIPT, resolve the path to docker.py in configure; for TARGET, move it to config-$(TARGET).mak and use a symbolic link to break the cycle. The symbolic link is still needed because tests/tcg includes dummy config files for targets that are not buildable. Once that is cleaned up, the symbolic link will go away too. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-20-alex.bennee@linaro.org> --- configure | 23 ++++++++++++++--------- tests/Makefile.include | 9 +++------ tests/tcg/Makefile.target | 2 +- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/configure b/configure index 15033a4935..d454e089f3 100755 --- a/configure +++ b/configure @@ -1784,6 +1784,9 @@ if test $use_containers = "yes"; then podman) container=podman ;; no) container=no ;; esac + if test "$container" != "no"; then + docker_py="$python $source_path/tests/docker/docker.py --engine $container" + fi fi # cross compilers defaults, can be overridden with --cross-cc-ARCH @@ -2153,16 +2156,16 @@ write_target_makefile() { write_container_target_makefile() { echo "EXTRA_CFLAGS=$target_cflags" if test -n "$container_cross_cc"; then - echo "CC=\$(DOCKER_SCRIPT) cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" - echo "CCAS=\$(DOCKER_SCRIPT) cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" + echo "CC=$docker_py cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" + echo "CCAS=$docker_py cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" fi - echo "AR=\$(DOCKER_SCRIPT) cc --cc $container_cross_ar -i qemu/$container_image -s $source_path --" - echo "AS=\$(DOCKER_SCRIPT) cc --cc $container_cross_as -i qemu/$container_image -s $source_path --" - echo "LD=\$(DOCKER_SCRIPT) cc --cc $container_cross_ld -i qemu/$container_image -s $source_path --" - echo "NM=\$(DOCKER_SCRIPT) cc --cc $container_cross_nm -i qemu/$container_image -s $source_path --" - echo "OBJCOPY=\$(DOCKER_SCRIPT) cc --cc $container_cross_objcopy -i qemu/$container_image -s $source_path --" - echo "RANLIB=\$(DOCKER_SCRIPT) cc --cc $container_cross_ranlib -i qemu/$container_image -s $source_path --" - echo "STRIP=\$(DOCKER_SCRIPT) cc --cc $container_cross_strip -i qemu/$container_image -s $source_path --" + echo "AR=$docker_py cc --cc $container_cross_ar -i qemu/$container_image -s $source_path --" + echo "AS=$docker_py cc --cc $container_cross_as -i qemu/$container_image -s $source_path --" + echo "LD=$docker_py cc --cc $container_cross_ld -i qemu/$container_image -s $source_path --" + echo "NM=$docker_py cc --cc $container_cross_nm -i qemu/$container_image -s $source_path --" + echo "OBJCOPY=$docker_py cc --cc $container_cross_objcopy -i qemu/$container_image -s $source_path --" + echo "RANLIB=$docker_py cc --cc $container_cross_ranlib -i qemu/$container_image -s $source_path --" + echo "STRIP=$docker_py cc --cc $container_cross_strip -i qemu/$container_image -s $source_path --" } @@ -2558,6 +2561,8 @@ for target in $target_list; do fi if test $got_cross_cc = yes; then mkdir -p tests/tcg/$target + ln -sf ../config-$target.mak tests/tcg/$target/config-target.mak + echo "TARGET=$target" >> "$config_target_mak" echo "QEMU=$PWD/$qemu" >> "$config_target_mak" echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> $makefile tcg_tests_targets="$tcg_tests_targets $target" diff --git a/tests/Makefile.include b/tests/Makefile.include index 3accb83b13..826b1895f4 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -50,23 +50,20 @@ $(foreach TARGET,$(TCG_TESTS_TARGETS), \ .PHONY: $(TCG_TESTS_TARGETS:%=build-tcg-tests-%) $(TCG_TESTS_TARGETS:%=build-tcg-tests-%): build-tcg-tests-%: $(BUILD_DIR)/tests/tcg/config-%.mak $(call quiet-command, \ - $(MAKE) -C tests/tcg/$* -f ../Makefile.target $(SUBDIR_MAKEFLAGS) \ - DOCKER_SCRIPT="$(DOCKER_SCRIPT)" \ - TARGET="$*" SRC_PATH="$(SRC_PATH)", \ + $(MAKE) -C tests/tcg/$* -f ../Makefile.target $(SUBDIR_MAKEFLAGS), \ "BUILD","$* guest-tests") .PHONY: $(TCG_TESTS_TARGETS:%=run-tcg-tests-%) $(TCG_TESTS_TARGETS:%=run-tcg-tests-%): run-tcg-tests-%: build-tcg-tests-% $(call quiet-command, \ $(MAKE) -C tests/tcg/$* -f ../Makefile.target $(SUBDIR_MAKEFLAGS) \ - TARGET="$*" SRC_PATH="$(SRC_PATH)" SPEED=$(SPEED) run, \ + SPEED=$(SPEED) run, \ "RUN", "$* guest-tests") .PHONY: $(TCG_TESTS_TARGETS:%=clean-tcg-tests-%) $(TCG_TESTS_TARGETS:%=clean-tcg-tests-%): clean-tcg-tests-%: $(call quiet-command, \ - $(MAKE) -C tests/tcg/$* -f ../Makefile.target $(SUBDIR_MAKEFLAGS) \ - TARGET="$*" SRC_PATH="$(SRC_PATH)" clean, \ + $(MAKE) -C tests/tcg/$* -f ../Makefile.target $(SUBDIR_MAKEFLAGS) clean, \ "CLEAN", "$* guest-tests") .PHONY: build-tcg diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index c896d1033e..b9c3d247e9 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -31,7 +31,7 @@ all: -include ../config-host.mak --include ../config-$(TARGET).mak +-include config-target.mak # Get semihosting definitions for user-mode emulation ifeq ($(filter %-softmmu, $(TARGET)),) From d674342e2e29feb7dd3ccf44e2116f78e611e906 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:00 +0100 Subject: [PATCH 0842/1020] tests/tcg: remove -f from Makefile invocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of linking tests/tcg/Makefile.target into the build tree, name the symbolic link "Makefile" and create it in every target subdirectory. This makes it possible to just invoke "make" in tests/tcg subdirectories. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-21-alex.bennee@linaro.org> --- configure | 7 ++++--- tests/Makefile.include | 7 +++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/configure b/configure index d454e089f3..2dc4217f19 100755 --- a/configure +++ b/configure @@ -2243,7 +2243,6 @@ fi # tests might fail. Prefer to keep the relevant files in their own # directory and symlink the directory instead. LINKS="Makefile" -LINKS="$LINKS tests/tcg/Makefile.target" LINKS="$LINKS pc-bios/optionrom/Makefile" LINKS="$LINKS pc-bios/s390-ccw/Makefile" LINKS="$LINKS pc-bios/vof/Makefile" @@ -2457,6 +2456,7 @@ fi echo "# Automatically generated by configure - do not modify" > $makefile config_host_mak=tests/tcg/config-host.mak +mkdir -p tests/tcg echo "# Automatically generated by configure - do not modify" > $config_host_mak echo "SRC_PATH=$source_path" >> $config_host_mak echo "HOST_CC=$host_cc" >> $config_host_mak @@ -2560,8 +2560,9 @@ for target in $target_list; do got_cross_cc=yes fi if test $got_cross_cc = yes; then - mkdir -p tests/tcg/$target - ln -sf ../config-$target.mak tests/tcg/$target/config-target.mak + mkdir -p "tests/tcg/$target" + ln -sf "$source_path/tests/tcg/Makefile.target" "tests/tcg/$target/Makefile" + ln -sf "../config-$target.mak" "tests/tcg/$target/config-target.mak" echo "TARGET=$target" >> "$config_target_mak" echo "QEMU=$PWD/$qemu" >> "$config_target_mak" echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> $makefile diff --git a/tests/Makefile.include b/tests/Makefile.include index 826b1895f4..caef287957 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -50,20 +50,19 @@ $(foreach TARGET,$(TCG_TESTS_TARGETS), \ .PHONY: $(TCG_TESTS_TARGETS:%=build-tcg-tests-%) $(TCG_TESTS_TARGETS:%=build-tcg-tests-%): build-tcg-tests-%: $(BUILD_DIR)/tests/tcg/config-%.mak $(call quiet-command, \ - $(MAKE) -C tests/tcg/$* -f ../Makefile.target $(SUBDIR_MAKEFLAGS), \ + $(MAKE) -C tests/tcg/$* $(SUBDIR_MAKEFLAGS), \ "BUILD","$* guest-tests") .PHONY: $(TCG_TESTS_TARGETS:%=run-tcg-tests-%) $(TCG_TESTS_TARGETS:%=run-tcg-tests-%): run-tcg-tests-%: build-tcg-tests-% $(call quiet-command, \ - $(MAKE) -C tests/tcg/$* -f ../Makefile.target $(SUBDIR_MAKEFLAGS) \ - SPEED=$(SPEED) run, \ + $(MAKE) -C tests/tcg/$* $(SUBDIR_MAKEFLAGS) SPEED=$(SPEED) run, \ "RUN", "$* guest-tests") .PHONY: $(TCG_TESTS_TARGETS:%=clean-tcg-tests-%) $(TCG_TESTS_TARGETS:%=clean-tcg-tests-%): clean-tcg-tests-%: $(call quiet-command, \ - $(MAKE) -C tests/tcg/$* -f ../Makefile.target $(SUBDIR_MAKEFLAGS) clean, \ + $(MAKE) -C tests/tcg/$* $(SUBDIR_MAKEFLAGS) clean, \ "CLEAN", "$* guest-tests") .PHONY: build-tcg From 6ffe81370aab511f438ece256977def804f9b6e2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:01 +0100 Subject: [PATCH 0843/1020] tests/tcg: add distclean rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-22-alex.bennee@linaro.org> --- tests/Makefile.include | 11 +++++++++++ tests/tcg/Makefile.target | 3 +++ 2 files changed, 14 insertions(+) diff --git a/tests/Makefile.include b/tests/Makefile.include index caef287957..9ed67721e2 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -42,6 +42,7 @@ tests/tcg/Makefile.prereqs: config-host.mak # Per guest TCG tests BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TCG_TESTS_TARGETS)) CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TCG_TESTS_TARGETS)) +DISTCLEAN_TCG_TARGET_RULES=$(patsubst %,distclean-tcg-tests-%, $(TCG_TESTS_TARGETS)) RUN_TCG_TARGET_RULES=$(patsubst %,run-tcg-tests-%, $(TCG_TESTS_TARGETS)) $(foreach TARGET,$(TCG_TESTS_TARGETS), \ @@ -65,6 +66,12 @@ $(TCG_TESTS_TARGETS:%=clean-tcg-tests-%): clean-tcg-tests-%: $(MAKE) -C tests/tcg/$* $(SUBDIR_MAKEFLAGS) clean, \ "CLEAN", "$* guest-tests") +.PHONY: $(TCG_TESTS_TARGETS:%=distclean-tcg-tests-%) +$(TCG_TESTS_TARGETS:%=distclean-tcg-tests-%): distclean-tcg-tests-%: + $(call quiet-command, \ + $(MAKE) -C tests/tcg/$* $(SUBDIR_MAKEFLAGS) distclean, \ + "CLEAN", "$* guest-tests") + .PHONY: build-tcg build-tcg: $(BUILD_TCG_TARGET_RULES) @@ -75,6 +82,9 @@ check-tcg: $(RUN_TCG_TARGET_RULES) .PHONY: clean-tcg clean-tcg: $(CLEAN_TCG_TARGET_RULES) +.PHONY: distclean-tcg +distclean-tcg: $(DISTCLEAN_TCG_TARGET_RULES) + # Python venv for running tests .PHONY: check-venv check-avocado check-acceptance check-acceptance-deprecated-warning @@ -159,5 +169,6 @@ check-clean: rm -rf $(TESTS_VENV_DIR) $(TESTS_RESULTS_DIR) clean: check-clean clean-tcg +distclean: distclean-tcg endif diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index b9c3d247e9..c14eca82c2 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -189,3 +189,6 @@ run: $(RUN_TESTS) clean: rm -f $(TESTS) *.o $(CLEANFILES) + +distclean: + rm -f config-target.mak ../config-$(TARGET).mak From 37b0dba45c4e44a02000a4170f25af0110f501d5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:02 +0100 Subject: [PATCH 0844/1020] tests/tcg: unify ppc64 and ppc64le Makefiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make tests/tcg/ppc64le include tests/tcg/ppc64 instead of duplicating the rules. Because the ppc64le vpath includes tests/tcg/ppc64 but not vice versa, the tests have to be moved from tests/tcg/ppc64le/ to tests/tcg/ppc64. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-23-alex.bennee@linaro.org> --- tests/tcg/ppc64/Makefile.target | 1 - tests/tcg/{ppc64le => ppc64}/bcdsub.c | 0 tests/tcg/{ppc64le => ppc64}/byte_reverse.c | 0 tests/tcg/{ppc64le => ppc64}/mffsce.c | 0 tests/tcg/{ppc64le => ppc64}/mtfsf.c | 0 .../{ppc64le => ppc64}/non_signalling_xscv.c | 0 .../signal_save_restore_xer.c | 0 tests/tcg/{ppc64le => ppc64}/xxspltw.c | 0 tests/tcg/ppc64le/Makefile.target | 26 +------------------ 9 files changed, 1 insertion(+), 26 deletions(-) rename tests/tcg/{ppc64le => ppc64}/bcdsub.c (100%) rename tests/tcg/{ppc64le => ppc64}/byte_reverse.c (100%) rename tests/tcg/{ppc64le => ppc64}/mffsce.c (100%) rename tests/tcg/{ppc64le => ppc64}/mtfsf.c (100%) rename tests/tcg/{ppc64le => ppc64}/non_signalling_xscv.c (100%) rename tests/tcg/{ppc64le => ppc64}/signal_save_restore_xer.c (100%) rename tests/tcg/{ppc64le => ppc64}/xxspltw.c (100%) diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target index 331fae628e..7db7a3e2b3 100644 --- a/tests/tcg/ppc64/Makefile.target +++ b/tests/tcg/ppc64/Makefile.target @@ -3,7 +3,6 @@ # ppc64 specific tweaks VPATH += $(SRC_PATH)/tests/tcg/ppc64 -VPATH += $(SRC_PATH)/tests/tcg/ppc64le ifneq ($(CROSS_CC_HAS_POWER8_VECTOR),) PPC64_TESTS=bcdsub non_signalling_xscv diff --git a/tests/tcg/ppc64le/bcdsub.c b/tests/tcg/ppc64/bcdsub.c similarity index 100% rename from tests/tcg/ppc64le/bcdsub.c rename to tests/tcg/ppc64/bcdsub.c diff --git a/tests/tcg/ppc64le/byte_reverse.c b/tests/tcg/ppc64/byte_reverse.c similarity index 100% rename from tests/tcg/ppc64le/byte_reverse.c rename to tests/tcg/ppc64/byte_reverse.c diff --git a/tests/tcg/ppc64le/mffsce.c b/tests/tcg/ppc64/mffsce.c similarity index 100% rename from tests/tcg/ppc64le/mffsce.c rename to tests/tcg/ppc64/mffsce.c diff --git a/tests/tcg/ppc64le/mtfsf.c b/tests/tcg/ppc64/mtfsf.c similarity index 100% rename from tests/tcg/ppc64le/mtfsf.c rename to tests/tcg/ppc64/mtfsf.c diff --git a/tests/tcg/ppc64le/non_signalling_xscv.c b/tests/tcg/ppc64/non_signalling_xscv.c similarity index 100% rename from tests/tcg/ppc64le/non_signalling_xscv.c rename to tests/tcg/ppc64/non_signalling_xscv.c diff --git a/tests/tcg/ppc64le/signal_save_restore_xer.c b/tests/tcg/ppc64/signal_save_restore_xer.c similarity index 100% rename from tests/tcg/ppc64le/signal_save_restore_xer.c rename to tests/tcg/ppc64/signal_save_restore_xer.c diff --git a/tests/tcg/ppc64le/xxspltw.c b/tests/tcg/ppc64/xxspltw.c similarity index 100% rename from tests/tcg/ppc64le/xxspltw.c rename to tests/tcg/ppc64/xxspltw.c diff --git a/tests/tcg/ppc64le/Makefile.target b/tests/tcg/ppc64le/Makefile.target index 6ca3003f02..daad5118a5 100644 --- a/tests/tcg/ppc64le/Makefile.target +++ b/tests/tcg/ppc64le/Makefile.target @@ -4,28 +4,4 @@ VPATH += $(SRC_PATH)/tests/tcg/ppc64le -ifneq ($(CROSS_CC_HAS_POWER8_VECTOR),) -PPC64LE_TESTS=bcdsub non_signalling_xscv -endif -$(PPC64LE_TESTS): CFLAGS += -mpower8-vector - -ifneq ($(CROSS_CC_HAS_POWER10),) -PPC64LE_TESTS += byte_reverse sha512-vector -endif -byte_reverse: CFLAGS += -mcpu=power10 -run-byte_reverse: QEMU_OPTS+=-cpu POWER10 -run-plugin-byte_reverse-with-%: QEMU_OPTS+=-cpu POWER10 - -sha512-vector: CFLAGS +=-mcpu=power10 -O3 -sha512-vector: sha512.c - $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) - -run-sha512-vector: QEMU_OPTS+=-cpu POWER10 -run-plugin-sha512-vector-with-%: QEMU_OPTS+=-cpu POWER10 - -PPC64LE_TESTS += mtfsf -PPC64LE_TESTS += mffsce -PPC64LE_TESTS += signal_save_restore_xer -PPC64LE_TESTS += xxspltw - -TESTS += $(PPC64LE_TESTS) +include $(SRC_PATH)/tests/tcg/ppc64/Makefile.target From c6cf8a20521c7114893042cb7c75866bd07838ae Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:03 +0100 Subject: [PATCH 0845/1020] tests/tcg: clean up calls to run-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Almost all invocations of run-test have either "$* on $(TARGET_NAME)" or "$< on $(TARGET_NAME)" as the last argument. So provide a default test name, while allowing an escape hatch for custom names. As an additional simplification, remove the need to do shell quoting. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-24-alex.bennee@linaro.org> --- tests/tcg/Makefile.target | 21 +++++++++---------- tests/tcg/aarch64/Makefile.softmmu-target | 6 ++---- tests/tcg/aarch64/Makefile.target | 6 +++--- tests/tcg/arm/Makefile.target | 9 ++++---- tests/tcg/cris/Makefile.target | 2 +- tests/tcg/i386/Makefile.softmmu-target | 3 +-- tests/tcg/i386/Makefile.target | 5 ++--- tests/tcg/multiarch/Makefile.target | 18 +++++++--------- .../multiarch/system/Makefile.softmmu-target | 2 +- tests/tcg/s390x/Makefile.target | 2 +- tests/tcg/x86_64/Makefile.softmmu-target | 3 +-- 11 files changed, 34 insertions(+), 43 deletions(-) diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index c14eca82c2..cd0a2ad873 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -41,14 +41,16 @@ endif # for including , in command strings COMMA := , -quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1)) +quiet-@ = $(if $(V),,@$(if $1,printf " %-7s %s\n" "$(strip $1)" "$(strip $2)" && )) +quiet-command = $(call quiet-@,$2,$3)$1 # $1 = test name, $2 = cmd, $3 = desc ifeq ($(filter %-softmmu, $(TARGET)),) run-test = $(call quiet-command, timeout --foreground $(TIMEOUT) $2 > $1.out, \ - "TEST",$3) + TEST,$(or $3, $*, $<) on $(TARGET_NAME)) else -run-test = $(call quiet-command, timeout --foreground $(TIMEOUT) $2,"TEST",$3) +run-test = $(call quiet-command, timeout --foreground $(TIMEOUT) $2, \ + TEST,$(or $3, $*, $<) on $(TARGET_NAME)) endif # $1 = test name, $2 = reference @@ -56,7 +58,7 @@ endif # we know it failed and then force failure at the end. diff-out = $(call quiet-command, diff -q $1.out $2 || \ (diff -u $1.out $2 | head -n 10 && false), \ - "DIFF","$1.out with $2") + DIFF,$1.out with $2) # $1 = test name, $2 = reason skip-test = @printf " SKIPPED %s on $(TARGET_NAME) because %s\n" $1 $2 @@ -155,21 +157,19 @@ RUN_TESTS+=$(EXTRA_RUNS) ifeq ($(filter %-softmmu, $(TARGET)),) run-%: % - $(call run-test, $<, $(QEMU) $(QEMU_OPTS) $<, "$< on $(TARGET_NAME)") + $(call run-test, $<, $(QEMU) $(QEMU_OPTS) $<) run-plugin-%: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ -plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \ -d plugin -D $*.pout \ - $(call strip-plugin,$<), \ - "$* on $(TARGET_NAME)") + $(call strip-plugin,$<)) else run-%: % $(call run-test, $<, \ $(QEMU) -monitor none -display none \ -chardev file$(COMMA)path=$<.out$(COMMA)id=output \ - $(QEMU_OPTS) $<, \ - "$< on $(TARGET_NAME)") + $(QEMU_OPTS) $<) run-plugin-%: $(call run-test, $@, \ @@ -177,8 +177,7 @@ run-plugin-%: -chardev file$(COMMA)path=$@.out$(COMMA)id=output \ -plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \ -d plugin -D $*.pout \ - $(QEMU_OPTS) $(call strip-plugin,$<), \ - "$* on $(TARGET_NAME)") + $(QEMU_OPTS) $(call strip-plugin,$<)) endif gdb-%: % diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target index f6fcd4829e..84a9990f8d 100644 --- a/tests/tcg/aarch64/Makefile.softmmu-target +++ b/tests/tcg/aarch64/Makefile.softmmu-target @@ -50,8 +50,7 @@ run-memory-record: memory-record memory $(QEMU) -monitor none -display none \ -chardev file$(COMMA)path=$<.out$(COMMA)id=output \ -icount shift=5$(COMMA)rr=record$(COMMA)rrfile=record.bin \ - $(QEMU_OPTS) memory, \ - "$< on $(TARGET_NAME)") + $(QEMU_OPTS) memory) .PHONY: memory-replay run-memory-replay: memory-replay run-memory-record @@ -59,8 +58,7 @@ run-memory-replay: memory-replay run-memory-record $(QEMU) -monitor none -display none \ -chardev file$(COMMA)path=$<.out$(COMMA)id=output \ -icount shift=5$(COMMA)rr=replay$(COMMA)rrfile=record.bin \ - $(QEMU_OPTS) memory, \ - "$< on $(TARGET_NAME)") + $(QEMU_OPTS) memory) EXTRA_RUNS+=run-memory-replay diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target index d6a74d24dc..9837a809dc 100644 --- a/tests/tcg/aarch64/Makefile.target +++ b/tests/tcg/aarch64/Makefile.target @@ -55,7 +55,7 @@ sha1-vector: CFLAGS=-O3 sha1-vector: sha1.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) run-sha1-vector: sha1-vector run-sha1 - $(call run-test, $<, $(QEMU) $(QEMU_OPTS) $<, "$< on $(TARGET_NAME)") + $(call run-test, $<, $(QEMU) $(QEMU_OPTS) $<) $(call diff-out, sha1-vector, sha1.out) TESTS += sha1-vector @@ -75,14 +75,14 @@ run-gdbstub-sysregs: sysregs --gdb $(HAVE_GDB_BIN) \ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ --bin $< --test $(AARCH64_SRC)/gdbstub/test-sve.py, \ - "basic gdbstub SVE support") + basic gdbstub SVE support) run-gdbstub-sve-ioctls: sve-ioctls $(call run-test, $@, $(GDB_SCRIPT) \ --gdb $(HAVE_GDB_BIN) \ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ --bin $< --test $(AARCH64_SRC)/gdbstub/test-sve-ioctl.py, \ - "basic gdbstub SVE ZLEN support") + basic gdbstub SVE ZLEN support) EXTRA_RUNS += run-gdbstub-sysregs run-gdbstub-sve-ioctls endif diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target index 2f815120a5..b3b1504a1c 100644 --- a/tests/tcg/arm/Makefile.target +++ b/tests/tcg/arm/Makefile.target @@ -26,7 +26,7 @@ ARM_TESTS += fcvt fcvt: LDFLAGS+=-lm # fcvt: CFLAGS+=-march=armv8.2-a+fp16 -mfpu=neon-fp-armv8 run-fcvt: fcvt - $(call run-test,fcvt,$(QEMU) $<,"$< on $(TARGET_NAME)") + $(call run-test,fcvt,$(QEMU) $<) $(call diff-out,fcvt,$(ARM_SRC)/fcvt.ref) # PC alignment test @@ -44,13 +44,12 @@ semihosting-arm: semihosting.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) run-semihosting-arm: semihosting-arm - $(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)") + $(call run-test,$<,$(QEMU) $< 2> $<.err) run-plugin-semihosting-arm-with-%: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ -plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \ - $(call strip-plugin,$<) 2> $<.err, \ - "$< on $(TARGET_NAME) with $*") + $(call strip-plugin,$<) 2> $<.err) ARM_TESTS += semiconsole-arm @@ -75,7 +74,7 @@ sha1-vector: CFLAGS=-O3 sha1-vector: sha1.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS) run-sha1-vector: sha1-vector run-sha1 - $(call run-test, $<, $(QEMU) $(QEMU_OPTS) $<, "$< on $(TARGET_NAME)") + $(call run-test, $<, $(QEMU) $(QEMU_OPTS) $<) $(call diff-out, sha1-vector, sha1.out) ARM_TESTS += sha1-vector diff --git a/tests/tcg/cris/Makefile.target b/tests/tcg/cris/Makefile.target index e72d3cbdb2..372287bd03 100644 --- a/tests/tcg/cris/Makefile.target +++ b/tests/tcg/cris/Makefile.target @@ -56,4 +56,4 @@ SIMG:=cris-axis-linux-gnu-run # e.g.: make -f ../../tests/tcg/Makefile run-check_orm-on-sim run-%-on-sim: - $(call run-test, $<, $(SIMG) $<, "$< on $(TARGET_NAME) with SIM") + $(call run-test, $<, $(SIMG) $<) diff --git a/tests/tcg/i386/Makefile.softmmu-target b/tests/tcg/i386/Makefile.softmmu-target index 9b9038d0be..ed922d59c8 100644 --- a/tests/tcg/i386/Makefile.softmmu-target +++ b/tests/tcg/i386/Makefile.softmmu-target @@ -40,8 +40,7 @@ run-plugin-%-with-libinsn.so: -chardev file$(COMMA)path=$@.out$(COMMA)id=output \ -plugin ../../plugin/libinsn.so$(COMMA)inline=on \ -d plugin -D $*-with-libinsn.so.pout \ - $(QEMU_OPTS) $*, \ - "$* on $(TARGET_NAME)") + $(QEMU_OPTS) $*) # Running QEMU_OPTS+=-device isa-debugcon,chardev=output -device isa-debug-exit,iobase=0xf4,iosize=0x4 -kernel diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index 599f192529..8af066efc5 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -53,7 +53,7 @@ test-i386-fprem.ref: test-i386-fprem run-test-i386-fprem: TIMEOUT=60 run-test-i386-fprem: test-i386-fprem test-i386-fprem.ref - $(call run-test,test-i386-fprem, $(QEMU) $<,"$< on $(TARGET_NAME)") + $(call run-test,test-i386-fprem, $(QEMU) $<) $(call diff-out,test-i386-fprem, test-i386-fprem.ref) else SKIP_I386_TESTS+=test-i386-fprem @@ -63,8 +63,7 @@ endif run-plugin-%-with-libinsn.so: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ -plugin ../../plugin/libinsn.so$(COMMA)inline=on \ - -d plugin -D $*-with-libinsn.so.pout $*, \ - "$* (inline) on $(TARGET_NAME)") + -d plugin -D $*-with-libinsn.so.pout $*) # Update TESTS I386_TESTS:=$(filter-out $(SKIP_I386_TESTS), $(ALL_X86_TESTS)) diff --git a/tests/tcg/multiarch/Makefile.target b/tests/tcg/multiarch/Makefile.target index 6bba523729..78104f9bbb 100644 --- a/tests/tcg/multiarch/Makefile.target +++ b/tests/tcg/multiarch/Makefile.target @@ -26,7 +26,7 @@ float_%: float_%.c libs/float_helpers.c $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< $(MULTIARCH_SRC)/libs/float_helpers.c -o $@ $(LDFLAGS) run-float_%: float_% - $(call run-test,$<, $(QEMU) $(QEMU_OPTS) $<,"$< on $(TARGET_NAME)") + $(call run-test,$<, $(QEMU) $(QEMU_OPTS) $<) $(call conditional-diff-out,$<,$(SRC_PATH)/tests/tcg/$(TARGET_NAME)/$<.ref) @@ -42,13 +42,11 @@ signals: LDFLAGS+=-lrt -lpthread # default case (host page size) run-test-mmap: test-mmap - $(call run-test, test-mmap, $(QEMU) $<, \ - "$< (default) on $(TARGET_NAME)") + $(call run-test, test-mmap, $(QEMU) $<, $< (default)) # additional page sizes (defined by each architecture adding to EXTRA_RUNS) run-test-mmap-%: test-mmap - $(call run-test, test-mmap-$*, $(QEMU) -p $* $<,\ - "$< ($* byte pages) on $(TARGET_NAME)") + $(call run-test, test-mmap-$*, $(QEMU) -p $* $<, $< ($* byte pages)) ifneq ($(HAVE_GDB_BIN),) GDB_SCRIPT=$(SRC_PATH)/tests/guest-debug/run-test.py @@ -58,21 +56,21 @@ run-gdbstub-sha1: sha1 --gdb $(HAVE_GDB_BIN) \ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ --bin $< --test $(MULTIARCH_SRC)/gdbstub/sha1.py, \ - "basic gdbstub support") + basic gdbstub support) run-gdbstub-qxfer-auxv-read: sha1 $(call run-test, $@, $(GDB_SCRIPT) \ --gdb $(HAVE_GDB_BIN) \ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ --bin $< --test $(MULTIARCH_SRC)/gdbstub/test-qxfer-auxv-read.py, \ - "basic gdbstub qXfer:auxv:read support") + basic gdbstub qXfer:auxv:read support) run-gdbstub-thread-breakpoint: testthread $(call run-test, $@, $(GDB_SCRIPT) \ --gdb $(HAVE_GDB_BIN) \ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ --bin $< --test $(MULTIARCH_SRC)/gdbstub/test-thread-breakpoint.py, \ - "hitting a breakpoint on non-main thread") + hitting a breakpoint on non-main thread) else run-gdbstub-%: @@ -94,13 +92,13 @@ VPATH += $(MULTIARCH_SRC)/arm-compat-semi semihosting: CFLAGS+=-I$(SRC_PATH)/tests/tcg/$(TARGET_NAME) run-semihosting: semihosting - $(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)") + $(call run-test,$<,$(QEMU) $< 2> $<.err) run-plugin-semihosting-with-%: $(call run-test, $@, $(QEMU) $(QEMU_OPTS) \ -plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \ $(call strip-plugin,$<) 2> $<.err, \ - "$< on $(TARGET_NAME) with $*") + $< with $*) semiconsole: CFLAGS+=-I$(SRC_PATH)/tests/tcg/$(TARGET_NAME) diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target b/tests/tcg/multiarch/system/Makefile.softmmu-target index 625ed792c6..368b64d531 100644 --- a/tests/tcg/multiarch/system/Makefile.softmmu-target +++ b/tests/tcg/multiarch/system/Makefile.softmmu-target @@ -25,7 +25,7 @@ run-gdbstub-memory: memory --qargs \ "-monitor none -display none -chardev file$(COMMA)path=$<.out$(COMMA)id=output $(QEMU_OPTS)" \ --bin $< --test $(MULTIARCH_SRC)/gdbstub/memory.py, \ - "softmmu gdbstub support") + softmmu gdbstub support) else run-gdbstub-%: diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 5e13a41c3f..c830313e67 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -41,7 +41,7 @@ run-gdbstub-signals-s390x: signals-s390x --gdb $(HAVE_GDB_BIN) \ --qemu $(QEMU) --qargs "$(QEMU_OPTS)" \ --bin $< --test $(S390X_SRC)/gdbstub/test-signals-s390x.py, \ - "mixing signals and debugging on s390x") + mixing signals and debugging) EXTRA_RUNS += run-gdbstub-signals-s390x endif diff --git a/tests/tcg/x86_64/Makefile.softmmu-target b/tests/tcg/x86_64/Makefile.softmmu-target index 2afa3298bf..7207fee94c 100644 --- a/tests/tcg/x86_64/Makefile.softmmu-target +++ b/tests/tcg/x86_64/Makefile.softmmu-target @@ -40,8 +40,7 @@ run-plugin-%-with-libinsn.so: -chardev file$(COMMA)path=$@.out$(COMMA)id=output \ -plugin ../../plugin/libinsn.so$(COMMA)inline=on \ -d plugin -D $*-with-libinsn.so.pout \ - $(QEMU_OPTS) $*, \ - "$* on $(TARGET_NAME)") + $(QEMU_OPTS) $*) # Running QEMU_OPTS+=-device isa-debugcon,chardev=output -device isa-debug-exit,iobase=0xf4,iosize=0x4 -kernel From 15b273f8e6a4740768fba3878a346c82ef48a966 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:04 +0100 Subject: [PATCH 0846/1020] tests/tcg: move compiler tests to Makefiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Further decoupling of tests/tcg from the main QEMU Makefile, and making the build more similar between the cross compiler case and the vetted container images. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-25-alex.bennee@linaro.org> --- configure | 65 +---------------------- tests/tcg/Makefile.target | 10 +++- tests/tcg/aarch64/Makefile.softmmu-target | 5 ++ tests/tcg/aarch64/Makefile.target | 9 ++++ tests/tcg/i386/Makefile.target | 6 +++ tests/tcg/ppc64/Makefile.target | 7 +++ 6 files changed, 38 insertions(+), 64 deletions(-) diff --git a/configure b/configure index 2dc4217f19..0255b127f5 100755 --- a/configure +++ b/configure @@ -2490,73 +2490,11 @@ for target in $target_list; do probe_target_compiler $target if test $got_cross_cc = yes; then - # Test for compiler features for optional tests. We only do this - # for cross compilers because ensuring the docker containers based - # compilers is a requirememt for adding a new test that needs a - # compiler feature. - - echo "BUILD_STATIC=$build_static" >> "$config_target_mak" write_target_makefile >> "$config_target_mak" - case $target in - aarch64-*) - if do_compiler "$target_cc" $target_cflags \ - -march=armv8.1-a+sve -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_SVE=y" >> "$config_target_mak" - fi - if do_compiler "$target_cc" $target_cflags \ - -march=armv8.1-a+sve2 -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_SVE2=y" >> "$config_target_mak" - fi - if do_compiler "$target_cc" $target_cflags \ - -march=armv8.3-a -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_ARMV8_3=y" >> "$config_target_mak" - fi - if do_compiler "$target_cc" $target_cflags \ - -mbranch-protection=standard -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_ARMV8_BTI=y" >> "$config_target_mak" - fi - if do_compiler "$target_cc" $target_cflags \ - -march=armv8.5-a+memtag -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_ARMV8_MTE=y" >> "$config_target_mak" - fi - ;; - ppc*) - if do_compiler "$target_cc" $target_cflags \ - -mpower8-vector -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_POWER8_VECTOR=y" >> "$config_target_mak" - fi - if do_compiler "$target_cc" $target_cflags \ - -mpower10 -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_POWER10=y" >> "$config_target_mak" - fi - ;; - i386-linux-user) - if do_compiler "$target_cc" $target_cflags \ - -Werror -fno-pie -o $TMPE $TMPC; then - echo "CROSS_CC_HAS_I386_NOPIE=y" >> "$config_target_mak" - fi - ;; - esac elif test -n "$container_image"; then + build_static=y echo "build-tcg-tests-$target: docker-image-$container_image" >> $makefile - echo "BUILD_STATIC=y" >> "$config_target_mak" write_container_target_makefile >> "$config_target_mak" - case $target in - aarch64-*) - echo "CROSS_CC_HAS_SVE=y" >> "$config_target_mak" - echo "CROSS_CC_HAS_SVE2=y" >> "$config_target_mak" - echo "CROSS_CC_HAS_ARMV8_3=y" >> "$config_target_mak" - echo "CROSS_CC_HAS_ARMV8_BTI=y" >> "$config_target_mak" - echo "CROSS_CC_HAS_ARMV8_MTE=y" >> "$config_target_mak" - ;; - ppc*) - echo "CROSS_CC_HAS_POWER8_VECTOR=y" >> "$config_target_mak" - echo "CROSS_CC_HAS_POWER10=y" >> "$config_target_mak" - ;; - i386-linux-user) - echo "CROSS_CC_HAS_I386_NOPIE=y" >> "$config_target_mak" - ;; - esac got_cross_cc=yes fi if test $got_cross_cc = yes; then @@ -2565,6 +2503,7 @@ for target in $target_list; do ln -sf "../config-$target.mak" "tests/tcg/$target/config-target.mak" echo "TARGET=$target" >> "$config_target_mak" echo "QEMU=$PWD/$qemu" >> "$config_target_mak" + echo "BUILD_STATIC=$build_static" >> "$config_target_mak" echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> $makefile tcg_tests_targets="$tcg_tests_targets $target" fi diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index cd0a2ad873..75257f2b29 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -40,10 +40,18 @@ endif # for including , in command strings COMMA := , +NULL := +SPACE := $(NULL) # +TARGET_PREFIX=tests/tcg/$(TARGET):$(SPACE) quiet-@ = $(if $(V),,@$(if $1,printf " %-7s %s\n" "$(strip $1)" "$(strip $2)" && )) quiet-command = $(call quiet-@,$2,$3)$1 +cc-test = $(CC) -Werror $1 -c -o /dev/null -xc /dev/null >/dev/null 2>&1 +cc-option = if $(call cc-test, $1); then \ + echo "$(TARGET_PREFIX)$1 detected" && echo "$(strip $2)=y" >&3; else \ + echo "$(TARGET_PREFIX)$1 not detected"; fi + # $1 = test name, $2 = cmd, $3 = desc ifeq ($(filter %-softmmu, $(TARGET)),) run-test = $(call quiet-command, timeout --foreground $(TIMEOUT) $2 > $1.out, \ @@ -190,4 +198,4 @@ clean: rm -f $(TESTS) *.o $(CLEANFILES) distclean: - rm -f config-target.mak ../config-$(TARGET).mak + rm -f config-cc.mak config-target.mak ../config-$(TARGET).mak diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target index 84a9990f8d..a1368905f5 100644 --- a/tests/tcg/aarch64/Makefile.softmmu-target +++ b/tests/tcg/aarch64/Makefile.softmmu-target @@ -19,6 +19,11 @@ EXTRA_RUNS+=$(MULTIARCH_RUNS) CFLAGS+=-nostdlib -ggdb -O0 $(MINILIB_INC) LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc +config-cc.mak: Makefile + $(quiet-@)( \ + $(call cc-option,-march=armv8.3-a, CROSS_CC_HAS_ARMV8_3)) 3> config-cc.mak +-include config-cc.mak + # building head blobs .PRECIOUS: $(CRT_OBJS) diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target index 9837a809dc..fc8d90ed69 100644 --- a/tests/tcg/aarch64/Makefile.target +++ b/tests/tcg/aarch64/Makefile.target @@ -17,6 +17,15 @@ run-fcvt: fcvt $(call run-test,$<,$(QEMU) $<, "$< on $(TARGET_NAME)") $(call diff-out,$<,$(AARCH64_SRC)/fcvt.ref) +config-cc.mak: Makefile + $(quiet-@)( \ + $(call cc-option,-march=armv8.1-a+sve, CROSS_CC_HAS_SVE); \ + $(call cc-option,-march=armv8.1-a+sve2, CROSS_CC_HAS_SVE2); \ + $(call cc-option,-march=armv8.3-a, CROSS_CC_HAS_ARMV8_3); \ + $(call cc-option,-mbranch-protection=standard, CROSS_CC_HAS_ARMV8_BTI); \ + $(call cc-option,-march=armv8.5-a+memtag, CROSS_CC_HAS_ARMV8_MTE)) 3> config-cc.mak +-include config-cc.mak + # Pauth Tests ifneq ($(CROSS_CC_HAS_ARMV8_3),) AARCH64_TESTS += pauth-1 pauth-2 pauth-4 pauth-5 diff --git a/tests/tcg/i386/Makefile.target b/tests/tcg/i386/Makefile.target index 8af066efc5..3273aa8061 100644 --- a/tests/tcg/i386/Makefile.target +++ b/tests/tcg/i386/Makefile.target @@ -5,6 +5,12 @@ I386_SRC=$(SRC_PATH)/tests/tcg/i386 # Set search path for all sources VPATH += $(I386_SRC) +config-cc.mak: Makefile + $(quiet-@)( \ + $(call cc-option,-fno-pie, CROSS_CC_HAS_I386_NOPIE)) 3> config-cc.mak + +-include config-cc.mak + I386_SRCS=$(notdir $(wildcard $(I386_SRC)/*.c)) ALL_X86_TESTS=$(I386_SRCS:.c=) SKIP_I386_TESTS=test-i386-ssse3 test-avx test-3dnow test-mmx diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target index 7db7a3e2b3..f081f1c683 100644 --- a/tests/tcg/ppc64/Makefile.target +++ b/tests/tcg/ppc64/Makefile.target @@ -4,6 +4,13 @@ VPATH += $(SRC_PATH)/tests/tcg/ppc64 +config-cc.mak: Makefile + $(quiet-@)( \ + $(call cc-option,-mpower8-vector, CROSS_CC_HAS_POWER8_VECTOR); \ + $(call cc-option,-mpower10, CROSS_CC_HAS_POWER10)) 3> config-cc.mak + +-include config-cc.mak + ifneq ($(CROSS_CC_HAS_POWER8_VECTOR),) PPC64_TESTS=bcdsub non_signalling_xscv endif From b898bf28469847cbe4e576000e83ec103bf9b174 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:05 +0100 Subject: [PATCH 0847/1020] configure: move tests/tcg/Makefile.prereqs to root build directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It will not be specific to tests/tcg anymore, since it will be possible to build firmware using container-based cross compilers too. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-26-alex.bennee@linaro.org> --- Makefile | 5 ++++- configure | 15 +++++++-------- tests/Makefile.include | 3 --- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Makefile b/Makefile index 0fcde48bec..357592ad39 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,9 @@ configure: ; ifneq ($(wildcard config-host.mak),) include config-host.mak +include Makefile.prereqs +Makefile.prereqs: config-host.mak + git-submodule-update: .git-submodule-status: git-submodule-update config-host.mak Makefile: .git-submodule-status @@ -217,7 +220,7 @@ qemu-%.tar.bz2: distclean: clean recurse-distclean -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : - rm -f config-host.mak qemu-bundle + rm -f config-host.mak Makefile.prereqs qemu-bundle rm -f tests/tcg/config-*.mak rm -f config.status rm -f roms/seabios/config.mak diff --git a/configure b/configure index 0255b127f5..a71e38d20a 100755 --- a/configure +++ b/configure @@ -2154,6 +2154,7 @@ write_target_makefile() { } write_container_target_makefile() { + echo "$1: docker-image-$container_image" >> Makefile.prereqs echo "EXTRA_CFLAGS=$target_cflags" if test -n "$container_cross_cc"; then echo "CC=$docker_py cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" @@ -2258,6 +2259,8 @@ for f in $LINKS ; do fi done +echo "# Automatically generated by configure - do not modify" > Makefile.prereqs + # Mac OS X ships with a broken assembler roms= if test "$targetos" != "darwin" && test "$targetos" != "sunos" && \ @@ -2452,10 +2455,7 @@ if test "$safe_stack" = "yes"; then fi # tests/tcg configuration -(makefile=tests/tcg/Makefile.prereqs -echo "# Automatically generated by configure - do not modify" > $makefile - -config_host_mak=tests/tcg/config-host.mak +(config_host_mak=tests/tcg/config-host.mak mkdir -p tests/tcg echo "# Automatically generated by configure - do not modify" > $config_host_mak echo "SRC_PATH=$source_path" >> $config_host_mak @@ -2493,8 +2493,7 @@ for target in $target_list; do write_target_makefile >> "$config_target_mak" elif test -n "$container_image"; then build_static=y - echo "build-tcg-tests-$target: docker-image-$container_image" >> $makefile - write_container_target_makefile >> "$config_target_mak" + write_container_target_makefile build-tcg-tests-$target >> "$config_target_mak" got_cross_cc=yes fi if test $got_cross_cc = yes; then @@ -2504,11 +2503,11 @@ for target in $target_list; do echo "TARGET=$target" >> "$config_target_mak" echo "QEMU=$PWD/$qemu" >> "$config_target_mak" echo "BUILD_STATIC=$build_static" >> "$config_target_mak" - echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> $makefile + echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> Makefile.prereqs tcg_tests_targets="$tcg_tests_targets $target" fi done -echo "TCG_TESTS_TARGETS=$tcg_tests_targets" >> $makefile) +echo "TCG_TESTS_TARGETS=$tcg_tests_targets" >> config-host.mak) if test "$skip_meson" = no; then cross="config-meson.cross.new" diff --git a/tests/Makefile.include b/tests/Makefile.include index 9ed67721e2..9422ddaece 100644 --- a/tests/Makefile.include +++ b/tests/Makefile.include @@ -36,9 +36,6 @@ export SRC_PATH SPEED = quick --include tests/tcg/Makefile.prereqs -tests/tcg/Makefile.prereqs: config-host.mak - # Per guest TCG tests BUILD_TCG_TARGET_RULES=$(patsubst %,build-tcg-tests-%, $(TCG_TESTS_TARGETS)) CLEAN_TCG_TARGET_RULES=$(patsubst %,clean-tcg-tests-%, $(TCG_TESTS_TARGETS)) From 0825cae023133871dfbd803cae9f004cb7447a48 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:06 +0100 Subject: [PATCH 0848/1020] configure: unify creation of cross-compilation Makefiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let write_target_makefile handle both host and container cross compilers. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-27-alex.bennee@linaro.org> --- configure | 94 +++++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/configure b/configure index a71e38d20a..a843a5637a 100755 --- a/configure +++ b/configure @@ -2126,51 +2126,49 @@ probe_target_compiler() { write_target_makefile() { echo "EXTRA_CFLAGS=$target_cflags" - if test -n "$target_cc"; then - echo "CC=$target_cc" - echo "CCAS=$target_ccas" - fi - if test -n "$target_ar"; then - echo "AR=$target_ar" - fi - if test -n "$target_as"; then - echo "AS=$target_as" - fi - if test -n "$target_ld"; then - echo "LD=$target_ld" - fi - if test -n "$target_nm"; then - echo "NM=$target_nm" - fi - if test -n "$target_objcopy"; then - echo "OBJCOPY=$target_objcopy" - fi - if test -n "$target_ranlib"; then - echo "RANLIB=$target_ranlib" - fi - if test -n "$target_strip"; then - echo "STRIP=$target_strip" + if test -z "$target_cc" && test -z "$target_as"; then + test -z "$container_image" && error_exit "Internal error: could not find cross compiler for $1?" + echo "$1: docker-image-$container_image" >> Makefile.prereqs + if test -n "$container_cross_cc"; then + echo "CC=$docker_py cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" + echo "CCAS=$docker_py cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" + fi + echo "AR=$docker_py cc --cc $container_cross_ar -i qemu/$container_image -s $source_path --" + echo "AS=$docker_py cc --cc $container_cross_as -i qemu/$container_image -s $source_path --" + echo "LD=$docker_py cc --cc $container_cross_ld -i qemu/$container_image -s $source_path --" + echo "NM=$docker_py cc --cc $container_cross_nm -i qemu/$container_image -s $source_path --" + echo "OBJCOPY=$docker_py cc --cc $container_cross_objcopy -i qemu/$container_image -s $source_path --" + echo "RANLIB=$docker_py cc --cc $container_cross_ranlib -i qemu/$container_image -s $source_path --" + echo "STRIP=$docker_py cc --cc $container_cross_strip -i qemu/$container_image -s $source_path --" + else + if test -n "$target_cc"; then + echo "CC=$target_cc" + echo "CCAS=$target_ccas" + fi + if test -n "$target_ar"; then + echo "AR=$target_ar" + fi + if test -n "$target_as"; then + echo "AS=$target_as" + fi + if test -n "$target_ld"; then + echo "LD=$target_ld" + fi + if test -n "$target_nm"; then + echo "NM=$target_nm" + fi + if test -n "$target_objcopy"; then + echo "OBJCOPY=$target_objcopy" + fi + if test -n "$target_ranlib"; then + echo "RANLIB=$target_ranlib" + fi + if test -n "$target_strip"; then + echo "STRIP=$target_strip" + fi fi } -write_container_target_makefile() { - echo "$1: docker-image-$container_image" >> Makefile.prereqs - echo "EXTRA_CFLAGS=$target_cflags" - if test -n "$container_cross_cc"; then - echo "CC=$docker_py cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" - echo "CCAS=$docker_py cc --cc $container_cross_cc -i qemu/$container_image -s $source_path --" - fi - echo "AR=$docker_py cc --cc $container_cross_ar -i qemu/$container_image -s $source_path --" - echo "AS=$docker_py cc --cc $container_cross_as -i qemu/$container_image -s $source_path --" - echo "LD=$docker_py cc --cc $container_cross_ld -i qemu/$container_image -s $source_path --" - echo "NM=$docker_py cc --cc $container_cross_nm -i qemu/$container_image -s $source_path --" - echo "OBJCOPY=$docker_py cc --cc $container_cross_objcopy -i qemu/$container_image -s $source_path --" - echo "RANLIB=$docker_py cc --cc $container_cross_ranlib -i qemu/$container_image -s $source_path --" - echo "STRIP=$docker_py cc --cc $container_cross_strip -i qemu/$container_image -s $source_path --" -} - - - ########################################## # check for vfio_user_server @@ -2488,15 +2486,9 @@ for target in $target_list; do ;; esac - probe_target_compiler $target - if test $got_cross_cc = yes; then - write_target_makefile >> "$config_target_mak" - elif test -n "$container_image"; then - build_static=y - write_container_target_makefile build-tcg-tests-$target >> "$config_target_mak" - got_cross_cc=yes - fi - if test $got_cross_cc = yes; then + if probe_target_compiler $target || test -n "$container_image"; then + test -n "$container_image" && build_static=y + write_target_makefile "build-tcg-tests-$target >> "$config_target_mak" mkdir -p "tests/tcg/$target" ln -sf "$source_path/tests/tcg/Makefile.target" "tests/tcg/$target/Makefile" ln -sf "../config-$target.mak" "tests/tcg/$target/config-target.mak" From c7022a703c497aca6e409d46534896f8ee06a209 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:07 +0100 Subject: [PATCH 0849/1020] configure: cleanup creation of tests/tcg target config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the symlink to tests/tcg/config-*.mak, which is possible now that unused target config files are not created either. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-28-alex.bennee@linaro.org> --- Makefile | 2 +- configure | 12 +++++------- meson.build | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/Makefile b/Makefile index 357592ad39..a48103cc8a 100644 --- a/Makefile +++ b/Makefile @@ -221,7 +221,7 @@ qemu-%.tar.bz2: distclean: clean recurse-distclean -$(quiet-@)test -f build.ninja && $(NINJA) $(NINJAFLAGS) -t clean -g || : rm -f config-host.mak Makefile.prereqs qemu-bundle - rm -f tests/tcg/config-*.mak + rm -f tests/tcg/*/config-target.mak tests/tcg/config-host.mak rm -f config.status rm -f roms/seabios/config.mak rm -f qemu-plugins-ld.symbols qemu-plugins-ld64.symbols diff --git a/configure b/configure index a843a5637a..45ee6f4eb3 100755 --- a/configure +++ b/configure @@ -2468,10 +2468,6 @@ tcg_tests_targets= for target in $target_list; do arch=${target%%-*} - config_target_mak=tests/tcg/config-$target.mak - - echo "# Automatically generated by configure - do not modify" > $config_target_mak - echo "TARGET_NAME=$arch" >> "$config_target_mak" case $target in xtensa*-linux-user) # the toolchain is not complete with headers, only build softmmu tests @@ -2488,13 +2484,15 @@ for target in $target_list; do if probe_target_compiler $target || test -n "$container_image"; then test -n "$container_image" && build_static=y - write_target_makefile "build-tcg-tests-$target >> "$config_target_mak" mkdir -p "tests/tcg/$target" + config_target_mak=tests/tcg/$target/config-target.mak ln -sf "$source_path/tests/tcg/Makefile.target" "tests/tcg/$target/Makefile" - ln -sf "../config-$target.mak" "tests/tcg/$target/config-target.mak" + echo "# Automatically generated by configure - do not modify" > "$config_target_mak" + echo "TARGET_NAME=$arch" >> "$config_target_mak" echo "TARGET=$target" >> "$config_target_mak" - echo "QEMU=$PWD/$qemu" >> "$config_target_mak" + write_target_makefile "build-tcg-tests-$target" >> "$config_target_mak" echo "BUILD_STATIC=$build_static" >> "$config_target_mak" + echo "QEMU=$PWD/$qemu" >> "$config_target_mak" echo "run-tcg-tests-$target: $qemu\$(EXESUF)" >> Makefile.prereqs tcg_tests_targets="$tcg_tests_targets $target" fi diff --git a/meson.build b/meson.build index 4321b8f8da..536e819c60 100644 --- a/meson.build +++ b/meson.build @@ -3764,7 +3764,7 @@ summary(summary_info, bool_yn: true, section: 'Compilation') summary_info = {} have_cross = false foreach target: target_dirs - tcg_mak = meson.current_build_dir() / 'tests/tcg' / 'config-' + target + '.mak' + tcg_mak = meson.current_build_dir() / 'tests/tcg' / target / 'config-target.mak' if fs.exists(tcg_mak) config_cross_tcg = keyval.load(tcg_mak) if 'CC' in config_cross_tcg From 730fe750fba63023e294ff0acf0f874369f1946f Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:08 +0100 Subject: [PATCH 0850/1020] configure: build ROMs with container-based cross compilers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit s390-ccw remains a bit more complex, because the -march=z900 test is done only for the native cross compiler. Otherwise, all that is needed is to pass the (now mandatory) target argument to write_target_makefile. Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-29-alex.bennee@linaro.org> --- configure | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/configure b/configure index 45ee6f4eb3..baa69189f0 100755 --- a/configure +++ b/configure @@ -2121,7 +2121,7 @@ probe_target_compiler() { target_ranlib= target_strip= fi - test -n "$target_cc" + test -n "$target_cc" || test -n "$container_image" } write_target_makefile() { @@ -2268,7 +2268,7 @@ if test "$targetos" != "darwin" && test "$targetos" != "sunos" && \ config_mak=pc-bios/optionrom/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak echo "TOPSRC_DIR=$source_path" >> $config_mak - write_target_makefile >> $config_mak + write_target_makefile pc-bios/optionrom/all >> $config_mak fi if test "$softmmu" = yes && probe_target_compiler ppc-softmmu; then @@ -2276,25 +2276,31 @@ if test "$softmmu" = yes && probe_target_compiler ppc-softmmu; then config_mak=pc-bios/vof/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak echo "SRC_DIR=$source_path/pc-bios/vof" >> $config_mak - write_target_makefile >> $config_mak + write_target_makefile pc-bios/vof/all >> $config_mak fi # Only build s390-ccw bios if the compiler has -march=z900 or -march=z10 # (which is the lowest architecture level that Clang supports) if test "$softmmu" = yes && probe_target_compiler s390x-softmmu; then - write_c_skeleton - do_compiler "$target_cc" $target_cc_cflags -march=z900 -o $TMPO -c $TMPC - has_z900=$? - if [ $has_z900 = 0 ] || do_compiler "$target_cc" $target_cc_cflags -march=z10 -msoft-float -Werror -o $TMPO -c $TMPC; then - if [ $has_z900 != 0 ]; then - echo "WARNING: Your compiler does not support the z900!" - echo " The s390-ccw bios will only work with guest CPUs >= z10." + got_cross_cc=no + if test -n "$target_cc"; then + write_c_skeleton + do_compiler "$target_cc" $target_cc_cflags -march=z900 -o $TMPO -c $TMPC + has_z900=$? + if [ $has_z900 = 0 ] || do_compiler "$target_cc" $target_cc_cflags -march=z10 -msoft-float -Werror -o $TMPO -c $TMPC; then + if [ $has_z900 != 0 ]; then + echo "WARNING: Your compiler does not support the z900!" + echo " The s390-ccw bios will only work with guest CPUs >= z10." + fi + got_cross_cc=yes fi + fi + if test "$got_cross_cc" = yes || test -n "$container_image"; then roms="$roms pc-bios/s390-ccw" config_mak=pc-bios/s390-ccw/config-host.mak echo "# Automatically generated by configure - do not modify" > $config_mak echo "SRC_PATH=$source_path/pc-bios/s390-ccw" >> $config_mak - write_target_makefile >> $config_mak + write_target_makefile pc-bios/s390-ccw/all >> $config_mak # SLOF is required for building the s390-ccw firmware on s390x, # since it is using the libnet code from SLOF for network booting. git_submodules="${git_submodules} roms/SLOF" @@ -2482,7 +2488,7 @@ for target in $target_list; do ;; esac - if probe_target_compiler $target || test -n "$container_image"; then + if probe_target_compiler $target; then test -n "$container_image" && build_static=y mkdir -p "tests/tcg/$target" config_target_mak=tests/tcg/$target/config-target.mak From f9236995b38f42a6e0a5c4a9d2c5153e1e6cc0ed Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:09 +0100 Subject: [PATCH 0851/1020] pc-bios/optionrom: Adopt meson style Make output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-30-alex.bennee@linaro.org> --- pc-bios/optionrom/Makefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pc-bios/optionrom/Makefile b/pc-bios/optionrom/Makefile index f514e4f84b..b1fff0ba6c 100644 --- a/pc-bios/optionrom/Makefile +++ b/pc-bios/optionrom/Makefile @@ -12,8 +12,8 @@ NULL := SPACE := $(NULL) # TARGET_PREFIX := $(patsubst %/,%:$(SPACE),$(TARGET_DIR)) -quiet-@ = $(if $(V),,@) -quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1)) +quiet-@ = $(if $(V),,@$(if $1,printf "%s\n" "$(TARGET_PREFIX)$1" && )) +quiet-command = $(call quiet-@,$2 $@)$1 # Flags for dependency generation override CPPFLAGS += -MMD -MP -MT $@ -MF $(@D)/$(*F).d @@ -41,19 +41,19 @@ override LDFLAGS = -nostdlib -Wl,-T,$(SRC_DIR)/flat.lds pvh.img: pvh.o pvh_main.o %.o: %.S - $(call quiet-command,$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<,"AS","$@") + $(call quiet-command,$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<,Assembling) %.o: %.c - $(call quiet-command,$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@,"CC","$@") + $(call quiet-command,$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@,Compiling) %.img: %.o - $(call quiet-command,$(CC) $(CFLAGS) $(LDFLAGS) -s -o $@ $^,"BUILD","$@") + $(call quiet-command,$(CC) $(CFLAGS) $(LDFLAGS) -s -o $@ $^,Linking) %.raw: %.img - $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,"BUILD","$@") + $(call quiet-command,$(OBJCOPY) -O binary -j .text $< $@,Extracting raw object) %.bin: %.raw - $(call quiet-command,$(PYTHON) $(TOPSRC_DIR)/scripts/signrom.py $< $@,"SIGN","$@") + $(call quiet-command,$(PYTHON) $(TOPSRC_DIR)/scripts/signrom.py $< $@,Computing checksum into) include $(wildcard *.d) From b5fc8458fff07bdefa9d501a5d9c3564738ce446 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:10 +0100 Subject: [PATCH 0852/1020] pc-bios/s390-ccw: Adopt meson style Make output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-31-alex.bennee@linaro.org> --- pc-bios/s390-ccw/Makefile | 12 ++++++------ pc-bios/s390-ccw/netboot.mak | 20 ++++++++++---------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile index 965e633f43..10e8f5cb63 100644 --- a/pc-bios/s390-ccw/Makefile +++ b/pc-bios/s390-ccw/Makefile @@ -10,8 +10,8 @@ NULL := SPACE := $(NULL) # TARGET_PREFIX := $(patsubst %/,%:$(SPACE),$(TARGET_DIR)) -quiet-@ = $(if $(V),,@) -quiet-command = $(if $(V),$1,$(if $(2),@printf " %-7s %s\n" $2 $3 && $1, @$1)) +quiet-@ = $(if $(V),,@$(if $1,printf "%s\n" "$(TARGET_PREFIX)$1" && )) +quiet-command = $(call quiet-@,$2 $@)$1 VPATH_SUFFIXES = %.c %.h %.S %.m %.mak %.sh %.rc Kconfig% %.json.in set-vpath = $(if $1,$(foreach PATTERN,$(VPATH_SUFFIXES),$(eval vpath $(PATTERN) $1))) @@ -22,11 +22,11 @@ QEMU_DGFLAGS = -MMD -MP -MT $@ -MF $(@D)/$(*F).d %.o: %.c $(call quiet-command,$(CC) $(EXTRA_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) \ - -c -o $@ $<,"CC","$(TARGET_DIR)$@") + -c -o $@ $<,Compiling) %.o: %.S $(call quiet-command,$(CCAS) $(EXTRA_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) \ - -c -o $@ $<,"CCAS","$(TARGET_DIR)$@") + -c -o $@ $<,Assembling) .PHONY : all clean build-all distclean @@ -58,10 +58,10 @@ LDFLAGS += -Wl,-pie -nostdlib build-all: s390-ccw.img s390-netboot.img s390-ccw.elf: $(OBJECTS) - $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),"BUILD","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) $(LDFLAGS) -o $@ $(OBJECTS),Linking) s390-ccw.img: s390-ccw.elf - $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@") + $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,Stripping $< into) $(OBJECTS): Makefile diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak index ee59a5f4de..046aa35587 100644 --- a/pc-bios/s390-ccw/netboot.mak +++ b/pc-bios/s390-ccw/netboot.mak @@ -11,10 +11,10 @@ NETLDFLAGS := $(LDFLAGS) -Wl,-Ttext=0x7800000 $(NETOBJS): EXTRA_CFLAGS += $(LIBC_INC) $(LIBNET_INC) s390-netboot.elf: $(NETOBJS) libnet.a libc.a - $(call quiet-command,$(CC) $(NETLDFLAGS) -o $@ $^,"BUILD","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) $(NETLDFLAGS) -o $@ $^,Linking) s390-netboot.img: s390-netboot.elf - $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,"STRIP","$(TARGET_DIR)$@") + $(call quiet-command,$(STRIP) --strip-unneeded $< -o $@,Stripping $< into) # libc files: @@ -23,30 +23,30 @@ LIBC_CFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ CTYPE_OBJS = isdigit.o isxdigit.o toupper.o %.o : $(SLOF_DIR)/lib/libc/ctype/%.c - $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) STRING_OBJS = strcat.o strchr.o strrchr.o strcpy.o strlen.o strncpy.o \ strcmp.o strncmp.o strcasecmp.o strncasecmp.o strstr.o \ memset.o memcpy.o memmove.o memcmp.o %.o : $(SLOF_DIR)/lib/libc/string/%.c - $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) STDLIB_OBJS = atoi.o atol.o strtoul.o strtol.o rand.o malloc.o free.o %.o : $(SLOF_DIR)/lib/libc/stdlib/%.c - $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) STDIO_OBJS = sprintf.o snprintf.o vfprintf.o vsnprintf.o vsprintf.o fprintf.o \ printf.o putc.o puts.o putchar.o stdchnls.o fileno.o %.o : $(SLOF_DIR)/lib/libc/stdio/%.c - $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) sbrk.o: $(SLOF_DIR)/slof/sbrk.c - $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) $(LIBC_CFLAGS) -c -o $@ $<,Compiling) LIBCOBJS := $(STRING_OBJS) $(CTYPE_OBJS) $(STDLIB_OBJS) $(STDIO_OBJS) sbrk.o libc.a: $(LIBCOBJS) - $(call quiet-command,$(AR) -rc $@ $^,"AR","$(TARGET_DIR)$@") + $(call quiet-command,$(AR) -rc $@ $^,Creating static library) # libnet files: @@ -56,7 +56,7 @@ LIBNETCFLAGS = $(EXTRA_CFLAGS) $(CFLAGS) $(LIBC_INC) $(LIBNET_INC) \ -DDHCPARCH=0x1F -MMD -MP -MT $@ -MF $(@:%.o=%.d) %.o : $(SLOF_DIR)/lib/libnet/%.c - $(call quiet-command,$(CC) $(LIBNETCFLAGS) -c -o $@ $<,"CC","$(TARGET_DIR)$@") + $(call quiet-command,$(CC) $(LIBNETCFLAGS) -c -o $@ $<,Compiling) libnet.a: $(LIBNETOBJS) - $(call quiet-command,$(AR) -rc $@ $^,"AR","$(TARGET_DIR)$@") + $(call quiet-command,$(AR) -rc $@ $^,Creating static library) From 3cc70a9994bf0967c7a2bda539ed43926fb4c2cb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 29 Sep 2022 12:42:11 +0100 Subject: [PATCH 0853/1020] pc-bios/vof: Adopt meson style Make output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paolo Bonzini Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-32-alex.bennee@linaro.org> --- pc-bios/vof/Makefile | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/pc-bios/vof/Makefile b/pc-bios/vof/Makefile index 4e59009e67..d1eb6ced7e 100644 --- a/pc-bios/vof/Makefile +++ b/pc-bios/vof/Makefile @@ -2,19 +2,26 @@ include config.mak VPATH=$(SRC_DIR) all: vof.bin +NULL := +SPACE := $(NULL) # +TARGET_PREFIX := $(patsubst %/,%:$(SPACE),$(TARGET_DIR)) + +quiet-@ = $(if $(V),,@$(if $1,,printf "%s\n" "$(TARGET_PREFIX)$1" && )) +quiet-command = $(call quiet-@,$2 $@)$1 + EXTRA_CFLAGS += -mcpu=power4 %.o: %.S - $(CC) $(EXTRA_CFLAGS) -c -o $@ $< + $(call quiet-command, $(CC) $(EXTRA_CFLAGS) -c -o $@ $<,Assembling) %.o: %.c - $(CC) $(EXTRA_CFLAGS) -c -fno-stack-protector -o $@ $< + $(call quiet-command, $(CC) $(EXTRA_CFLAGS) -c -fno-stack-protector -o $@ $<,Compiling) vof.elf: entry.o main.o ci.o bootmem.o libc.o - $(LD) -nostdlib -e_start -T$(SRC_DIR)/vof.lds -EB -o $@ $^ + $(call quiet-command, $(LD) -nostdlib -e_start -T$(SRC_DIR)/vof.lds -EB -o $@ $^,Linking) %.bin: %.elf - $(OBJCOPY) -O binary -j .text -j .data -j .toc -j .got2 $^ $@ + $(call quiet-command, $(OBJCOPY) -O binary -j .text -j .data -j .toc -j .got2 $^ $@,Extracting raw object) clean: rm -f *.o vof.bin vof.elf *~ From bf0c50d4aa851e78c91096f510303831a2aadaeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:12 +0100 Subject: [PATCH 0854/1020] monitor: expose monitor_puts to rest of code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This helps us construct strings elsewhere before echoing to the monitor. It avoids having to jump through hoops like: monitor_printf(mon, "%s", s->str); It will be useful in following patches but for now convert all existing plain "%s" printfs to use the _puts api. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Reviewed-by: Kevin Wolf Reviewed-by: Markus Armbruster Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220929114231.583801-33-alex.bennee@linaro.org> --- block/monitor/block-hmp-cmds.c | 10 +++++----- docs/devel/writing-monitor-commands.rst | 2 +- hw/misc/mos6522.c | 2 +- include/monitor/monitor.h | 1 + monitor/hmp-cmds.c | 8 ++++---- monitor/hmp.c | 2 +- monitor/monitor-internal.h | 1 - target/i386/helper.c | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/block/monitor/block-hmp-cmds.c b/block/monitor/block-hmp-cmds.c index bfb3c043a0..939a520d17 100644 --- a/block/monitor/block-hmp-cmds.c +++ b/block/monitor/block-hmp-cmds.c @@ -638,16 +638,16 @@ static void print_block_info(Monitor *mon, BlockInfo *info, assert(!info || !info->has_inserted || info->inserted == inserted); if (info && *info->device) { - monitor_printf(mon, "%s", info->device); + monitor_puts(mon, info->device); if (inserted && inserted->has_node_name) { monitor_printf(mon, " (%s)", inserted->node_name); } } else { assert(info || inserted); - monitor_printf(mon, "%s", - inserted && inserted->has_node_name ? inserted->node_name - : info && info->has_qdev ? info->qdev - : ""); + monitor_puts(mon, + inserted && inserted->has_node_name ? inserted->node_name + : info && info->has_qdev ? info->qdev + : ""); } if (inserted) { diff --git a/docs/devel/writing-monitor-commands.rst b/docs/devel/writing-monitor-commands.rst index 4aa2bb904d..2fefedcd98 100644 --- a/docs/devel/writing-monitor-commands.rst +++ b/docs/devel/writing-monitor-commands.rst @@ -716,7 +716,7 @@ message. Here's the implementation of the "info roms" HMP command:: if (hmp_handle_error(mon, err)) { return; } - monitor_printf(mon, "%s", info->human_readable_text); + monitor_puts(mon, info->human_readable_text); } Also, you have to add the function's prototype to the hmp.h file. diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c index f9e646350e..fe38c44426 100644 --- a/hw/misc/mos6522.c +++ b/hw/misc/mos6522.c @@ -595,7 +595,7 @@ void hmp_info_via(Monitor *mon, const QDict *qdict) if (hmp_handle_error(mon, err)) { return; } - monitor_printf(mon, "%s", info->human_readable_text); + monitor_puts(mon, info->human_readable_text); } static const MemoryRegionOps mos6522_ops = { diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h index a4b40e8391..737e750670 100644 --- a/include/monitor/monitor.h +++ b/include/monitor/monitor.h @@ -31,6 +31,7 @@ void monitor_resume(Monitor *mon); int monitor_get_fd(Monitor *mon, const char *fdname, Error **errp); int monitor_fd_param(Monitor *mon, const char *fdname, Error **errp); +int monitor_puts(Monitor *mon, const char *str); int monitor_vprintf(Monitor *mon, const char *fmt, va_list ap) G_GNUC_PRINTF(2, 0); int monitor_printf(Monitor *mon, const char *fmt, ...) G_GNUC_PRINTF(2, 3); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index c6cd6f91dd..f90eea8d01 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -730,7 +730,7 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev) monitor_printf(mon, " "); if (dev->class_info->has_desc) { - monitor_printf(mon, "%s", dev->class_info->desc); + monitor_puts(mon, dev->class_info->desc); } else { monitor_printf(mon, "Class %04" PRId64, dev->class_info->q_class); } @@ -2258,12 +2258,12 @@ static void print_stats_schema_value(Monitor *mon, StatsSchemaValue *value) if (unit && value->base == 10 && value->exponent >= -18 && value->exponent <= 18 && value->exponent % 3 == 0) { - monitor_printf(mon, "%s", si_prefix(value->exponent)); + monitor_puts(mon, si_prefix(value->exponent)); } else if (unit && value->base == 2 && value->exponent >= 0 && value->exponent <= 60 && value->exponent % 10 == 0) { - monitor_printf(mon, "%s", iec_binary_prefix(value->exponent)); + monitor_puts(mon, iec_binary_prefix(value->exponent)); } else if (value->exponent) { /* Use exponential notation and write the unit's English name */ monitor_printf(mon, "* %d^%d%s", @@ -2273,7 +2273,7 @@ static void print_stats_schema_value(Monitor *mon, StatsSchemaValue *value) } if (value->has_unit) { - monitor_printf(mon, "%s", unit ? unit : StatsUnit_str(value->unit)); + monitor_puts(mon, unit ? unit : StatsUnit_str(value->unit)); } /* Print bucket size for linear histograms */ diff --git a/monitor/hmp.c b/monitor/hmp.c index a3375d0341..43fd69f984 100644 --- a/monitor/hmp.c +++ b/monitor/hmp.c @@ -1094,7 +1094,7 @@ static void hmp_info_human_readable_text(Monitor *mon, return; } - monitor_printf(mon, "%s", info->human_readable_text); + monitor_puts(mon, info->human_readable_text); } static void handle_hmp_command_exec(Monitor *mon, diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index caa2e90ef2..a2cdbbf646 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -174,7 +174,6 @@ extern int mon_refcount; extern HMPCommand hmp_cmds[]; -int monitor_puts(Monitor *mon, const char *str); void monitor_data_init(Monitor *mon, bool is_qmp, bool skip_flush, bool use_io_thread); void monitor_data_destroy(Monitor *mon); diff --git a/target/i386/helper.c b/target/i386/helper.c index fa409e9c44..b954ccda50 100644 --- a/target/i386/helper.c +++ b/target/i386/helper.c @@ -415,7 +415,7 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data) if (need_reset) { emit_guest_memory_failure(MEMORY_FAILURE_ACTION_RESET, ar, recursive); - monitor_printf(params->mon, "%s", msg); + monitor_puts(params->mon, msg); qemu_log_mask(CPU_LOG_RESET, "%s\n", msg); qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); return; From 4332099f0e69b938fa968a98e130845010ec6fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:13 +0100 Subject: [PATCH 0855/1020] disas: generalise plugin_printf and use for monitor_disas MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than assembling our output piecemeal lets use the same approach as the plugin disas interface to build the disassembly string before printing it. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220929114231.583801-34-alex.bennee@linaro.org> --- disas.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/disas.c b/disas.c index e31438f349..f07b6e760b 100644 --- a/disas.c +++ b/disas.c @@ -239,7 +239,7 @@ void target_disas(FILE *out, CPUState *cpu, target_ulong code, } } -static int plugin_printf(FILE *stream, const char *fmt, ...) +static int gstring_printf(FILE *stream, const char *fmt, ...) { /* We abuse the FILE parameter to pass a GString. */ GString *s = (GString *)stream; @@ -270,7 +270,7 @@ char *plugin_disas(CPUState *cpu, uint64_t addr, size_t size) GString *ds = g_string_new(NULL); initialize_debug_target(&s, cpu); - s.info.fprintf_func = plugin_printf; + s.info.fprintf_func = gstring_printf; s.info.stream = (FILE *)ds; /* abuse this slot */ s.info.buffer_vma = addr; s.info.buffer_length = size; @@ -358,15 +358,19 @@ void monitor_disas(Monitor *mon, CPUState *cpu, { int count, i; CPUDebug s; + g_autoptr(GString) ds = g_string_new(""); initialize_debug_target(&s, cpu); - s.info.fprintf_func = qemu_fprintf; + s.info.fprintf_func = gstring_printf; + s.info.stream = (FILE *)ds; /* abuse this slot */ + if (is_physical) { s.info.read_memory_func = physical_read_memory; } s.info.buffer_vma = pc; if (s.info.cap_arch >= 0 && cap_disas_monitor(&s.info, pc, nb_insn)) { + monitor_puts(mon, ds->str); return; } @@ -376,13 +380,16 @@ void monitor_disas(Monitor *mon, CPUState *cpu, return; } - for(i = 0; i < nb_insn; i++) { - monitor_printf(mon, "0x" TARGET_FMT_lx ": ", pc); + for (i = 0; i < nb_insn; i++) { + g_string_append_printf(ds, "0x" TARGET_FMT_lx ": ", pc); count = s.info.print_insn(pc, &s.info); - monitor_printf(mon, "\n"); - if (count < 0) - break; + g_string_append_c(ds, '\n'); + if (count < 0) { + break; + } pc += count; } + + monitor_puts(mon, ds->str); } #endif From 90bbf9d9dbbbc3956fd0e9a641e724d210190757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:14 +0100 Subject: [PATCH 0856/1020] disas: use result of ->read_memory_func MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This gets especially confusing if you start plugging in host addresses from a trace and you wonder why the output keeps changing. Report when read_memory_func fails instead of blindly disassembling the buffer contents. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220929114231.583801-35-alex.bennee@linaro.org> --- disas.c | 18 ++++++------ disas/capstone.c | 71 ++++++++++++++++++++++++++++-------------------- 2 files changed, 51 insertions(+), 38 deletions(-) diff --git a/disas.c b/disas.c index f07b6e760b..94d3b45042 100644 --- a/disas.c +++ b/disas.c @@ -83,18 +83,18 @@ static int print_insn_objdump(bfd_vma pc, disassemble_info *info, const char *prefix) { int i, n = info->buffer_length; - uint8_t *buf = g_malloc(n); + g_autofree uint8_t *buf = g_malloc(n); - info->read_memory_func(pc, buf, n, info); - - for (i = 0; i < n; ++i) { - if (i % 32 == 0) { - info->fprintf_func(info->stream, "\n%s: ", prefix); + if (info->read_memory_func(pc, buf, n, info) == 0) { + for (i = 0; i < n; ++i) { + if (i % 32 == 0) { + info->fprintf_func(info->stream, "\n%s: ", prefix); + } + info->fprintf_func(info->stream, "%02x", buf[i]); } - info->fprintf_func(info->stream, "%02x", buf[i]); + } else { + info->fprintf_func(info->stream, "unable to read memory"); } - - g_free(buf); return n; } diff --git a/disas/capstone.c b/disas/capstone.c index 20bc8f9669..fe3efb0d3c 100644 --- a/disas/capstone.c +++ b/disas/capstone.c @@ -191,37 +191,43 @@ bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size) size_t tsize = MIN(sizeof(cap_buf) - csize, size); const uint8_t *cbuf = cap_buf; - info->read_memory_func(pc + csize, cap_buf + csize, tsize, info); - csize += tsize; - size -= tsize; + if (info->read_memory_func(pc + csize, cap_buf + csize, tsize, info) == 0) { + csize += tsize; + size -= tsize; - while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { - cap_dump_insn(info, insn); - } + while (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { + cap_dump_insn(info, insn); + } + + /* If the target memory is not consumed, go back for more... */ + if (size != 0) { + /* + * ... taking care to move any remaining fractional insn + * to the beginning of the buffer. + */ + if (csize != 0) { + memmove(cap_buf, cbuf, csize); + } + continue; + } - /* If the target memory is not consumed, go back for more... */ - if (size != 0) { /* - * ... taking care to move any remaining fractional insn - * to the beginning of the buffer. + * Since the target memory is consumed, we should not have + * a remaining fractional insn. */ if (csize != 0) { - memmove(cap_buf, cbuf, csize); + info->fprintf_func(info->stream, + "Disassembler disagrees with translator " + "over instruction decoding\n" + "Please report this to qemu-devel@nongnu.org\n"); } - continue; - } + break; - /* - * Since the target memory is consumed, we should not have - * a remaining fractional insn. - */ - if (csize != 0) { + } else { info->fprintf_func(info->stream, - "Disassembler disagrees with translator " - "over instruction decoding\n" - "Please report this to qemu-devel@nongnu.org\n"); + "0x%08" PRIx64 ": unable to read memory\n", pc); + break; } - break; } cs_close(&handle); @@ -286,16 +292,23 @@ bool cap_disas_monitor(disassemble_info *info, uint64_t pc, int count) /* Make certain that we can make progress. */ assert(tsize != 0); - info->read_memory_func(pc + csize, cap_buf + csize, tsize, info); - csize += tsize; + if (info->read_memory_func(pc + csize, cap_buf + csize, + tsize, info) == 0) + { + csize += tsize; - if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { - cap_dump_insn(info, insn); - if (--count <= 0) { - break; + if (cs_disasm_iter(handle, &cbuf, &csize, &pc, insn)) { + cap_dump_insn(info, insn); + if (--count <= 0) { + break; + } } + memmove(cap_buf, cbuf, csize); + } else { + info->fprintf_func(info->stream, + "0x%08" PRIx64 ": unable to read memory\n", pc); + break; } - memmove(cap_buf, cbuf, csize); } cs_close(&handle); From b7855bf65f5bed868b06d6492a6d8a174f6cb71b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:15 +0100 Subject: [PATCH 0857/1020] plugins: extend execlog to filter matches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes the whole execlog is just two much so add the ability to filter by instruction opcode or address. [AJB: this shows for example qemu-system-aarch64 -display none -serial mon:stdio \ -M virt -cpu max \ -semihosting-config enable=on \ -kernel ./tests/tcg/aarch64-softmmu/memory-sve \ -plugin ./contrib/plugins/libexeclog.so,ifilter=st1w,afilter=0x40001808 -d plugin -D plugin.out the st1w SVE instruction is not instrumenting its stores.] Signed-off-by: Alex BennĂ©e Reviewed-by: Alexandre Iooss Cc: Robert Henry Cc: Aaron Lindsay Message-Id: <20220929114231.583801-36-alex.bennee@linaro.org> --- contrib/plugins/execlog.c | 96 ++++++++++++++++++++++++++++++++------ docs/devel/tcg-plugins.rst | 9 +++- 2 files changed, 90 insertions(+), 15 deletions(-) diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index a5275dcc15..e659ac9cbb 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -20,6 +20,9 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION; /* Store last executed instruction on each vCPU as a GString */ GArray *last_exec; +static GPtrArray *imatches; +static GArray *amatches; + /** * Add memory read or write information to current instruction log */ @@ -85,12 +88,13 @@ static void vcpu_insn_exec(unsigned int cpu_index, void *udata) static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) { struct qemu_plugin_insn *insn; - uint64_t insn_vaddr; - uint32_t insn_opcode; - char *insn_disas; + bool skip = (imatches || amatches) ? true : false; size_t n = qemu_plugin_tb_n_insns(tb); for (size_t i = 0; i < n; i++) { + char *insn_disas; + uint64_t insn_vaddr; + /* * `insn` is shared between translations in QEMU, copy needed data here. * `output` is never freed as it might be used multiple times during @@ -99,20 +103,52 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) * a limitation for CISC architectures. */ insn = qemu_plugin_tb_get_insn(tb, i); - insn_vaddr = qemu_plugin_insn_vaddr(insn); - insn_opcode = *((uint32_t *)qemu_plugin_insn_data(insn)); insn_disas = qemu_plugin_insn_disas(insn); - char *output = g_strdup_printf("0x%"PRIx64", 0x%"PRIx32", \"%s\"", - insn_vaddr, insn_opcode, insn_disas); + insn_vaddr = qemu_plugin_insn_vaddr(insn); - /* Register callback on memory read or write */ - qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem, - QEMU_PLUGIN_CB_NO_REGS, - QEMU_PLUGIN_MEM_RW, NULL); + /* + * If we are filtering we better check out if we have any + * hits. The skip "latches" so we can track memory accesses + * after the instruction we care about. + */ + if (skip && imatches) { + int j; + for (j = 0; j < imatches->len && skip; j++) { + char *m = g_ptr_array_index(imatches, j); + if (g_str_has_prefix(insn_disas, m)) { + skip = false; + } + } + } + + if (skip && amatches) { + int j; + for (j = 0; j < amatches->len && skip; j++) { + uint64_t v = g_array_index(amatches, uint64_t, j); + if (v == insn_vaddr) { + skip = false; + } + } + } + + if (skip) { + g_free(insn_disas); + } else { + uint32_t insn_opcode; + insn_opcode = *((uint32_t *)qemu_plugin_insn_data(insn)); + char *output = g_strdup_printf("0x%"PRIx64", 0x%"PRIx32", \"%s\"", + insn_vaddr, insn_opcode, insn_disas); + + /* Register callback on memory read or write */ + qemu_plugin_register_vcpu_mem_cb(insn, vcpu_mem, + QEMU_PLUGIN_CB_NO_REGS, + QEMU_PLUGIN_MEM_RW, NULL); + + /* Register callback on instruction */ + qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec, + QEMU_PLUGIN_CB_NO_REGS, output); + } - /* Register callback on instruction */ - qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec, - QEMU_PLUGIN_CB_NO_REGS, output); } } @@ -132,6 +168,25 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) } } +/* Add a match to the array of matches */ +static void parse_insn_match(char *match) +{ + if (!imatches) { + imatches = g_ptr_array_new(); + } + g_ptr_array_add(imatches, match); +} + +static void parse_vaddr_match(char *match) +{ + uint64_t v = g_ascii_strtoull(match, NULL, 16); + + if (!amatches) { + amatches = g_array_new(false, true, sizeof(uint64_t)); + } + g_array_append_val(amatches, v); +} + /** * Install the plugin */ @@ -145,6 +200,19 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id, */ last_exec = g_array_new(FALSE, FALSE, sizeof(GString *)); + for (int i = 0; i < argc; i++) { + char *opt = argv[i]; + g_autofree char **tokens = g_strsplit(opt, "=", 2); + if (g_strcmp0(tokens[0], "ifilter") == 0) { + parse_insn_match(tokens[1]); + } else if (g_strcmp0(tokens[0], "afilter") == 0) { + parse_vaddr_match(tokens[1]); + } else { + fprintf(stderr, "option parsing failed: %s\n", opt); + return -1; + } + } + /* Register translation block and exit callbacks */ qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans); qemu_plugin_register_atexit_cb(id, plugin_exit, NULL); diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index a7cc44aa20..a503d44cee 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -346,7 +346,7 @@ The execlog tool traces executed instructions with memory access. It can be used for debugging and security analysis purposes. Please be aware that this will generate a lot of output. -The plugin takes no argument:: +The plugin needs default argument:: qemu-system-arm $(QEMU_ARGS) \ -plugin ./contrib/plugins/libexeclog.so -d plugin @@ -364,6 +364,13 @@ which will output an execution trace following this structure:: 0, 0xd34, 0xf9c8f000, "bl #0x10c8" 0, 0x10c8, 0xfff96c43, "ldr r3, [r0, #0x44]", load, 0x200000e4, RAM +the output can be filtered to only track certain instructions or +addresses using the `ifilter` or `afilter` options. You can stack the +arguments if required:: + + qemu-system-arm $(QEMU_ARGS) \ + -plugin ./contrib/plugins/libexeclog.so,ifilter=st1w,afilter=0x40001808 -d plugin + - contrib/plugins/cache.c Cache modelling plugin that measures the performance of a given L1 cache From 5413c37f3b2acdae53c19ed16632c723fc93f109 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Thu, 29 Sep 2022 12:42:16 +0100 Subject: [PATCH 0858/1020] plugins: Assert mmu_idx in range before use in qemu_plugin_get_hwaddr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Coverity reports out-of-bound accesses here. This should be a false positive due to how the index is decoded from MemOpIdx. Fixes: Coverity CID 1487201 Signed-off-by: Richard Henderson Reviewed-by: Damien Hedde Message-Id: <20220401190233.329360-1-richard.henderson@linaro.org> Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220929114231.583801-37-alex.bennee@linaro.org> --- plugins/api.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/api.c b/plugins/api.c index 7bf71b189d..2078b16edb 100644 --- a/plugins/api.c +++ b/plugins/api.c @@ -289,6 +289,8 @@ struct qemu_plugin_hwaddr *qemu_plugin_get_hwaddr(qemu_plugin_meminfo_t info, enum qemu_plugin_mem_rw rw = get_plugin_meminfo_rw(info); hwaddr_info.is_store = (rw & QEMU_PLUGIN_MEM_W) != 0; + assert(mmu_idx < NB_MMU_MODES); + if (!tlb_plugin_lookup(cpu, vaddr, mmu_idx, hwaddr_info.is_store, &hwaddr_info)) { error_report("invalid use of qemu_plugin_get_hwaddr"); From 1d0603a990b4363ec7680bd99a249f43ad42cc21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:17 +0100 Subject: [PATCH 0859/1020] docs/devel: clean-up qemu invocations in tcg-plugins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We currently have the final binaries in the root of the build dir so the build prefix is superfluous. Additionally add a shell prompt to be more in line with the rest of the code. Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220929114231.583801-38-alex.bennee@linaro.org> --- docs/devel/tcg-plugins.rst | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index a503d44cee..a6fdde01f8 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -172,7 +172,7 @@ slightly faster (but not thread safe) counters. Example:: - ./aarch64-linux-user/qemu-aarch64 \ + $ qemu-aarch64 \ -plugin contrib/plugins/libhotblocks.so -d plugin \ ./tests/tcg/aarch64-linux-user/sha1 SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6 @@ -186,7 +186,7 @@ Example:: Similar to hotblocks but this time tracks memory accesses:: - ./aarch64-linux-user/qemu-aarch64 \ + $ qemu-aarch64 \ -plugin contrib/plugins/libhotpages.so -d plugin \ ./tests/tcg/aarch64-linux-user/sha1 SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6 @@ -220,7 +220,7 @@ counted. You can give a value to the ``count`` argument for a class of instructions to break it down fully, so for example to see all the system registers accesses:: - ./aarch64-softmmu/qemu-system-aarch64 $(QEMU_ARGS) \ + $ qemu-system-aarch64 $(QEMU_ARGS) \ -append "root=/dev/sda2 systemd.unit=benchmark.service" \ -smp 4 -plugin ./contrib/plugins/libhowvec.so,count=sreg -d plugin @@ -288,10 +288,10 @@ for the plugin is a path for the socket the two instances will communicate over:: - ./sparc-softmmu/qemu-system-sparc -monitor none -parallel none \ + $ qemu-system-sparc -monitor none -parallel none \ -net none -M SS-20 -m 256 -kernel day11/zImage.elf \ -plugin ./contrib/plugins/liblockstep.so,sockpath=lockstep-sparc.sock \ - -d plugin,nochain + -d plugin,nochain which will eventually report:: @@ -348,7 +348,7 @@ Please be aware that this will generate a lot of output. The plugin needs default argument:: - qemu-system-arm $(QEMU_ARGS) \ + $ qemu-system-arm $(QEMU_ARGS) \ -plugin ./contrib/plugins/libexeclog.so -d plugin which will output an execution trace following this structure:: @@ -365,10 +365,10 @@ which will output an execution trace following this structure:: 0, 0x10c8, 0xfff96c43, "ldr r3, [r0, #0x44]", load, 0x200000e4, RAM the output can be filtered to only track certain instructions or -addresses using the `ifilter` or `afilter` options. You can stack the +addresses using the ``ifilter`` or ``afilter`` options. You can stack the arguments if required:: - qemu-system-arm $(QEMU_ARGS) \ + $ qemu-system-arm $(QEMU_ARGS) \ -plugin ./contrib/plugins/libexeclog.so,ifilter=st1w,afilter=0x40001808 -d plugin - contrib/plugins/cache.c @@ -377,7 +377,7 @@ Cache modelling plugin that measures the performance of a given L1 cache configuration, and optionally a unified L2 per-core cache when a given working set is run:: - qemu-x86_64 -plugin ./contrib/plugins/libcache.so \ + $ qemu-x86_64 -plugin ./contrib/plugins/libcache.so \ -d plugin -D cache.log ./tests/tcg/x86_64-linux-user/float_convs will report the following:: From 7f522743dfcea095fe77755386e980cbb5db4ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:18 +0100 Subject: [PATCH 0860/1020] docs/devel: move API to end of tcg-plugins.rst MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API documentation is quite dry and doesn't flow nicely with the rest of the document. Move it to its own section at the bottom along with a little leader text to remind people to update it. Signed-off-by: Alex BennĂ©e Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220929114231.583801-39-alex.bennee@linaro.org> --- docs/devel/tcg-plugins.rst | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index a6fdde01f8..8b40b2a606 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -110,11 +110,6 @@ details are opaque to plugins. The plugin is able to query select details of instructions and system configuration only through the exported *qemu_plugin* functions. -API -~~~ - -.. kernel-doc:: include/qemu/qemu-plugin.h - Internals --------- @@ -448,3 +443,13 @@ The plugin has a number of arguments, all of them are optional: associativity of the L2 cache, respectively. Setting any of the L2 configuration arguments implies ``l2=on``. (default: N = 2097152 (2MB), B = 64, A = 16) + +API +--- + +The following API is generated from the inline documentation in +``include/qemu/qemu-plugin.h``. Please ensure any updates to the API +include the full kernel-doc annotations. + +.. kernel-doc:: include/qemu/qemu-plugin.h + From 8c1f1020d6e7dd329f5cf0cd8fd108dfb224eaec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:19 +0100 Subject: [PATCH 0861/1020] contrib/plugins: reset skip when matching in execlog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The purpose of the matches was to only track the execution of instructions we care about. Without resetting skip to the value at the start of the block we end up dumping all instructions after the match with the consequent load on the instrumentation. Signed-off-by: Alex BennĂ©e Cc: Alexandre Iooss Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220929114231.583801-40-alex.bennee@linaro.org> --- contrib/plugins/execlog.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/contrib/plugins/execlog.c b/contrib/plugins/execlog.c index e659ac9cbb..1b3bb7ebba 100644 --- a/contrib/plugins/execlog.c +++ b/contrib/plugins/execlog.c @@ -88,7 +88,7 @@ static void vcpu_insn_exec(unsigned int cpu_index, void *udata) static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) { struct qemu_plugin_insn *insn; - bool skip = (imatches || amatches) ? true : false; + bool skip = (imatches || amatches); size_t n = qemu_plugin_tb_n_insns(tb); for (size_t i = 0; i < n; i++) { @@ -147,6 +147,9 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) /* Register callback on instruction */ qemu_plugin_register_vcpu_insn_exec_cb(insn, vcpu_insn_exec, QEMU_PLUGIN_CB_NO_REGS, output); + + /* reset skip */ + skip = (imatches || amatches); } } From 59195c6558913dcc6ec6d8cfb71f0461a7769174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:20 +0100 Subject: [PATCH 0862/1020] docs/devel: document the test plugins MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although the test plugins are fairly basic they are still useful for some things so we should document their existence. Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-41-alex.bennee@linaro.org> --- docs/devel/tcg-plugins.rst | 137 +++++++++++++++++++++++++++++++++++-- 1 file changed, 133 insertions(+), 4 deletions(-) diff --git a/docs/devel/tcg-plugins.rst b/docs/devel/tcg-plugins.rst index 8b40b2a606..9740a70406 100644 --- a/docs/devel/tcg-plugins.rst +++ b/docs/devel/tcg-plugins.rst @@ -145,12 +145,141 @@ Example Plugins There are a number of plugins included with QEMU and you are encouraged to contribute your own plugins plugins upstream. There is a -``contrib/plugins`` directory where they can go. +``contrib/plugins`` directory where they can go. There are also some +basic plugins that are used to test and exercise the API during the +``make check-tcg`` target in ``tests\plugins``. -- tests/plugins +- tests/plugins/empty.c -These are some basic plugins that are used to test and exercise the -API during the ``make check-tcg`` target. +Purely a test plugin for measuring the overhead of the plugins system +itself. Does no instrumentation. + +- tests/plugins/bb.c + +A very basic plugin which will measure execution in course terms as +each basic block is executed. By default the results are shown once +execution finishes:: + + $ qemu-aarch64 -plugin tests/plugin/libbb.so \ + -d plugin ./tests/tcg/aarch64-linux-user/sha1 + SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6 + bb's: 2277338, insns: 158483046 + +Behaviour can be tweaked with the following arguments: + + * inline=true|false + + Use faster inline addition of a single counter. Not per-cpu and not + thread safe. + + * idle=true|false + + Dump the current execution stats whenever the guest vCPU idles + +- tests/plugins/insn.c + +This is a basic instruction level instrumentation which can count the +number of instructions executed on each core/thread:: + + $ qemu-aarch64 -plugin tests/plugin/libinsn.so \ + -d plugin ./tests/tcg/aarch64-linux-user/threadcount + Created 10 threads + Done + cpu 0 insns: 46765 + cpu 1 insns: 3694 + cpu 2 insns: 3694 + cpu 3 insns: 2994 + cpu 4 insns: 1497 + cpu 5 insns: 1497 + cpu 6 insns: 1497 + cpu 7 insns: 1497 + total insns: 63135 + +Behaviour can be tweaked with the following arguments: + + * inline=true|false + + Use faster inline addition of a single counter. Not per-cpu and not + thread safe. + + * sizes=true|false + + Give a summary of the instruction sizes for the execution + + * match= + + Only instrument instructions matching the string prefix. Will show + some basic stats including how many instructions have executed since + the last execution. For example:: + + $ qemu-aarch64 -plugin tests/plugin/libinsn.so,match=bl \ + -d plugin ./tests/tcg/aarch64-linux-user/sha512-vector + ... + 0x40069c, 'bl #0x4002b0', 10 hits, 1093 match hits, Δ+1257 since last match, 98 avg insns/match + 0x4006ac, 'bl #0x403690', 10 hits, 1094 match hits, Δ+47 since last match, 98 avg insns/match + 0x4037fc, 'bl #0x4002b0', 18 hits, 1095 match hits, Δ+22 since last match, 98 avg insns/match + 0x400720, 'bl #0x403690', 10 hits, 1096 match hits, Δ+58 since last match, 98 avg insns/match + 0x4037fc, 'bl #0x4002b0', 19 hits, 1097 match hits, Δ+22 since last match, 98 avg insns/match + 0x400730, 'bl #0x403690', 10 hits, 1098 match hits, Δ+33 since last match, 98 avg insns/match + 0x4037ac, 'bl #0x4002b0', 12 hits, 1099 match hits, Δ+20 since last match, 98 avg insns/match + ... + +For more detailed execution tracing see the ``execlog`` plugin for +other options. + +- tests/plugins/mem.c + +Basic instruction level memory instrumentation:: + + $ qemu-aarch64 -plugin tests/plugin/libmem.so,inline=true \ + -d plugin ./tests/tcg/aarch64-linux-user/sha1 + SHA1=15dd99a1991e0b3826fede3deffc1feba42278e6 + inline mem accesses: 79525013 + +Behaviour can be tweaked with the following arguments: + + * inline=true|false + + Use faster inline addition of a single counter. Not per-cpu and not + thread safe. + + * callback=true|false + + Use callbacks on each memory instrumentation. + + * hwaddr=true|false + + Count IO accesses (only for system emulation) + +- tests/plugins/syscall.c + +A basic syscall tracing plugin. This only works for user-mode. By +default it will give a summary of syscall stats at the end of the +run:: + + $ qemu-aarch64 -plugin tests/plugin/libsyscall \ + -d plugin ./tests/tcg/aarch64-linux-user/threadcount + Created 10 threads + Done + syscall no. calls errors + 226 12 0 + 99 11 11 + 115 11 0 + 222 11 0 + 93 10 0 + 220 10 0 + 233 10 0 + 215 8 0 + 214 4 0 + 134 2 0 + 64 2 0 + 96 1 0 + 94 1 0 + 80 1 0 + 261 1 0 + 78 1 0 + 160 1 0 + 135 1 0 - contrib/plugins/hotblocks.c From 424d5ecf520621e9b9bd802995558f83bd0e37af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:21 +0100 Subject: [PATCH 0863/1020] semihosting: update link to spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The old link has moved but it seems the document is now hosted on Arm's github along with a license update to CC-BY-SA-4.0. Signed-off-by: Alex BennĂ©e Reviewed-by: Richard Henderson Message-Id: <20220929114231.583801-42-alex.bennee@linaro.org> --- semihosting/arm-compat-semi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c index e741674238..bfea9e9337 100644 --- a/semihosting/arm-compat-semi.c +++ b/semihosting/arm-compat-semi.c @@ -24,7 +24,7 @@ * * ARM Semihosting is documented in: * Semihosting for AArch32 and AArch64 Release 2.0 - * https://static.docs.arm.com/100863/0200/semihosting.pdf + * https://github.com/ARM-software/abi-aa/blob/main/semihosting/semihosting.rst * * RISC-V Semihosting is documented in: * RISC-V Semihosting From 842b42df2b5d3bf5ccbafba19dc756d531dcce23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:22 +0100 Subject: [PATCH 0864/1020] gdbstub: move into its own sub directory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is in preparation of future refactoring as well as cleaning up the source tree. Aside from the minor tweaks to meson and trace.h this is pure code motion. Reviewed-by: Richard Henderson Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-43-alex.bennee@linaro.org> --- MAINTAINERS | 2 +- gdbstub.c => gdbstub/gdbstub.c | 2 +- gdbstub/meson.build | 1 + gdbstub/trace-events | 29 +++++++++++++++++++++++++++++ gdbstub/trace.h | 1 + meson.build | 4 +++- trace-events | 28 ---------------------------- 7 files changed, 36 insertions(+), 31 deletions(-) rename gdbstub.c => gdbstub/gdbstub.c (99%) create mode 100644 gdbstub/meson.build create mode 100644 gdbstub/trace-events create mode 100644 gdbstub/trace.h diff --git a/MAINTAINERS b/MAINTAINERS index 789172b2a8..e1530b51a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2677,7 +2677,7 @@ GDB stub M: Alex BennĂ©e R: Philippe Mathieu-DaudĂ© S: Maintained -F: gdbstub* +F: gdbstub/* F: include/exec/gdbstub.h F: gdb-xml/ F: tests/tcg/multiarch/gdbstub/ diff --git a/gdbstub.c b/gdbstub/gdbstub.c similarity index 99% rename from gdbstub.c rename to gdbstub/gdbstub.c index cf869b10e3..7d8fe475b3 100644 --- a/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -29,7 +29,7 @@ #include "qemu/ctype.h" #include "qemu/cutils.h" #include "qemu/module.h" -#include "trace/trace-root.h" +#include "trace.h" #include "exec/gdbstub.h" #ifdef CONFIG_USER_ONLY #include "qemu.h" diff --git a/gdbstub/meson.build b/gdbstub/meson.build new file mode 100644 index 0000000000..6d4ae2d03c --- /dev/null +++ b/gdbstub/meson.build @@ -0,0 +1 @@ +specific_ss.add(files('gdbstub.c')) diff --git a/gdbstub/trace-events b/gdbstub/trace-events new file mode 100644 index 0000000000..03f0c303bf --- /dev/null +++ b/gdbstub/trace-events @@ -0,0 +1,29 @@ +# See docs/devel/tracing.rst for syntax documentation. + +# gdbstub.c +gdbstub_op_start(const char *device) "Starting gdbstub using device %s" +gdbstub_op_exiting(uint8_t code) "notifying exit with code=0x%02x" +gdbstub_op_continue(void) "Continuing all CPUs" +gdbstub_op_continue_cpu(int cpu_index) "Continuing CPU %d" +gdbstub_op_stepping(int cpu_index) "Stepping CPU %d" +gdbstub_op_extra_info(const char *info) "Thread extra info: %s" +gdbstub_hit_watchpoint(const char *type, int cpu_gdb_index, uint64_t vaddr) "Watchpoint hit, type=\"%s\" cpu=%d, vaddr=0x%" PRIx64 "" +gdbstub_hit_internal_error(void) "RUN_STATE_INTERNAL_ERROR" +gdbstub_hit_break(void) "RUN_STATE_DEBUG" +gdbstub_hit_paused(void) "RUN_STATE_PAUSED" +gdbstub_hit_shutdown(void) "RUN_STATE_SHUTDOWN" +gdbstub_hit_io_error(void) "RUN_STATE_IO_ERROR" +gdbstub_hit_watchdog(void) "RUN_STATE_WATCHDOG" +gdbstub_hit_unknown(int state) "Unknown run state=0x%x" +gdbstub_io_reply(const char *message) "Sent: %s" +gdbstub_io_binaryreply(size_t ofs, const char *line) "0x%04zx: %s" +gdbstub_io_command(const char *command) "Received: %s" +gdbstub_io_got_ack(void) "Got ACK" +gdbstub_io_got_unexpected(uint8_t ch) "Got 0x%02x when expecting ACK/NACK" +gdbstub_err_got_nack(void) "Got NACK, retransmitting" +gdbstub_err_garbage(uint8_t ch) "received garbage between packets: 0x%02x" +gdbstub_err_overrun(void) "command buffer overrun, dropping command" +gdbstub_err_invalid_repeat(uint8_t ch) "got invalid RLE count: 0x%02x" +gdbstub_err_invalid_rle(void) "got invalid RLE sequence" +gdbstub_err_checksum_invalid(uint8_t ch) "got invalid command checksum digit: 0x%02x" +gdbstub_err_checksum_incorrect(uint8_t expected, uint8_t got) "got command packet with incorrect checksum, expected=0x%02x, received=0x%02x" diff --git a/gdbstub/trace.h b/gdbstub/trace.h new file mode 100644 index 0000000000..dee87b1238 --- /dev/null +++ b/gdbstub/trace.h @@ -0,0 +1 @@ +#include "trace/trace-gdbstub.h" diff --git a/meson.build b/meson.build index 536e819c60..b686dfef75 100644 --- a/meson.build +++ b/meson.build @@ -2863,6 +2863,7 @@ trace_events_subdirs = [ 'qom', 'monitor', 'util', + 'gdbstub', ] if have_linux_user trace_events_subdirs += [ 'linux-user' ] @@ -2986,6 +2987,7 @@ subdir('authz') subdir('crypto') subdir('ui') subdir('hw') +subdir('gdbstub') if enable_modules @@ -3063,7 +3065,7 @@ common_ss.add(files('cpus-common.c')) subdir('softmmu') common_ss.add(capstone) -specific_ss.add(files('cpu.c', 'disas.c', 'gdbstub.c'), capstone) +specific_ss.add(files('cpu.c', 'disas.c'), capstone) # Work around a gcc bug/misfeature wherein constant propagation looks # through an alias: diff --git a/trace-events b/trace-events index bc71006675..035f3d570d 100644 --- a/trace-events +++ b/trace-events @@ -46,34 +46,6 @@ ram_block_discard_range(const char *rbname, void *hva, size_t length, bool need_ memory_notdirty_write_access(uint64_t vaddr, uint64_t ram_addr, unsigned size) "0x%" PRIx64 " ram_addr 0x%" PRIx64 " size %u" memory_notdirty_set_dirty(uint64_t vaddr) "0x%" PRIx64 -# gdbstub.c -gdbstub_op_start(const char *device) "Starting gdbstub using device %s" -gdbstub_op_exiting(uint8_t code) "notifying exit with code=0x%02x" -gdbstub_op_continue(void) "Continuing all CPUs" -gdbstub_op_continue_cpu(int cpu_index) "Continuing CPU %d" -gdbstub_op_stepping(int cpu_index) "Stepping CPU %d" -gdbstub_op_extra_info(const char *info) "Thread extra info: %s" -gdbstub_hit_watchpoint(const char *type, int cpu_gdb_index, uint64_t vaddr) "Watchpoint hit, type=\"%s\" cpu=%d, vaddr=0x%" PRIx64 "" -gdbstub_hit_internal_error(void) "RUN_STATE_INTERNAL_ERROR" -gdbstub_hit_break(void) "RUN_STATE_DEBUG" -gdbstub_hit_paused(void) "RUN_STATE_PAUSED" -gdbstub_hit_shutdown(void) "RUN_STATE_SHUTDOWN" -gdbstub_hit_io_error(void) "RUN_STATE_IO_ERROR" -gdbstub_hit_watchdog(void) "RUN_STATE_WATCHDOG" -gdbstub_hit_unknown(int state) "Unknown run state=0x%x" -gdbstub_io_reply(const char *message) "Sent: %s" -gdbstub_io_binaryreply(size_t ofs, const char *line) "0x%04zx: %s" -gdbstub_io_command(const char *command) "Received: %s" -gdbstub_io_got_ack(void) "Got ACK" -gdbstub_io_got_unexpected(uint8_t ch) "Got 0x%02x when expecting ACK/NACK" -gdbstub_err_got_nack(void) "Got NACK, retransmitting" -gdbstub_err_garbage(uint8_t ch) "received garbage between packets: 0x%02x" -gdbstub_err_overrun(void) "command buffer overrun, dropping command" -gdbstub_err_invalid_repeat(uint8_t ch) "got invalid RLE count: 0x%02x" -gdbstub_err_invalid_rle(void) "got invalid RLE sequence" -gdbstub_err_checksum_invalid(uint8_t ch) "got invalid command checksum digit: 0x%02x" -gdbstub_err_checksum_incorrect(uint8_t expected, uint8_t got) "got command packet with incorrect checksum, expected=0x%02x, received=0x%02x" - # job.c job_state_transition(void *job, int ret, const char *legal, const char *s0, const char *s1) "job %p (ret: %d) attempting %s transition (%s-->%s)" job_apply_verb(void *job, const char *state, const char *verb, const char *legal) "job %p in state %s; applying verb %s (%s)" From 3b7a93880a88fb2e3c0e71378a7d39d25103d734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:23 +0100 Subject: [PATCH 0865/1020] gdbstub: move sstep flags probing into AccelClass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The support of single-stepping is very much dependent on support from the accelerator we are using. To avoid special casing in gdbstub move the probing out to an AccelClass function so future accelerators can put their code there. Reviewed-by: Richard Henderson Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Alex BennĂ©e Reviewed-by: Mads Ynddal Message-Id: <20220929114231.583801-44-alex.bennee@linaro.org> --- accel/accel-common.c | 10 ++++++++++ accel/kvm/kvm-all.c | 14 +++++++++++++- accel/tcg/tcg-all.c | 17 +++++++++++++++++ gdbstub/gdbstub.c | 22 ++++------------------ include/qemu/accel.h | 12 ++++++++++++ include/sysemu/kvm.h | 8 -------- 6 files changed, 56 insertions(+), 27 deletions(-) diff --git a/accel/accel-common.c b/accel/accel-common.c index 50035bda55..df72cc989a 100644 --- a/accel/accel-common.c +++ b/accel/accel-common.c @@ -129,6 +129,16 @@ bool accel_cpu_realizefn(CPUState *cpu, Error **errp) return true; } +int accel_supported_gdbstub_sstep_flags(void) +{ + AccelState *accel = current_accel(); + AccelClass *acc = ACCEL_GET_CLASS(accel); + if (acc->gdbstub_supported_sstep_flags) { + return acc->gdbstub_supported_sstep_flags(); + } + return 0; +} + static const TypeInfo accel_cpu_type = { .name = TYPE_ACCEL_CPU, .parent = TYPE_OBJECT, diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 5acab1767f..c55938453a 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -175,7 +175,7 @@ bool kvm_direct_msi_allowed; bool kvm_ioeventfd_any_length_allowed; bool kvm_msi_use_devid; bool kvm_has_guest_debug; -int kvm_sstep_flags; +static int kvm_sstep_flags; static bool kvm_immediate_exit; static hwaddr kvm_max_slot_size = ~0; @@ -3712,6 +3712,17 @@ static void kvm_accel_instance_init(Object *obj) s->kvm_dirty_ring_size = 0; } +/** + * kvm_gdbstub_sstep_flags(): + * + * Returns: SSTEP_* flags that KVM supports for guest debug. The + * support is probed during kvm_init() + */ +static int kvm_gdbstub_sstep_flags(void) +{ + return kvm_sstep_flags; +} + static void kvm_accel_class_init(ObjectClass *oc, void *data) { AccelClass *ac = ACCEL_CLASS(oc); @@ -3719,6 +3730,7 @@ static void kvm_accel_class_init(ObjectClass *oc, void *data) ac->init_machine = kvm_init; ac->has_memory = kvm_accel_has_memory; ac->allowed = &kvm_allowed; + ac->gdbstub_supported_sstep_flags = kvm_gdbstub_sstep_flags; object_class_property_add(oc, "kernel-irqchip", "on|off|split", NULL, kvm_set_kernel_irqchip, diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c index 47952eecd7..30b503fb22 100644 --- a/accel/tcg/tcg-all.c +++ b/accel/tcg/tcg-all.c @@ -25,6 +25,7 @@ #include "qemu/osdep.h" #include "sysemu/tcg.h" +#include "sysemu/replay.h" #include "sysemu/cpu-timers.h" #include "tcg/tcg.h" #include "qapi/error.h" @@ -207,12 +208,28 @@ static void tcg_set_splitwx(Object *obj, bool value, Error **errp) s->splitwx_enabled = value; } +static int tcg_gdbstub_supported_sstep_flags(void) +{ + /* + * In replay mode all events will come from the log and can't be + * suppressed otherwise we would break determinism. However as those + * events are tied to the number of executed instructions we won't see + * them occurring every time we single step. + */ + if (replay_mode != REPLAY_MODE_NONE) { + return SSTEP_ENABLE; + } else { + return SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; + } +} + static void tcg_accel_class_init(ObjectClass *oc, void *data) { AccelClass *ac = ACCEL_CLASS(oc); ac->name = "tcg"; ac->init_machine = tcg_init_machine; ac->allowed = &tcg_allowed; + ac->gdbstub_supported_sstep_flags = tcg_gdbstub_supported_sstep_flags; object_class_property_add_str(oc, "thread", tcg_get_thread, diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index 7d8fe475b3..a0755e6505 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -383,27 +383,13 @@ static void init_gdbserver_state(void) gdbserver_state.last_packet = g_byte_array_sized_new(MAX_PACKET_LENGTH + 4); /* - * In replay mode all events will come from the log and can't be - * suppressed otherwise we would break determinism. However as those - * events are tied to the number of executed instructions we won't see - * them occurring every time we single step. - */ - if (replay_mode != REPLAY_MODE_NONE) { - gdbserver_state.supported_sstep_flags = SSTEP_ENABLE; - } else if (kvm_enabled()) { - gdbserver_state.supported_sstep_flags = kvm_get_supported_sstep_flags(); - } else { - gdbserver_state.supported_sstep_flags = - SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; - } - - /* - * By default use no IRQs and no timers while single stepping so as to - * make single stepping like an ICE HW step. + * What single-step modes are supported is accelerator dependent. + * By default try to use no IRQs and no timers while single + * stepping so as to make single stepping like a typical ICE HW step. */ + gdbserver_state.supported_sstep_flags = accel_supported_gdbstub_sstep_flags(); gdbserver_state.sstep_flags = SSTEP_ENABLE | SSTEP_NOIRQ | SSTEP_NOTIMER; gdbserver_state.sstep_flags &= gdbserver_state.supported_sstep_flags; - } #ifndef CONFIG_USER_ONLY diff --git a/include/qemu/accel.h b/include/qemu/accel.h index be56da1b99..ce4747634a 100644 --- a/include/qemu/accel.h +++ b/include/qemu/accel.h @@ -43,6 +43,10 @@ typedef struct AccelClass { bool (*has_memory)(MachineState *ms, AddressSpace *as, hwaddr start_addr, hwaddr size); #endif + + /* gdbstub related hooks */ + int (*gdbstub_supported_sstep_flags)(void); + bool *allowed; /* * Array of global properties that would be applied when specific @@ -92,4 +96,12 @@ void accel_cpu_instance_init(CPUState *cpu); */ bool accel_cpu_realizefn(CPUState *cpu, Error **errp); +/** + * accel_supported_gdbstub_sstep_flags: + * + * Returns the supported single step modes for the configured + * accelerator. + */ +int accel_supported_gdbstub_sstep_flags(void); + #endif /* QEMU_ACCEL_H */ diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index efd6dee818..a20ad51aad 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -47,7 +47,6 @@ extern bool kvm_direct_msi_allowed; extern bool kvm_ioeventfd_any_length_allowed; extern bool kvm_msi_use_devid; extern bool kvm_has_guest_debug; -extern int kvm_sstep_flags; #define kvm_enabled() (kvm_allowed) /** @@ -174,12 +173,6 @@ extern int kvm_sstep_flags; */ #define kvm_supports_guest_debug() (kvm_has_guest_debug) -/* - * kvm_supported_sstep_flags - * Returns: SSTEP_* flags that KVM supports for guest debug - */ -#define kvm_get_supported_sstep_flags() (kvm_sstep_flags) - #else #define kvm_enabled() (0) @@ -198,7 +191,6 @@ extern int kvm_sstep_flags; #define kvm_ioeventfd_any_length_enabled() (false) #define kvm_msi_devid_required() (false) #define kvm_supports_guest_debug() (false) -#define kvm_get_supported_sstep_flags() (0) #endif /* CONFIG_KVM_IS_POSSIBLE */ From ae7467b1ac49e10c548099e9f9c59af895af2d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:24 +0100 Subject: [PATCH 0866/1020] gdbstub: move breakpoint logic to accel ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As HW virtualization requires specific support to handle breakpoints lets push out special casing out of the core gdbstub code and into AccelOpsClass. This will make it easier to add other accelerator support and reduces some of the stub shenanigans. Reviewed-by: Richard Henderson Signed-off-by: Alex BennĂ©e Reviewed-by: Mads Ynddal Message-Id: <20220929114231.583801-45-alex.bennee@linaro.org> --- accel/kvm/kvm-accel-ops.c | 8 +++ accel/kvm/kvm-all.c | 24 +------ accel/kvm/kvm-cpus.h | 3 + accel/stubs/kvm-stub.c | 16 ----- accel/tcg/tcg-accel-ops.c | 92 +++++++++++++++++++++++++++ gdbstub/gdbstub.c | 127 +++---------------------------------- gdbstub/internals.h | 16 +++++ gdbstub/meson.build | 8 +++ gdbstub/softmmu.c | 42 ++++++++++++ gdbstub/user.c | 62 ++++++++++++++++++ include/sysemu/accel-ops.h | 6 ++ include/sysemu/cpus.h | 3 + include/sysemu/kvm.h | 5 -- softmmu/cpus.c | 7 ++ 14 files changed, 259 insertions(+), 160 deletions(-) create mode 100644 gdbstub/internals.h create mode 100644 gdbstub/softmmu.c create mode 100644 gdbstub/user.c diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c index c4244a23c6..5c0e37514c 100644 --- a/accel/kvm/kvm-accel-ops.c +++ b/accel/kvm/kvm-accel-ops.c @@ -16,12 +16,14 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "qemu/main-loop.h" +#include "sysemu/kvm.h" #include "sysemu/kvm_int.h" #include "sysemu/runstate.h" #include "sysemu/cpus.h" #include "qemu/guest-random.h" #include "qapi/error.h" +#include #include "kvm-cpus.h" static void *kvm_vcpu_thread_fn(void *arg) @@ -95,6 +97,12 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data) ops->synchronize_post_init = kvm_cpu_synchronize_post_init; ops->synchronize_state = kvm_cpu_synchronize_state; ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm; + +#ifdef KVM_CAP_SET_GUEST_DEBUG + ops->insert_breakpoint = kvm_insert_breakpoint; + ops->remove_breakpoint = kvm_remove_breakpoint; + ops->remove_all_breakpoints = kvm_remove_all_breakpoints; +#endif } static const TypeInfo kvm_accel_ops_type = { diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index c55938453a..b8c734fe3a 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3287,8 +3287,7 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) return data.err; } -int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, - target_ulong len, int type) +int kvm_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len) { struct kvm_sw_breakpoint *bp; int err; @@ -3326,8 +3325,7 @@ int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, return 0; } -int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr, - target_ulong len, int type) +int kvm_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len) { struct kvm_sw_breakpoint *bp; int err; @@ -3393,26 +3391,10 @@ void kvm_remove_all_breakpoints(CPUState *cpu) #else /* !KVM_CAP_SET_GUEST_DEBUG */ -int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) +static int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) { return -EINVAL; } - -int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, - target_ulong len, int type) -{ - return -EINVAL; -} - -int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr, - target_ulong len, int type) -{ - return -EINVAL; -} - -void kvm_remove_all_breakpoints(CPUState *cpu) -{ -} #endif /* !KVM_CAP_SET_GUEST_DEBUG */ static int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h index bf0bd1bee4..33e435d62b 100644 --- a/accel/kvm/kvm-cpus.h +++ b/accel/kvm/kvm-cpus.h @@ -18,5 +18,8 @@ void kvm_destroy_vcpu(CPUState *cpu); void kvm_cpu_synchronize_post_reset(CPUState *cpu); void kvm_cpu_synchronize_post_init(CPUState *cpu); void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); +int kvm_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len); +int kvm_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len); +void kvm_remove_all_breakpoints(CPUState *cpu); #endif /* KVM_CPUS_H */ diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index 2ac5f9c036..2d79333143 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -51,22 +51,6 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) return -ENOSYS; } -int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, - target_ulong len, int type) -{ - return -EINVAL; -} - -int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr, - target_ulong len, int type) -{ - return -EINVAL; -} - -void kvm_remove_all_breakpoints(CPUState *cpu) -{ -} - int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) { return 1; diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c index 786d90c08f..965c2ad581 100644 --- a/accel/tcg/tcg-accel-ops.c +++ b/accel/tcg/tcg-accel-ops.c @@ -32,6 +32,8 @@ #include "qemu/main-loop.h" #include "qemu/guest-random.h" #include "exec/exec-all.h" +#include "exec/hwaddr.h" +#include "exec/gdbstub.h" #include "tcg-accel-ops.h" #include "tcg-accel-ops-mttcg.h" @@ -91,6 +93,92 @@ void tcg_handle_interrupt(CPUState *cpu, int mask) } } +/* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */ +static inline int xlat_gdb_type(CPUState *cpu, int gdbtype) +{ + static const int xlat[] = { + [GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE, + [GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ, + [GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS, + }; + + CPUClass *cc = CPU_GET_CLASS(cpu); + int cputype = xlat[gdbtype]; + + if (cc->gdb_stop_before_watchpoint) { + cputype |= BP_STOP_BEFORE_ACCESS; + } + return cputype; +} + +static int tcg_insert_breakpoint(CPUState *cs, int type, hwaddr addr, hwaddr len) +{ + CPUState *cpu; + int err = 0; + + switch (type) { + case GDB_BREAKPOINT_SW: + case GDB_BREAKPOINT_HW: + CPU_FOREACH(cpu) { + err = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL); + if (err) { + break; + } + } + return err; + case GDB_WATCHPOINT_WRITE: + case GDB_WATCHPOINT_READ: + case GDB_WATCHPOINT_ACCESS: + CPU_FOREACH(cpu) { + err = cpu_watchpoint_insert(cpu, addr, len, + xlat_gdb_type(cpu, type), NULL); + if (err) { + break; + } + } + return err; + default: + return -ENOSYS; + } +} + +static int tcg_remove_breakpoint(CPUState *cs, int type, hwaddr addr, hwaddr len) +{ + CPUState *cpu; + int err = 0; + + switch (type) { + case GDB_BREAKPOINT_SW: + case GDB_BREAKPOINT_HW: + CPU_FOREACH(cpu) { + err = cpu_breakpoint_remove(cpu, addr, BP_GDB); + if (err) { + break; + } + } + return err; + case GDB_WATCHPOINT_WRITE: + case GDB_WATCHPOINT_READ: + case GDB_WATCHPOINT_ACCESS: + CPU_FOREACH(cpu) { + err = cpu_watchpoint_remove(cpu, addr, len, + xlat_gdb_type(cpu, type)); + if (err) { + break; + } + } + return err; + default: + return -ENOSYS; + } +} + +static inline void tcg_remove_all_breakpoints(CPUState *cpu) +{ + cpu_breakpoint_remove_all(cpu, BP_GDB); + cpu_watchpoint_remove_all(cpu, BP_GDB); +} + static void tcg_accel_ops_init(AccelOpsClass *ops) { if (qemu_tcg_mttcg_enabled()) { @@ -109,6 +197,10 @@ static void tcg_accel_ops_init(AccelOpsClass *ops) ops->handle_interrupt = tcg_handle_interrupt; } } + + ops->insert_breakpoint = tcg_insert_breakpoint; + ops->remove_breakpoint = tcg_remove_breakpoint; + ops->remove_all_breakpoints = tcg_remove_all_breakpoints; } static void tcg_accel_ops_class_init(ObjectClass *oc, void *data) diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index a0755e6505..ff9f3f9586 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -49,8 +49,11 @@ #include "sysemu/runstate.h" #include "semihosting/semihost.h" #include "exec/exec-all.h" +#include "exec/hwaddr.h" #include "sysemu/replay.h" +#include "internals.h" + #ifdef CONFIG_USER_ONLY #define GDB_ATTACHED "0" #else @@ -1012,130 +1015,16 @@ void gdb_register_coprocessor(CPUState *cpu, } } -#ifndef CONFIG_USER_ONLY -/* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */ -static inline int xlat_gdb_type(CPUState *cpu, int gdbtype) -{ - static const int xlat[] = { - [GDB_WATCHPOINT_WRITE] = BP_GDB | BP_MEM_WRITE, - [GDB_WATCHPOINT_READ] = BP_GDB | BP_MEM_READ, - [GDB_WATCHPOINT_ACCESS] = BP_GDB | BP_MEM_ACCESS, - }; - - CPUClass *cc = CPU_GET_CLASS(cpu); - int cputype = xlat[gdbtype]; - - if (cc->gdb_stop_before_watchpoint) { - cputype |= BP_STOP_BEFORE_ACCESS; - } - return cputype; -} -#endif - -static int gdb_breakpoint_insert(int type, target_ulong addr, target_ulong len) -{ - CPUState *cpu; - int err = 0; - - if (kvm_enabled()) { - return kvm_insert_breakpoint(gdbserver_state.c_cpu, addr, len, type); - } - - switch (type) { - case GDB_BREAKPOINT_SW: - case GDB_BREAKPOINT_HW: - CPU_FOREACH(cpu) { - err = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL); - if (err) { - break; - } - } - return err; -#ifndef CONFIG_USER_ONLY - case GDB_WATCHPOINT_WRITE: - case GDB_WATCHPOINT_READ: - case GDB_WATCHPOINT_ACCESS: - CPU_FOREACH(cpu) { - err = cpu_watchpoint_insert(cpu, addr, len, - xlat_gdb_type(cpu, type), NULL); - if (err) { - break; - } - } - return err; -#endif - default: - return -ENOSYS; - } -} - -static int gdb_breakpoint_remove(int type, target_ulong addr, target_ulong len) -{ - CPUState *cpu; - int err = 0; - - if (kvm_enabled()) { - return kvm_remove_breakpoint(gdbserver_state.c_cpu, addr, len, type); - } - - switch (type) { - case GDB_BREAKPOINT_SW: - case GDB_BREAKPOINT_HW: - CPU_FOREACH(cpu) { - err = cpu_breakpoint_remove(cpu, addr, BP_GDB); - if (err) { - break; - } - } - return err; -#ifndef CONFIG_USER_ONLY - case GDB_WATCHPOINT_WRITE: - case GDB_WATCHPOINT_READ: - case GDB_WATCHPOINT_ACCESS: - CPU_FOREACH(cpu) { - err = cpu_watchpoint_remove(cpu, addr, len, - xlat_gdb_type(cpu, type)); - if (err) - break; - } - return err; -#endif - default: - return -ENOSYS; - } -} - -static inline void gdb_cpu_breakpoint_remove_all(CPUState *cpu) -{ - cpu_breakpoint_remove_all(cpu, BP_GDB); -#ifndef CONFIG_USER_ONLY - cpu_watchpoint_remove_all(cpu, BP_GDB); -#endif -} - static void gdb_process_breakpoint_remove_all(GDBProcess *p) { CPUState *cpu = get_first_cpu_in_process(p); while (cpu) { - gdb_cpu_breakpoint_remove_all(cpu); + gdb_breakpoint_remove_all(cpu); cpu = gdb_next_cpu_in_process(cpu); } } -static void gdb_breakpoint_remove_all(void) -{ - CPUState *cpu; - - if (kvm_enabled()) { - kvm_remove_all_breakpoints(gdbserver_state.c_cpu); - return; - } - - CPU_FOREACH(cpu) { - gdb_cpu_breakpoint_remove_all(cpu); - } -} static void gdb_set_cpu_pc(target_ulong pc) { @@ -1667,7 +1556,8 @@ static void handle_insert_bp(GArray *params, void *user_ctx) return; } - res = gdb_breakpoint_insert(get_param(params, 0)->val_ul, + res = gdb_breakpoint_insert(gdbserver_state.c_cpu, + get_param(params, 0)->val_ul, get_param(params, 1)->val_ull, get_param(params, 2)->val_ull); if (res >= 0) { @@ -1690,7 +1580,8 @@ static void handle_remove_bp(GArray *params, void *user_ctx) return; } - res = gdb_breakpoint_remove(get_param(params, 0)->val_ul, + res = gdb_breakpoint_remove(gdbserver_state.c_cpu, + get_param(params, 0)->val_ul, get_param(params, 1)->val_ull, get_param(params, 2)->val_ull); if (res >= 0) { @@ -2541,7 +2432,7 @@ static void handle_target_halt(GArray *params, void *user_ctx) * because gdb is doing an initial connect and the state * should be cleaned up. */ - gdb_breakpoint_remove_all(); + gdb_breakpoint_remove_all(gdbserver_state.c_cpu); } static int gdb_handle_packet(const char *line_buf) diff --git a/gdbstub/internals.h b/gdbstub/internals.h new file mode 100644 index 0000000000..41e2e72dbf --- /dev/null +++ b/gdbstub/internals.h @@ -0,0 +1,16 @@ +/* + * gdbstub internals + * + * Copyright (c) 2022 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef _INTERNALS_H_ +#define _INTERNALS_H_ + +int gdb_breakpoint_insert(CPUState *cs, int type, hwaddr addr, hwaddr len); +int gdb_breakpoint_remove(CPUState *cs, int type, hwaddr addr, hwaddr len); +void gdb_breakpoint_remove_all(CPUState *cs); + +#endif /* _INTERNALS_H_ */ diff --git a/gdbstub/meson.build b/gdbstub/meson.build index 6d4ae2d03c..fc895a2c39 100644 --- a/gdbstub/meson.build +++ b/gdbstub/meson.build @@ -1 +1,9 @@ +# +# The main gdbstub still relies on per-build definitions of various +# types. The bits pushed to softmmu/user.c try to use guest agnostic +# types such as hwaddr. +# + specific_ss.add(files('gdbstub.c')) +softmmu_ss.add(files('softmmu.c')) +user_ss.add(files('user.c')) diff --git a/gdbstub/softmmu.c b/gdbstub/softmmu.c new file mode 100644 index 0000000000..4e73890379 --- /dev/null +++ b/gdbstub/softmmu.c @@ -0,0 +1,42 @@ +/* + * gdb server stub - softmmu specific bits + * + * Debug integration depends on support from the individual + * accelerators so most of this involves calling the ops helpers. + * + * Copyright (c) 2022 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "exec/gdbstub.h" +#include "exec/hwaddr.h" +#include "sysemu/cpus.h" +#include "internals.h" + +int gdb_breakpoint_insert(CPUState *cs, int type, hwaddr addr, hwaddr len) +{ + const AccelOpsClass *ops = cpus_get_accel(); + if (ops->insert_breakpoint) { + return ops->insert_breakpoint(cs, type, addr, len); + } + return -ENOSYS; +} + +int gdb_breakpoint_remove(CPUState *cs, int type, hwaddr addr, hwaddr len) +{ + const AccelOpsClass *ops = cpus_get_accel(); + if (ops->remove_breakpoint) { + return ops->remove_breakpoint(cs, type, addr, len); + } + return -ENOSYS; +} + +void gdb_breakpoint_remove_all(CPUState *cs) +{ + const AccelOpsClass *ops = cpus_get_accel(); + if (ops->remove_all_breakpoints) { + ops->remove_all_breakpoints(cs); + } +} diff --git a/gdbstub/user.c b/gdbstub/user.c new file mode 100644 index 0000000000..42652b28a7 --- /dev/null +++ b/gdbstub/user.c @@ -0,0 +1,62 @@ +/* + * gdbstub user-mode helper routines. + * + * We know for user-mode we are using TCG so we can call stuff directly. + * + * Copyright (c) 2022 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "exec/hwaddr.h" +#include "exec/gdbstub.h" +#include "hw/core/cpu.h" +#include "internals.h" + +int gdb_breakpoint_insert(CPUState *cs, int type, hwaddr addr, hwaddr len) +{ + CPUState *cpu; + int err = 0; + + switch (type) { + case GDB_BREAKPOINT_SW: + case GDB_BREAKPOINT_HW: + CPU_FOREACH(cpu) { + err = cpu_breakpoint_insert(cpu, addr, BP_GDB, NULL); + if (err) { + break; + } + } + return err; + default: + /* user-mode doesn't support watchpoints */ + return -ENOSYS; + } +} + +int gdb_breakpoint_remove(CPUState *cs, int type, hwaddr addr, hwaddr len) +{ + CPUState *cpu; + int err = 0; + + switch (type) { + case GDB_BREAKPOINT_SW: + case GDB_BREAKPOINT_HW: + CPU_FOREACH(cpu) { + err = cpu_breakpoint_remove(cpu, addr, BP_GDB); + if (err) { + break; + } + } + return err; + default: + /* user-mode doesn't support watchpoints */ + return -ENOSYS; + } +} + +void gdb_breakpoint_remove_all(CPUState *cs) +{ + cpu_breakpoint_remove_all(cs, BP_GDB); +} diff --git a/include/sysemu/accel-ops.h b/include/sysemu/accel-ops.h index a0572ea87a..86794ac273 100644 --- a/include/sysemu/accel-ops.h +++ b/include/sysemu/accel-ops.h @@ -10,6 +10,7 @@ #ifndef ACCEL_OPS_H #define ACCEL_OPS_H +#include "exec/hwaddr.h" #include "qom/object.h" #define ACCEL_OPS_SUFFIX "-ops" @@ -44,6 +45,11 @@ struct AccelOpsClass { int64_t (*get_virtual_clock)(void); int64_t (*get_elapsed_ticks)(void); + + /* gdbstub hooks */ + int (*insert_breakpoint)(CPUState *cpu, int type, hwaddr addr, hwaddr len); + int (*remove_breakpoint)(CPUState *cpu, int type, hwaddr addr, hwaddr len); + void (*remove_all_breakpoints)(CPUState *cpu); }; #endif /* ACCEL_OPS_H */ diff --git a/include/sysemu/cpus.h b/include/sysemu/cpus.h index b5c87d48b3..1bace3379b 100644 --- a/include/sysemu/cpus.h +++ b/include/sysemu/cpus.h @@ -7,6 +7,9 @@ /* register accel-specific operations */ void cpus_register_accel(const AccelOpsClass *i); +/* return registers ops */ +const AccelOpsClass *cpus_get_accel(void); + /* accel/dummy-cpus.c */ /* Create a dummy vcpu for AccelOpsClass->create_vcpu_thread */ diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index a20ad51aad..21d3f1d01e 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -254,11 +254,6 @@ int kvm_on_sigbus(int code, void *addr); void kvm_flush_coalesced_mmio_buffer(void); -int kvm_insert_breakpoint(CPUState *cpu, target_ulong addr, - target_ulong len, int type); -int kvm_remove_breakpoint(CPUState *cpu, target_ulong addr, - target_ulong len, int type); -void kvm_remove_all_breakpoints(CPUState *cpu); int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap); /* internal API */ diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 23b30484b2..61b27ff59d 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -617,6 +617,13 @@ void cpus_register_accel(const AccelOpsClass *ops) cpus_accel = ops; } +const AccelOpsClass *cpus_get_accel(void) +{ + /* broken if we call this early */ + assert(cpus_accel); + return cpus_accel; +} + void qemu_init_vcpu(CPUState *cpu) { MachineState *ms = MACHINE(qdev_get_machine()); From a48e7d9e52f8fe8b47f4c74f3e99d9d677b87fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:25 +0100 Subject: [PATCH 0867/1020] gdbstub: move guest debug support check to ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes the final hard coding of kvm_enabled() in gdbstub and moves the check to an AccelOps. Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Alex BennĂ©e Reviewed-by: Mads Ynddal Message-Id: <20220929114231.583801-46-alex.bennee@linaro.org> --- accel/kvm/kvm-accel-ops.c | 1 + accel/kvm/kvm-all.c | 6 ++++++ accel/kvm/kvm-cpus.h | 1 + accel/tcg/tcg-accel-ops.c | 6 ++++++ gdbstub/gdbstub.c | 5 ++--- gdbstub/internals.h | 1 + gdbstub/softmmu.c | 9 +++++++++ gdbstub/user.c | 6 ++++++ include/sysemu/accel-ops.h | 1 + include/sysemu/kvm.h | 7 ------- 10 files changed, 33 insertions(+), 10 deletions(-) diff --git a/accel/kvm/kvm-accel-ops.c b/accel/kvm/kvm-accel-ops.c index 5c0e37514c..fbf4fe3497 100644 --- a/accel/kvm/kvm-accel-ops.c +++ b/accel/kvm/kvm-accel-ops.c @@ -99,6 +99,7 @@ static void kvm_accel_ops_class_init(ObjectClass *oc, void *data) ops->synchronize_pre_loadvm = kvm_cpu_synchronize_pre_loadvm; #ifdef KVM_CAP_SET_GUEST_DEBUG + ops->supports_guest_debug = kvm_supports_guest_debug; ops->insert_breakpoint = kvm_insert_breakpoint; ops->remove_breakpoint = kvm_remove_breakpoint; ops->remove_all_breakpoints = kvm_remove_all_breakpoints; diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index b8c734fe3a..6ebff6e5a6 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3287,6 +3287,12 @@ int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) return data.err; } +bool kvm_supports_guest_debug(void) +{ + /* probed during kvm_init() */ + return kvm_has_guest_debug; +} + int kvm_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len) { struct kvm_sw_breakpoint *bp; diff --git a/accel/kvm/kvm-cpus.h b/accel/kvm/kvm-cpus.h index 33e435d62b..fd63fe6a59 100644 --- a/accel/kvm/kvm-cpus.h +++ b/accel/kvm/kvm-cpus.h @@ -18,6 +18,7 @@ void kvm_destroy_vcpu(CPUState *cpu); void kvm_cpu_synchronize_post_reset(CPUState *cpu); void kvm_cpu_synchronize_post_init(CPUState *cpu); void kvm_cpu_synchronize_pre_loadvm(CPUState *cpu); +bool kvm_supports_guest_debug(void); int kvm_insert_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len); int kvm_remove_breakpoint(CPUState *cpu, int type, hwaddr addr, hwaddr len); void kvm_remove_all_breakpoints(CPUState *cpu); diff --git a/accel/tcg/tcg-accel-ops.c b/accel/tcg/tcg-accel-ops.c index 965c2ad581..19cbf1db3a 100644 --- a/accel/tcg/tcg-accel-ops.c +++ b/accel/tcg/tcg-accel-ops.c @@ -93,6 +93,11 @@ void tcg_handle_interrupt(CPUState *cpu, int mask) } } +static bool tcg_supports_guest_debug(void) +{ + return true; +} + /* Translate GDB watchpoint type to a flags value for cpu_watchpoint_* */ static inline int xlat_gdb_type(CPUState *cpu, int gdbtype) { @@ -198,6 +203,7 @@ static void tcg_accel_ops_init(AccelOpsClass *ops) } } + ops->supports_guest_debug = tcg_supports_guest_debug; ops->insert_breakpoint = tcg_insert_breakpoint; ops->remove_breakpoint = tcg_remove_breakpoint; ops->remove_all_breakpoints = tcg_remove_all_breakpoints; diff --git a/gdbstub/gdbstub.c b/gdbstub/gdbstub.c index ff9f3f9586..be88ca0d71 100644 --- a/gdbstub/gdbstub.c +++ b/gdbstub/gdbstub.c @@ -45,7 +45,6 @@ #include "qemu/sockets.h" #include "sysemu/hw_accel.h" -#include "sysemu/kvm.h" #include "sysemu/runstate.h" #include "semihosting/semihost.h" #include "exec/exec-all.h" @@ -3447,8 +3446,8 @@ int gdbserver_start(const char *device) return -1; } - if (kvm_enabled() && !kvm_supports_guest_debug()) { - error_report("gdbstub: KVM doesn't support guest debugging"); + if (!gdb_supports_guest_debug()) { + error_report("gdbstub: current accelerator doesn't support guest debugging"); return -1; } diff --git a/gdbstub/internals.h b/gdbstub/internals.h index 41e2e72dbf..eabb0341d1 100644 --- a/gdbstub/internals.h +++ b/gdbstub/internals.h @@ -9,6 +9,7 @@ #ifndef _INTERNALS_H_ #define _INTERNALS_H_ +bool gdb_supports_guest_debug(void); int gdb_breakpoint_insert(CPUState *cs, int type, hwaddr addr, hwaddr len); int gdb_breakpoint_remove(CPUState *cs, int type, hwaddr addr, hwaddr len); void gdb_breakpoint_remove_all(CPUState *cs); diff --git a/gdbstub/softmmu.c b/gdbstub/softmmu.c index 4e73890379..f208c6cf15 100644 --- a/gdbstub/softmmu.c +++ b/gdbstub/softmmu.c @@ -15,6 +15,15 @@ #include "sysemu/cpus.h" #include "internals.h" +bool gdb_supports_guest_debug(void) +{ + const AccelOpsClass *ops = cpus_get_accel(); + if (ops->supports_guest_debug) { + return ops->supports_guest_debug(); + } + return false; +} + int gdb_breakpoint_insert(CPUState *cs, int type, hwaddr addr, hwaddr len) { const AccelOpsClass *ops = cpus_get_accel(); diff --git a/gdbstub/user.c b/gdbstub/user.c index 42652b28a7..033e5fdd71 100644 --- a/gdbstub/user.c +++ b/gdbstub/user.c @@ -14,6 +14,12 @@ #include "hw/core/cpu.h" #include "internals.h" +bool gdb_supports_guest_debug(void) +{ + /* user-mode == TCG == supported */ + return true; +} + int gdb_breakpoint_insert(CPUState *cs, int type, hwaddr addr, hwaddr len) { CPUState *cpu; diff --git a/include/sysemu/accel-ops.h b/include/sysemu/accel-ops.h index 86794ac273..8cc7996def 100644 --- a/include/sysemu/accel-ops.h +++ b/include/sysemu/accel-ops.h @@ -47,6 +47,7 @@ struct AccelOpsClass { int64_t (*get_elapsed_ticks)(void); /* gdbstub hooks */ + bool (*supports_guest_debug)(void); int (*insert_breakpoint)(CPUState *cpu, int type, hwaddr addr, hwaddr len); int (*remove_breakpoint)(CPUState *cpu, int type, hwaddr addr, hwaddr len); void (*remove_all_breakpoints)(CPUState *cpu); diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 21d3f1d01e..6e1bd01725 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -46,7 +46,6 @@ extern bool kvm_readonly_mem_allowed; extern bool kvm_direct_msi_allowed; extern bool kvm_ioeventfd_any_length_allowed; extern bool kvm_msi_use_devid; -extern bool kvm_has_guest_debug; #define kvm_enabled() (kvm_allowed) /** @@ -168,11 +167,6 @@ extern bool kvm_has_guest_debug; */ #define kvm_msi_devid_required() (kvm_msi_use_devid) -/* - * Does KVM support guest debugging - */ -#define kvm_supports_guest_debug() (kvm_has_guest_debug) - #else #define kvm_enabled() (0) @@ -190,7 +184,6 @@ extern bool kvm_has_guest_debug; #define kvm_direct_msi_enabled() (false) #define kvm_ioeventfd_any_length_enabled() (false) #define kvm_msi_devid_required() (false) -#define kvm_supports_guest_debug() (false) #endif /* CONFIG_KVM_IS_POSSIBLE */ From c7f1c5373507de48250dcff3487787a674a0ac5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:26 +0100 Subject: [PATCH 0868/1020] accel/kvm: move kvm_update_guest_debug to inline stub MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alex BennĂ©e Message-Id: <20220929114231.583801-47-alex.bennee@linaro.org> --- accel/kvm/kvm-all.c | 6 ------ accel/stubs/kvm-stub.c | 5 ----- include/sysemu/kvm.h | 16 ++++++++++++++++ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 6ebff6e5a6..423fb1936f 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3395,12 +3395,6 @@ void kvm_remove_all_breakpoints(CPUState *cpu) } } -#else /* !KVM_CAP_SET_GUEST_DEBUG */ - -static int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) -{ - return -EINVAL; -} #endif /* !KVM_CAP_SET_GUEST_DEBUG */ static int kvm_set_signal_mask(CPUState *cpu, const sigset_t *sigset) diff --git a/accel/stubs/kvm-stub.c b/accel/stubs/kvm-stub.c index 2d79333143..5d2dd8f351 100644 --- a/accel/stubs/kvm-stub.c +++ b/accel/stubs/kvm-stub.c @@ -46,11 +46,6 @@ int kvm_has_many_ioeventfds(void) return 0; } -int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) -{ - return -ENOSYS; -} - int kvm_on_sigbus_vcpu(CPUState *cpu, int code, void *addr) { return 1; diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 6e1bd01725..790d35ef78 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -247,7 +247,23 @@ int kvm_on_sigbus(int code, void *addr); void kvm_flush_coalesced_mmio_buffer(void); +/** + * kvm_update_guest_debug(): ensure KVM debug structures updated + * @cs: the CPUState for this cpu + * @reinject_trap: KVM trap injection control + * + * There are usually per-arch specifics which will be handled by + * calling down to kvm_arch_update_guest_debug after the generic + * fields have been set. + */ +#ifdef KVM_CAP_SET_GUEST_DEBUG int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap); +#else +static inline int kvm_update_guest_debug(CPUState *cpu, unsigned long reinject_trap) +{ + return -EINVAL; +} +#endif /* internal API */ From bc093f8b1a7e10e5e40d4cbf234614e47d93ab30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:27 +0100 Subject: [PATCH 0869/1020] contrib/gitdm: add mapping for Loongson Technology MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Please confirm you are happy with this mapping. Signed-off-by: Alex BennĂ©e Acked-by: Song Gao Message-Id: <20220929114231.583801-48-alex.bennee@linaro.org> --- contrib/gitdm/domain-map | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/gitdm/domain-map b/contrib/gitdm/domain-map index 2800d9f986..434ef53afc 100644 --- a/contrib/gitdm/domain-map +++ b/contrib/gitdm/domain-map @@ -19,6 +19,7 @@ ibm.com IBM igalia.com Igalia intel.com Intel linaro.org Linaro +loongson.cn Loongson Technology lwn.net LWN microsoft.com Microsoft mvista.com MontaVista From 13b2918fdd93fd8cca03730a8b42aaa2c38bbd3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:28 +0100 Subject: [PATCH 0870/1020] contrib/gitdm: add Paul to individual contributors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Also map his old codesourcery address to his canonical address. Signed-off-by: Alex BennĂ©e Cc: Paul Brook Message-Id: <20220929114231.583801-49-alex.bennee@linaro.org> --- .mailmap | 1 + contrib/gitdm/group-map-individuals | 1 + 2 files changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 8c326709cf..1f7319b70b 100644 --- a/.mailmap +++ b/.mailmap @@ -65,6 +65,7 @@ James Hogan Leif Lindholm Leif Lindholm Radoslaw Biernacki +Paul Brook Paul Burton Paul Burton Paul Burton diff --git a/contrib/gitdm/group-map-individuals b/contrib/gitdm/group-map-individuals index f816aa8770..6322b3476d 100644 --- a/contrib/gitdm/group-map-individuals +++ b/contrib/gitdm/group-map-individuals @@ -34,3 +34,4 @@ bmeng.cn@gmail.com liq3ea@gmail.com chetan4windows@gmail.com akihiko.odaki@gmail.com +paul@nowt.org From 9c86422df61455abf945927db279d0d4462d4306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:29 +0100 Subject: [PATCH 0871/1020] contrib/gitdm: add WANG Xuerui to individual contributers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit His blog confirms he is not affiliated with Loongson. Signed-off-by: Alex BennĂ©e Reviewed-by: WANG Xuerui Message-Id: <20220929114231.583801-50-alex.bennee@linaro.org> --- contrib/gitdm/group-map-individuals | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/gitdm/group-map-individuals b/contrib/gitdm/group-map-individuals index 6322b3476d..e19d79626c 100644 --- a/contrib/gitdm/group-map-individuals +++ b/contrib/gitdm/group-map-individuals @@ -35,3 +35,4 @@ liq3ea@gmail.com chetan4windows@gmail.com akihiko.odaki@gmail.com paul@nowt.org +git@xen0n.name From effc4015c706273206a8e83730a8fa488601b7df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:30 +0100 Subject: [PATCH 0872/1020] contrib/gitdm: add ISCAS to the academics group MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The English website (http://english.is.cas.cn/) in on a slightly different domain but has the same logo as http://www.iscas.ac.cn/. Signed-off-by: Alex BennĂ©e Reviewed-by: Weiwei Li Message-Id: <20220929114231.583801-51-alex.bennee@linaro.org> --- contrib/gitdm/group-map-academics | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/gitdm/group-map-academics b/contrib/gitdm/group-map-academics index 44745ca85b..877a11e69b 100644 --- a/contrib/gitdm/group-map-academics +++ b/contrib/gitdm/group-map-academics @@ -19,3 +19,6 @@ edu.cn # Boston University bu.edu + +# Institute of Software Chinese Academy of Sciences +iscas.ac.cn From fd0ddd22b82e34a3260538630ded3a0ecdee06fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 29 Sep 2022 12:42:31 +0100 Subject: [PATCH 0873/1020] contrib/gitdm: add China Telecom to the domain map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alex BennĂ©e Acked-by: Hyman Huang(黄勇) Message-Id: <20220929114231.583801-52-alex.bennee@linaro.org> --- contrib/gitdm/domain-map | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/gitdm/domain-map b/contrib/gitdm/domain-map index 434ef53afc..3727918641 100644 --- a/contrib/gitdm/domain-map +++ b/contrib/gitdm/domain-map @@ -10,6 +10,7 @@ bytedance.com ByteDance cmss.chinamobile.com China Mobile citrix.com Citrix crudebyte.com Crudebyte +chinatelecom.cn China Telecom eldorado.org.br Instituto de Pesquisas Eldorado fujitsu.com Fujitsu google.com Google From 15fe7182fb9466dd6061201a673f652f5ef4d5f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 26 Sep 2022 14:46:03 +0100 Subject: [PATCH 0874/1020] contrib/gitdm: add Simon to individual contributors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Please confirm this is the correct mapping for you. Signed-off-by: Alex BennĂ©e Reviewed-by: Simon Safar Message-Id: <20220926134609.3301945-2-alex.bennee@linaro.org> --- contrib/gitdm/group-map-individuals | 1 + 1 file changed, 1 insertion(+) diff --git a/contrib/gitdm/group-map-individuals b/contrib/gitdm/group-map-individuals index e19d79626c..53883cc526 100644 --- a/contrib/gitdm/group-map-individuals +++ b/contrib/gitdm/group-map-individuals @@ -36,3 +36,4 @@ chetan4windows@gmail.com akihiko.odaki@gmail.com paul@nowt.org git@xen0n.name +simon@simonsafar.com From 37e62694e4bcc937c8c5fa6153302a5451fb12c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Mon, 26 Sep 2022 14:46:08 +0100 Subject: [PATCH 0875/1020] =?UTF-8?q?contrib/gitdm:=20add=20Universit?= =?UTF-8?q?=C3=A9=20Grenoble=20Alpes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit again to the academic group map. Signed-off-by: Alex BennĂ©e Cc: FrĂ©dĂ©ric PĂ©trot Reviewed-by: Philippe Mathieu-DaudĂ© Message-Id: <20220926134609.3301945-7-alex.bennee@linaro.org> --- contrib/gitdm/group-map-academics | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contrib/gitdm/group-map-academics b/contrib/gitdm/group-map-academics index 877a11e69b..082458e1bd 100644 --- a/contrib/gitdm/group-map-academics +++ b/contrib/gitdm/group-map-academics @@ -22,3 +22,6 @@ bu.edu # Institute of Software Chinese Academy of Sciences iscas.ac.cn + +# UniversitĂ© Grenoble Alpes +univ-grenoble-alpes.fr From f7e15affa8e574a800180de3bde1a6462aec7241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 4 Oct 2022 12:52:21 +0100 Subject: [PATCH 0876/1020] plugins: add [pre|post]fork helpers to linux-user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Special care needs to be taken in ensuring locks are in a consistent state across fork events. Add helpers so the plugin system can ensure that. Signed-off-by: Alex BennĂ©e Fixes: https://gitlab.com/qemu-project/qemu/-/issues/358 Reviewed-by: Daniel P. BerrangĂ© Tested-by: Daniel P. BerrangĂ© Message-Id: <20221004115221.2174499-1-alex.bennee@linaro.org> --- include/qemu/plugin.h | 24 ++++++++++++++++++++++++ linux-user/main.c | 2 ++ plugins/core.c | 20 ++++++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/include/qemu/plugin.h b/include/qemu/plugin.h index 145f8a221a..a772e14193 100644 --- a/include/qemu/plugin.h +++ b/include/qemu/plugin.h @@ -224,6 +224,23 @@ void qemu_plugin_disable_mem_helpers(CPUState *cpu); */ void qemu_plugin_user_exit(void); +/** + * qemu_plugin_user_prefork_lock(): take plugin lock before forking + * + * This is a user-mode only helper to take the internal plugin lock + * before a fork event. This is ensure a consistent lock state + */ +void qemu_plugin_user_prefork_lock(void); + +/** + * qemu_plugin_user_postfork(): reset the plugin lock + * @is_child: is this thread the child + * + * This user-mode only helper resets the lock state after a fork so we + * can continue using the plugin interface. + */ +void qemu_plugin_user_postfork(bool is_child); + #else /* !CONFIG_PLUGIN */ static inline void qemu_plugin_add_opts(void) @@ -287,6 +304,13 @@ static inline void qemu_plugin_disable_mem_helpers(CPUState *cpu) static inline void qemu_plugin_user_exit(void) { } + +static inline void qemu_plugin_user_prefork_lock(void) +{ } + +static inline void qemu_plugin_user_postfork(bool is_child) +{ } + #endif /* !CONFIG_PLUGIN */ #endif /* QEMU_PLUGIN_H */ diff --git a/linux-user/main.c b/linux-user/main.c index 88fccfe261..a17fed045b 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -142,10 +142,12 @@ void fork_start(void) start_exclusive(); mmap_fork_start(); cpu_list_lock(); + qemu_plugin_user_prefork_lock(); } void fork_end(int child) { + qemu_plugin_user_postfork(child); mmap_fork_end(child); if (child) { CPUState *cpu, *next_cpu; diff --git a/plugins/core.c b/plugins/core.c index c3ae284994..ccb770a485 100644 --- a/plugins/core.c +++ b/plugins/core.c @@ -526,6 +526,26 @@ void qemu_plugin_user_exit(void) qemu_plugin_atexit_cb(); } +/* + * Helpers for *-user to ensure locks are sane across fork() events. + */ + +void qemu_plugin_user_prefork_lock(void) +{ + qemu_rec_mutex_lock(&plugin.lock); +} + +void qemu_plugin_user_postfork(bool is_child) +{ + if (is_child) { + /* should we just reset via plugin_init? */ + qemu_rec_mutex_init(&plugin.lock); + } else { + qemu_rec_mutex_unlock(&plugin.lock); + } +} + + /* * Call this function after longjmp'ing to the main loop. It's possible that the * last instruction of a TB might have used helpers, and therefore the From 1af0006ab959864dfa2f59e9136c5fb93000b61f Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Thu, 11 Aug 2022 12:10:54 +0000 Subject: [PATCH 0877/1020] dump: Replace opaque DumpState pointer with a typed one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's always better to convey the type of a pointer if at all possible. So let's add the DumpState typedef to typedefs.h and move the dump note functions from the opaque pointers to DumpState pointers. Signed-off-by: Janosch Frank CC: Peter Maydell CC: CĂ©dric Le Goater CC: Daniel Henrique Barboza CC: David Gibson CC: Greg Kurz CC: Palmer Dabbelt CC: Alistair Francis CC: Bin Meng CC: Cornelia Huck CC: Thomas Huth CC: Richard Henderson CC: David Hildenbrand Acked-by: Daniel Henrique Barboza Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220811121111.9878-2-frankja@linux.ibm.com> --- include/hw/core/sysemu-cpu-ops.h | 8 ++++---- include/qemu/typedefs.h | 1 + target/arm/arch_dump.c | 6 ++---- target/arm/cpu.h | 4 ++-- target/i386/arch_dump.c | 30 +++++++++++++++--------------- target/i386/cpu.h | 8 ++++---- target/ppc/arch_dump.c | 18 +++++++++--------- target/ppc/cpu.h | 4 ++-- target/riscv/arch_dump.c | 6 ++---- target/riscv/cpu.h | 4 ++-- target/s390x/arch_dump.c | 10 +++++----- target/s390x/s390x-internal.h | 2 +- 12 files changed, 49 insertions(+), 52 deletions(-) diff --git a/include/hw/core/sysemu-cpu-ops.h b/include/hw/core/sysemu-cpu-ops.h index a9ba39e5f2..ee169b872c 100644 --- a/include/hw/core/sysemu-cpu-ops.h +++ b/include/hw/core/sysemu-cpu-ops.h @@ -53,25 +53,25 @@ typedef struct SysemuCPUOps { * 32-bit VM coredump. */ int (*write_elf32_note)(WriteCoreDumpFunction f, CPUState *cpu, - int cpuid, void *opaque); + int cpuid, DumpState *s); /** * @write_elf64_note: Callback for writing a CPU-specific ELF note to a * 64-bit VM coredump. */ int (*write_elf64_note)(WriteCoreDumpFunction f, CPUState *cpu, - int cpuid, void *opaque); + int cpuid, DumpState *s); /** * @write_elf32_qemunote: Callback for writing a CPU- and QEMU-specific ELF * note to a 32-bit VM coredump. */ int (*write_elf32_qemunote)(WriteCoreDumpFunction f, CPUState *cpu, - void *opaque); + DumpState *s); /** * @write_elf64_qemunote: Callback for writing a CPU- and QEMU-specific ELF * note to a 64-bit VM coredump. */ int (*write_elf64_qemunote)(WriteCoreDumpFunction f, CPUState *cpu, - void *opaque); + DumpState *s); /** * @virtio_is_big_endian: Callback to return %true if a CPU which supports * runtime configurable endianness is currently big-endian. diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h index 5f95169827..6d4e6d9708 100644 --- a/include/qemu/typedefs.h +++ b/include/qemu/typedefs.h @@ -131,6 +131,7 @@ typedef struct VirtIODevice VirtIODevice; typedef struct Visitor Visitor; typedef struct VMChangeStateEntry VMChangeStateEntry; typedef struct VMStateDescription VMStateDescription; +typedef struct DumpState DumpState; /* * Pointer types diff --git a/target/arm/arch_dump.c b/target/arm/arch_dump.c index b1f040e69f..2d8e41ab8a 100644 --- a/target/arm/arch_dump.c +++ b/target/arm/arch_dump.c @@ -232,12 +232,11 @@ static int aarch64_write_elf64_sve(WriteCoreDumpFunction f, #endif int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { struct aarch64_note note; ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; - DumpState *s = opaque; uint64_t pstate, sp; int ret, i; @@ -360,12 +359,11 @@ static int arm_write_elf32_vfp(WriteCoreDumpFunction f, CPUARMState *env, } int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { struct arm_note note; ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; - DumpState *s = opaque; int ret, i; bool fpvalid = cpu_isar_feature(aa32_vfp_simd, cpu); diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 429ed42eec..85dc263318 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1102,9 +1102,9 @@ int arm_gen_dynamic_svereg_xml(CPUState *cpu, int base_reg); const char *arm_gdb_get_dynamic_xml(CPUState *cpu, const char *xmlname); int arm_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque); + int cpuid, DumpState *s); int arm_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque); + int cpuid, DumpState *s); #ifdef TARGET_AARCH64 int aarch64_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); diff --git a/target/i386/arch_dump.c b/target/i386/arch_dump.c index 004141fc04..c290910a04 100644 --- a/target/i386/arch_dump.c +++ b/target/i386/arch_dump.c @@ -42,7 +42,7 @@ typedef struct { static int x86_64_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env, int id, - void *opaque) + DumpState *s) { x86_64_user_regs_struct regs; Elf64_Nhdr *note; @@ -94,7 +94,7 @@ static int x86_64_write_elf64_note(WriteCoreDumpFunction f, buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong); memcpy(buf, ®s, sizeof(x86_64_user_regs_struct)); - ret = f(note, note_size, opaque); + ret = f(note, note_size, s); g_free(note); if (ret < 0) { return -1; @@ -148,7 +148,7 @@ static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUX86State *env, } static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env, - int id, void *opaque) + int id, DumpState *s) { x86_elf_prstatus prstatus; Elf64_Nhdr *note; @@ -170,7 +170,7 @@ static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env, buf += ROUND_UP(name_size, 4); memcpy(buf, &prstatus, sizeof(prstatus)); - ret = f(note, note_size, opaque); + ret = f(note, note_size, s); g_free(note); if (ret < 0) { return -1; @@ -180,7 +180,7 @@ static int x86_write_elf64_note(WriteCoreDumpFunction f, CPUX86State *env, } int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { X86CPU *cpu = X86_CPU(cs); int ret; @@ -189,10 +189,10 @@ int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, bool lma = !!(first_x86_cpu->env.hflags & HF_LMA_MASK); if (lma) { - ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, opaque); + ret = x86_64_write_elf64_note(f, &cpu->env, cpuid, s); } else { #endif - ret = x86_write_elf64_note(f, &cpu->env, cpuid, opaque); + ret = x86_write_elf64_note(f, &cpu->env, cpuid, s); #ifdef TARGET_X86_64 } #endif @@ -201,7 +201,7 @@ int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, } int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { X86CPU *cpu = X86_CPU(cs); x86_elf_prstatus prstatus; @@ -224,7 +224,7 @@ int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, buf += ROUND_UP(name_size, 4); memcpy(buf, &prstatus, sizeof(prstatus)); - ret = f(note, note_size, opaque); + ret = f(note, note_size, s); g_free(note); if (ret < 0) { return -1; @@ -329,7 +329,7 @@ static void qemu_get_cpustate(QEMUCPUState *s, CPUX86State *env) static inline int cpu_write_qemu_note(WriteCoreDumpFunction f, CPUX86State *env, - void *opaque, + DumpState *s, int type) { QEMUCPUState state; @@ -369,7 +369,7 @@ static inline int cpu_write_qemu_note(WriteCoreDumpFunction f, buf += ROUND_UP(name_size, 4); memcpy(buf, &state, sizeof(state)); - ret = f(note, note_size, opaque); + ret = f(note, note_size, s); g_free(note); if (ret < 0) { return -1; @@ -379,19 +379,19 @@ static inline int cpu_write_qemu_note(WriteCoreDumpFunction f, } int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cs, - void *opaque) + DumpState *s) { X86CPU *cpu = X86_CPU(cs); - return cpu_write_qemu_note(f, &cpu->env, opaque, 1); + return cpu_write_qemu_note(f, &cpu->env, s, 1); } int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cs, - void *opaque) + DumpState *s) { X86CPU *cpu = X86_CPU(cs); - return cpu_write_qemu_note(f, &cpu->env, opaque, 0); + return cpu_write_qemu_note(f, &cpu->env, s, 0); } int cpu_get_dump_info(ArchDumpInfo *info, diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 82004b65b9..b75108d6a3 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1938,13 +1938,13 @@ extern const VMStateDescription vmstate_x86_cpu; int x86_cpu_pending_interrupt(CPUState *cs, int interrupt_request); int x86_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu, - int cpuid, void *opaque); + int cpuid, DumpState *s); int x86_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu, - int cpuid, void *opaque); + int cpuid, DumpState *s); int x86_cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu, - void *opaque); + DumpState *s); int x86_cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, - void *opaque); + DumpState *s); void x86_cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list, Error **errp); diff --git a/target/ppc/arch_dump.c b/target/ppc/arch_dump.c index 1139cead9f..f58e6359d5 100644 --- a/target/ppc/arch_dump.c +++ b/target/ppc/arch_dump.c @@ -270,23 +270,23 @@ ssize_t cpu_get_note_size(int class, int machine, int nr_cpus) static int ppc_write_all_elf_notes(const char *note_name, WriteCoreDumpFunction f, PowerPCCPU *cpu, int id, - void *opaque) + DumpState *s) { - NoteFuncArg arg = { .state = opaque }; + NoteFuncArg arg = { .state = s }; int ret = -1; int note_size; const NoteFuncDesc *nf; for (nf = note_func; nf->note_contents_func; nf++) { - arg.note.hdr.n_namesz = cpu_to_dump32(opaque, sizeof(arg.note.name)); - arg.note.hdr.n_descsz = cpu_to_dump32(opaque, nf->contents_size); + arg.note.hdr.n_namesz = cpu_to_dump32(s, sizeof(arg.note.name)); + arg.note.hdr.n_descsz = cpu_to_dump32(s, nf->contents_size); strncpy(arg.note.name, note_name, sizeof(arg.note.name)); (*nf->note_contents_func)(&arg, cpu); note_size = sizeof(arg.note) - sizeof(arg.note.contents) + nf->contents_size; - ret = f(&arg.note, note_size, opaque); + ret = f(&arg.note, note_size, s); if (ret < 0) { return -1; } @@ -295,15 +295,15 @@ static int ppc_write_all_elf_notes(const char *note_name, } int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { PowerPCCPU *cpu = POWERPC_CPU(cs); - return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, opaque); + return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, s); } int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { PowerPCCPU *cpu = POWERPC_CPU(cs); - return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, opaque); + return ppc_write_all_elf_notes("CORE", f, cpu, cpuid, s); } diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h index 7f73e2ac81..cca6c4e51c 100644 --- a/target/ppc/cpu.h +++ b/target/ppc/cpu.h @@ -1354,9 +1354,9 @@ void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu); const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name); #endif int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque); + int cpuid, DumpState *s); int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque); + int cpuid, DumpState *s); #ifndef CONFIG_USER_ONLY void ppc_cpu_do_interrupt(CPUState *cpu); bool ppc_cpu_exec_interrupt(CPUState *cpu, int int_req); diff --git a/target/riscv/arch_dump.c b/target/riscv/arch_dump.c index 709f621d82..736a232956 100644 --- a/target/riscv/arch_dump.c +++ b/target/riscv/arch_dump.c @@ -64,12 +64,11 @@ static void riscv64_note_init(struct riscv64_note *note, DumpState *s, } int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { struct riscv64_note note; RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; - DumpState *s = opaque; int ret, i = 0; const char name[] = "CORE"; @@ -134,12 +133,11 @@ static void riscv32_note_init(struct riscv32_note *note, DumpState *s, } int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { struct riscv32_note note; RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; - DumpState *s = opaque; int ret, i; const char name[] = "CORE"; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index b131fa8c8e..3a9e25053f 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -534,9 +534,9 @@ extern const char * const riscv_fpr_regnames[]; const char *riscv_cpu_get_trap_name(target_ulong cause, bool async); void riscv_cpu_do_interrupt(CPUState *cpu); int riscv_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque); + int cpuid, DumpState *s); int riscv_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque); + int cpuid, DumpState *s); int riscv_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg); int riscv_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg); int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero); diff --git a/target/s390x/arch_dump.c b/target/s390x/arch_dump.c index 08daf93ae1..f60a14920d 100644 --- a/target/s390x/arch_dump.c +++ b/target/s390x/arch_dump.c @@ -204,7 +204,7 @@ static const NoteFuncDesc note_linux[] = { static int s390x_write_elf64_notes(const char *note_name, WriteCoreDumpFunction f, S390CPU *cpu, int id, - void *opaque, + DumpState *s, const NoteFuncDesc *funcs) { Note note; @@ -222,7 +222,7 @@ static int s390x_write_elf64_notes(const char *note_name, (*nf->note_contents_func)(¬e, cpu, id); note_size = sizeof(note) - sizeof(note.contents) + nf->contents_size; - ret = f(¬e, note_size, opaque); + ret = f(¬e, note_size, s); if (ret < 0) { return -1; @@ -235,16 +235,16 @@ static int s390x_write_elf64_notes(const char *note_name, int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque) + int cpuid, DumpState *s) { S390CPU *cpu = S390_CPU(cs); int r; - r = s390x_write_elf64_notes("CORE", f, cpu, cpuid, opaque, note_core); + r = s390x_write_elf64_notes("CORE", f, cpu, cpuid, s, note_core); if (r) { return r; } - return s390x_write_elf64_notes("LINUX", f, cpu, cpuid, opaque, note_linux); + return s390x_write_elf64_notes("LINUX", f, cpu, cpuid, s, note_linux); } int cpu_get_dump_info(ArchDumpInfo *info, diff --git a/target/s390x/s390x-internal.h b/target/s390x/s390x-internal.h index 6aba7fd0ca..b5ae0ae364 100644 --- a/target/s390x/s390x-internal.h +++ b/target/s390x/s390x-internal.h @@ -227,7 +227,7 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb, /* arch_dump.c */ int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, - int cpuid, void *opaque); + int cpuid, DumpState *s); /* cc_helper.c */ From afae6056ea79e2d89fd90867de3a01732eae724f Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Thu, 11 Aug 2022 12:10:55 +0000 Subject: [PATCH 0878/1020] dump: Rename write_elf_loads to write_elf_phdr_loads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's make it a bit clearer that we write the program headers of the PT_LOAD type. Signed-off-by: Janosch Frank Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Janis Schoetterl-Glausch Reviewed-by: Steffen Eiden Message-Id: <20220811121111.9878-3-frankja@linux.ibm.com> --- dump/dump.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index 4d9658ffa2..0ed7cf9c7b 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -490,7 +490,7 @@ static void get_offset_range(hwaddr phys_addr, } } -static void write_elf_loads(DumpState *s, Error **errp) +static void write_elf_phdr_loads(DumpState *s, Error **errp) { ERRP_GUARD(); hwaddr offset, filesz; @@ -573,8 +573,8 @@ static void dump_begin(DumpState *s, Error **errp) return; } - /* write all PT_LOAD to vmcore */ - write_elf_loads(s, errp); + /* write all PT_LOADs to vmcore */ + write_elf_phdr_loads(s, errp); if (*errp) { return; } From 1e8113032f5b1efc5da66382470ce4809c76f8f2 Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Thu, 11 Aug 2022 12:10:56 +0000 Subject: [PATCH 0879/1020] dump: Refactor dump_iterate and introduce dump_filter_memblock_*() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The iteration over the memblocks in dump_iterate() is hard to understand so it's about time to clean it up. Instead of manually grabbing the next memblock we can use QTAILQ_FOREACH to iterate over all memblocks. Additionally we move the calculation of the offset and length out by introducing and using the dump_filter_memblock_*() functions. These functions will later be used to cleanup other parts of dump.c. Signed-off-by: Janosch Frank Reviewed-by: Janis Schoetterl-Glausch Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220811121111.9878-4-frankja@linux.ibm.com> --- dump/dump.c | 80 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 35 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index 0ed7cf9c7b..340de5a1e7 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -591,31 +591,43 @@ static void dump_begin(DumpState *s, Error **errp) write_elf_notes(s, errp); } -static int get_next_block(DumpState *s, GuestPhysBlock *block) +static int64_t dump_filtered_memblock_size(GuestPhysBlock *block, + int64_t filter_area_start, + int64_t filter_area_length) { - while (1) { - block = QTAILQ_NEXT(block, next); - if (!block) { - /* no more block */ - return 1; - } + int64_t size, left, right; - s->start = 0; - s->next_block = block; - if (s->has_filter) { - if (block->target_start >= s->begin + s->length || - block->target_end <= s->begin) { - /* This block is out of the range */ - continue; - } - - if (s->begin > block->target_start) { - s->start = s->begin - block->target_start; - } - } - - return 0; + /* No filter, return full size */ + if (!filter_area_length) { + return block->target_end - block->target_start; } + + /* calculate the overlapped region. */ + left = MAX(filter_area_start, block->target_start); + right = MIN(filter_area_start + filter_area_length, block->target_end); + size = right - left; + size = size > 0 ? size : 0; + + return size; +} + +static int64_t dump_filtered_memblock_start(GuestPhysBlock *block, + int64_t filter_area_start, + int64_t filter_area_length) +{ + if (filter_area_length) { + /* return -1 if the block is not within filter area */ + if (block->target_start >= filter_area_start + filter_area_length || + block->target_end <= filter_area_start) { + return -1; + } + + if (filter_area_start > block->target_start) { + return filter_area_start - block->target_start; + } + } + + return 0; } /* write all memory to vmcore */ @@ -623,24 +635,22 @@ static void dump_iterate(DumpState *s, Error **errp) { ERRP_GUARD(); GuestPhysBlock *block; - int64_t size; + int64_t memblock_size, memblock_start; - do { - block = s->next_block; - - size = block->target_end - block->target_start; - if (s->has_filter) { - size -= s->start; - if (s->begin + s->length < block->target_end) { - size -= block->target_end - (s->begin + s->length); - } + QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { + memblock_start = dump_filtered_memblock_start(block, s->begin, s->length); + if (memblock_start == -1) { + continue; } - write_memory(s, block, s->start, size, errp); + + memblock_size = dump_filtered_memblock_size(block, s->begin, s->length); + + /* Write the memory to file */ + write_memory(s, block, memblock_start, memblock_size, errp); if (*errp) { return; } - - } while (!get_next_block(s, block)); + } } static void create_vmcore(DumpState *s, Error **errp) From 0c2994ac9009577b967529ce18e269da5b280351 Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Thu, 11 Aug 2022 12:10:57 +0000 Subject: [PATCH 0880/1020] dump: Rework get_start_block MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit get_start_block() returns the start address of the first memory block or -1. With the GuestPhysBlock iterator conversion we don't need to set the start address and can therefore remove that code and the "start" DumpState struct member. The only functionality left is the validation of the start block so it only makes sense to re-name the function to validate_start_block() Signed-off-by: Janosch Frank Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Janis Schoetterl-Glausch Message-Id: <20220811121111.9878-5-frankja@linux.ibm.com> --- dump/dump.c | 20 ++++++-------------- include/sysemu/dump.h | 2 -- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index 340de5a1e7..e204912a89 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -1500,30 +1500,22 @@ static void create_kdump_vmcore(DumpState *s, Error **errp) } } -static ram_addr_t get_start_block(DumpState *s) +static int validate_start_block(DumpState *s) { GuestPhysBlock *block; if (!s->has_filter) { - s->next_block = QTAILQ_FIRST(&s->guest_phys_blocks.head); return 0; } QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { + /* This block is out of the range */ if (block->target_start >= s->begin + s->length || block->target_end <= s->begin) { - /* This block is out of the range */ continue; } - - s->next_block = block; - if (s->begin > block->target_start) { - s->start = s->begin - block->target_start; - } else { - s->start = 0; - } - return s->start; - } + return 0; + } return -1; } @@ -1670,8 +1662,8 @@ static void dump_init(DumpState *s, int fd, bool has_format, goto cleanup; } - s->start = get_start_block(s); - if (s->start == -1) { + /* Is the filter filtering everything? */ + if (validate_start_block(s) == -1) { error_setg(errp, QERR_INVALID_PARAMETER, "begin"); goto cleanup; } diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h index ffc2ea1072..7fce1d4af6 100644 --- a/include/sysemu/dump.h +++ b/include/sysemu/dump.h @@ -166,8 +166,6 @@ typedef struct DumpState { hwaddr memory_offset; int fd; - GuestPhysBlock *next_block; - ram_addr_t start; bool has_filter; int64_t begin; int64_t length; From dddf725f70bfe7f5adb41fa31dbd06e767271bda Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Thu, 11 Aug 2022 12:10:58 +0000 Subject: [PATCH 0881/1020] dump: Rework filter area variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While the DumpState begin and length variables directly mirror the API variable names they are not very descriptive. So let's add a "filter_area_" prefix and make has_filter a function checking length > 0. Signed-off-by: Janosch Frank Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220811121111.9878-6-frankja@linux.ibm.com> --- dump/dump.c | 53 +++++++++++++++++++++++++------------------ include/sysemu/dump.h | 13 ++++++++--- 2 files changed, 41 insertions(+), 25 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index e204912a89..b043337bc7 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -59,6 +59,11 @@ static inline bool dump_is_64bit(DumpState *s) return s->dump_info.d_class == ELFCLASS64; } +static inline bool dump_has_filter(DumpState *s) +{ + return s->filter_area_length > 0; +} + uint16_t cpu_to_dump16(DumpState *s, uint16_t val) { if (s->dump_info.d_endian == ELFDATA2LSB) { @@ -443,29 +448,30 @@ static void get_offset_range(hwaddr phys_addr, *p_offset = -1; *p_filesz = 0; - if (s->has_filter) { - if (phys_addr < s->begin || phys_addr >= s->begin + s->length) { + if (dump_has_filter(s)) { + if (phys_addr < s->filter_area_begin || + phys_addr >= s->filter_area_begin + s->filter_area_length) { return; } } QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { - if (s->has_filter) { - if (block->target_start >= s->begin + s->length || - block->target_end <= s->begin) { + if (dump_has_filter(s)) { + if (block->target_start >= s->filter_area_begin + s->filter_area_length || + block->target_end <= s->filter_area_begin) { /* This block is out of the range */ continue; } - if (s->begin <= block->target_start) { + if (s->filter_area_begin <= block->target_start) { start = block->target_start; } else { - start = s->begin; + start = s->filter_area_begin; } size_in_block = block->target_end - start; - if (s->begin + s->length < block->target_end) { - size_in_block -= block->target_end - (s->begin + s->length); + if (s->filter_area_begin + s->filter_area_length < block->target_end) { + size_in_block -= block->target_end - (s->filter_area_begin + s->filter_area_length); } } else { start = block->target_start; @@ -638,12 +644,12 @@ static void dump_iterate(DumpState *s, Error **errp) int64_t memblock_size, memblock_start; QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { - memblock_start = dump_filtered_memblock_start(block, s->begin, s->length); + memblock_start = dump_filtered_memblock_start(block, s->filter_area_begin, s->filter_area_length); if (memblock_start == -1) { continue; } - memblock_size = dump_filtered_memblock_size(block, s->begin, s->length); + memblock_size = dump_filtered_memblock_size(block, s->filter_area_begin, s->filter_area_length); /* Write the memory to file */ write_memory(s, block, memblock_start, memblock_size, errp); @@ -1504,14 +1510,14 @@ static int validate_start_block(DumpState *s) { GuestPhysBlock *block; - if (!s->has_filter) { + if (!dump_has_filter(s)) { return 0; } QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { /* This block is out of the range */ - if (block->target_start >= s->begin + s->length || - block->target_end <= s->begin) { + if (block->target_start >= s->filter_area_begin + s->filter_area_length || + block->target_end <= s->filter_area_begin) { continue; } return 0; @@ -1550,10 +1556,10 @@ static int64_t dump_calculate_size(DumpState *s) int64_t size = 0, total = 0, left = 0, right = 0; QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { - if (s->has_filter) { + if (dump_has_filter(s)) { /* calculate the overlapped region. */ - left = MAX(s->begin, block->target_start); - right = MIN(s->begin + s->length, block->target_end); + left = MAX(s->filter_area_begin, block->target_start); + right = MIN(s->filter_area_begin + s->filter_area_length, block->target_end); size = right - left; size = size > 0 ? size : 0; } else { @@ -1643,9 +1649,12 @@ static void dump_init(DumpState *s, int fd, bool has_format, } s->fd = fd; - s->has_filter = has_filter; - s->begin = begin; - s->length = length; + if (has_filter && !length) { + error_setg(errp, QERR_INVALID_PARAMETER, "length"); + goto cleanup; + } + s->filter_area_begin = begin; + s->filter_area_length = length; memory_mapping_list_init(&s->list); @@ -1778,8 +1787,8 @@ static void dump_init(DumpState *s, int fd, bool has_format, return; } - if (s->has_filter) { - memory_mapping_filter(&s->list, s->begin, s->length); + if (dump_has_filter(s)) { + memory_mapping_filter(&s->list, s->filter_area_begin, s->filter_area_length); } /* diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h index 7fce1d4af6..b62513d87d 100644 --- a/include/sysemu/dump.h +++ b/include/sysemu/dump.h @@ -166,9 +166,16 @@ typedef struct DumpState { hwaddr memory_offset; int fd; - bool has_filter; - int64_t begin; - int64_t length; + /* + * Dump filter area variables + * + * A filtered dump only contains the guest memory designated by + * the start address and length variables defined below. + * + * If length is 0, no filtering is applied. + */ + int64_t filter_area_begin; /* Start address of partial guest memory area */ + int64_t filter_area_length; /* Length of partial guest memory area */ uint8_t *note_buf; /* buffer for notes */ size_t note_buf_offset; /* the writing place in note_buf */ From c370d5300f9ac1f90f8158082d22262b904fe30e Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Thu, 11 Aug 2022 12:10:59 +0000 Subject: [PATCH 0882/1020] dump: Rework dump_calculate_size function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dump_calculate_size() sums up all the sizes of the guest memory blocks. Since we already have a function that calculates the size of a single memory block (dump_get_memblock_size()) we can simply iterate over the blocks and use the function instead of calculating the size ourselves. Signed-off-by: Janosch Frank Reviewed-by: Marc-AndrĂ© Lureau Reviewed-by: Janis Schoetterl-Glausch Message-Id: <20220811121111.9878-7-frankja@linux.ibm.com> --- dump/dump.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index b043337bc7..d82cc46d7d 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -1548,25 +1548,19 @@ bool qemu_system_dump_in_progress(void) return (qatomic_read(&state->status) == DUMP_STATUS_ACTIVE); } -/* calculate total size of memory to be dumped (taking filter into - * acoount.) */ +/* + * calculate total size of memory to be dumped (taking filter into + * account.) + */ static int64_t dump_calculate_size(DumpState *s) { GuestPhysBlock *block; - int64_t size = 0, total = 0, left = 0, right = 0; + int64_t total = 0; QTAILQ_FOREACH(block, &s->guest_phys_blocks.head, next) { - if (dump_has_filter(s)) { - /* calculate the overlapped region. */ - left = MAX(s->filter_area_begin, block->target_start); - right = MIN(s->filter_area_begin + s->filter_area_length, block->target_end); - size = right - left; - size = size > 0 ? size : 0; - } else { - /* count the whole region in */ - size = (block->target_end - block->target_start); - } - total += size; + total += dump_filtered_memblock_size(block, + s->filter_area_begin, + s->filter_area_length); } return total; From 670e76998a61ca171200fcded3865b294a2d1243 Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Thu, 11 Aug 2022 12:11:00 +0000 Subject: [PATCH 0883/1020] dump: Split elf header functions into prepare and write MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's split the write from the modification of the elf header so we can consolidate the write of the data in one function. Signed-off-by: Janosch Frank Reviewed-by: Janis Schoetterl-Glausch Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220811121111.9878-8-frankja@linux.ibm.com> --- dump/dump.c | 100 ++++++++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 47 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index d82cc46d7d..8a2a97a85e 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -131,7 +131,7 @@ static int fd_write_vmcore(const void *buf, size_t size, void *opaque) return 0; } -static void write_elf64_header(DumpState *s, Error **errp) +static void prepare_elf64_header(DumpState *s, Elf64_Ehdr *elf_header) { /* * phnum in the elf header is 16 bit, if we have more segments we @@ -139,34 +139,27 @@ static void write_elf64_header(DumpState *s, Error **errp) * special section. */ uint16_t phnum = MIN(s->phdr_num, PN_XNUM); - Elf64_Ehdr elf_header; - int ret; - memset(&elf_header, 0, sizeof(Elf64_Ehdr)); - memcpy(&elf_header, ELFMAG, SELFMAG); - elf_header.e_ident[EI_CLASS] = ELFCLASS64; - elf_header.e_ident[EI_DATA] = s->dump_info.d_endian; - elf_header.e_ident[EI_VERSION] = EV_CURRENT; - elf_header.e_type = cpu_to_dump16(s, ET_CORE); - elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine); - elf_header.e_version = cpu_to_dump32(s, EV_CURRENT); - elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header)); - elf_header.e_phoff = cpu_to_dump64(s, s->phdr_offset); - elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr)); - elf_header.e_phnum = cpu_to_dump16(s, phnum); + memset(elf_header, 0, sizeof(Elf64_Ehdr)); + memcpy(elf_header, ELFMAG, SELFMAG); + elf_header->e_ident[EI_CLASS] = ELFCLASS64; + elf_header->e_ident[EI_DATA] = s->dump_info.d_endian; + elf_header->e_ident[EI_VERSION] = EV_CURRENT; + elf_header->e_type = cpu_to_dump16(s, ET_CORE); + elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine); + elf_header->e_version = cpu_to_dump32(s, EV_CURRENT); + elf_header->e_ehsize = cpu_to_dump16(s, sizeof(elf_header)); + elf_header->e_phoff = cpu_to_dump64(s, s->phdr_offset); + elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf64_Phdr)); + elf_header->e_phnum = cpu_to_dump16(s, phnum); if (s->shdr_num) { - elf_header.e_shoff = cpu_to_dump64(s, s->shdr_offset); - elf_header.e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr)); - elf_header.e_shnum = cpu_to_dump16(s, s->shdr_num); - } - - ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s); - if (ret < 0) { - error_setg_errno(errp, -ret, "dump: failed to write elf header"); + elf_header->e_shoff = cpu_to_dump64(s, s->shdr_offset); + elf_header->e_shentsize = cpu_to_dump16(s, sizeof(Elf64_Shdr)); + elf_header->e_shnum = cpu_to_dump16(s, s->shdr_num); } } -static void write_elf32_header(DumpState *s, Error **errp) +static void prepare_elf32_header(DumpState *s, Elf32_Ehdr *elf_header) { /* * phnum in the elf header is 16 bit, if we have more segments we @@ -174,28 +167,45 @@ static void write_elf32_header(DumpState *s, Error **errp) * special section. */ uint16_t phnum = MIN(s->phdr_num, PN_XNUM); - Elf32_Ehdr elf_header; + + memset(elf_header, 0, sizeof(Elf32_Ehdr)); + memcpy(elf_header, ELFMAG, SELFMAG); + elf_header->e_ident[EI_CLASS] = ELFCLASS32; + elf_header->e_ident[EI_DATA] = s->dump_info.d_endian; + elf_header->e_ident[EI_VERSION] = EV_CURRENT; + elf_header->e_type = cpu_to_dump16(s, ET_CORE); + elf_header->e_machine = cpu_to_dump16(s, s->dump_info.d_machine); + elf_header->e_version = cpu_to_dump32(s, EV_CURRENT); + elf_header->e_ehsize = cpu_to_dump16(s, sizeof(elf_header)); + elf_header->e_phoff = cpu_to_dump32(s, s->phdr_offset); + elf_header->e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr)); + elf_header->e_phnum = cpu_to_dump16(s, phnum); + if (s->shdr_num) { + elf_header->e_shoff = cpu_to_dump32(s, s->shdr_offset); + elf_header->e_shentsize = cpu_to_dump16(s, sizeof(Elf32_Shdr)); + elf_header->e_shnum = cpu_to_dump16(s, s->shdr_num); + } +} + +static void write_elf_header(DumpState *s, Error **errp) +{ + Elf32_Ehdr elf32_header; + Elf64_Ehdr elf64_header; + size_t header_size; + void *header_ptr; int ret; - memset(&elf_header, 0, sizeof(Elf32_Ehdr)); - memcpy(&elf_header, ELFMAG, SELFMAG); - elf_header.e_ident[EI_CLASS] = ELFCLASS32; - elf_header.e_ident[EI_DATA] = s->dump_info.d_endian; - elf_header.e_ident[EI_VERSION] = EV_CURRENT; - elf_header.e_type = cpu_to_dump16(s, ET_CORE); - elf_header.e_machine = cpu_to_dump16(s, s->dump_info.d_machine); - elf_header.e_version = cpu_to_dump32(s, EV_CURRENT); - elf_header.e_ehsize = cpu_to_dump16(s, sizeof(elf_header)); - elf_header.e_phoff = cpu_to_dump32(s, s->phdr_offset); - elf_header.e_phentsize = cpu_to_dump16(s, sizeof(Elf32_Phdr)); - elf_header.e_phnum = cpu_to_dump16(s, phnum); - if (s->shdr_num) { - elf_header.e_shoff = cpu_to_dump32(s, s->shdr_offset); - elf_header.e_shentsize = cpu_to_dump16(s, sizeof(Elf32_Shdr)); - elf_header.e_shnum = cpu_to_dump16(s, s->shdr_num); + if (dump_is_64bit(s)) { + prepare_elf64_header(s, &elf64_header); + header_size = sizeof(elf64_header); + header_ptr = &elf64_header; + } else { + prepare_elf32_header(s, &elf32_header); + header_size = sizeof(elf32_header); + header_ptr = &elf32_header; } - ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s); + ret = fd_write_vmcore(header_ptr, header_size, s); if (ret < 0) { error_setg_errno(errp, -ret, "dump: failed to write elf header"); } @@ -564,11 +574,7 @@ static void dump_begin(DumpState *s, Error **errp) */ /* write elf header to vmcore */ - if (dump_is_64bit(s)) { - write_elf64_header(s, errp); - } else { - write_elf32_header(s, errp); - } + write_elf_header(s, errp); if (*errp) { return; } From 2341a94d3a0a8a93a5a977e642da1807b8edaab8 Mon Sep 17 00:00:00 2001 From: Janosch Frank Date: Thu, 11 Aug 2022 12:11:01 +0000 Subject: [PATCH 0884/1020] dump: Rename write_elf*_phdr_note to prepare_elf*_phdr_note MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The functions in question do not actually write to the file descriptor they set up a buffer which is later written to the fd. Signed-off-by: Janosch Frank Reviewed-by: Janis Schoetterl-Glausch Reviewed-by: Marc-AndrĂ© Lureau Message-Id: <20220811121111.9878-9-frankja@linux.ibm.com> --- dump/dump.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index 8a2a97a85e..a905316fe5 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -260,7 +260,7 @@ static void write_elf32_load(DumpState *s, MemoryMapping *memory_mapping, } } -static void write_elf64_phdr_note(DumpState *s, Elf64_Phdr *phdr) +static void prepare_elf64_phdr_note(DumpState *s, Elf64_Phdr *phdr) { memset(phdr, 0, sizeof(*phdr)); phdr->p_type = cpu_to_dump32(s, PT_NOTE); @@ -316,7 +316,7 @@ static void write_elf64_notes(WriteCoreDumpFunction f, DumpState *s, write_guest_note(f, s, errp); } -static void write_elf32_phdr_note(DumpState *s, Elf32_Phdr *phdr) +static void prepare_elf32_phdr_note(DumpState *s, Elf32_Phdr *phdr) { memset(phdr, 0, sizeof(*phdr)); phdr->p_type = cpu_to_dump32(s, PT_NOTE); @@ -364,11 +364,11 @@ static void write_elf_phdr_note(DumpState *s, Error **errp) int ret; if (dump_is_64bit(s)) { - write_elf64_phdr_note(s, &phdr64); + prepare_elf64_phdr_note(s, &phdr64); size = sizeof(phdr64); phdr = &phdr64; } else { - write_elf32_phdr_note(s, &phdr32); + prepare_elf32_phdr_note(s, &phdr32); size = sizeof(phdr32); phdr = &phdr32; } From 08df343874fcddd260021a04ce3c5a34f2c48164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 25 Aug 2022 12:40:12 +0400 Subject: [PATCH 0885/1020] dump: simplify a bit kdump get_next_page() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should be functionally equivalent, but slightly easier to read, with simplified paths and checks at the end of the function. The following patch is a major rewrite to get rid of the assert(). Signed-off-by: Marc-AndrĂ© Lureau Reviewed-by: David Hildenbrand --- dump/dump.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index a905316fe5..b55a497c42 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -1132,17 +1132,11 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr, if (!block) { block = QTAILQ_FIRST(&s->guest_phys_blocks.head); *blockptr = block; - assert((block->target_start & ~target_page_mask) == 0); - assert((block->target_end & ~target_page_mask) == 0); - *pfnptr = dump_paddr_to_pfn(s, block->target_start); - if (bufptr) { - *bufptr = block->host_addr; - } - return true; + addr = block->target_start; + } else { + addr = dump_pfn_to_paddr(s, *pfnptr + 1); } - - *pfnptr = *pfnptr + 1; - addr = dump_pfn_to_paddr(s, *pfnptr); + assert(block != NULL); if ((addr >= block->target_start) && (addr + s->dump_info.page_size <= block->target_end)) { @@ -1154,12 +1148,13 @@ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr, if (!block) { return false; } - assert((block->target_start & ~target_page_mask) == 0); - assert((block->target_end & ~target_page_mask) == 0); - *pfnptr = dump_paddr_to_pfn(s, block->target_start); + addr = block->target_start; buf = block->host_addr; } + assert((block->target_start & ~target_page_mask) == 0); + assert((block->target_end & ~target_page_mask) == 0); + *pfnptr = dump_paddr_to_pfn(s, addr); if (bufptr) { *bufptr = buf; } From 94d788408d2d5a6474c99b2c9cf06913b9db7c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Mon, 5 Sep 2022 16:06:21 +0400 Subject: [PATCH 0886/1020] dump: fix kdump to work over non-aligned blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrite get_next_page() to work over non-aligned blocks. When it encounters non aligned addresses, it will try to fill a page provided by the caller. This solves a kdump crash with "tpm-crb-cmd" RAM memory region, qemu-kvm: ../dump/dump.c:1162: _Bool get_next_page(GuestPhysBlock **, uint64_t *, uint8_t **, DumpState *): Assertion `(block->target_start & ~target_page_mask) == 0' failed. because: guest_phys_block_add_section: target_start=00000000fed40080 target_end=00000000fed41000: added (count: 4) Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2120480 Signed-off-by: Marc-AndrĂ© Lureau Acked-by: David Hildenbrand --- dump/dump.c | 79 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 56 insertions(+), 23 deletions(-) diff --git a/dump/dump.c b/dump/dump.c index b55a497c42..236559b03a 100644 --- a/dump/dump.c +++ b/dump/dump.c @@ -1116,50 +1116,81 @@ static uint64_t dump_pfn_to_paddr(DumpState *s, uint64_t pfn) } /* - * exam every page and return the page frame number and the address of the page. - * bufptr can be NULL. note: the blocks here is supposed to reflect guest-phys - * blocks, so block->target_start and block->target_end should be interal - * multiples of the target page size. + * Return the page frame number and the page content in *bufptr. bufptr can be + * NULL. If not NULL, *bufptr must contains a target page size of pre-allocated + * memory. This is not necessarily the memory returned. */ static bool get_next_page(GuestPhysBlock **blockptr, uint64_t *pfnptr, uint8_t **bufptr, DumpState *s) { GuestPhysBlock *block = *blockptr; - hwaddr addr, target_page_mask = ~((hwaddr)s->dump_info.page_size - 1); - uint8_t *buf; + uint32_t page_size = s->dump_info.page_size; + uint8_t *buf = NULL, *hbuf; + hwaddr addr; /* block == NULL means the start of the iteration */ if (!block) { block = QTAILQ_FIRST(&s->guest_phys_blocks.head); *blockptr = block; addr = block->target_start; + *pfnptr = dump_paddr_to_pfn(s, addr); } else { - addr = dump_pfn_to_paddr(s, *pfnptr + 1); + *pfnptr += 1; + addr = dump_pfn_to_paddr(s, *pfnptr); } assert(block != NULL); - if ((addr >= block->target_start) && - (addr + s->dump_info.page_size <= block->target_end)) { - buf = block->host_addr + (addr - block->target_start); - } else { - /* the next page is in the next block */ - block = QTAILQ_NEXT(block, next); - *blockptr = block; - if (!block) { - return false; + while (1) { + if (addr >= block->target_start && addr < block->target_end) { + size_t n = MIN(block->target_end - addr, page_size - addr % page_size); + hbuf = block->host_addr + (addr - block->target_start); + if (!buf) { + if (n == page_size) { + /* this is a whole target page, go for it */ + assert(addr % page_size == 0); + buf = hbuf; + break; + } else if (bufptr) { + assert(*bufptr); + buf = *bufptr; + memset(buf, 0, page_size); + } else { + return true; + } + } + + memcpy(buf + addr % page_size, hbuf, n); + addr += n; + if (addr % page_size == 0) { + /* we filled up the page */ + break; + } + } else { + /* the next page is in the next block */ + *blockptr = block = QTAILQ_NEXT(block, next); + if (!block) { + break; + } + + addr = block->target_start; + /* are we still in the same page? */ + if (dump_paddr_to_pfn(s, addr) != *pfnptr) { + if (buf) { + /* no, but we already filled something earlier, return it */ + break; + } else { + /* else continue from there */ + *pfnptr = dump_paddr_to_pfn(s, addr); + } + } } - addr = block->target_start; - buf = block->host_addr; } - assert((block->target_start & ~target_page_mask) == 0); - assert((block->target_end & ~target_page_mask) == 0); - *pfnptr = dump_paddr_to_pfn(s, addr); if (bufptr) { *bufptr = buf; } - return true; + return buf != NULL; } static void write_dump_bitmap(DumpState *s, Error **errp) @@ -1297,6 +1328,7 @@ static void write_dump_pages(DumpState *s, Error **errp) uint8_t *buf; GuestPhysBlock *block_iter = NULL; uint64_t pfn_iter; + g_autofree uint8_t *page = NULL; /* get offset of page_desc and page_data in dump file */ offset_desc = s->offset_page; @@ -1332,12 +1364,13 @@ static void write_dump_pages(DumpState *s, Error **errp) } offset_data += s->dump_info.page_size; + page = g_malloc(s->dump_info.page_size); /* * dump memory to vmcore page by page. zero page will all be resided in the * first page of page section */ - while (get_next_page(&block_iter, &pfn_iter, &buf, s)) { + for (buf = page; get_next_page(&block_iter, &pfn_iter, &buf, s); buf = page) { /* check zero page */ if (buffer_is_zero(buf, s->dump_info.page_size)) { ret = write_cache(&page_desc, &pd_zero, sizeof(PageDescriptor), From 34f58df51daf49863077d2b809f08510a20b4d9a Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 30 Sep 2022 19:19:08 +0200 Subject: [PATCH 0887/1020] Revert "qapi: fix examples of blockdev-add with qcow2" This reverts commit b6522938327141235b97ab38e40c6c4512587373. Kevin Wolf NAKed this patch, because: 'file' is a required member (defined in BlockdevOptionsGenericFormat), removing it makes the example invalid. 'data-file' is only an additional optional member to be used for external data files (i.e. when the guest data is kept separate from the metadata in the .qcow2 file). However, it had already been merged then. Revert. Signed-off-by: Markus Armbruster Message-Id: <20220930171908.846769-1-armbru@redhat.com> Reviewed-by: Victor Toso Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- qapi/block-core.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qapi/block-core.json b/qapi/block-core.json index f21fa235f2..882b266532 100644 --- a/qapi/block-core.json +++ b/qapi/block-core.json @@ -1541,8 +1541,8 @@ # -> { "execute": "blockdev-add", # "arguments": { "driver": "qcow2", # "node-name": "node1534", -# "data-file": { "driver": "file", -# "filename": "hd1.qcow2" }, +# "file": { "driver": "file", +# "filename": "hd1.qcow2" }, # "backing": null } } # # <- { "return": {} } @@ -4378,7 +4378,7 @@ # "arguments": { # "driver": "qcow2", # "node-name": "test1", -# "data-file": { +# "file": { # "driver": "file", # "filename": "test.qcow2" # } @@ -4395,7 +4395,7 @@ # "cache": { # "direct": true # }, -# "data-file": { +# "file": { # "driver": "file", # "filename": "/tmp/test.qcow2" # }, @@ -4477,7 +4477,7 @@ # "arguments": { # "driver": "qcow2", # "node-name": "node0", -# "data-file": { +# "file": { # "driver": "file", # "filename": "test.qcow2" # } From ef770f8101f6a3f4fb38a4fa693dfe68a0ac6bf2 Mon Sep 17 00:00:00 2001 From: Alberto Faria Date: Wed, 5 Oct 2022 18:52:09 +0100 Subject: [PATCH 0888/1020] coroutine: Drop coroutine_fn annotation from qemu_coroutine_self() qemu_coroutine_self() can be called from outside coroutine context, returning the leader coroutine, and several such invocations currently exist (mostly in qcow2 tracing calls). Signed-off-by: Alberto Faria Message-Id: <20221005175209.975797-1-afaria@redhat.com> Reviewed-by: Kevin Wolf Reviewed-by: Paolo Bonzini Signed-off-by: Kevin Wolf --- include/qemu/coroutine.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index 08c5bb3c76..414b677302 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -97,7 +97,7 @@ AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co); /** * Get the currently executing coroutine */ -Coroutine *coroutine_fn qemu_coroutine_self(void); +Coroutine *qemu_coroutine_self(void); /** * Return whether or not currently inside a coroutine From 82c45371ba698ff63e9d3d4792a34593f73e54d8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:48:59 +0200 Subject: [PATCH 0889/1020] block/nvme: separate nvme_get_free_req cases for coroutine/non-coroutine context nvme_get_free_req has very difference semantics when called in coroutine context (where it waits) and in non-coroutine context (where it doesn't). Split the two cases to make it clear what is being requested. Cc: qemu-block@nongnu.org Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-2-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/nvme.c | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/block/nvme.c b/block/nvme.c index 01fb28aa63..0870f87bc6 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -293,34 +293,42 @@ static void nvme_kick(NVMeQueuePair *q) q->need_kick = 0; } -/* Find a free request element if any, otherwise: - * a) if in coroutine context, try to wait for one to become available; - * b) if not in coroutine, return NULL; - */ -static NVMeRequest *nvme_get_free_req(NVMeQueuePair *q) +static NVMeRequest *nvme_get_free_req_nofail_locked(NVMeQueuePair *q) { NVMeRequest *req; - qemu_mutex_lock(&q->lock); - - while (q->free_req_head == -1) { - if (qemu_in_coroutine()) { - trace_nvme_free_req_queue_wait(q->s, q->index); - qemu_co_queue_wait(&q->free_req_queue, &q->lock); - } else { - qemu_mutex_unlock(&q->lock); - return NULL; - } - } - req = &q->reqs[q->free_req_head]; q->free_req_head = req->free_req_next; req->free_req_next = -1; - - qemu_mutex_unlock(&q->lock); return req; } +/* Return a free request element if any, otherwise return NULL. */ +static NVMeRequest *nvme_get_free_req_nowait(NVMeQueuePair *q) +{ + QEMU_LOCK_GUARD(&q->lock); + if (q->free_req_head == -1) { + return NULL; + } + return nvme_get_free_req_nofail_locked(q); +} + +/* + * Wait for a free request to become available if necessary, then + * return it. + */ +static coroutine_fn NVMeRequest *nvme_get_free_req(NVMeQueuePair *q) +{ + QEMU_LOCK_GUARD(&q->lock); + + while (q->free_req_head == -1) { + trace_nvme_free_req_queue_wait(q->s, q->index); + qemu_co_queue_wait(&q->free_req_queue, &q->lock); + } + + return nvme_get_free_req_nofail_locked(q); +} + /* With q->lock */ static void nvme_put_free_req_locked(NVMeQueuePair *q, NVMeRequest *req) { @@ -506,7 +514,7 @@ static int nvme_admin_cmd_sync(BlockDriverState *bs, NvmeCmd *cmd) AioContext *aio_context = bdrv_get_aio_context(bs); NVMeRequest *req; int ret = -EINPROGRESS; - req = nvme_get_free_req(q); + req = nvme_get_free_req_nowait(q); if (!req) { return -EBUSY; } From 881a4c553c06caa3b05a729b13d3cc781506c3a8 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:00 +0200 Subject: [PATCH 0890/1020] block: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-3-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block.c | 7 ++++--- block/block-backend.c | 10 +++++----- block/io.c | 22 +++++++++++----------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/block.c b/block.c index bc85f46eed..9b0fae5c1e 100644 --- a/block.c +++ b/block.c @@ -631,9 +631,10 @@ static int64_t create_file_fallback_truncate(BlockBackend *blk, * Helper function for bdrv_create_file_fallback(): Zero the first * sector to remove any potentially pre-existing image header. */ -static int create_file_fallback_zero_first_sector(BlockBackend *blk, - int64_t current_size, - Error **errp) +static int coroutine_fn +create_file_fallback_zero_first_sector(BlockBackend *blk, + int64_t current_size, + Error **errp) { int64_t bytes_to_clear; int ret; diff --git a/block/block-backend.c b/block/block-backend.c index d4a5df2ac2..aa4adf06ae 100644 --- a/block/block-backend.c +++ b/block/block-backend.c @@ -1546,7 +1546,7 @@ static BlockAIOCB *blk_aio_prwv(BlockBackend *blk, int64_t offset, return &acb->common; } -static void blk_aio_read_entry(void *opaque) +static void coroutine_fn blk_aio_read_entry(void *opaque) { BlkAioEmAIOCB *acb = opaque; BlkRwCo *rwco = &acb->rwco; @@ -1558,7 +1558,7 @@ static void blk_aio_read_entry(void *opaque) blk_aio_complete(acb); } -static void blk_aio_write_entry(void *opaque) +static void coroutine_fn blk_aio_write_entry(void *opaque) { BlkAioEmAIOCB *acb = opaque; BlkRwCo *rwco = &acb->rwco; @@ -1669,7 +1669,7 @@ int coroutine_fn blk_co_ioctl(BlockBackend *blk, unsigned long int req, return ret; } -static void blk_aio_ioctl_entry(void *opaque) +static void coroutine_fn blk_aio_ioctl_entry(void *opaque) { BlkAioEmAIOCB *acb = opaque; BlkRwCo *rwco = &acb->rwco; @@ -1703,7 +1703,7 @@ blk_co_do_pdiscard(BlockBackend *blk, int64_t offset, int64_t bytes) return bdrv_co_pdiscard(blk->root, offset, bytes); } -static void blk_aio_pdiscard_entry(void *opaque) +static void coroutine_fn blk_aio_pdiscard_entry(void *opaque) { BlkAioEmAIOCB *acb = opaque; BlkRwCo *rwco = &acb->rwco; @@ -1747,7 +1747,7 @@ static int coroutine_fn blk_co_do_flush(BlockBackend *blk) return bdrv_co_flush(blk_bs(blk)); } -static void blk_aio_flush_entry(void *opaque) +static void coroutine_fn blk_aio_flush_entry(void *opaque) { BlkAioEmAIOCB *acb = opaque; BlkRwCo *rwco = &acb->rwco; diff --git a/block/io.c b/block/io.c index c3200bcdff..d30073036e 100644 --- a/block/io.c +++ b/block/io.c @@ -751,11 +751,11 @@ static void coroutine_fn tracked_request_end(BdrvTrackedRequest *req) /** * Add an active request to the tracked requests list */ -static void tracked_request_begin(BdrvTrackedRequest *req, - BlockDriverState *bs, - int64_t offset, - int64_t bytes, - enum BdrvTrackedRequestType type) +static void coroutine_fn tracked_request_begin(BdrvTrackedRequest *req, + BlockDriverState *bs, + int64_t offset, + int64_t bytes, + enum BdrvTrackedRequestType type) { bdrv_check_request(offset, bytes, &error_abort); @@ -794,7 +794,7 @@ static bool tracked_request_overlaps(BdrvTrackedRequest *req, } /* Called with self->bs->reqs_lock held */ -static BdrvTrackedRequest * +static coroutine_fn BdrvTrackedRequest * bdrv_find_conflicting_request(BdrvTrackedRequest *self) { BdrvTrackedRequest *req; @@ -1635,10 +1635,10 @@ static bool bdrv_init_padding(BlockDriverState *bs, return true; } -static int bdrv_padding_rmw_read(BdrvChild *child, - BdrvTrackedRequest *req, - BdrvRequestPadding *pad, - bool zero_middle) +static coroutine_fn int bdrv_padding_rmw_read(BdrvChild *child, + BdrvTrackedRequest *req, + BdrvRequestPadding *pad, + bool zero_middle) { QEMUIOVector local_qiov; BlockDriverState *bs = child->bs; @@ -3159,7 +3159,7 @@ out: return ret; } -int bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf) +int coroutine_fn bdrv_co_ioctl(BlockDriverState *bs, int req, void *buf) { BlockDriver *drv = bs->drv; CoroutineIOCompletion co = { From 3840144987840131c6d490d2460443e4b9ef062e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:01 +0200 Subject: [PATCH 0891/1020] qcow2: remove incorrect coroutine_fn annotations This is incorrect because qcow2_mark_clean() calls qcow2_flush_caches(). qcow2_mark_clean() is called from non-coroutine context in qcow2_inactivate() and qcow2_amend_options(). Reviewed-by: Alberto Faria Reviewed-by: Eric Blake Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-4-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/qcow2-refcount.c | 4 ++-- block/qcow2.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index c4d99817b6..1a6277c783 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -1206,7 +1206,7 @@ void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry, } } -int coroutine_fn qcow2_write_caches(BlockDriverState *bs) +int qcow2_write_caches(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; int ret; @@ -1226,7 +1226,7 @@ int coroutine_fn qcow2_write_caches(BlockDriverState *bs) return 0; } -int coroutine_fn qcow2_flush_caches(BlockDriverState *bs) +int qcow2_flush_caches(BlockDriverState *bs) { int ret = qcow2_write_caches(bs); if (ret < 0) { diff --git a/block/qcow2.h b/block/qcow2.h index ba436a8d0d..c8d9e8ea79 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -874,8 +874,8 @@ void qcow2_free_any_cluster(BlockDriverState *bs, uint64_t l2_entry, int qcow2_update_snapshot_refcount(BlockDriverState *bs, int64_t l1_table_offset, int l1_size, int addend); -int coroutine_fn qcow2_flush_caches(BlockDriverState *bs); -int coroutine_fn qcow2_write_caches(BlockDriverState *bs); +int qcow2_flush_caches(BlockDriverState *bs); +int qcow2_write_caches(BlockDriverState *bs); int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res, BdrvCheckMode fix); From 9fb26291acf9806e5b1211db2315e1d4140cfe40 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:02 +0200 Subject: [PATCH 0892/1020] nbd: remove incorrect coroutine_fn annotations nbd_co_establish_connection_cancel() cancels a coroutine but is not called from coroutine context itself, for example in nbd_cancel_in_flight() and in timer callbacks reconnect_delay_timer_cb() and open_timer_cb(). Reviewed-by: Alberto Faria Reviewed-by: Eric Blake Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-5-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/block/nbd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/block/nbd.h b/include/block/nbd.h index c74b7a9d2e..4ede3b2bd0 100644 --- a/include/block/nbd.h +++ b/include/block/nbd.h @@ -424,6 +424,6 @@ QIOChannel *coroutine_fn nbd_co_establish_connection(NBDClientConnection *conn, NBDExportInfo *info, bool blocking, Error **errp); -void coroutine_fn nbd_co_establish_connection_cancel(NBDClientConnection *conn); +void nbd_co_establish_connection_cancel(NBDClientConnection *conn); #endif From a248b856a8a9683fa03bbb6e1d684a9c67d92791 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:03 +0200 Subject: [PATCH 0893/1020] coroutine: remove incorrect coroutine_fn annotations qemu_coroutine_get_aio_context inspects a coroutine, but it does not have to be called from the coroutine itself (or from any coroutine). Reviewed-by: Alberto Faria Reviewed-by: Eric Blake Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-6-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/qemu/coroutine.h | 2 +- util/qemu-coroutine.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/qemu/coroutine.h b/include/qemu/coroutine.h index 414b677302..aae33cce17 100644 --- a/include/qemu/coroutine.h +++ b/include/qemu/coroutine.h @@ -92,7 +92,7 @@ void coroutine_fn qemu_coroutine_yield(void); /** * Get the AioContext of the given coroutine */ -AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co); +AioContext *qemu_coroutine_get_aio_context(Coroutine *co); /** * Get the currently executing coroutine diff --git a/util/qemu-coroutine.c b/util/qemu-coroutine.c index 4a8bd63ef0..356b746f0b 100644 --- a/util/qemu-coroutine.c +++ b/util/qemu-coroutine.c @@ -213,7 +213,7 @@ bool qemu_coroutine_entered(Coroutine *co) return co->caller; } -AioContext *coroutine_fn qemu_coroutine_get_aio_context(Coroutine *co) +AioContext *qemu_coroutine_get_aio_context(Coroutine *co) { return co->ctx; } From 617b4b17fbddb31742bb9a854e6acdbee65c4fc0 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:05 +0200 Subject: [PATCH 0894/1020] blkverify: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Reviewed-by: Eric Blake Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-8-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/blkverify.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/blkverify.c b/block/blkverify.c index e4a37af3b2..020b1ae7b6 100644 --- a/block/blkverify.c +++ b/block/blkverify.c @@ -258,7 +258,7 @@ blkverify_co_pwritev(BlockDriverState *bs, int64_t offset, int64_t bytes, return blkverify_co_prwv(bs, &r, offset, bytes, qiov, qiov, flags, true); } -static int blkverify_co_flush(BlockDriverState *bs) +static int coroutine_fn blkverify_co_flush(BlockDriverState *bs) { BDRVBlkverifyState *s = bs->opaque; From dda56b759734b5f3f4c162f8d5822b8b2a9a60f9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:06 +0200 Subject: [PATCH 0895/1020] file-posix: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Reviewed-by: Eric Blake Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-9-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/file-posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/file-posix.c b/block/file-posix.c index 66fdb07820..ad3021938b 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -2180,7 +2180,7 @@ static void raw_aio_unplug(BlockDriverState *bs) #endif } -static int raw_co_flush_to_disk(BlockDriverState *bs) +static int coroutine_fn raw_co_flush_to_disk(BlockDriverState *bs) { BDRVRawState *s = bs->opaque; RawPosixAIOData acb; From 3d6dcf40cebca93b432bfd888009cb1bcaa70a40 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:07 +0200 Subject: [PATCH 0896/1020] iscsi: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Reviewed-by: Eric Blake Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-10-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/iscsi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/iscsi.c b/block/iscsi.c index 612de127e5..a316d46d96 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -290,7 +290,8 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, } } -static void iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask) +static void coroutine_fn +iscsi_co_init_iscsitask(IscsiLun *iscsilun, struct IscsiTask *iTask) { *iTask = (struct IscsiTask) { .co = qemu_coroutine_self(), From 8e5a19df670423d5166351c38fa5b849d13ffb2e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:08 +0200 Subject: [PATCH 0897/1020] nbd: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Reviewed-by: Eric Blake Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-11-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/nbd.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/block/nbd.c b/block/nbd.c index 97683cce27..494b9d683e 100644 --- a/block/nbd.c +++ b/block/nbd.c @@ -983,11 +983,12 @@ static void nbd_iter_request_error(NBDReplyChunkIter *iter, int ret) * nbd_reply_chunk_iter_receive * The pointer stored in @payload requires g_free() to free it. */ -static bool nbd_reply_chunk_iter_receive(BDRVNBDState *s, - NBDReplyChunkIter *iter, - uint64_t handle, - QEMUIOVector *qiov, NBDReply *reply, - void **payload) +static bool coroutine_fn nbd_reply_chunk_iter_receive(BDRVNBDState *s, + NBDReplyChunkIter *iter, + uint64_t handle, + QEMUIOVector *qiov, + NBDReply *reply, + void **payload) { int ret, request_ret; NBDReply local_reply; From ee15ee36205258ba7ced7a48358e32468109cd70 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:09 +0200 Subject: [PATCH 0898/1020] nfs: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-12-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/nfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/nfs.c b/block/nfs.c index 444c40b458..596ebe98cb 100644 --- a/block/nfs.c +++ b/block/nfs.c @@ -223,7 +223,7 @@ static void nfs_process_write(void *arg) qemu_mutex_unlock(&client->mutex); } -static void nfs_co_init_task(BlockDriverState *bs, NFSRPC *task) +static void coroutine_fn nfs_co_init_task(BlockDriverState *bs, NFSRPC *task) { *task = (NFSRPC) { .co = qemu_coroutine_self(), From 711b12e7c35fc0c8970ac9e8a8dca72e18458c09 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:10 +0200 Subject: [PATCH 0899/1020] nvme: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-13-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/nvme.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/block/nvme.c b/block/nvme.c index 0870f87bc6..2b24f95164 100644 --- a/block/nvme.c +++ b/block/nvme.c @@ -1242,8 +1242,10 @@ static inline bool nvme_qiov_aligned(BlockDriverState *bs, return true; } -static int nvme_co_prw(BlockDriverState *bs, uint64_t offset, uint64_t bytes, - QEMUIOVector *qiov, bool is_write, int flags) +static coroutine_fn int nvme_co_prw(BlockDriverState *bs, + uint64_t offset, uint64_t bytes, + QEMUIOVector *qiov, bool is_write, + int flags) { BDRVNVMeState *s = bs->opaque; int r; From 7644d2dca88916a0f69aa72a4e591c3d79c212db Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:11 +0200 Subject: [PATCH 0900/1020] parallels: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-14-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/parallels.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/block/parallels.c b/block/parallels.c index a229c06f25..c1523e7dab 100644 --- a/block/parallels.c +++ b/block/parallels.c @@ -165,8 +165,9 @@ static int64_t block_status(BDRVParallelsState *s, int64_t sector_num, return start_off; } -static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num, - int nb_sectors, int *pnum) +static coroutine_fn int64_t allocate_clusters(BlockDriverState *bs, + int64_t sector_num, + int nb_sectors, int *pnum) { int ret = 0; BDRVParallelsState *s = bs->opaque; From 050ed2e7362c9086c07a86965ac754d1e46a7138 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:12 +0200 Subject: [PATCH 0901/1020] qcow2: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-15-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/qcow2-cluster.c | 21 ++++++++++++--------- block/qcow2-refcount.c | 2 +- block/qcow2.c | 5 +++-- block/qcow2.h | 15 ++++++++------- 4 files changed, 24 insertions(+), 19 deletions(-) diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c index fd32316d6f..0f293950a1 100644 --- a/block/qcow2-cluster.c +++ b/block/qcow2-cluster.c @@ -884,7 +884,7 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, return 0; } -static int perform_cow(BlockDriverState *bs, QCowL2Meta *m) +static int coroutine_fn perform_cow(BlockDriverState *bs, QCowL2Meta *m) { BDRVQcow2State *s = bs->opaque; Qcow2COWRegion *start = &m->cow_start; @@ -1024,7 +1024,8 @@ fail: return ret; } -int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m) +int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs, + QCowL2Meta *m) { BDRVQcow2State *s = bs->opaque; int i, j = 0, l2_index, ret; @@ -1397,8 +1398,9 @@ static int count_single_write_clusters(BlockDriverState *bs, int nb_clusters, * information on cluster allocation may be invalid now. The caller * must start over anyway, so consider *cur_bytes undefined. */ -static int handle_dependencies(BlockDriverState *bs, uint64_t guest_offset, - uint64_t *cur_bytes, QCowL2Meta **m) +static int coroutine_fn handle_dependencies(BlockDriverState *bs, + uint64_t guest_offset, + uint64_t *cur_bytes, QCowL2Meta **m) { BDRVQcow2State *s = bs->opaque; QCowL2Meta *old_alloc; @@ -1772,9 +1774,10 @@ out: * * Return 0 on success and -errno in error cases */ -int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, - unsigned int *bytes, uint64_t *host_offset, - QCowL2Meta **m) +int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, + unsigned int *bytes, + uint64_t *host_offset, + QCowL2Meta **m) { BDRVQcow2State *s = bs->opaque; uint64_t start, remaining; @@ -2105,8 +2108,8 @@ out: return ret; } -int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, int flags) +int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, int flags) { BDRVQcow2State *s = bs->opaque; uint64_t end_offset = offset + bytes; diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c index 1a6277c783..1fbb07ca77 100644 --- a/block/qcow2-refcount.c +++ b/block/qcow2-refcount.c @@ -3706,7 +3706,7 @@ int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size) return -EIO; } -int qcow2_detect_metadata_preallocation(BlockDriverState *bs) +int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs) { BDRVQcow2State *s = bs->opaque; int64_t i, end_cluster, cluster_count = 0, threshold; diff --git a/block/qcow2.c b/block/qcow2.c index 6c8c8b2b5a..b57f7cc8ee 100644 --- a/block/qcow2.c +++ b/block/qcow2.c @@ -2448,7 +2448,7 @@ static bool merge_cow(uint64_t offset, unsigned bytes, * Return 1 if the COW regions read as zeroes, 0 if not, < 0 on error. * Note that returning 0 does not guarantee non-zero data. */ -static int is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) +static int coroutine_fn is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) { /* * This check is designed for optimization shortcut so it must be @@ -2466,7 +2466,8 @@ static int is_zero_cow(BlockDriverState *bs, QCowL2Meta *m) m->cow_end.nb_bytes); } -static int handle_alloc_space(BlockDriverState *bs, QCowL2Meta *l2meta) +static int coroutine_fn handle_alloc_space(BlockDriverState *bs, + QCowL2Meta *l2meta) { BDRVQcow2State *s = bs->opaque; QCowL2Meta *m; diff --git a/block/qcow2.h b/block/qcow2.h index c8d9e8ea79..3e7c5e80b6 100644 --- a/block/qcow2.h +++ b/block/qcow2.h @@ -895,7 +895,7 @@ int qcow2_change_refcount_order(BlockDriverState *bs, int refcount_order, void *cb_opaque, Error **errp); int qcow2_shrink_reftable(BlockDriverState *bs); int64_t qcow2_get_last_cluster(BlockDriverState *bs, int64_t size); -int qcow2_detect_metadata_preallocation(BlockDriverState *bs); +int coroutine_fn qcow2_detect_metadata_preallocation(BlockDriverState *bs); /* qcow2-cluster.c functions */ int qcow2_grow_l1_table(BlockDriverState *bs, uint64_t min_size, @@ -908,9 +908,9 @@ int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num, int qcow2_get_host_offset(BlockDriverState *bs, uint64_t offset, unsigned int *bytes, uint64_t *host_offset, QCow2SubclusterType *subcluster_type); -int qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, - unsigned int *bytes, uint64_t *host_offset, - QCowL2Meta **m); +int coroutine_fn qcow2_alloc_host_offset(BlockDriverState *bs, uint64_t offset, + unsigned int *bytes, + uint64_t *host_offset, QCowL2Meta **m); int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, uint64_t offset, int compressed_size, @@ -918,13 +918,14 @@ int qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs, void qcow2_parse_compressed_l2_entry(BlockDriverState *bs, uint64_t l2_entry, uint64_t *coffset, int *csize); -int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m); +int coroutine_fn qcow2_alloc_cluster_link_l2(BlockDriverState *bs, + QCowL2Meta *m); void qcow2_alloc_cluster_abort(BlockDriverState *bs, QCowL2Meta *m); int qcow2_cluster_discard(BlockDriverState *bs, uint64_t offset, uint64_t bytes, enum qcow2_discard_type type, bool full_discard); -int qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, int flags); +int coroutine_fn qcow2_subcluster_zeroize(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, int flags); int qcow2_expand_zero_clusters(BlockDriverState *bs, BlockDriverAmendStatusCB *status_cb, From 3e614042c4ab0f371351e1a8bf0577bd0c9defab Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:13 +0200 Subject: [PATCH 0902/1020] copy-before-write: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-16-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/copy-before-write.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/block/copy-before-write.c b/block/copy-before-write.c index c24b8dd117..afbdd04489 100644 --- a/block/copy-before-write.c +++ b/block/copy-before-write.c @@ -203,9 +203,9 @@ static int coroutine_fn cbw_co_flush(BlockDriverState *bs) * It's guaranteed that guest writes will not interact in the region until * cbw_snapshot_read_unlock() called. */ -static BlockReq *cbw_snapshot_read_lock(BlockDriverState *bs, - int64_t offset, int64_t bytes, - int64_t *pnum, BdrvChild **file) +static coroutine_fn BlockReq * +cbw_snapshot_read_lock(BlockDriverState *bs, int64_t offset, int64_t bytes, + int64_t *pnum, BdrvChild **file) { BDRVCopyBeforeWriteState *s = bs->opaque; BlockReq *req = g_new(BlockReq, 1); @@ -240,7 +240,8 @@ static BlockReq *cbw_snapshot_read_lock(BlockDriverState *bs, return req; } -static void cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req) +static coroutine_fn void +cbw_snapshot_read_unlock(BlockDriverState *bs, BlockReq *req) { BDRVCopyBeforeWriteState *s = bs->opaque; From 9bae2aca0f852e3b7547ef954e481c63aef1f553 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:14 +0200 Subject: [PATCH 0903/1020] curl: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-17-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/curl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/curl.c b/block/curl.c index 1e0f609579..cba4c4cac7 100644 --- a/block/curl.c +++ b/block/curl.c @@ -855,7 +855,7 @@ out_noclean: return -EINVAL; } -static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb) +static void coroutine_fn curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb) { CURLState *state; int running; From b383ae60a2bdc58b76e7c1f5a79e82075a0a2507 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:15 +0200 Subject: [PATCH 0904/1020] qed: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-18-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/qed.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/qed.c b/block/qed.c index 324ca0e95a..bda00e6257 100644 --- a/block/qed.c +++ b/block/qed.c @@ -254,7 +254,7 @@ static CachedL2Table *qed_new_l2_table(BDRVQEDState *s) return l2_table; } -static bool qed_plug_allocating_write_reqs(BDRVQEDState *s) +static bool coroutine_fn qed_plug_allocating_write_reqs(BDRVQEDState *s) { qemu_co_mutex_lock(&s->table_lock); @@ -273,7 +273,7 @@ static bool qed_plug_allocating_write_reqs(BDRVQEDState *s) return true; } -static void qed_unplug_allocating_write_reqs(BDRVQEDState *s) +static void coroutine_fn qed_unplug_allocating_write_reqs(BDRVQEDState *s) { qemu_co_mutex_lock(&s->table_lock); assert(s->allocating_write_reqs_plugged); From 2987ae7d84dd46e784effb2107a21489fab95781 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:16 +0200 Subject: [PATCH 0905/1020] quorum: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-19-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/quorum.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/block/quorum.c b/block/quorum.c index f33f30d36b..970f63d9f9 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -161,11 +161,10 @@ static bool quorum_64bits_compare(QuorumVoteValue *a, QuorumVoteValue *b) return a->l == b->l; } -static QuorumAIOCB *quorum_aio_get(BlockDriverState *bs, - QEMUIOVector *qiov, - uint64_t offset, - uint64_t bytes, - int flags) +static QuorumAIOCB *coroutine_fn quorum_aio_get(BlockDriverState *bs, + QEMUIOVector *qiov, + uint64_t offset, uint64_t bytes, + int flags) { BDRVQuorumState *s = bs->opaque; QuorumAIOCB *acb = g_new(QuorumAIOCB, 1); @@ -273,7 +272,7 @@ static void quorum_report_bad_versions(BDRVQuorumState *s, } } -static void quorum_rewrite_entry(void *opaque) +static void coroutine_fn quorum_rewrite_entry(void *opaque) { QuorumCo *co = opaque; QuorumAIOCB *acb = co->acb; @@ -574,7 +573,7 @@ free_exit: quorum_free_vote_list(&acb->votes); } -static void read_quorum_children_entry(void *opaque) +static void coroutine_fn read_quorum_children_entry(void *opaque) { QuorumCo *co = opaque; QuorumAIOCB *acb = co->acb; @@ -602,7 +601,7 @@ static void read_quorum_children_entry(void *opaque) } } -static int read_quorum_children(QuorumAIOCB *acb) +static int coroutine_fn read_quorum_children(QuorumAIOCB *acb) { BDRVQuorumState *s = acb->bs->opaque; int i; @@ -643,7 +642,7 @@ static int read_quorum_children(QuorumAIOCB *acb) return acb->vote_ret; } -static int read_fifo_child(QuorumAIOCB *acb) +static int coroutine_fn read_fifo_child(QuorumAIOCB *acb) { BDRVQuorumState *s = acb->bs->opaque; int n, ret; @@ -664,8 +663,10 @@ static int read_fifo_child(QuorumAIOCB *acb) return ret; } -static int quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, - QEMUIOVector *qiov, BdrvRequestFlags flags) +static int coroutine_fn quorum_co_preadv(BlockDriverState *bs, + int64_t offset, int64_t bytes, + QEMUIOVector *qiov, + BdrvRequestFlags flags) { BDRVQuorumState *s = bs->opaque; QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags); @@ -684,7 +685,7 @@ static int quorum_co_preadv(BlockDriverState *bs, int64_t offset, int64_t bytes, return ret; } -static void write_quorum_entry(void *opaque) +static void coroutine_fn write_quorum_entry(void *opaque) { QuorumCo *co = opaque; QuorumAIOCB *acb = co->acb; @@ -715,9 +716,9 @@ static void write_quorum_entry(void *opaque) } } -static int quorum_co_pwritev(BlockDriverState *bs, int64_t offset, - int64_t bytes, QEMUIOVector *qiov, - BdrvRequestFlags flags) +static int coroutine_fn quorum_co_pwritev(BlockDriverState *bs, int64_t offset, + int64_t bytes, QEMUIOVector *qiov, + BdrvRequestFlags flags) { BDRVQuorumState *s = bs->opaque; QuorumAIOCB *acb = quorum_aio_get(bs, qiov, offset, bytes, flags); @@ -746,8 +747,9 @@ static int quorum_co_pwritev(BlockDriverState *bs, int64_t offset, return ret; } -static int quorum_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset, - int64_t bytes, BdrvRequestFlags flags) +static int coroutine_fn quorum_co_pwrite_zeroes(BlockDriverState *bs, + int64_t offset, int64_t bytes, + BdrvRequestFlags flags) { return quorum_co_pwritev(bs, offset, bytes, NULL, From 4cb1bc3464136832d936eca00330ad70d70d770e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:17 +0200 Subject: [PATCH 0906/1020] throttle: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-20-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/throttle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/throttle.c b/block/throttle.c index 6e8d52fa24..ddd450593a 100644 --- a/block/throttle.c +++ b/block/throttle.c @@ -162,7 +162,7 @@ static int coroutine_fn throttle_co_pwritev_compressed(BlockDriverState *bs, BDRV_REQ_WRITE_COMPRESSED); } -static int throttle_co_flush(BlockDriverState *bs) +static int coroutine_fn throttle_co_flush(BlockDriverState *bs) { return bdrv_co_flush(bs->file->bs); } From b4df990377bdaa6d6ad4a507e12750988eba5913 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:18 +0200 Subject: [PATCH 0907/1020] vmdk: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-21-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/vmdk.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/block/vmdk.c b/block/vmdk.c index fe07a54866..f7d8856dfb 100644 --- a/block/vmdk.c +++ b/block/vmdk.c @@ -1787,10 +1787,11 @@ static int coroutine_fn vmdk_co_block_status(BlockDriverState *bs, return ret; } -static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, - int64_t offset_in_cluster, QEMUIOVector *qiov, - uint64_t qiov_offset, uint64_t n_bytes, - uint64_t offset) +static int coroutine_fn +vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, + int64_t offset_in_cluster, QEMUIOVector *qiov, + uint64_t qiov_offset, uint64_t n_bytes, + uint64_t offset) { int ret; VmdkGrainMarker *data = NULL; @@ -1868,9 +1869,10 @@ static int vmdk_write_extent(VmdkExtent *extent, int64_t cluster_offset, return ret; } -static int vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, - int64_t offset_in_cluster, QEMUIOVector *qiov, - int bytes) +static int coroutine_fn +vmdk_read_extent(VmdkExtent *extent, int64_t cluster_offset, + int64_t offset_in_cluster, QEMUIOVector *qiov, + int bytes) { int ret; int cluster_bytes, buf_bytes; @@ -2015,9 +2017,9 @@ fail: * * Returns: error code with 0 for success. */ -static int vmdk_pwritev(BlockDriverState *bs, uint64_t offset, - uint64_t bytes, QEMUIOVector *qiov, - bool zeroed, bool zero_dry_run) +static int coroutine_fn vmdk_pwritev(BlockDriverState *bs, uint64_t offset, + uint64_t bytes, QEMUIOVector *qiov, + bool zeroed, bool zero_dry_run) { BDRVVmdkState *s = bs->opaque; VmdkExtent *extent = NULL; From 06753a0750a1973983505c2b544445042f555ba6 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:19 +0200 Subject: [PATCH 0908/1020] job: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-22-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/qemu/job.h | 2 +- job.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/qemu/job.h b/include/qemu/job.h index c105b31076..397ac39608 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -436,7 +436,7 @@ void coroutine_fn job_pause_point(Job *job); * * Yield the job coroutine. */ -void job_yield(Job *job); +void coroutine_fn job_yield(Job *job); /** * @job: The job that calls the function. diff --git a/job.c b/job.c index 075c6f3a20..20f0d8b2cd 100644 --- a/job.c +++ b/job.c @@ -525,7 +525,7 @@ void coroutine_fn job_pause_point(Job *job) } } -void job_yield(Job *job) +void coroutine_fn job_yield(Job *job) { assert(job->busy); From 46cd09dee10d66a6943fa0c8b133355048e81206 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:20 +0200 Subject: [PATCH 0909/1020] coroutine-lock: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-23-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- util/qemu-coroutine-lock.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/util/qemu-coroutine-lock.c b/util/qemu-coroutine-lock.c index 9ad24ab1af..15c82d9348 100644 --- a/util/qemu-coroutine-lock.c +++ b/util/qemu-coroutine-lock.c @@ -135,7 +135,7 @@ typedef struct CoWaitRecord { QSLIST_ENTRY(CoWaitRecord) next; } CoWaitRecord; -static void push_waiter(CoMutex *mutex, CoWaitRecord *w) +static void coroutine_fn push_waiter(CoMutex *mutex, CoWaitRecord *w) { w->co = qemu_coroutine_self(); QSLIST_INSERT_HEAD_ATOMIC(&mutex->from_push, w, next); @@ -332,7 +332,7 @@ void qemu_co_rwlock_init(CoRwlock *lock) } /* Releases the internal CoMutex. */ -static void qemu_co_rwlock_maybe_wake_one(CoRwlock *lock) +static void coroutine_fn qemu_co_rwlock_maybe_wake_one(CoRwlock *lock) { CoRwTicket *tkt = QSIMPLEQ_FIRST(&lock->tickets); Coroutine *co = NULL; @@ -365,7 +365,7 @@ static void qemu_co_rwlock_maybe_wake_one(CoRwlock *lock) } } -void qemu_co_rwlock_rdlock(CoRwlock *lock) +void coroutine_fn qemu_co_rwlock_rdlock(CoRwlock *lock) { Coroutine *self = qemu_coroutine_self(); @@ -390,7 +390,7 @@ void qemu_co_rwlock_rdlock(CoRwlock *lock) self->locks_held++; } -void qemu_co_rwlock_unlock(CoRwlock *lock) +void coroutine_fn qemu_co_rwlock_unlock(CoRwlock *lock) { Coroutine *self = qemu_coroutine_self(); @@ -408,7 +408,7 @@ void qemu_co_rwlock_unlock(CoRwlock *lock) qemu_co_rwlock_maybe_wake_one(lock); } -void qemu_co_rwlock_downgrade(CoRwlock *lock) +void coroutine_fn qemu_co_rwlock_downgrade(CoRwlock *lock) { qemu_co_mutex_lock(&lock->mutex); assert(lock->owners == -1); @@ -418,7 +418,7 @@ void qemu_co_rwlock_downgrade(CoRwlock *lock) qemu_co_rwlock_maybe_wake_one(lock); } -void qemu_co_rwlock_wrlock(CoRwlock *lock) +void coroutine_fn qemu_co_rwlock_wrlock(CoRwlock *lock) { Coroutine *self = qemu_coroutine_self(); @@ -438,7 +438,7 @@ void qemu_co_rwlock_wrlock(CoRwlock *lock) self->locks_held++; } -void qemu_co_rwlock_upgrade(CoRwlock *lock) +void coroutine_fn qemu_co_rwlock_upgrade(CoRwlock *lock) { qemu_co_mutex_lock(&lock->mutex); assert(lock->owners > 0); From 7390b08a2d021d9b5391c0d98fa959c5c2013be2 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 22 Sep 2022 10:49:21 +0200 Subject: [PATCH 0910/1020] raw-format: add missing coroutine_fn annotations Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-24-pbonzini@redhat.com> [kwolf: Fixed up coding style] Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/raw-format.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/block/raw-format.c b/block/raw-format.c index c7278e348e..f337ac7569 100644 --- a/block/raw-format.c +++ b/block/raw-format.c @@ -411,7 +411,8 @@ static void raw_lock_medium(BlockDriverState *bs, bool locked) bdrv_lock_medium(bs->file->bs, locked); } -static int raw_co_ioctl(BlockDriverState *bs, unsigned long int req, void *buf) +static int coroutine_fn raw_co_ioctl(BlockDriverState *bs, + unsigned long int req, void *buf) { BDRVRawState *s = bs->opaque; if (s->offset || s->has_size) { From 9204028dbbdaf742264c5de40dfcc3dfd43a6355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 22 Sep 2022 10:49:22 +0200 Subject: [PATCH 0911/1020] 9p: add missing coroutine_fn annotations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Signed-off-by: Marc-AndrĂ© Lureau Acked-by: Greg Kurz Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-25-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- hw/9pfs/9p.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 994f952600..a523ac34a9 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -424,21 +424,24 @@ typedef struct V9fsGetlock extern int open_fd_hw; extern int total_open_fd; -static inline void v9fs_path_write_lock(V9fsState *s) +static inline void coroutine_fn +v9fs_path_write_lock(V9fsState *s) { if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { qemu_co_rwlock_wrlock(&s->rename_lock); } } -static inline void v9fs_path_read_lock(V9fsState *s) +static inline void coroutine_fn +v9fs_path_read_lock(V9fsState *s) { if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { qemu_co_rwlock_rdlock(&s->rename_lock); } } -static inline void v9fs_path_unlock(V9fsState *s) +static inline void coroutine_fn +v9fs_path_unlock(V9fsState *s) { if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { qemu_co_rwlock_unlock(&s->rename_lock); From 38e8f9af08bc00939479131f38c95139d91ee126 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 22 Sep 2022 10:49:23 +0200 Subject: [PATCH 0912/1020] migration: add missing coroutine_fn annotations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Signed-off-by: Marc-AndrĂ© Lureau Reviewed-by: Juan Quintela Reviewed-by: Stefan Hajnoczi Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-26-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- migration/migration.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/migration/migration.c b/migration/migration.c index bb8bbddfe4..739bb683f3 100644 --- a/migration/migration.c +++ b/migration/migration.c @@ -574,7 +574,8 @@ static void process_incoming_migration_bh(void *opaque) migration_incoming_state_destroy(); } -static void process_incoming_migration_co(void *opaque) +static void coroutine_fn +process_incoming_migration_co(void *opaque) { MigrationIncomingState *mis = migration_incoming_get_current(); PostcopyState ps; From f7bbb1564d389e180c2dee7fbbad78b381e4d4ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 22 Sep 2022 10:49:24 +0200 Subject: [PATCH 0913/1020] test-coroutine: add missing coroutine_fn annotations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Callers of coroutine_fn must be coroutine_fn themselves, or the call must be within "if (qemu_in_coroutine())". Apply coroutine_fn to functions where this holds. Signed-off-by: Marc-AndrĂ© Lureau Reviewed-by: Alberto Faria Signed-off-by: Paolo Bonzini Message-Id: <20220922084924.201610-27-pbonzini@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- tests/unit/test-coroutine.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/test-coroutine.c b/tests/unit/test-coroutine.c index aa77a3bcb3..e16b80c245 100644 --- a/tests/unit/test-coroutine.c +++ b/tests/unit/test-coroutine.c @@ -610,7 +610,7 @@ static void perf_baseline(void) g_test_message("Function call %u iterations: %f s", maxcycles, duration); } -static __attribute__((noinline)) void perf_cost_func(void *opaque) +static __attribute__((noinline)) void coroutine_fn perf_cost_func(void *opaque) { qemu_coroutine_yield(); } From 2ffc10d53b6ab57ab228359709f8703b0b010430 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Thu, 6 Oct 2022 14:26:07 +0200 Subject: [PATCH 0914/1020] quorum: Remove unnecessary forward declaration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kevin Wolf Message-Id: <20221006122607.162769-1-kwolf@redhat.com> Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-DaudĂ© Signed-off-by: Kevin Wolf --- block/quorum.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/block/quorum.c b/block/quorum.c index 970f63d9f9..f9e6539ceb 100644 --- a/block/quorum.c +++ b/block/quorum.c @@ -232,8 +232,6 @@ static bool quorum_has_too_much_io_failed(QuorumAIOCB *acb) return false; } -static int read_fifo_child(QuorumAIOCB *acb); - static void quorum_copy_qiov(QEMUIOVector *dest, QEMUIOVector *source) { int i; From 55c5a25a0363f153d8875a60001342eb6fe6e4f5 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:31:54 -0400 Subject: [PATCH 0915/1020] job.c: make job_mutex and job_lock/unlock() public job mutex will be used to protect the job struct elements and list, replacing AioContext locks. Right now use a shared lock for all jobs, in order to keep things simple. Once the AioContext lock is gone, we can introduce per-job locks. To simplify the switch from aiocontext to job lock, introduce *nop* lock/unlock functions and macros. We want to always call job_lock/unlock outside the AioContext locks, and not vice-versa, otherwise we might get a deadlock. This is not straightforward to do, and that's why we start with nop functions. Once everything is protected by job_lock/unlock, we can change the nop into an actual mutex and remove the aiocontext lock. Since job_mutex is already being used, add static real_job_{lock/unlock} for the existing usage. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Stefan Hajnoczi Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220926093214.506243-2-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- include/qemu/job.h | 24 ++++++++++++++++++++++++ job.c | 35 +++++++++++++++++++++++------------ 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/include/qemu/job.h b/include/qemu/job.h index 397ac39608..e625547bdb 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -303,6 +303,30 @@ typedef enum JobCreateFlags { JOB_MANUAL_DISMISS = 0x04, } JobCreateFlags; +extern QemuMutex job_mutex; + +#define JOB_LOCK_GUARD() /* QEMU_LOCK_GUARD(&job_mutex) */ + +#define WITH_JOB_LOCK_GUARD() /* WITH_QEMU_LOCK_GUARD(&job_mutex) */ + +/** + * job_lock: + * + * Take the mutex protecting the list of jobs and their status. + * Most functions called by the monitor need to call job_lock + * and job_unlock manually. On the other hand, function called + * by the block jobs themselves and by the block layer will take the + * lock for you. + */ +void job_lock(void); + +/** + * job_unlock: + * + * Release the mutex protecting the list of jobs and their status. + */ +void job_unlock(void); + /** * Allocate and return a new job transaction. Jobs can be added to the * transaction using job_txn_add_job(). diff --git a/job.c b/job.c index 20f0d8b2cd..7365db827a 100644 --- a/job.c +++ b/job.c @@ -32,6 +32,12 @@ #include "trace/trace-root.h" #include "qapi/qapi-events-job.h" +/* + * job_mutex protects the jobs list, but also makes the + * struct job fields thread-safe. + */ +QemuMutex job_mutex; + static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs); /* Job State Transition Table */ @@ -74,17 +80,22 @@ struct JobTxn { int refcnt; }; -/* Right now, this mutex is only needed to synchronize accesses to job->busy - * and job->sleep_timer, such as concurrent calls to job_do_yield and - * job_enter. */ -static QemuMutex job_mutex; +void job_lock(void) +{ + /* nop */ +} -static void job_lock(void) +void job_unlock(void) +{ + /* nop */ +} + +static void real_job_lock(void) { qemu_mutex_lock(&job_mutex); } -static void job_unlock(void) +static void real_job_unlock(void) { qemu_mutex_unlock(&job_mutex); } @@ -450,21 +461,21 @@ void job_enter_cond(Job *job, bool(*fn)(Job *job)) return; } - job_lock(); + real_job_lock(); if (job->busy) { - job_unlock(); + real_job_unlock(); return; } if (fn && !fn(job)) { - job_unlock(); + real_job_unlock(); return; } assert(!job->deferred_to_main_loop); timer_del(&job->sleep_timer); job->busy = true; - job_unlock(); + real_job_unlock(); aio_co_enter(job->aio_context, job->co); } @@ -481,13 +492,13 @@ void job_enter(Job *job) * called explicitly. */ static void coroutine_fn job_do_yield(Job *job, uint64_t ns) { - job_lock(); + real_job_lock(); if (ns != -1) { timer_mod(&job->sleep_timer, ns); } job->busy = false; job_event_idle(job); - job_unlock(); + real_job_unlock(); qemu_coroutine_yield(); /* Set by job_enter_cond() before re-entering the coroutine. */ From d08f07541fa34eb83680837eb45a6e1f75d177bc Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:31:55 -0400 Subject: [PATCH 0916/1020] job.h: categorize fields in struct Job Categorize the fields in struct Job to understand which ones need to be protected by the job mutex and which don't. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi Message-Id: <20220926093214.506243-3-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- include/qemu/job.h | 61 +++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/include/qemu/job.h b/include/qemu/job.h index e625547bdb..8530c6a4e1 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -40,27 +40,52 @@ typedef struct JobTxn JobTxn; * Long-running operation. */ typedef struct Job { + + /* Fields set at initialization (job_create), and never modified */ + /** The ID of the job. May be NULL for internal jobs. */ char *id; - /** The type of this job. */ + /** + * The type of this job. + * All callbacks are called with job_mutex *not* held. + */ const JobDriver *driver; + /** + * The coroutine that executes the job. If not NULL, it is reentered when + * busy is false and the job is cancelled. + * Initialized in job_start() + */ + Coroutine *co; + + /** True if this job should automatically finalize itself */ + bool auto_finalize; + + /** True if this job should automatically dismiss itself */ + bool auto_dismiss; + + /** The completion function that will be called when the job completes. */ + BlockCompletionFunc *cb; + + /** The opaque value that is passed to the completion function. */ + void *opaque; + + /* ProgressMeter API is thread-safe */ + ProgressMeter progress; + + + /** Protected by AioContext lock */ + + /** AioContext to run the job coroutine in */ + AioContext *aio_context; + /** Reference count of the block job */ int refcnt; /** Current state; See @JobStatus for details. */ JobStatus status; - /** AioContext to run the job coroutine in */ - AioContext *aio_context; - - /** - * The coroutine that executes the job. If not NULL, it is reentered when - * busy is false and the job is cancelled. - */ - Coroutine *co; - /** * Timer that is used by @job_sleep_ns. Accessed under job_mutex (in * job.c). @@ -112,14 +137,6 @@ typedef struct Job { /** Set to true when the job has deferred work to the main loop. */ bool deferred_to_main_loop; - /** True if this job should automatically finalize itself */ - bool auto_finalize; - - /** True if this job should automatically dismiss itself */ - bool auto_dismiss; - - ProgressMeter progress; - /** * Return code from @run and/or @prepare callback(s). * Not final until the job has reached the CONCLUDED status. @@ -134,12 +151,6 @@ typedef struct Job { */ Error *err; - /** The completion function that will be called when the job completes. */ - BlockCompletionFunc *cb; - - /** The opaque value that is passed to the completion function. */ - void *opaque; - /** Notifiers called when a cancelled job is finalised */ NotifierList on_finalize_cancelled; @@ -167,6 +178,7 @@ typedef struct Job { /** * Callbacks and other information about a Job driver. + * All callbacks are invoked with job_mutex *not* held. */ struct JobDriver { @@ -472,7 +484,6 @@ void coroutine_fn job_yield(Job *job); */ void coroutine_fn job_sleep_ns(Job *job, int64_t ns); - /** Returns the JobType of a given Job. */ JobType job_type(const Job *job); From 544f4d5258d4e4dd6652d28607b605e7801ed7dd Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:31:56 -0400 Subject: [PATCH 0917/1020] job.c: API functions not used outside should be static job_event_* functions can all be static, as they are not used outside job.c. Same applies for job_txn_add_job(). Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Stefan Hajnoczi Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Kevin Wolf Message-Id: <20220926093214.506243-4-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- include/qemu/job.h | 18 ------------------ job.c | 22 +++++++++++++++++++--- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/include/qemu/job.h b/include/qemu/job.h index 8530c6a4e1..e3e31e2548 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -358,18 +358,6 @@ JobTxn *job_txn_new(void); */ void job_txn_unref(JobTxn *txn); -/** - * @txn: The transaction (may be NULL) - * @job: Job to add to the transaction - * - * Add @job to the transaction. The @job must not already be in a transaction. - * The caller must call either job_txn_unref() or job_completed() to release - * the reference that is automatically grabbed here. - * - * If @txn is NULL, the function does nothing. - */ -void job_txn_add_job(JobTxn *txn, Job *job); - /** * Create a new long-running job and return it. * @@ -431,12 +419,6 @@ void job_progress_set_remaining(Job *job, uint64_t remaining); */ void job_progress_increase_remaining(Job *job, uint64_t delta); -/** To be called when a cancelled job is finalised. */ -void job_event_cancelled(Job *job); - -/** To be called when a successfully completed job is finalised. */ -void job_event_completed(Job *job); - /** * Conditionally enter the job coroutine if the job is ready to run, not * already busy and fn() returns true. fn() is called while under the job_lock diff --git a/job.c b/job.c index 7365db827a..9500b5b36e 100644 --- a/job.c +++ b/job.c @@ -125,7 +125,17 @@ void job_txn_unref(JobTxn *txn) } } -void job_txn_add_job(JobTxn *txn, Job *job) +/** + * @txn: The transaction (may be NULL) + * @job: Job to add to the transaction + * + * Add @job to the transaction. The @job must not already be in a transaction. + * The caller must call either job_txn_unref() or job_completed() to release + * the reference that is automatically grabbed here. + * + * If @txn is NULL, the function does nothing. + */ +static void job_txn_add_job(JobTxn *txn, Job *job) { if (!txn) { return; @@ -427,12 +437,18 @@ void job_progress_increase_remaining(Job *job, uint64_t delta) progress_increase_remaining(&job->progress, delta); } -void job_event_cancelled(Job *job) +/** + * To be called when a cancelled job is finalised. + */ +static void job_event_cancelled(Job *job) { notifier_list_notify(&job->on_finalize_cancelled, job); } -void job_event_completed(Job *job) +/** + * To be called when a successfully completed job is finalised. + */ +static void job_event_completed(Job *job) { notifier_list_notify(&job->on_finalize_completed, job); } From fd4b14e299d7def753f2d753e61d125cd5e1cbd8 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:31:57 -0400 Subject: [PATCH 0918/1020] aio-wait.h: introduce AIO_WAIT_WHILE_UNLOCKED Same as AIO_WAIT_WHILE macro, but if we are in the Main loop do not release and then acquire ctx_ 's aiocontext. Once all Aiocontext locks go away, this macro will replace AIO_WAIT_WHILE. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Stefan Hajnoczi Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220926093214.506243-5-eesposit@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/block/aio-wait.h | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/include/block/aio-wait.h b/include/block/aio-wait.h index 54840f8622..dd9a7f6461 100644 --- a/include/block/aio-wait.h +++ b/include/block/aio-wait.h @@ -59,10 +59,13 @@ typedef struct { extern AioWait global_aio_wait; /** - * AIO_WAIT_WHILE: + * AIO_WAIT_WHILE_INTERNAL: * @ctx: the aio context, or NULL if multiple aio contexts (for which the * caller does not hold a lock) are involved in the polling condition. * @cond: wait while this conditional expression is true + * @unlock: whether to unlock and then lock again @ctx. This apples + * only when waiting for another AioContext from the main loop. + * Otherwise it's ignored. * * Wait while a condition is true. Use this to implement synchronous * operations that require event loop activity. @@ -75,7 +78,7 @@ extern AioWait global_aio_wait; * wait on conditions between two IOThreads since that could lead to deadlock, * go via the main loop instead. */ -#define AIO_WAIT_WHILE(ctx, cond) ({ \ +#define AIO_WAIT_WHILE_INTERNAL(ctx, cond, unlock) ({ \ bool waited_ = false; \ AioWait *wait_ = &global_aio_wait; \ AioContext *ctx_ = (ctx); \ @@ -92,11 +95,11 @@ extern AioWait global_aio_wait; assert(qemu_get_current_aio_context() == \ qemu_get_aio_context()); \ while ((cond)) { \ - if (ctx_) { \ + if (unlock && ctx_) { \ aio_context_release(ctx_); \ } \ aio_poll(qemu_get_aio_context(), true); \ - if (ctx_) { \ + if (unlock && ctx_) { \ aio_context_acquire(ctx_); \ } \ waited_ = true; \ @@ -105,6 +108,12 @@ extern AioWait global_aio_wait; qatomic_dec(&wait_->num_waiters); \ waited_; }) +#define AIO_WAIT_WHILE(ctx, cond) \ + AIO_WAIT_WHILE_INTERNAL(ctx, cond, true) + +#define AIO_WAIT_WHILE_UNLOCKED(ctx, cond) \ + AIO_WAIT_WHILE_INTERNAL(ctx, cond, false) + /** * aio_wait_kick: * Wake up the main thread if it is waiting on AIO_WAIT_WHILE(). During From afe1e8a7b3e671993cf55e2321408650c7620999 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:31:58 -0400 Subject: [PATCH 0919/1020] job.c: add job_lock/unlock while keeping job.h intact With "intact" we mean that all job.h functions implicitly take the lock. Therefore API callers are unmodified. This means that: - many static functions that will be always called with job lock held become _locked, and call _locked functions - all public functions take the lock internally if needed, and call _locked functions - all public functions called internally by other functions in job.c will have a _locked counterpart (sometimes public), to avoid deadlocks (job lock already taken). These functions are not used for now. - some public functions called only from exernal files (not job.c) do not have _locked() counterpart and take the lock inside. Others won't need the lock at all because use fields only set at initialization and never modified. job_{lock/unlock} is independent from real_job_{lock/unlock}. Note: at this stage, job_{lock/unlock} and job lock guard macros are *nop* Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220926093214.506243-6-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- include/qemu/job.h | 138 +++++++++- job.c | 670 +++++++++++++++++++++++++++++++-------------- 2 files changed, 591 insertions(+), 217 deletions(-) diff --git a/include/qemu/job.h b/include/qemu/job.h index e3e31e2548..870dce1535 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -358,8 +358,15 @@ JobTxn *job_txn_new(void); */ void job_txn_unref(JobTxn *txn); +/* + * Same as job_txn_unref(), but called with job lock held. + * Might release the lock temporarily. + */ +void job_txn_unref_locked(JobTxn *txn); + /** * Create a new long-running job and return it. + * Called with job_mutex *not* held. * * @job_id: The id of the newly-created job, or %NULL for internal jobs * @driver: The class object for the newly-created job. @@ -380,17 +387,25 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn, */ void job_ref(Job *job); +/* Same as job_ref(), but called with job lock held. */ +void job_ref_locked(Job *job); + /** * Release a reference that was previously acquired with job_ref() or * job_create(). If it's the last reference to the object, it will be freed. */ void job_unref(Job *job); +/* Same as job_unref(), but called with job lock held. */ +void job_unref_locked(Job *job); + /** * @job: The job that has made progress * @done: How much progress the job made since the last call * * Updates the progress counter of the job. + * + * May be called with mutex held or not held. */ void job_progress_update(Job *job, uint64_t done); @@ -401,6 +416,8 @@ void job_progress_update(Job *job, uint64_t done); * * Sets the expected end value of the progress counter of a job so that a * completion percentage can be calculated when the progress is updated. + * + * May be called with mutex held or not held. */ void job_progress_set_remaining(Job *job, uint64_t remaining); @@ -416,6 +433,8 @@ void job_progress_set_remaining(Job *job, uint64_t remaining); * length before, and job_progress_update() afterwards. * (So the operation acts as a parenthesis in regards to the main job * operation running in background.) + * + * May be called with mutex held or not held. */ void job_progress_increase_remaining(Job *job, uint64_t delta); @@ -426,11 +445,19 @@ void job_progress_increase_remaining(Job *job, uint64_t delta); */ void job_enter_cond(Job *job, bool(*fn)(Job *job)); +/* + * Same as job_enter_cond(), but called with job lock held. + * Might release the lock temporarily. + */ +void job_enter_cond_locked(Job *job, bool(*fn)(Job *job)); + /** * @job: A job that has not yet been started. * * Begins execution of a job. * Takes ownership of one reference to the job object. + * + * Called with job_mutex *not* held. */ void job_start(Job *job); @@ -438,6 +465,7 @@ void job_start(Job *job); * @job: The job to enter. * * Continue the specified job by entering the coroutine. + * Called with job_mutex *not* held. */ void job_enter(Job *job); @@ -446,6 +474,8 @@ void job_enter(Job *job); * * Pause now if job_pause() has been called. Jobs that perform lots of I/O * must call this between requests so that the job can be paused. + * + * Called with job_mutex *not* held. */ void coroutine_fn job_pause_point(Job *job); @@ -453,6 +483,7 @@ void coroutine_fn job_pause_point(Job *job); * @job: The job that calls the function. * * Yield the job coroutine. + * Called with job_mutex *not* held. */ void coroutine_fn job_yield(Job *job); @@ -463,6 +494,8 @@ void coroutine_fn job_yield(Job *job); * Put the job to sleep (assuming that it wasn't canceled) for @ns * %QEMU_CLOCK_REALTIME nanoseconds. Canceling the job will immediately * interrupt the wait. + * + * Called with job_mutex *not* held. */ void coroutine_fn job_sleep_ns(Job *job, int64_t ns); @@ -475,21 +508,40 @@ const char *job_type_str(const Job *job); /** Returns true if the job should not be visible to the management layer. */ bool job_is_internal(Job *job); -/** Returns whether the job is being cancelled. */ +/** + * Returns whether the job is being cancelled. + * Called with job_mutex *not* held. + */ bool job_is_cancelled(Job *job); +/* Same as job_is_cancelled(), but called with job lock held. */ +bool job_is_cancelled_locked(Job *job); + /** * Returns whether the job is scheduled for cancellation (at an * indefinite point). + * Called with job_mutex *not* held. */ bool job_cancel_requested(Job *job); -/** Returns whether the job is in a completed state. */ +/** + * Returns whether the job is in a completed state. + * Called with job_mutex *not* held. + */ bool job_is_completed(Job *job); -/** Returns whether the job is ready to be completed. */ +/* Same as job_is_completed(), but called with job lock held. */ +bool job_is_completed_locked(Job *job); + +/** + * Returns whether the job is ready to be completed. + * Called with job_mutex *not* held. + */ bool job_is_ready(Job *job); +/* Same as job_is_ready(), but called with job lock held. */ +bool job_is_ready_locked(Job *job); + /** * Request @job to pause at the next pause point. Must be paired with * job_resume(). If the job is supposed to be resumed by user action, call @@ -497,24 +549,45 @@ bool job_is_ready(Job *job); */ void job_pause(Job *job); +/* Same as job_pause(), but called with job lock held. */ +void job_pause_locked(Job *job); + /** Resumes a @job paused with job_pause. */ void job_resume(Job *job); +/* + * Same as job_resume(), but called with job lock held. + * Might release the lock temporarily. + */ +void job_resume_locked(Job *job); + /** * Asynchronously pause the specified @job. * Do not allow a resume until a matching call to job_user_resume. */ void job_user_pause(Job *job, Error **errp); +/* Same as job_user_pause(), but called with job lock held. */ +void job_user_pause_locked(Job *job, Error **errp); + /** Returns true if the job is user-paused. */ bool job_user_paused(Job *job); +/* Same as job_user_paused(), but called with job lock held. */ +bool job_user_paused_locked(Job *job); + /** * Resume the specified @job. * Must be paired with a preceding job_user_pause. */ void job_user_resume(Job *job, Error **errp); +/* + * Same as job_user_resume(), but called with job lock held. + * Might release the lock temporarily. + */ +void job_user_resume_locked(Job *job, Error **errp); + /** * Get the next element from the list of block jobs after @job, or the * first one if @job is %NULL. @@ -523,6 +596,9 @@ void job_user_resume(Job *job, Error **errp); */ Job *job_next(Job *job); +/* Same as job_next(), but called with job lock held. */ +Job *job_next_locked(Job *job); + /** * Get the job identified by @id (which must not be %NULL). * @@ -530,6 +606,9 @@ Job *job_next(Job *job); */ Job *job_get(const char *id); +/* Same as job_get(), but called with job lock held. */ +Job *job_get_locked(const char *id); + /** * Check whether the verb @verb can be applied to @job in its current state. * Returns 0 if the verb can be applied; otherwise errp is set and -EPERM @@ -537,27 +616,48 @@ Job *job_get(const char *id); */ int job_apply_verb(Job *job, JobVerb verb, Error **errp); -/** The @job could not be started, free it. */ +/* Same as job_apply_verb, but called with job lock held. */ +int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp); + +/** + * The @job could not be started, free it. + * Called with job_mutex *not* held. + */ void job_early_fail(Job *job); -/** Moves the @job from RUNNING to READY */ +/** + * Moves the @job from RUNNING to READY. + * Called with job_mutex *not* held. + */ void job_transition_to_ready(Job *job); /** Asynchronously complete the specified @job. */ void job_complete(Job *job, Error **errp); +/* + * Same as job_complete(), but called with job lock held. + * Might release the lock temporarily. + */ +void job_complete_locked(Job *job, Error **errp); + /** * Asynchronously cancel the specified @job. If @force is true, the job should * be cancelled immediately without waiting for a consistent state. */ void job_cancel(Job *job, bool force); +/* Same as job_cancel(), but called with job lock held. */ +void job_cancel_locked(Job *job, bool force); + /** * Cancels the specified job like job_cancel(), but may refuse to do so if the * operation isn't meaningful in the current state of the job. */ void job_user_cancel(Job *job, bool force, Error **errp); +/* Same as job_user_cancel(), but called with job lock held. */ +void job_user_cancel_locked(Job *job, bool force, Error **errp); + /** * Synchronously cancel the @job. The completion callback is called * before the function returns. If @force is false, the job may @@ -571,7 +671,14 @@ void job_user_cancel(Job *job, bool force, Error **errp); */ int job_cancel_sync(Job *job, bool force); -/** Synchronously force-cancels all jobs using job_cancel_sync(). */ +/* Same as job_cancel_sync, but called with job lock held. */ +int job_cancel_sync_locked(Job *job, bool force); + +/** + * Synchronously force-cancels all jobs using job_cancel_sync_locked(). + * + * Called with job_lock *not* held. + */ void job_cancel_sync_all(void); /** @@ -590,6 +697,9 @@ void job_cancel_sync_all(void); */ int job_complete_sync(Job *job, Error **errp); +/* Same as job_complete_sync, but called with job lock held. */ +int job_complete_sync_locked(Job *job, Error **errp); + /** * For a @job that has finished its work and is pending awaiting explicit * acknowledgement to commit its work, this will commit that work. @@ -600,12 +710,18 @@ int job_complete_sync(Job *job, Error **errp); */ void job_finalize(Job *job, Error **errp); +/* Same as job_finalize(), but called with job lock held. */ +void job_finalize_locked(Job *job, Error **errp); + /** * Remove the concluded @job from the query list and resets the passed pointer * to %NULL. Returns an error if the job is not actually concluded. */ void job_dismiss(Job **job, Error **errp); +/* Same as job_dismiss(), but called with job lock held. */ +void job_dismiss_locked(Job **job, Error **errp); + /** * Synchronously finishes the given @job. If @finish is given, it is called to * trigger completion or cancellation of the job. @@ -615,6 +731,14 @@ void job_dismiss(Job **job, Error **errp); * * Callers must hold the AioContext lock of job->aio_context. */ -int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp); +int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), + Error **errp); + +/* + * Same as job_finish_sync(), but called with job lock held. + * Might release the lock temporarily. + */ +int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp), + Error **errp); #endif diff --git a/job.c b/job.c index 9500b5b36e..87564979cb 100644 --- a/job.c +++ b/job.c @@ -38,6 +38,7 @@ */ QemuMutex job_mutex; +/* Protected by job_mutex */ static QLIST_HEAD(, Job) jobs = QLIST_HEAD_INITIALIZER(jobs); /* Job State Transition Table */ @@ -113,18 +114,25 @@ JobTxn *job_txn_new(void) return txn; } -static void job_txn_ref(JobTxn *txn) +/* Called with job_mutex held. */ +static void job_txn_ref_locked(JobTxn *txn) { txn->refcnt++; } -void job_txn_unref(JobTxn *txn) +void job_txn_unref_locked(JobTxn *txn) { if (txn && --txn->refcnt == 0) { g_free(txn); } } +void job_txn_unref(JobTxn *txn) +{ + JOB_LOCK_GUARD(); + job_txn_unref_locked(txn); +} + /** * @txn: The transaction (may be NULL) * @job: Job to add to the transaction @@ -134,8 +142,10 @@ void job_txn_unref(JobTxn *txn) * the reference that is automatically grabbed here. * * If @txn is NULL, the function does nothing. + * + * Called with job_mutex held. */ -static void job_txn_add_job(JobTxn *txn, Job *job) +static void job_txn_add_job_locked(JobTxn *txn, Job *job) { if (!txn) { return; @@ -145,19 +155,21 @@ static void job_txn_add_job(JobTxn *txn, Job *job) job->txn = txn; QLIST_INSERT_HEAD(&txn->jobs, job, txn_list); - job_txn_ref(txn); + job_txn_ref_locked(txn); } -static void job_txn_del_job(Job *job) +/* Called with job_mutex held. */ +static void job_txn_del_job_locked(Job *job) { if (job->txn) { QLIST_REMOVE(job, txn_list); - job_txn_unref(job->txn); + job_txn_unref_locked(job->txn); job->txn = NULL; } } -static int job_txn_apply(Job *job, int fn(Job *)) +/* Called with job_mutex held, but releases it temporarily. */ +static int job_txn_apply_locked(Job *job, int fn(Job *)) { AioContext *inner_ctx; Job *other_job, *next; @@ -170,7 +182,7 @@ static int job_txn_apply(Job *job, int fn(Job *)) * we need to release it here to avoid holding the lock twice - which would * break AIO_WAIT_WHILE from within fn. */ - job_ref(job); + job_ref_locked(job); aio_context_release(job->aio_context); QLIST_FOREACH_SAFE(other_job, &txn->jobs, txn_list, next) { @@ -188,7 +200,7 @@ static int job_txn_apply(Job *job, int fn(Job *)) * can't use a local variable to cache it. */ aio_context_acquire(job->aio_context); - job_unref(job); + job_unref_locked(job); return rc; } @@ -197,7 +209,8 @@ bool job_is_internal(Job *job) return (job->id == NULL); } -static void job_state_transition(Job *job, JobStatus s1) +/* Called with job_mutex held. */ +static void job_state_transition_locked(Job *job, JobStatus s1) { JobStatus s0 = job->status; assert(s1 >= 0 && s1 < JOB_STATUS__MAX); @@ -212,7 +225,7 @@ static void job_state_transition(Job *job, JobStatus s1) } } -int job_apply_verb(Job *job, JobVerb verb, Error **errp) +int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp) { JobStatus s0 = job->status; assert(verb >= 0 && verb < JOB_VERB__MAX); @@ -226,6 +239,12 @@ int job_apply_verb(Job *job, JobVerb verb, Error **errp) return -EPERM; } +int job_apply_verb(Job *job, JobVerb verb, Error **errp) +{ + JOB_LOCK_GUARD(); + return job_apply_verb_locked(job, verb, errp); +} + JobType job_type(const Job *job) { return job->driver->job_type; @@ -236,19 +255,32 @@ const char *job_type_str(const Job *job) return JobType_str(job_type(job)); } -bool job_is_cancelled(Job *job) +bool job_is_cancelled_locked(Job *job) { /* force_cancel may be true only if cancelled is true, too */ assert(job->cancelled || !job->force_cancel); return job->force_cancel; } -bool job_cancel_requested(Job *job) +bool job_is_cancelled(Job *job) +{ + JOB_LOCK_GUARD(); + return job_is_cancelled_locked(job); +} + +/* Called with job_mutex held. */ +static bool job_cancel_requested_locked(Job *job) { return job->cancelled; } -bool job_is_ready(Job *job) +bool job_cancel_requested(Job *job) +{ + JOB_LOCK_GUARD(); + return job_cancel_requested_locked(job); +} + +bool job_is_ready_locked(Job *job) { switch (job->status) { case JOB_STATUS_UNDEFINED: @@ -270,39 +302,52 @@ bool job_is_ready(Job *job) return false; } +bool job_is_ready(Job *job) +{ + JOB_LOCK_GUARD(); + return job_is_ready_locked(job); +} + +bool job_is_completed_locked(Job *job) +{ + switch (job->status) { + case JOB_STATUS_UNDEFINED: + case JOB_STATUS_CREATED: + case JOB_STATUS_RUNNING: + case JOB_STATUS_PAUSED: + case JOB_STATUS_READY: + case JOB_STATUS_STANDBY: + return false; + case JOB_STATUS_WAITING: + case JOB_STATUS_PENDING: + case JOB_STATUS_ABORTING: + case JOB_STATUS_CONCLUDED: + case JOB_STATUS_NULL: + return true; + default: + g_assert_not_reached(); + } + return false; +} + bool job_is_completed(Job *job) { - switch (job->status) { - case JOB_STATUS_UNDEFINED: - case JOB_STATUS_CREATED: - case JOB_STATUS_RUNNING: - case JOB_STATUS_PAUSED: - case JOB_STATUS_READY: - case JOB_STATUS_STANDBY: - return false; - case JOB_STATUS_WAITING: - case JOB_STATUS_PENDING: - case JOB_STATUS_ABORTING: - case JOB_STATUS_CONCLUDED: - case JOB_STATUS_NULL: - return true; - default: - g_assert_not_reached(); - } - return false; + JOB_LOCK_GUARD(); + return job_is_completed_locked(job); } -static bool job_started(Job *job) +static bool job_started_locked(Job *job) { return job->co; } -static bool job_should_pause(Job *job) +/* Called with job_mutex held. */ +static bool job_should_pause_locked(Job *job) { return job->pause_count > 0; } -Job *job_next(Job *job) +Job *job_next_locked(Job *job) { if (!job) { return QLIST_FIRST(&jobs); @@ -310,7 +355,13 @@ Job *job_next(Job *job) return QLIST_NEXT(job, job_list); } -Job *job_get(const char *id) +Job *job_next(Job *job) +{ + JOB_LOCK_GUARD(); + return job_next_locked(job); +} + +Job *job_get_locked(const char *id) { Job *job; @@ -323,6 +374,13 @@ Job *job_get(const char *id) return NULL; } +Job *job_get(const char *id) +{ + JOB_LOCK_GUARD(); + return job_get_locked(id); +} + +/* Called with job_mutex *not* held. */ static void job_sleep_timer_cb(void *opaque) { Job *job = opaque; @@ -336,6 +394,8 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn, { Job *job; + JOB_LOCK_GUARD(); + if (job_id) { if (flags & JOB_INTERNAL) { error_setg(errp, "Cannot specify job ID for internal job"); @@ -345,7 +405,7 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn, error_setg(errp, "Invalid job ID '%s'", job_id); return NULL; } - if (job_get(job_id)) { + if (job_get_locked(job_id)) { error_setg(errp, "Job ID '%s' already in use", job_id); return NULL; } @@ -375,7 +435,7 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn, notifier_list_init(&job->on_ready); notifier_list_init(&job->on_idle); - job_state_transition(job, JOB_STATUS_CREATED); + job_state_transition_locked(job, JOB_STATUS_CREATED); aio_timer_init(qemu_get_aio_context(), &job->sleep_timer, QEMU_CLOCK_REALTIME, SCALE_NS, job_sleep_timer_cb, job); @@ -386,21 +446,27 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn, * consolidating the job management logic */ if (!txn) { txn = job_txn_new(); - job_txn_add_job(txn, job); - job_txn_unref(txn); + job_txn_add_job_locked(txn, job); + job_txn_unref_locked(txn); } else { - job_txn_add_job(txn, job); + job_txn_add_job_locked(txn, job); } return job; } -void job_ref(Job *job) +void job_ref_locked(Job *job) { ++job->refcnt; } -void job_unref(Job *job) +void job_ref(Job *job) +{ + JOB_LOCK_GUARD(); + job_ref_locked(job); +} + +void job_unref_locked(Job *job) { GLOBAL_STATE_CODE(); @@ -410,7 +476,9 @@ void job_unref(Job *job) assert(!job->txn); if (job->driver->free) { + job_unlock(); job->driver->free(job); + job_lock(); } QLIST_REMOVE(job, job_list); @@ -422,6 +490,12 @@ void job_unref(Job *job) } } +void job_unref(Job *job) +{ + JOB_LOCK_GUARD(); + job_unref_locked(job); +} + void job_progress_update(Job *job, uint64_t done) { progress_work_done(&job->progress, done); @@ -439,38 +513,43 @@ void job_progress_increase_remaining(Job *job, uint64_t delta) /** * To be called when a cancelled job is finalised. + * Called with job_mutex held. */ -static void job_event_cancelled(Job *job) +static void job_event_cancelled_locked(Job *job) { notifier_list_notify(&job->on_finalize_cancelled, job); } /** * To be called when a successfully completed job is finalised. + * Called with job_mutex held. */ -static void job_event_completed(Job *job) +static void job_event_completed_locked(Job *job) { notifier_list_notify(&job->on_finalize_completed, job); } -static void job_event_pending(Job *job) +/* Called with job_mutex held. */ +static void job_event_pending_locked(Job *job) { notifier_list_notify(&job->on_pending, job); } -static void job_event_ready(Job *job) +/* Called with job_mutex held. */ +static void job_event_ready_locked(Job *job) { notifier_list_notify(&job->on_ready, job); } -static void job_event_idle(Job *job) +/* Called with job_mutex held. */ +static void job_event_idle_locked(Job *job) { notifier_list_notify(&job->on_idle, job); } -void job_enter_cond(Job *job, bool(*fn)(Job *job)) +void job_enter_cond_locked(Job *job, bool(*fn)(Job *job)) { - if (!job_started(job)) { + if (!job_started_locked(job)) { return; } if (job->deferred_to_main_loop) { @@ -492,12 +571,21 @@ void job_enter_cond(Job *job, bool(*fn)(Job *job)) timer_del(&job->sleep_timer); job->busy = true; real_job_unlock(); + job_unlock(); aio_co_enter(job->aio_context, job->co); + job_lock(); +} + +void job_enter_cond(Job *job, bool(*fn)(Job *job)) +{ + JOB_LOCK_GUARD(); + job_enter_cond_locked(job, fn); } void job_enter(Job *job) { - job_enter_cond(job, NULL); + JOB_LOCK_GUARD(); + job_enter_cond_locked(job, NULL); } /* Yield, and schedule a timer to reenter the coroutine after @ns nanoseconds. @@ -505,100 +593,129 @@ void job_enter(Job *job) * is allowed and cancels the timer. * * If @ns is (uint64_t) -1, no timer is scheduled and job_enter() must be - * called explicitly. */ -static void coroutine_fn job_do_yield(Job *job, uint64_t ns) + * called explicitly. + * + * Called with job_mutex held, but releases it temporarily. + */ +static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns) { real_job_lock(); if (ns != -1) { timer_mod(&job->sleep_timer, ns); } job->busy = false; - job_event_idle(job); + job_event_idle_locked(job); real_job_unlock(); + job_unlock(); qemu_coroutine_yield(); + job_lock(); /* Set by job_enter_cond() before re-entering the coroutine. */ assert(job->busy); } -void coroutine_fn job_pause_point(Job *job) +/* Called with job_mutex held, but releases it temporarily. */ +static void coroutine_fn job_pause_point_locked(Job *job) { - assert(job && job_started(job)); + assert(job && job_started_locked(job)); - if (!job_should_pause(job)) { + if (!job_should_pause_locked(job)) { return; } - if (job_is_cancelled(job)) { + if (job_is_cancelled_locked(job)) { return; } if (job->driver->pause) { + job_unlock(); job->driver->pause(job); + job_lock(); } - if (job_should_pause(job) && !job_is_cancelled(job)) { + if (job_should_pause_locked(job) && !job_is_cancelled_locked(job)) { JobStatus status = job->status; - job_state_transition(job, status == JOB_STATUS_READY - ? JOB_STATUS_STANDBY - : JOB_STATUS_PAUSED); + job_state_transition_locked(job, status == JOB_STATUS_READY + ? JOB_STATUS_STANDBY + : JOB_STATUS_PAUSED); job->paused = true; - job_do_yield(job, -1); + job_do_yield_locked(job, -1); job->paused = false; - job_state_transition(job, status); + job_state_transition_locked(job, status); } if (job->driver->resume) { + job_unlock(); job->driver->resume(job); + job_lock(); } } +void coroutine_fn job_pause_point(Job *job) +{ + JOB_LOCK_GUARD(); + job_pause_point_locked(job); +} + +static void coroutine_fn job_yield_locked(Job *job) +{ + assert(job->busy); + + /* Check cancellation *before* setting busy = false, too! */ + if (job_is_cancelled_locked(job)) { + return; + } + + if (!job_should_pause_locked(job)) { + job_do_yield_locked(job, -1); + } + + job_pause_point_locked(job); +} + void coroutine_fn job_yield(Job *job) { - assert(job->busy); - - /* Check cancellation *before* setting busy = false, too! */ - if (job_is_cancelled(job)) { - return; - } - - if (!job_should_pause(job)) { - job_do_yield(job, -1); - } - - job_pause_point(job); + JOB_LOCK_GUARD(); + job_yield_locked(job); } void coroutine_fn job_sleep_ns(Job *job, int64_t ns) { + JOB_LOCK_GUARD(); assert(job->busy); /* Check cancellation *before* setting busy = false, too! */ - if (job_is_cancelled(job)) { + if (job_is_cancelled_locked(job)) { return; } - if (!job_should_pause(job)) { - job_do_yield(job, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ns); + if (!job_should_pause_locked(job)) { + job_do_yield_locked(job, qemu_clock_get_ns(QEMU_CLOCK_REALTIME) + ns); } - job_pause_point(job); + job_pause_point_locked(job); } -/* Assumes the block_job_mutex is held */ -static bool job_timer_not_pending(Job *job) +/* Assumes the job_mutex is held */ +static bool job_timer_not_pending_locked(Job *job) { return !timer_pending(&job->sleep_timer); } -void job_pause(Job *job) +void job_pause_locked(Job *job) { job->pause_count++; if (!job->paused) { - job_enter(job); + job_enter_cond_locked(job, NULL); } } -void job_resume(Job *job) +void job_pause(Job *job) +{ + JOB_LOCK_GUARD(); + job_pause_locked(job); +} + +void job_resume_locked(Job *job) { assert(job->pause_count > 0); job->pause_count--; @@ -607,12 +724,18 @@ void job_resume(Job *job) } /* kick only if no timer is pending */ - job_enter_cond(job, job_timer_not_pending); + job_enter_cond_locked(job, job_timer_not_pending_locked); } -void job_user_pause(Job *job, Error **errp) +void job_resume(Job *job) { - if (job_apply_verb(job, JOB_VERB_PAUSE, errp)) { + JOB_LOCK_GUARD(); + job_resume_locked(job); +} + +void job_user_pause_locked(Job *job, Error **errp) +{ + if (job_apply_verb_locked(job, JOB_VERB_PAUSE, errp)) { return; } if (job->user_paused) { @@ -620,15 +743,27 @@ void job_user_pause(Job *job, Error **errp) return; } job->user_paused = true; - job_pause(job); + job_pause_locked(job); } -bool job_user_paused(Job *job) +void job_user_pause(Job *job, Error **errp) +{ + JOB_LOCK_GUARD(); + job_user_pause_locked(job, errp); +} + +bool job_user_paused_locked(Job *job) { return job->user_paused; } -void job_user_resume(Job *job, Error **errp) +bool job_user_paused(Job *job) +{ + JOB_LOCK_GUARD(); + return job_user_paused_locked(job); +} + +void job_user_resume_locked(Job *job, Error **errp) { assert(job); GLOBAL_STATE_CODE(); @@ -636,66 +771,84 @@ void job_user_resume(Job *job, Error **errp) error_setg(errp, "Can't resume a job that was not paused"); return; } - if (job_apply_verb(job, JOB_VERB_RESUME, errp)) { + if (job_apply_verb_locked(job, JOB_VERB_RESUME, errp)) { return; } if (job->driver->user_resume) { + job_unlock(); job->driver->user_resume(job); + job_lock(); } job->user_paused = false; - job_resume(job); + job_resume_locked(job); } -static void job_do_dismiss(Job *job) +void job_user_resume(Job *job, Error **errp) +{ + JOB_LOCK_GUARD(); + job_user_resume_locked(job, errp); +} + +/* Called with job_mutex held, but releases it temporarily. */ +static void job_do_dismiss_locked(Job *job) { assert(job); job->busy = false; job->paused = false; job->deferred_to_main_loop = true; - job_txn_del_job(job); + job_txn_del_job_locked(job); - job_state_transition(job, JOB_STATUS_NULL); - job_unref(job); + job_state_transition_locked(job, JOB_STATUS_NULL); + job_unref_locked(job); } -void job_dismiss(Job **jobptr, Error **errp) +void job_dismiss_locked(Job **jobptr, Error **errp) { Job *job = *jobptr; /* similarly to _complete, this is QMP-interface only. */ assert(job->id); - if (job_apply_verb(job, JOB_VERB_DISMISS, errp)) { + if (job_apply_verb_locked(job, JOB_VERB_DISMISS, errp)) { return; } - job_do_dismiss(job); + job_do_dismiss_locked(job); *jobptr = NULL; } +void job_dismiss(Job **jobptr, Error **errp) +{ + JOB_LOCK_GUARD(); + job_dismiss_locked(jobptr, errp); +} + void job_early_fail(Job *job) { + JOB_LOCK_GUARD(); assert(job->status == JOB_STATUS_CREATED); - job_do_dismiss(job); + job_do_dismiss_locked(job); } -static void job_conclude(Job *job) +/* Called with job_mutex held. */ +static void job_conclude_locked(Job *job) { - job_state_transition(job, JOB_STATUS_CONCLUDED); - if (job->auto_dismiss || !job_started(job)) { - job_do_dismiss(job); + job_state_transition_locked(job, JOB_STATUS_CONCLUDED); + if (job->auto_dismiss || !job_started_locked(job)) { + job_do_dismiss_locked(job); } } -static void job_update_rc(Job *job) +/* Called with job_mutex held. */ +static void job_update_rc_locked(Job *job) { - if (!job->ret && job_is_cancelled(job)) { + if (!job->ret && job_is_cancelled_locked(job)) { job->ret = -ECANCELED; } if (job->ret) { if (!job->err) { error_setg(&job->err, "%s", strerror(-job->ret)); } - job_state_transition(job, JOB_STATUS_ABORTING); + job_state_transition_locked(job, JOB_STATUS_ABORTING); } } @@ -725,43 +878,57 @@ static void job_clean(Job *job) } } -static int job_finalize_single(Job *job) +/* Called with job_mutex held, but releases it temporarily */ +static int job_finalize_single_locked(Job *job) { - assert(job_is_completed(job)); + int job_ret; + + assert(job_is_completed_locked(job)); /* Ensure abort is called for late-transactional failures */ - job_update_rc(job); + job_update_rc_locked(job); - if (!job->ret) { + job_ret = job->ret; + job_unlock(); + + if (!job_ret) { job_commit(job); } else { job_abort(job); } job_clean(job); + job_lock(); + if (job->cb) { - job->cb(job->opaque, job->ret); + job_ret = job->ret; + job_unlock(); + job->cb(job->opaque, job_ret); + job_lock(); } /* Emit events only if we actually started */ - if (job_started(job)) { - if (job_is_cancelled(job)) { - job_event_cancelled(job); + if (job_started_locked(job)) { + if (job_is_cancelled_locked(job)) { + job_event_cancelled_locked(job); } else { - job_event_completed(job); + job_event_completed_locked(job); } } - job_txn_del_job(job); - job_conclude(job); + job_txn_del_job_locked(job); + job_conclude_locked(job); return 0; } -static void job_cancel_async(Job *job, bool force) +/* Called with job_mutex held, but releases it temporarily */ +static void job_cancel_async_locked(Job *job, bool force) { GLOBAL_STATE_CODE(); if (job->driver->cancel) { + job_unlock(); force = job->driver->cancel(job, force); + job_lock(); } else { /* No .cancel() means the job will behave as if force-cancelled */ force = true; @@ -770,7 +937,9 @@ static void job_cancel_async(Job *job, bool force) if (job->user_paused) { /* Do not call job_enter here, the caller will handle it. */ if (job->driver->user_resume) { + job_unlock(); job->driver->user_resume(job); + job_lock(); } job->user_paused = false; assert(job->pause_count > 0); @@ -791,7 +960,8 @@ static void job_cancel_async(Job *job, bool force) } } -static void job_completed_txn_abort(Job *job) +/* Called with job_mutex held, but releases it temporarily. */ +static void job_completed_txn_abort_locked(Job *job) { AioContext *ctx; JobTxn *txn = job->txn; @@ -804,7 +974,7 @@ static void job_completed_txn_abort(Job *job) return; } txn->aborting = true; - job_txn_ref(txn); + job_txn_ref_locked(txn); /* * We can only hold the single job's AioContext lock while calling @@ -812,7 +982,7 @@ static void job_completed_txn_abort(Job *job) * calls of AIO_WAIT_WHILE(), which could deadlock otherwise. * Note that the job's AioContext may change when it is finalized. */ - job_ref(job); + job_ref_locked(job); aio_context_release(job->aio_context); /* Other jobs are effectively cancelled by us, set the status for @@ -827,7 +997,7 @@ static void job_completed_txn_abort(Job *job) * Therefore, pass force=true to terminate all other jobs as quickly * as possible. */ - job_cancel_async(other_job, true); + job_cancel_async_locked(other_job, true); aio_context_release(ctx); } } @@ -839,11 +1009,11 @@ static void job_completed_txn_abort(Job *job) */ ctx = other_job->aio_context; aio_context_acquire(ctx); - if (!job_is_completed(other_job)) { - assert(job_cancel_requested(other_job)); - job_finish_sync(other_job, NULL, NULL); + if (!job_is_completed_locked(other_job)) { + assert(job_cancel_requested_locked(other_job)); + job_finish_sync_locked(other_job, NULL, NULL); } - job_finalize_single(other_job); + job_finalize_single_locked(other_job); aio_context_release(ctx); } @@ -852,110 +1022,132 @@ static void job_completed_txn_abort(Job *job) * even if the job went away during job_finalize_single(). */ aio_context_acquire(job->aio_context); - job_unref(job); + job_unref_locked(job); - job_txn_unref(txn); + job_txn_unref_locked(txn); } -static int job_prepare(Job *job) +/* Called with job_mutex held, but releases it temporarily */ +static int job_prepare_locked(Job *job) { + int ret; + GLOBAL_STATE_CODE(); if (job->ret == 0 && job->driver->prepare) { - job->ret = job->driver->prepare(job); - job_update_rc(job); + job_unlock(); + ret = job->driver->prepare(job); + job_lock(); + job->ret = ret; + job_update_rc_locked(job); } return job->ret; } -static int job_needs_finalize(Job *job) +/* Called with job_mutex held */ +static int job_needs_finalize_locked(Job *job) { return !job->auto_finalize; } -static void job_do_finalize(Job *job) +/* Called with job_mutex held */ +static void job_do_finalize_locked(Job *job) { int rc; assert(job && job->txn); /* prepare the transaction to complete */ - rc = job_txn_apply(job, job_prepare); + rc = job_txn_apply_locked(job, job_prepare_locked); if (rc) { - job_completed_txn_abort(job); + job_completed_txn_abort_locked(job); } else { - job_txn_apply(job, job_finalize_single); + job_txn_apply_locked(job, job_finalize_single_locked); } } +void job_finalize_locked(Job *job, Error **errp) +{ + assert(job && job->id); + if (job_apply_verb_locked(job, JOB_VERB_FINALIZE, errp)) { + return; + } + job_do_finalize_locked(job); +} + void job_finalize(Job *job, Error **errp) { - assert(job && job->id); - if (job_apply_verb(job, JOB_VERB_FINALIZE, errp)) { - return; - } - job_do_finalize(job); + JOB_LOCK_GUARD(); + job_finalize_locked(job, errp); } -static int job_transition_to_pending(Job *job) +/* Called with job_mutex held. */ +static int job_transition_to_pending_locked(Job *job) { - job_state_transition(job, JOB_STATUS_PENDING); + job_state_transition_locked(job, JOB_STATUS_PENDING); if (!job->auto_finalize) { - job_event_pending(job); + job_event_pending_locked(job); } return 0; } void job_transition_to_ready(Job *job) { - job_state_transition(job, JOB_STATUS_READY); - job_event_ready(job); + JOB_LOCK_GUARD(); + job_state_transition_locked(job, JOB_STATUS_READY); + job_event_ready_locked(job); } -static void job_completed_txn_success(Job *job) +/* Called with job_mutex held. */ +static void job_completed_txn_success_locked(Job *job) { JobTxn *txn = job->txn; Job *other_job; - job_state_transition(job, JOB_STATUS_WAITING); + job_state_transition_locked(job, JOB_STATUS_WAITING); /* * Successful completion, see if there are other running jobs in this * txn. */ QLIST_FOREACH(other_job, &txn->jobs, txn_list) { - if (!job_is_completed(other_job)) { + if (!job_is_completed_locked(other_job)) { return; } assert(other_job->ret == 0); } - job_txn_apply(job, job_transition_to_pending); + job_txn_apply_locked(job, job_transition_to_pending_locked); /* If no jobs need manual finalization, automatically do so */ - if (job_txn_apply(job, job_needs_finalize) == 0) { - job_do_finalize(job); + if (job_txn_apply_locked(job, job_needs_finalize_locked) == 0) { + job_do_finalize_locked(job); } } -static void job_completed(Job *job) +/* Called with job_mutex held. */ +static void job_completed_locked(Job *job) { - assert(job && job->txn && !job_is_completed(job)); + assert(job && job->txn && !job_is_completed_locked(job)); - job_update_rc(job); + job_update_rc_locked(job); trace_job_completed(job, job->ret); if (job->ret) { - job_completed_txn_abort(job); + job_completed_txn_abort_locked(job); } else { - job_completed_txn_success(job); + job_completed_txn_success_locked(job); } } -/** Useful only as a type shim for aio_bh_schedule_oneshot. */ +/** + * Useful only as a type shim for aio_bh_schedule_oneshot. + * Called with job_mutex *not* held. + */ static void job_exit(void *opaque) { Job *job = (Job *)opaque; AioContext *ctx; + JOB_LOCK_GUARD(); - job_ref(job); + job_ref_locked(job); aio_context_acquire(job->aio_context); /* This is a lie, we're not quiescent, but still doing the completion @@ -963,9 +1155,9 @@ static void job_exit(void *opaque) * drain block nodes, and if .drained_poll still returned true, we would * deadlock. */ job->busy = false; - job_event_idle(job); + job_event_idle_locked(job); - job_completed(job); + job_completed_locked(job); /* * Note that calling job_completed can move the job to a different @@ -974,7 +1166,7 @@ static void job_exit(void *opaque) * the job underneath us. */ ctx = job->aio_context; - job_unref(job); + job_unref_locked(job); aio_context_release(ctx); } @@ -985,37 +1177,47 @@ static void job_exit(void *opaque) static void coroutine_fn job_co_entry(void *opaque) { Job *job = opaque; + int ret; assert(job && job->driver && job->driver->run); - assert(job->aio_context == qemu_get_current_aio_context()); - job_pause_point(job); - job->ret = job->driver->run(job, &job->err); - job->deferred_to_main_loop = true; - job->busy = true; + WITH_JOB_LOCK_GUARD() { + assert(job->aio_context == qemu_get_current_aio_context()); + job_pause_point_locked(job); + } + ret = job->driver->run(job, &job->err); + WITH_JOB_LOCK_GUARD() { + job->ret = ret; + job->deferred_to_main_loop = true; + job->busy = true; + } aio_bh_schedule_oneshot(qemu_get_aio_context(), job_exit, job); } void job_start(Job *job) { - assert(job && !job_started(job) && job->paused && - job->driver && job->driver->run); - job->co = qemu_coroutine_create(job_co_entry, job); - job->pause_count--; - job->busy = true; - job->paused = false; - job_state_transition(job, JOB_STATUS_RUNNING); + assert(qemu_in_main_thread()); + + WITH_JOB_LOCK_GUARD() { + assert(job && !job_started_locked(job) && job->paused && + job->driver && job->driver->run); + job->co = qemu_coroutine_create(job_co_entry, job); + job->pause_count--; + job->busy = true; + job->paused = false; + job_state_transition_locked(job, JOB_STATUS_RUNNING); + } aio_co_enter(job->aio_context, job->co); } -void job_cancel(Job *job, bool force) +void job_cancel_locked(Job *job, bool force) { if (job->status == JOB_STATUS_CONCLUDED) { - job_do_dismiss(job); + job_do_dismiss_locked(job); return; } - job_cancel_async(job, force); - if (!job_started(job)) { - job_completed(job); + job_cancel_async_locked(job, force); + if (!job_started_locked(job)) { + job_completed_locked(job); } else if (job->deferred_to_main_loop) { /* * job_cancel_async() ignores soft-cancel requests for jobs @@ -1027,102 +1229,150 @@ void job_cancel(Job *job, bool force) * choose to call job_is_cancelled() to show that we invoke * job_completed_txn_abort() only for force-cancelled jobs.) */ - if (job_is_cancelled(job)) { - job_completed_txn_abort(job); + if (job_is_cancelled_locked(job)) { + job_completed_txn_abort_locked(job); } } else { - job_enter(job); + job_enter_cond_locked(job, NULL); } } +void job_cancel(Job *job, bool force) +{ + JOB_LOCK_GUARD(); + job_cancel_locked(job, force); +} + +void job_user_cancel_locked(Job *job, bool force, Error **errp) +{ + if (job_apply_verb_locked(job, JOB_VERB_CANCEL, errp)) { + return; + } + job_cancel_locked(job, force); +} + void job_user_cancel(Job *job, bool force, Error **errp) { - if (job_apply_verb(job, JOB_VERB_CANCEL, errp)) { - return; - } - job_cancel(job, force); + JOB_LOCK_GUARD(); + job_user_cancel_locked(job, force, errp); } /* A wrapper around job_cancel() taking an Error ** parameter so it may be * used with job_finish_sync() without the need for (rather nasty) function - * pointer casts there. */ -static void job_cancel_err(Job *job, Error **errp) + * pointer casts there. + * + * Called with job_mutex held. + */ +static void job_cancel_err_locked(Job *job, Error **errp) { - job_cancel(job, false); + job_cancel_locked(job, false); } /** * Same as job_cancel_err(), but force-cancel. + * Called with job_mutex held. */ -static void job_force_cancel_err(Job *job, Error **errp) +static void job_force_cancel_err_locked(Job *job, Error **errp) { - job_cancel(job, true); + job_cancel_locked(job, true); +} + +int job_cancel_sync_locked(Job *job, bool force) +{ + if (force) { + return job_finish_sync_locked(job, &job_force_cancel_err_locked, NULL); + } else { + return job_finish_sync_locked(job, &job_cancel_err_locked, NULL); + } } int job_cancel_sync(Job *job, bool force) { - if (force) { - return job_finish_sync(job, &job_force_cancel_err, NULL); - } else { - return job_finish_sync(job, &job_cancel_err, NULL); - } + JOB_LOCK_GUARD(); + return job_cancel_sync_locked(job, force); } void job_cancel_sync_all(void) { Job *job; AioContext *aio_context; + JOB_LOCK_GUARD(); - while ((job = job_next(NULL))) { + while ((job = job_next_locked(NULL))) { aio_context = job->aio_context; aio_context_acquire(aio_context); - job_cancel_sync(job, true); + job_cancel_sync_locked(job, true); aio_context_release(aio_context); } } -int job_complete_sync(Job *job, Error **errp) +int job_complete_sync_locked(Job *job, Error **errp) { - return job_finish_sync(job, job_complete, errp); + return job_finish_sync_locked(job, job_complete_locked, errp); } -void job_complete(Job *job, Error **errp) +int job_complete_sync(Job *job, Error **errp) +{ + JOB_LOCK_GUARD(); + return job_complete_sync_locked(job, errp); +} + +void job_complete_locked(Job *job, Error **errp) { /* Should not be reachable via external interface for internal jobs */ assert(job->id); GLOBAL_STATE_CODE(); - if (job_apply_verb(job, JOB_VERB_COMPLETE, errp)) { + if (job_apply_verb_locked(job, JOB_VERB_COMPLETE, errp)) { return; } - if (job_cancel_requested(job) || !job->driver->complete) { + if (job_cancel_requested_locked(job) || !job->driver->complete) { error_setg(errp, "The active block job '%s' cannot be completed", job->id); return; } + job_unlock(); job->driver->complete(job, errp); + job_lock(); } -int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp) +void job_complete(Job *job, Error **errp) +{ + JOB_LOCK_GUARD(); + job_complete_locked(job, errp); +} + +int job_finish_sync_locked(Job *job, + void (*finish)(Job *, Error **errp), + Error **errp) { Error *local_err = NULL; int ret; - job_ref(job); + job_ref_locked(job); if (finish) { finish(job, &local_err); } if (local_err) { error_propagate(errp, local_err); - job_unref(job); + job_unref_locked(job); return -EBUSY; } + job_unlock(); AIO_WAIT_WHILE(job->aio_context, (job_enter(job), !job_is_completed(job))); + job_lock(); - ret = (job_is_cancelled(job) && job->ret == 0) ? -ECANCELED : job->ret; - job_unref(job); + ret = (job_is_cancelled_locked(job) && job->ret == 0) + ? -ECANCELED : job->ret; + job_unref_locked(job); return ret; } + +int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp) +{ + JOB_LOCK_GUARD(); + return job_finish_sync_locked(job, finish, errp); +} From bf61c583fc04b7fcfeeccec9be0044c85daac796 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:31:59 -0400 Subject: [PATCH 0920/1020] job: move and update comments from blockjob.c This comment applies more on job, it was left in blockjob as in the past the whole job logic was implemented there. Note: at this stage, job_{lock/unlock} and job lock guard macros are *nop*. No functional change intended. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Stefan Hajnoczi Message-Id: <20220926093214.506243-7-eesposit@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- blockjob.c | 20 -------------------- job.c | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/blockjob.c b/blockjob.c index 4868453d74..7da59a1f1c 100644 --- a/blockjob.c +++ b/blockjob.c @@ -36,21 +36,6 @@ #include "qemu/main-loop.h" #include "qemu/timer.h" -/* - * The block job API is composed of two categories of functions. - * - * The first includes functions used by the monitor. The monitor is - * peculiar in that it accesses the block job list with block_job_get, and - * therefore needs consistency across block_job_get and the actual operation - * (e.g. block_job_set_speed). The consistency is achieved with - * aio_context_acquire/release. These functions are declared in blockjob.h. - * - * The second includes functions used by the block job drivers and sometimes - * by the core block layer. These do not care about locking, because the - * whole coroutine runs under the AioContext lock, and are declared in - * blockjob_int.h. - */ - static bool is_block_job(Job *job) { return job_type(job) == JOB_TYPE_BACKUP || @@ -433,11 +418,6 @@ static void block_job_event_ready(Notifier *n, void *opaque) } -/* - * API for block job drivers and the block layer. These functions are - * declared in blockjob_int.h. - */ - void *block_job_create(const char *job_id, const BlockJobDriver *driver, JobTxn *txn, BlockDriverState *bs, uint64_t perm, uint64_t shared_perm, int64_t speed, int flags, diff --git a/job.c b/job.c index 87564979cb..926e385ac2 100644 --- a/job.c +++ b/job.c @@ -32,6 +32,22 @@ #include "trace/trace-root.h" #include "qapi/qapi-events-job.h" +/* + * The job API is composed of two categories of functions. + * + * The first includes functions used by the monitor. The monitor is + * peculiar in that it accesses the job list with job_get, and + * therefore needs consistency across job_get and the actual operation + * (e.g. job_user_cancel). To achieve this consistency, the caller + * calls job_lock/job_unlock itself around the whole operation. + * + * + * The second includes functions used by the job drivers and sometimes + * by the core block layer. These delegate the locking to the callee instead. + * + * TODO Actually make this true + */ + /* * job_mutex protects the jobs list, but also makes the * struct job fields thread-safe. From f41ab73fa283f4f4d79102d1c8e8bad456218751 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:00 -0400 Subject: [PATCH 0921/1020] blockjob: introduce block_job _locked() APIs Just as done with job.h, create _locked() functions in blockjob.h These functions will be later useful when caller has already taken the lock. All blockjob _locked functions call job _locked functions. Note: at this stage, job_{lock/unlock} and job lock guard macros are *nop*. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Kevin Wolf Reviewed-by: Stefan Hajnoczi Message-Id: <20220926093214.506243-8-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- blockjob.c | 52 ++++++++++++++++++++++++++++++++-------- include/block/blockjob.h | 18 ++++++++++++++ 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/blockjob.c b/blockjob.c index 7da59a1f1c..0d59aba439 100644 --- a/blockjob.c +++ b/blockjob.c @@ -44,21 +44,27 @@ static bool is_block_job(Job *job) job_type(job) == JOB_TYPE_STREAM; } -BlockJob *block_job_next(BlockJob *bjob) +BlockJob *block_job_next_locked(BlockJob *bjob) { Job *job = bjob ? &bjob->job : NULL; GLOBAL_STATE_CODE(); do { - job = job_next(job); + job = job_next_locked(job); } while (job && !is_block_job(job)); return job ? container_of(job, BlockJob, job) : NULL; } -BlockJob *block_job_get(const char *id) +BlockJob *block_job_next(BlockJob *bjob) { - Job *job = job_get(id); + JOB_LOCK_GUARD(); + return block_job_next_locked(bjob); +} + +BlockJob *block_job_get_locked(const char *id) +{ + Job *job = job_get_locked(id); GLOBAL_STATE_CODE(); if (job && is_block_job(job)) { @@ -68,6 +74,12 @@ BlockJob *block_job_get(const char *id) } } +BlockJob *block_job_get(const char *id) +{ + JOB_LOCK_GUARD(); + return block_job_get_locked(id); +} + void block_job_free(Job *job) { BlockJob *bjob = container_of(job, BlockJob, job); @@ -256,14 +268,14 @@ static bool job_timer_pending(Job *job) return timer_pending(&job->sleep_timer); } -bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) +bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp) { const BlockJobDriver *drv = block_job_driver(job); int64_t old_speed = job->speed; GLOBAL_STATE_CODE(); - if (job_apply_verb(&job->job, JOB_VERB_SET_SPEED, errp) < 0) { + if (job_apply_verb_locked(&job->job, JOB_VERB_SET_SPEED, errp) < 0) { return false; } if (speed < 0) { @@ -277,7 +289,9 @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) job->speed = speed; if (drv->set_speed) { + job_unlock(); drv->set_speed(job, speed); + job_lock(); } if (speed && speed <= old_speed) { @@ -285,18 +299,24 @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) } /* kick only if a timer is pending */ - job_enter_cond(&job->job, job_timer_pending); + job_enter_cond_locked(&job->job, job_timer_pending); return true; } +bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) +{ + JOB_LOCK_GUARD(); + return block_job_set_speed_locked(job, speed, errp); +} + int64_t block_job_ratelimit_get_delay(BlockJob *job, uint64_t n) { IO_CODE(); return ratelimit_calculate_delay(&job->limit, n); } -BlockJobInfo *block_job_query(BlockJob *job, Error **errp) +BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp) { BlockJobInfo *info; uint64_t progress_current, progress_total; @@ -320,7 +340,7 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp) info->len = progress_total; info->speed = job->speed; info->io_status = job->iostatus; - info->ready = job_is_ready(&job->job), + info->ready = job_is_ready_locked(&job->job), info->status = job->job.status; info->auto_finalize = job->job.auto_finalize; info->auto_dismiss = job->job.auto_dismiss; @@ -333,6 +353,12 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp) return info; } +BlockJobInfo *block_job_query(BlockJob *job, Error **errp) +{ + JOB_LOCK_GUARD(); + return block_job_query_locked(job, errp); +} + static void block_job_iostatus_set_err(BlockJob *job, int error) { if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { @@ -478,7 +504,7 @@ fail: return NULL; } -void block_job_iostatus_reset(BlockJob *job) +void block_job_iostatus_reset_locked(BlockJob *job) { GLOBAL_STATE_CODE(); if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { @@ -488,6 +514,12 @@ void block_job_iostatus_reset(BlockJob *job) job->iostatus = BLOCK_DEVICE_IO_STATUS_OK; } +void block_job_iostatus_reset(BlockJob *job) +{ + JOB_LOCK_GUARD(); + block_job_iostatus_reset_locked(job); +} + void block_job_user_resume(Job *job) { BlockJob *bjob = container_of(job, BlockJob, job); diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 6525e16fd5..8b65d3949d 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -92,6 +92,9 @@ typedef struct BlockJob { */ BlockJob *block_job_next(BlockJob *job); +/* Same as block_job_next(), but called with job lock held. */ +BlockJob *block_job_next_locked(BlockJob *job); + /** * block_job_get: * @id: The id of the block job. @@ -102,6 +105,9 @@ BlockJob *block_job_next(BlockJob *job); */ BlockJob *block_job_get(const char *id); +/* Same as block_job_get(), but called with job lock held. */ +BlockJob *block_job_get_locked(const char *id); + /** * block_job_add_bdrv: * @job: A block job @@ -145,6 +151,12 @@ bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs); */ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp); +/* + * Same as block_job_set_speed(), but called with job lock held. + * Might release the lock temporarily. + */ +bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp); + /** * block_job_query: * @job: The job to get information about. @@ -153,6 +165,9 @@ bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp); */ BlockJobInfo *block_job_query(BlockJob *job, Error **errp); +/* Same as block_job_query(), but called with job lock held. */ +BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp); + /** * block_job_iostatus_reset: * @job: The job whose I/O status should be reset. @@ -162,6 +177,9 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp); */ void block_job_iostatus_reset(BlockJob *job); +/* Same as block_job_iostatus_reset(), but called with job lock held. */ +void block_job_iostatus_reset_locked(BlockJob *job); + /* * block_job_get_aio_context: * From 962411244192a21717dcce216ec7bbc44272184c Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:01 -0400 Subject: [PATCH 0922/1020] jobs: add job lock in find_* functions Both blockdev.c and job-qmp.c have TOC/TOU conditions, because they first search for the job and then perform an action on it. Therefore, we need to do the search + action under the same job mutex critical section. Note: at this stage, job_{lock/unlock} and job lock guard macros are *nop*. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf Message-Id: <20220926093214.506243-9-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- blockdev.c | 67 +++++++++++++++++++++++++++++++++++++----------------- job-qmp.c | 57 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 86 insertions(+), 38 deletions(-) diff --git a/blockdev.c b/blockdev.c index 392d9476e6..2e941e2979 100644 --- a/blockdev.c +++ b/blockdev.c @@ -3313,9 +3313,13 @@ out: aio_context_release(aio_context); } -/* Get a block job using its ID and acquire its AioContext */ -static BlockJob *find_block_job(const char *id, AioContext **aio_context, - Error **errp) +/* + * Get a block job using its ID and acquire its AioContext. + * Called with job_mutex held. + */ +static BlockJob *find_block_job_locked(const char *id, + AioContext **aio_context, + Error **errp) { BlockJob *job; @@ -3323,7 +3327,7 @@ static BlockJob *find_block_job(const char *id, AioContext **aio_context, *aio_context = NULL; - job = block_job_get(id); + job = block_job_get_locked(id); if (!job) { error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE, @@ -3340,13 +3344,16 @@ static BlockJob *find_block_job(const char *id, AioContext **aio_context, void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp) { AioContext *aio_context; - BlockJob *job = find_block_job(device, &aio_context, errp); + BlockJob *job; + + JOB_LOCK_GUARD(); + job = find_block_job_locked(device, &aio_context, errp); if (!job) { return; } - block_job_set_speed(job, speed, errp); + block_job_set_speed_locked(job, speed, errp); aio_context_release(aio_context); } @@ -3354,7 +3361,10 @@ void qmp_block_job_cancel(const char *device, bool has_force, bool force, Error **errp) { AioContext *aio_context; - BlockJob *job = find_block_job(device, &aio_context, errp); + BlockJob *job; + + JOB_LOCK_GUARD(); + job = find_block_job_locked(device, &aio_context, errp); if (!job) { return; @@ -3364,14 +3374,14 @@ void qmp_block_job_cancel(const char *device, force = false; } - if (job_user_paused(&job->job) && !force) { + if (job_user_paused_locked(&job->job) && !force) { error_setg(errp, "The block job for device '%s' is currently paused", device); goto out; } trace_qmp_block_job_cancel(job); - job_user_cancel(&job->job, force, errp); + job_user_cancel_locked(&job->job, force, errp); out: aio_context_release(aio_context); } @@ -3379,57 +3389,69 @@ out: void qmp_block_job_pause(const char *device, Error **errp) { AioContext *aio_context; - BlockJob *job = find_block_job(device, &aio_context, errp); + BlockJob *job; + + JOB_LOCK_GUARD(); + job = find_block_job_locked(device, &aio_context, errp); if (!job) { return; } trace_qmp_block_job_pause(job); - job_user_pause(&job->job, errp); + job_user_pause_locked(&job->job, errp); aio_context_release(aio_context); } void qmp_block_job_resume(const char *device, Error **errp) { AioContext *aio_context; - BlockJob *job = find_block_job(device, &aio_context, errp); + BlockJob *job; + + JOB_LOCK_GUARD(); + job = find_block_job_locked(device, &aio_context, errp); if (!job) { return; } trace_qmp_block_job_resume(job); - job_user_resume(&job->job, errp); + job_user_resume_locked(&job->job, errp); aio_context_release(aio_context); } void qmp_block_job_complete(const char *device, Error **errp) { AioContext *aio_context; - BlockJob *job = find_block_job(device, &aio_context, errp); + BlockJob *job; + + JOB_LOCK_GUARD(); + job = find_block_job_locked(device, &aio_context, errp); if (!job) { return; } trace_qmp_block_job_complete(job); - job_complete(&job->job, errp); + job_complete_locked(&job->job, errp); aio_context_release(aio_context); } void qmp_block_job_finalize(const char *id, Error **errp) { AioContext *aio_context; - BlockJob *job = find_block_job(id, &aio_context, errp); + BlockJob *job; + + JOB_LOCK_GUARD(); + job = find_block_job_locked(id, &aio_context, errp); if (!job) { return; } trace_qmp_block_job_finalize(job); - job_ref(&job->job); - job_finalize(&job->job, errp); + job_ref_locked(&job->job); + job_finalize_locked(&job->job, errp); /* * Job's context might have changed via job_finalize (and job_txn_apply @@ -3437,23 +3459,26 @@ void qmp_block_job_finalize(const char *id, Error **errp) * one. */ aio_context = block_job_get_aio_context(job); - job_unref(&job->job); + job_unref_locked(&job->job); aio_context_release(aio_context); } void qmp_block_job_dismiss(const char *id, Error **errp) { AioContext *aio_context; - BlockJob *bjob = find_block_job(id, &aio_context, errp); + BlockJob *bjob; Job *job; + JOB_LOCK_GUARD(); + bjob = find_block_job_locked(id, &aio_context, errp); + if (!bjob) { return; } trace_qmp_block_job_dismiss(bjob); job = &bjob->job; - job_dismiss(&job, errp); + job_dismiss_locked(&job, errp); aio_context_release(aio_context); } diff --git a/job-qmp.c b/job-qmp.c index 829a28aa70..b1c456482a 100644 --- a/job-qmp.c +++ b/job-qmp.c @@ -29,14 +29,19 @@ #include "qapi/error.h" #include "trace/trace-root.h" -/* Get a job using its ID and acquire its AioContext */ -static Job *find_job(const char *id, AioContext **aio_context, Error **errp) +/* + * Get a job using its ID and acquire its AioContext. + * Called with job_mutex held. + */ +static Job *find_job_locked(const char *id, + AioContext **aio_context, + Error **errp) { Job *job; *aio_context = NULL; - job = job_get(id); + job = job_get_locked(id); if (!job) { error_setg(errp, "Job not found"); return NULL; @@ -51,71 +56,86 @@ static Job *find_job(const char *id, AioContext **aio_context, Error **errp) void qmp_job_cancel(const char *id, Error **errp) { AioContext *aio_context; - Job *job = find_job(id, &aio_context, errp); + Job *job; + + JOB_LOCK_GUARD(); + job = find_job_locked(id, &aio_context, errp); if (!job) { return; } trace_qmp_job_cancel(job); - job_user_cancel(job, true, errp); + job_user_cancel_locked(job, true, errp); aio_context_release(aio_context); } void qmp_job_pause(const char *id, Error **errp) { AioContext *aio_context; - Job *job = find_job(id, &aio_context, errp); + Job *job; + + JOB_LOCK_GUARD(); + job = find_job_locked(id, &aio_context, errp); if (!job) { return; } trace_qmp_job_pause(job); - job_user_pause(job, errp); + job_user_pause_locked(job, errp); aio_context_release(aio_context); } void qmp_job_resume(const char *id, Error **errp) { AioContext *aio_context; - Job *job = find_job(id, &aio_context, errp); + Job *job; + + JOB_LOCK_GUARD(); + job = find_job_locked(id, &aio_context, errp); if (!job) { return; } trace_qmp_job_resume(job); - job_user_resume(job, errp); + job_user_resume_locked(job, errp); aio_context_release(aio_context); } void qmp_job_complete(const char *id, Error **errp) { AioContext *aio_context; - Job *job = find_job(id, &aio_context, errp); + Job *job; + + JOB_LOCK_GUARD(); + job = find_job_locked(id, &aio_context, errp); if (!job) { return; } trace_qmp_job_complete(job); - job_complete(job, errp); + job_complete_locked(job, errp); aio_context_release(aio_context); } void qmp_job_finalize(const char *id, Error **errp) { AioContext *aio_context; - Job *job = find_job(id, &aio_context, errp); + Job *job; + + JOB_LOCK_GUARD(); + job = find_job_locked(id, &aio_context, errp); if (!job) { return; } trace_qmp_job_finalize(job); - job_ref(job); - job_finalize(job, errp); + job_ref_locked(job); + job_finalize_locked(job, errp); /* * Job's context might have changed via job_finalize (and job_txn_apply @@ -123,21 +143,24 @@ void qmp_job_finalize(const char *id, Error **errp) * one. */ aio_context = job->aio_context; - job_unref(job); + job_unref_locked(job); aio_context_release(aio_context); } void qmp_job_dismiss(const char *id, Error **errp) { AioContext *aio_context; - Job *job = find_job(id, &aio_context, errp); + Job *job; + + JOB_LOCK_GUARD(); + job = find_job_locked(id, &aio_context, errp); if (!job) { return; } trace_qmp_job_dismiss(job); - job_dismiss(&job, errp); + job_dismiss_locked(&job, errp); aio_context_release(aio_context); } From 191e7af3949b51a0a675a3e13539c17140dc2fba Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:02 -0400 Subject: [PATCH 0923/1020] jobs: use job locks also in the unit tests Add missing job synchronization in the unit tests, with explicit locks. We are deliberately using _locked functions wrapped by a guard instead of a normal call because the normal call will be removed in future, as the only usage is limited to the tests. In other words, if a function like job_pause() is/will be only used in tests to avoid: WITH_JOB_LOCK_GUARD(){ job_pause_locked(); } then it is not worth keeping job_pause(), and just use the guard. Note: at this stage, job_{lock/unlock} and job lock guard macros are *nop*. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Kevin Wolf Message-Id: <20220926093214.506243-10-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- tests/unit/test-bdrv-drain.c | 76 ++++++++++++-------- tests/unit/test-block-iothread.c | 8 ++- tests/unit/test-blockjob-txn.c | 24 ++++--- tests/unit/test-blockjob.c | 115 +++++++++++++++++++------------ 4 files changed, 140 insertions(+), 83 deletions(-) diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c index 36be84ae55..0db056ea63 100644 --- a/tests/unit/test-bdrv-drain.c +++ b/tests/unit/test-bdrv-drain.c @@ -943,61 +943,83 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, } } - g_assert_cmpint(job->job.pause_count, ==, 0); - g_assert_false(job->job.paused); - g_assert_true(tjob->running); - g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ + WITH_JOB_LOCK_GUARD() { + g_assert_cmpint(job->job.pause_count, ==, 0); + g_assert_false(job->job.paused); + g_assert_true(tjob->running); + g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ + } do_drain_begin_unlocked(drain_type, drain_bs); - if (drain_type == BDRV_DRAIN_ALL) { - /* bdrv_drain_all() drains both src and target */ - g_assert_cmpint(job->job.pause_count, ==, 2); - } else { - g_assert_cmpint(job->job.pause_count, ==, 1); + WITH_JOB_LOCK_GUARD() { + if (drain_type == BDRV_DRAIN_ALL) { + /* bdrv_drain_all() drains both src and target */ + g_assert_cmpint(job->job.pause_count, ==, 2); + } else { + g_assert_cmpint(job->job.pause_count, ==, 1); + } + g_assert_true(job->job.paused); + g_assert_false(job->job.busy); /* The job is paused */ } - g_assert_true(job->job.paused); - g_assert_false(job->job.busy); /* The job is paused */ do_drain_end_unlocked(drain_type, drain_bs); if (use_iothread) { - /* paused is reset in the I/O thread, wait for it */ + /* + * Here we are waiting for the paused status to change, + * so don't bother protecting the read every time. + * + * paused is reset in the I/O thread, wait for it + */ while (job->job.paused) { aio_poll(qemu_get_aio_context(), false); } } - g_assert_cmpint(job->job.pause_count, ==, 0); - g_assert_false(job->job.paused); - g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ + WITH_JOB_LOCK_GUARD() { + g_assert_cmpint(job->job.pause_count, ==, 0); + g_assert_false(job->job.paused); + g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ + } do_drain_begin_unlocked(drain_type, target); - if (drain_type == BDRV_DRAIN_ALL) { - /* bdrv_drain_all() drains both src and target */ - g_assert_cmpint(job->job.pause_count, ==, 2); - } else { - g_assert_cmpint(job->job.pause_count, ==, 1); + WITH_JOB_LOCK_GUARD() { + if (drain_type == BDRV_DRAIN_ALL) { + /* bdrv_drain_all() drains both src and target */ + g_assert_cmpint(job->job.pause_count, ==, 2); + } else { + g_assert_cmpint(job->job.pause_count, ==, 1); + } + g_assert_true(job->job.paused); + g_assert_false(job->job.busy); /* The job is paused */ } - g_assert_true(job->job.paused); - g_assert_false(job->job.busy); /* The job is paused */ do_drain_end_unlocked(drain_type, target); if (use_iothread) { - /* paused is reset in the I/O thread, wait for it */ + /* + * Here we are waiting for the paused status to change, + * so don't bother protecting the read every time. + * + * paused is reset in the I/O thread, wait for it + */ while (job->job.paused) { aio_poll(qemu_get_aio_context(), false); } } - g_assert_cmpint(job->job.pause_count, ==, 0); - g_assert_false(job->job.paused); - g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ + WITH_JOB_LOCK_GUARD() { + g_assert_cmpint(job->job.pause_count, ==, 0); + g_assert_false(job->job.paused); + g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ + } aio_context_acquire(ctx); - ret = job_complete_sync(&job->job, &error_abort); + WITH_JOB_LOCK_GUARD() { + ret = job_complete_sync_locked(&job->job, &error_abort); + } g_assert_cmpint(ret, ==, (result == TEST_JOB_SUCCESS ? 0 : -EIO)); if (use_iothread) { diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c index 8b55eccc89..96fd21c00a 100644 --- a/tests/unit/test-block-iothread.c +++ b/tests/unit/test-block-iothread.c @@ -583,7 +583,9 @@ static void test_attach_blockjob(void) } aio_context_acquire(ctx); - job_complete_sync(&tjob->common.job, &error_abort); + WITH_JOB_LOCK_GUARD() { + job_complete_sync_locked(&tjob->common.job, &error_abort); + } blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); aio_context_release(ctx); @@ -757,7 +759,9 @@ static void test_propagate_mirror(void) BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT, false, "filter_node", MIRROR_COPY_MODE_BACKGROUND, &error_abort); - job = job_get("job0"); + WITH_JOB_LOCK_GUARD() { + job = job_get_locked("job0"); + } filter = bdrv_find_node("filter_node"); /* Change the AioContext of src */ diff --git a/tests/unit/test-blockjob-txn.c b/tests/unit/test-blockjob-txn.c index c69028b450..d3b0bb24be 100644 --- a/tests/unit/test-blockjob-txn.c +++ b/tests/unit/test-blockjob-txn.c @@ -116,8 +116,10 @@ static void test_single_job(int expected) job = test_block_job_start(1, true, expected, &result, txn); job_start(&job->job); - if (expected == -ECANCELED) { - job_cancel(&job->job, false); + WITH_JOB_LOCK_GUARD() { + if (expected == -ECANCELED) { + job_cancel_locked(&job->job, false); + } } while (result == -EINPROGRESS) { @@ -160,13 +162,15 @@ static void test_pair_jobs(int expected1, int expected2) /* Release our reference now to trigger as many nice * use-after-free bugs as possible. */ - job_txn_unref(txn); + WITH_JOB_LOCK_GUARD() { + job_txn_unref_locked(txn); - if (expected1 == -ECANCELED) { - job_cancel(&job1->job, false); - } - if (expected2 == -ECANCELED) { - job_cancel(&job2->job, false); + if (expected1 == -ECANCELED) { + job_cancel_locked(&job1->job, false); + } + if (expected2 == -ECANCELED) { + job_cancel_locked(&job2->job, false); + } } while (result1 == -EINPROGRESS || result2 == -EINPROGRESS) { @@ -219,7 +223,9 @@ static void test_pair_jobs_fail_cancel_race(void) job_start(&job1->job); job_start(&job2->job); - job_cancel(&job1->job, false); + WITH_JOB_LOCK_GUARD() { + job_cancel_locked(&job1->job, false); + } /* Now make job2 finish before the main loop kicks jobs. This simulates * the race between a pending kick and another job completing. diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c index 4c9e1bf1e5..e4f126bb6d 100644 --- a/tests/unit/test-blockjob.c +++ b/tests/unit/test-blockjob.c @@ -211,8 +211,11 @@ static CancelJob *create_common(Job **pjob) bjob = mk_job(blk, "Steve", &test_cancel_driver, true, JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS); job = &bjob->job; - job_ref(job); - assert(job->status == JOB_STATUS_CREATED); + WITH_JOB_LOCK_GUARD() { + job_ref_locked(job); + assert(job->status == JOB_STATUS_CREATED); + } + s = container_of(bjob, CancelJob, common); s->blk = blk; @@ -231,12 +234,14 @@ static void cancel_common(CancelJob *s) aio_context_acquire(ctx); job_cancel_sync(&job->job, true); - if (sts != JOB_STATUS_CREATED && sts != JOB_STATUS_CONCLUDED) { - Job *dummy = &job->job; - job_dismiss(&dummy, &error_abort); + WITH_JOB_LOCK_GUARD() { + if (sts != JOB_STATUS_CREATED && sts != JOB_STATUS_CONCLUDED) { + Job *dummy = &job->job; + job_dismiss_locked(&dummy, &error_abort); + } + assert(job->job.status == JOB_STATUS_NULL); + job_unref_locked(&job->job); } - assert(job->job.status == JOB_STATUS_NULL); - job_unref(&job->job); destroy_blk(blk); aio_context_release(ctx); @@ -251,6 +256,13 @@ static void test_cancel_created(void) cancel_common(s); } +static void assert_job_status_is(Job *job, int status) +{ + WITH_JOB_LOCK_GUARD() { + assert(job->status == status); + } +} + static void test_cancel_running(void) { Job *job; @@ -259,7 +271,7 @@ static void test_cancel_running(void) s = create_common(&job); job_start(job); - assert(job->status == JOB_STATUS_RUNNING); + assert_job_status_is(job, JOB_STATUS_RUNNING); cancel_common(s); } @@ -272,11 +284,12 @@ static void test_cancel_paused(void) s = create_common(&job); job_start(job); - assert(job->status == JOB_STATUS_RUNNING); - - job_user_pause(job, &error_abort); + WITH_JOB_LOCK_GUARD() { + assert(job->status == JOB_STATUS_RUNNING); + job_user_pause_locked(job, &error_abort); + } job_enter(job); - assert(job->status == JOB_STATUS_PAUSED); + assert_job_status_is(job, JOB_STATUS_PAUSED); cancel_common(s); } @@ -289,11 +302,11 @@ static void test_cancel_ready(void) s = create_common(&job); job_start(job); - assert(job->status == JOB_STATUS_RUNNING); + assert_job_status_is(job, JOB_STATUS_RUNNING); s->should_converge = true; job_enter(job); - assert(job->status == JOB_STATUS_READY); + assert_job_status_is(job, JOB_STATUS_READY); cancel_common(s); } @@ -306,15 +319,16 @@ static void test_cancel_standby(void) s = create_common(&job); job_start(job); - assert(job->status == JOB_STATUS_RUNNING); + assert_job_status_is(job, JOB_STATUS_RUNNING); s->should_converge = true; job_enter(job); - assert(job->status == JOB_STATUS_READY); - - job_user_pause(job, &error_abort); + WITH_JOB_LOCK_GUARD() { + assert(job->status == JOB_STATUS_READY); + job_user_pause_locked(job, &error_abort); + } job_enter(job); - assert(job->status == JOB_STATUS_STANDBY); + assert_job_status_is(job, JOB_STATUS_STANDBY); cancel_common(s); } @@ -327,20 +341,21 @@ static void test_cancel_pending(void) s = create_common(&job); job_start(job); - assert(job->status == JOB_STATUS_RUNNING); + assert_job_status_is(job, JOB_STATUS_RUNNING); s->should_converge = true; job_enter(job); - assert(job->status == JOB_STATUS_READY); - - job_complete(job, &error_abort); + WITH_JOB_LOCK_GUARD() { + assert(job->status == JOB_STATUS_READY); + job_complete_locked(job, &error_abort); + } job_enter(job); while (!job->deferred_to_main_loop) { aio_poll(qemu_get_aio_context(), true); } - assert(job->status == JOB_STATUS_READY); + assert_job_status_is(job, JOB_STATUS_READY); aio_poll(qemu_get_aio_context(), true); - assert(job->status == JOB_STATUS_PENDING); + assert_job_status_is(job, JOB_STATUS_PENDING); cancel_common(s); } @@ -353,25 +368,28 @@ static void test_cancel_concluded(void) s = create_common(&job); job_start(job); - assert(job->status == JOB_STATUS_RUNNING); + assert_job_status_is(job, JOB_STATUS_RUNNING); s->should_converge = true; job_enter(job); - assert(job->status == JOB_STATUS_READY); - - job_complete(job, &error_abort); + WITH_JOB_LOCK_GUARD() { + assert(job->status == JOB_STATUS_READY); + job_complete_locked(job, &error_abort); + } job_enter(job); while (!job->deferred_to_main_loop) { aio_poll(qemu_get_aio_context(), true); } - assert(job->status == JOB_STATUS_READY); + assert_job_status_is(job, JOB_STATUS_READY); aio_poll(qemu_get_aio_context(), true); - assert(job->status == JOB_STATUS_PENDING); + assert_job_status_is(job, JOB_STATUS_PENDING); aio_context_acquire(job->aio_context); - job_finalize(job, &error_abort); + WITH_JOB_LOCK_GUARD() { + job_finalize_locked(job, &error_abort); + } aio_context_release(job->aio_context); - assert(job->status == JOB_STATUS_CONCLUDED); + assert_job_status_is(job, JOB_STATUS_CONCLUDED); cancel_common(s); } @@ -459,36 +477,43 @@ static void test_complete_in_standby(void) bjob = mk_job(blk, "job", &test_yielding_driver, true, JOB_MANUAL_FINALIZE | JOB_MANUAL_DISMISS); job = &bjob->job; - assert(job->status == JOB_STATUS_CREATED); + assert_job_status_is(job, JOB_STATUS_CREATED); /* Wait for the job to become READY */ job_start(job); aio_context_acquire(ctx); + /* + * Here we are waiting for the status to change, so don't bother + * protecting the read every time. + */ AIO_WAIT_WHILE(ctx, job->status != JOB_STATUS_READY); aio_context_release(ctx); /* Begin the drained section, pausing the job */ bdrv_drain_all_begin(); - assert(job->status == JOB_STATUS_STANDBY); + assert_job_status_is(job, JOB_STATUS_STANDBY); + /* Lock the IO thread to prevent the job from being run */ aio_context_acquire(ctx); /* This will schedule the job to resume it */ bdrv_drain_all_end(); - /* But the job cannot run, so it will remain on standby */ - assert(job->status == JOB_STATUS_STANDBY); + WITH_JOB_LOCK_GUARD() { + /* But the job cannot run, so it will remain on standby */ + assert(job->status == JOB_STATUS_STANDBY); - /* Even though the job is on standby, this should work */ - job_complete(job, &error_abort); + /* Even though the job is on standby, this should work */ + job_complete_locked(job, &error_abort); - /* The test is done now, clean up. */ - job_finish_sync(job, NULL, &error_abort); - assert(job->status == JOB_STATUS_PENDING); + /* The test is done now, clean up. */ + job_finish_sync_locked(job, NULL, &error_abort); + assert(job->status == JOB_STATUS_PENDING); - job_finalize(job, &error_abort); - assert(job->status == JOB_STATUS_CONCLUDED); + job_finalize_locked(job, &error_abort); + assert(job->status == JOB_STATUS_CONCLUDED); - job_dismiss(&job, &error_abort); + job_dismiss_locked(&job, &error_abort); + } destroy_blk(blk); aio_context_release(ctx); From 279ac06e55698b6152e7a6431f77b4db9d059002 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:03 -0400 Subject: [PATCH 0924/1020] block/mirror.c: use of job helpers in drivers Once job lock is used and aiocontext is removed, mirror has to perform job operations under the same critical section, Note: at this stage, job_{lock/unlock} and job lock guard macros are *nop*. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220926093214.506243-11-eesposit@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block/mirror.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index 3c4ab1159d..c6bf7f40ce 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -1152,8 +1152,10 @@ static void mirror_complete(Job *job, Error **errp) s->should_complete = true; /* If the job is paused, it will be re-entered when it is resumed */ - if (!job->paused) { - job_enter(job); + WITH_JOB_LOCK_GUARD() { + if (!job->paused) { + job_enter_cond_locked(job, NULL); + } } } @@ -1173,8 +1175,11 @@ static bool mirror_drained_poll(BlockJob *job) * from one of our own drain sections, to avoid a deadlock waiting for * ourselves. */ - if (!s->common.job.paused && !job_is_cancelled(&job->job) && !s->in_drain) { - return true; + WITH_JOB_LOCK_GUARD() { + if (!s->common.job.paused && !job_is_cancelled_locked(&job->job) + && !s->in_drain) { + return true; + } } return !!s->in_flight; From 880eeec61329abc0aead900f0037fce91571b1ec Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:04 -0400 Subject: [PATCH 0925/1020] jobs: group together API calls under the same job lock Now that the API offers also _locked() functions, take advantage of it and give also the caller control to take the lock and call _locked functions. This makes sense especially when we have for loops, because it makes no sense to have: for(job = job_next(); ...) where each job_next() takes the lock internally. Instead we want JOB_LOCK_GUARD(); for(job = job_next_locked(); ...) In addition, protect also direct field accesses, by either creating a new critical section or widening the existing ones. Note: at this stage, job_{lock/unlock} and job lock guard macros are *nop*. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220926093214.506243-12-eesposit@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- block.c | 17 ++++++++++------- blockdev.c | 14 ++++++++++---- blockjob.c | 35 ++++++++++++++++++++++------------- job-qmp.c | 9 ++++++--- monitor/qmp-cmds.c | 7 +++++-- qemu-img.c | 15 ++++++++++----- 6 files changed, 63 insertions(+), 34 deletions(-) diff --git a/block.c b/block.c index 9b0fae5c1e..1fbf6b9e69 100644 --- a/block.c +++ b/block.c @@ -4981,8 +4981,8 @@ static void bdrv_close(BlockDriverState *bs) void bdrv_close_all(void) { - assert(job_next(NULL) == NULL); GLOBAL_STATE_CODE(); + assert(job_next(NULL) == NULL); /* Drop references from requests still in flight, such as canceled block * jobs whose AIO context has not been polled yet */ @@ -6168,13 +6168,16 @@ XDbgBlockGraph *bdrv_get_xdbg_block_graph(Error **errp) } } - for (job = block_job_next(NULL); job; job = block_job_next(job)) { - GSList *el; + WITH_JOB_LOCK_GUARD() { + for (job = block_job_next_locked(NULL); job; + job = block_job_next_locked(job)) { + GSList *el; - xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB, - job->job.id); - for (el = job->nodes; el; el = el->next) { - xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data); + xdbg_graph_add_node(gr, job, X_DBG_BLOCK_GRAPH_NODE_TYPE_BLOCK_JOB, + job->job.id); + for (el = job->nodes; el; el = el->next) { + xdbg_graph_add_edge(gr, job, (BdrvChild *)el->data); + } } } diff --git a/blockdev.c b/blockdev.c index 2e941e2979..46090bb0aa 100644 --- a/blockdev.c +++ b/blockdev.c @@ -150,12 +150,15 @@ void blockdev_mark_auto_del(BlockBackend *blk) return; } - for (job = block_job_next(NULL); job; job = block_job_next(job)) { + JOB_LOCK_GUARD(); + + for (job = block_job_next_locked(NULL); job; + job = block_job_next_locked(job)) { if (block_job_has_bdrv(job, blk_bs(blk))) { AioContext *aio_context = job->job.aio_context; aio_context_acquire(aio_context); - job_cancel(&job->job, false); + job_cancel_locked(&job->job, false); aio_context_release(aio_context); } @@ -3756,7 +3759,10 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp) BlockJobInfoList *head = NULL, **tail = &head; BlockJob *job; - for (job = block_job_next(NULL); job; job = block_job_next(job)) { + JOB_LOCK_GUARD(); + + for (job = block_job_next_locked(NULL); job; + job = block_job_next_locked(job)) { BlockJobInfo *value; AioContext *aio_context; @@ -3765,7 +3771,7 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp) } aio_context = block_job_get_aio_context(job); aio_context_acquire(aio_context); - value = block_job_query(job, errp); + value = block_job_query_locked(job, errp); aio_context_release(aio_context); if (!value) { qapi_free_BlockJobInfoList(head); diff --git a/blockjob.c b/blockjob.c index 0d59aba439..96fb9d9f73 100644 --- a/blockjob.c +++ b/blockjob.c @@ -111,8 +111,10 @@ static bool child_job_drained_poll(BdrvChild *c) /* An inactive or completed job doesn't have any pending requests. Jobs * with !job->busy are either already paused or have a pause point after * being reentered, so no job driver code will run before they pause. */ - if (!job->busy || job_is_completed(job)) { - return false; + WITH_JOB_LOCK_GUARD() { + if (!job->busy || job_is_completed_locked(job)) { + return false; + } } /* Otherwise, assume that it isn't fully stopped yet, but allow the job to @@ -475,13 +477,15 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, job->ready_notifier.notify = block_job_event_ready; job->idle_notifier.notify = block_job_on_idle; - notifier_list_add(&job->job.on_finalize_cancelled, - &job->finalize_cancelled_notifier); - notifier_list_add(&job->job.on_finalize_completed, - &job->finalize_completed_notifier); - notifier_list_add(&job->job.on_pending, &job->pending_notifier); - notifier_list_add(&job->job.on_ready, &job->ready_notifier); - notifier_list_add(&job->job.on_idle, &job->idle_notifier); + WITH_JOB_LOCK_GUARD() { + notifier_list_add(&job->job.on_finalize_cancelled, + &job->finalize_cancelled_notifier); + notifier_list_add(&job->job.on_finalize_completed, + &job->finalize_completed_notifier); + notifier_list_add(&job->job.on_pending, &job->pending_notifier); + notifier_list_add(&job->job.on_ready, &job->ready_notifier); + notifier_list_add(&job->job.on_idle, &job->idle_notifier); + } error_setg(&job->blocker, "block device is in use by block job: %s", job_type_str(&job->job)); @@ -558,10 +562,15 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err, action); } if (action == BLOCK_ERROR_ACTION_STOP) { - if (!job->job.user_paused) { - job_pause(&job->job); - /* make the pause user visible, which will be resumed from QMP. */ - job->job.user_paused = true; + WITH_JOB_LOCK_GUARD() { + if (!job->job.user_paused) { + job_pause_locked(&job->job); + /* + * make the pause user visible, which will be + * resumed from QMP. + */ + job->job.user_paused = true; + } } block_job_iostatus_set_err(job, error); } diff --git a/job-qmp.c b/job-qmp.c index b1c456482a..393d3a5b81 100644 --- a/job-qmp.c +++ b/job-qmp.c @@ -164,7 +164,8 @@ void qmp_job_dismiss(const char *id, Error **errp) aio_context_release(aio_context); } -static JobInfo *job_query_single(Job *job, Error **errp) +/* Called with job_mutex held. */ +static JobInfo *job_query_single_locked(Job *job, Error **errp) { JobInfo *info; uint64_t progress_current; @@ -194,7 +195,9 @@ JobInfoList *qmp_query_jobs(Error **errp) JobInfoList *head = NULL, **tail = &head; Job *job; - for (job = job_next(NULL); job; job = job_next(job)) { + JOB_LOCK_GUARD(); + + for (job = job_next_locked(NULL); job; job = job_next_locked(job)) { JobInfo *value; AioContext *aio_context; @@ -203,7 +206,7 @@ JobInfoList *qmp_query_jobs(Error **errp) } aio_context = job->aio_context; aio_context_acquire(aio_context); - value = job_query_single(job, errp); + value = job_query_single_locked(job, errp); aio_context_release(aio_context); if (!value) { qapi_free_JobInfoList(head); diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c index 7314cd813d..81c8fdadf8 100644 --- a/monitor/qmp-cmds.c +++ b/monitor/qmp-cmds.c @@ -135,8 +135,11 @@ void qmp_cont(Error **errp) blk_iostatus_reset(blk); } - for (job = block_job_next(NULL); job; job = block_job_next(job)) { - block_job_iostatus_reset(job); + WITH_JOB_LOCK_GUARD() { + for (job = block_job_next_locked(NULL); job; + job = block_job_next_locked(job)) { + block_job_iostatus_reset_locked(job); + } } /* Continuing after completed migration. Images have been inactivated to diff --git a/qemu-img.c b/qemu-img.c index cab9776f42..e0a30b1f4c 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -912,9 +912,11 @@ static void run_block_job(BlockJob *job, Error **errp) int ret = 0; aio_context_acquire(aio_context); - job_ref(&job->job); + job_lock(); + job_ref_locked(&job->job); do { float progress = 0.0f; + job_unlock(); aio_poll(aio_context, true); progress_get_snapshot(&job->job.progress, &progress_current, @@ -923,14 +925,17 @@ static void run_block_job(BlockJob *job, Error **errp) progress = (float)progress_current / progress_total * 100.f; } qemu_progress_print(progress, 0); - } while (!job_is_ready(&job->job) && !job_is_completed(&job->job)); + job_lock(); + } while (!job_is_ready_locked(&job->job) && + !job_is_completed_locked(&job->job)); - if (!job_is_completed(&job->job)) { - ret = job_complete_sync(&job->job, errp); + if (!job_is_completed_locked(&job->job)) { + ret = job_complete_sync_locked(&job->job, errp); } else { ret = job->job.ret; } - job_unref(&job->job); + job_unref_locked(&job->job); + job_unlock(); aio_context_release(aio_context); /* publish completion progress only when success */ From ef02dac28e2ae7ac1d527dd715b459288bc652a5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 26 Sep 2022 05:32:05 -0400 Subject: [PATCH 0926/1020] job: detect change of aiocontext within job coroutine We want to make sure access of job->aio_context is always done under either BQL or job_mutex. The problem is that using aio_co_enter(job->aiocontext, job->co) in job_start and job_enter_cond makes the coroutine immediately resume, so we can't hold the job lock. And caching it is not safe either, as it might change. job_start is under BQL, so it can freely read job->aiocontext, but job_enter_cond is not. We want to avoid reading job->aio_context in job_enter_cond, therefore: 1) use aio_co_wake(), since it doesn't want an aiocontext as argument but uses job->co->ctx 2) detect possible discrepancy between job->co->ctx and job->aio_context by checking right after the coroutine resumes back from yielding if job->aio_context has changed. If so, reschedule the coroutine to the new context. Calling bdrv_try_set_aio_context() will issue the following calls (simplified): * in terms of bdrv callbacks: .drained_begin -> .set_aio_context -> .drained_end * in terms of child_job functions: child_job_drained_begin -> child_job_set_aio_context -> child_job_drained_end * in terms of job functions: job_pause_locked -> job_set_aio_context -> job_resume_locked We can see that after setting the new aio_context, job_resume_locked calls again job_enter_cond, which then invokes aio_co_wake(). But while job->aiocontext has been set in job_set_aio_context, job->co->ctx has not changed, so the coroutine would be entering in the wrong aiocontext. Using aio_co_schedule in job_resume_locked() might seem as a valid alternative, but the problem is that the bh resuming the coroutine is not scheduled immediately, and if in the meanwhile another bdrv_try_set_aio_context() is run (see test_propagate_mirror() in test-block-iothread.c), we would have the first schedule in the wrong aiocontext, and the second set of drains won't even manage to schedule the coroutine, as job->busy would still be true from the previous job_resume_locked(). The solution is to stick with aio_co_wake() and detect every time the coroutine resumes back from yielding if job->aio_context has changed. If so, we can reschedule it to the new context. Check for the aiocontext change in job_do_yield_locked because: 1) aio_co_reschedule_self requires to be in the running coroutine 2) since child_job_set_aio_context allows changing the aiocontext only while the job is paused, this is the exact place where the coroutine resumes, before running JobDriver's code. Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Stefan Hajnoczi Signed-off-by: Paolo Bonzini Message-Id: <20220926093214.506243-13-eesposit@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- job.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/job.c b/job.c index 926e385ac2..3ef5028751 100644 --- a/job.c +++ b/job.c @@ -588,7 +588,7 @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job)) job->busy = true; real_job_unlock(); job_unlock(); - aio_co_enter(job->aio_context, job->co); + aio_co_wake(job->co); job_lock(); } @@ -615,6 +615,8 @@ void job_enter(Job *job) */ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns) { + AioContext *next_aio_context; + real_job_lock(); if (ns != -1) { timer_mod(&job->sleep_timer, ns); @@ -626,7 +628,20 @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns) qemu_coroutine_yield(); job_lock(); - /* Set by job_enter_cond() before re-entering the coroutine. */ + next_aio_context = job->aio_context; + /* + * Coroutine has resumed, but in the meanwhile the job AioContext + * might have changed via bdrv_try_set_aio_context(), so we need to move + * the coroutine too in the new aiocontext. + */ + while (qemu_get_current_aio_context() != next_aio_context) { + job_unlock(); + aio_co_reschedule_self(next_aio_context); + job_lock(); + next_aio_context = job->aio_context; + } + + /* Set by job_enter_cond_locked() before re-entering the coroutine. */ assert(job->busy); } From 3ed4f708fe12537066d21f3dd111af013f7a6b8c Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:06 -0400 Subject: [PATCH 0927/1020] jobs: protect job.aio_context with BQL and job_mutex In order to make it thread safe, implement a "fake rwlock", where we allow reads under BQL *or* job_mutex held, but writes only under BQL *and* job_mutex. The only write we have is in child_job_set_aio_ctx, which always happens under drain (so the job is paused). For this reason, introduce job_set_aio_context and make sure that the context is set under BQL, job_mutex and drain. Also make sure all other places where the aiocontext is read are protected. The reads in commit.c and mirror.c are actually safe, because always done under BQL. Note: at this stage, job_{lock/unlock} and job lock guard macros are *nop*. Suggested-by: Paolo Bonzini Signed-off-by: Emanuele Giuseppe Esposito Message-Id: <20220926093214.506243-14-eesposit@redhat.com> Reviewed-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block/replication.c | 1 + blockjob.c | 3 ++- include/qemu/job.h | 23 ++++++++++++++++++++--- job.c | 12 ++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/block/replication.c b/block/replication.c index 55c8f894aa..5977f7a833 100644 --- a/block/replication.c +++ b/block/replication.c @@ -142,6 +142,7 @@ static void replication_close(BlockDriverState *bs) { BDRVReplicationState *s = bs->opaque; Job *commit_job; + GLOBAL_STATE_CODE(); if (s->stage == BLOCK_REPLICATION_RUNNING) { replication_stop(s->rs, false, NULL); diff --git a/blockjob.c b/blockjob.c index 96fb9d9f73..c8919cef9b 100644 --- a/blockjob.c +++ b/blockjob.c @@ -162,12 +162,13 @@ static void child_job_set_aio_ctx(BdrvChild *c, AioContext *ctx, bdrv_set_aio_context_ignore(sibling->bs, ctx, ignore); } - job->job.aio_context = ctx; + job_set_aio_context(&job->job, ctx); } static AioContext *child_job_get_parent_aio_context(BdrvChild *c) { BlockJob *job = c->opaque; + GLOBAL_STATE_CODE(); return job->job.aio_context; } diff --git a/include/qemu/job.h b/include/qemu/job.h index 870dce1535..c96387069d 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -74,12 +74,18 @@ typedef struct Job { /* ProgressMeter API is thread-safe */ ProgressMeter progress; + /** + * AioContext to run the job coroutine in. + * The job Aiocontext can be read when holding *either* + * the BQL (so we are in the main loop) or the job_mutex. + * It can only be written when we hold *both* BQL + * and the job_mutex. + */ + AioContext *aio_context; + /** Protected by AioContext lock */ - /** AioContext to run the job coroutine in */ - AioContext *aio_context; - /** Reference count of the block job */ int refcnt; @@ -741,4 +747,15 @@ int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp), Error **errp); +/** + * Sets the @job->aio_context. + * Called with job_mutex *not* held. + * + * This function must run in the main thread to protect against + * concurrent read in job_finish_sync_locked(), takes the job_mutex + * lock to protect against the read in job_do_yield_locked(), and must + * be called when the job is quiescent. + */ +void job_set_aio_context(Job *job, AioContext *ctx); + #endif diff --git a/job.c b/job.c index 3ef5028751..3e6f61c523 100644 --- a/job.c +++ b/job.c @@ -396,6 +396,17 @@ Job *job_get(const char *id) return job_get_locked(id); } +void job_set_aio_context(Job *job, AioContext *ctx) +{ + /* protect against read in job_finish_sync_locked and job_start */ + GLOBAL_STATE_CODE(); + /* protect against read in job_do_yield_locked */ + JOB_LOCK_GUARD(); + /* ensure the job is quiescent while the AioContext is changed */ + assert(job->paused || job_is_completed_locked(job)); + job->aio_context = ctx; +} + /* Called with job_mutex *not* held. */ static void job_sleep_timer_cb(void *opaque) { @@ -1379,6 +1390,7 @@ int job_finish_sync_locked(Job *job, { Error *local_err = NULL; int ret; + GLOBAL_STATE_CODE(); job_ref_locked(job); From 3937e12cf8887660d86034c7d54c4f2236f0cb0e Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:07 -0400 Subject: [PATCH 0928/1020] blockjob.h: categorize fields in struct BlockJob The same job lock is being used also to protect some of blockjob fields. Categorize them just as done in job.h. Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Emanuele Giuseppe Esposito Message-Id: <20220926093214.506243-15-eesposit@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/block/blockjob.h | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 8b65d3949d..10c24e240a 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -40,21 +40,38 @@ typedef struct BlockJobDriver BlockJobDriver; * Long-running operation on a BlockDriverState. */ typedef struct BlockJob { - /** Data belonging to the generic Job infrastructure */ + /** + * Data belonging to the generic Job infrastructure. + * Protected by job mutex. + */ Job job; - /** Status that is published by the query-block-jobs QMP API */ + /** + * Status that is published by the query-block-jobs QMP API. + * Protected by job mutex. + */ BlockDeviceIoStatus iostatus; - /** Speed that was set with @block_job_set_speed. */ + /** + * Speed that was set with @block_job_set_speed. + * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE). + */ int64_t speed; - /** Rate limiting data structure for implementing @speed. */ + /** + * Rate limiting data structure for implementing @speed. + * RateLimit API is thread-safe. + */ RateLimit limit; - /** Block other operations when block job is running */ + /** + * Block other operations when block job is running. + * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE). + */ Error *blocker; + /** All notifiers are set once in block_job_create() and never modified. */ + /** Called when a cancelled job is finalised. */ Notifier finalize_cancelled_notifier; @@ -70,7 +87,10 @@ typedef struct BlockJob { /** Called when the job coroutine yields or terminates */ Notifier idle_notifier; - /** BlockDriverStates that are involved in this block job */ + /** + * BlockDriverStates that are involved in this block job. + * Always modified and read under QEMU global mutex (GLOBAL_STATE_CODE). + */ GSList *nodes; } BlockJob; From 243c6ec7fe8a2ce8bf1481444049ffce649c8f76 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:08 -0400 Subject: [PATCH 0929/1020] blockjob: rename notifier callbacks as _locked They all are called with job_lock held, in job_event_*_locked() Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf Message-Id: <20220926093214.506243-16-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- blockjob.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/blockjob.c b/blockjob.c index c8919cef9b..d8fb5311c7 100644 --- a/blockjob.c +++ b/blockjob.c @@ -250,7 +250,8 @@ int block_job_add_bdrv(BlockJob *job, const char *name, BlockDriverState *bs, return 0; } -static void block_job_on_idle(Notifier *n, void *opaque) +/* Called with job_mutex lock held. */ +static void block_job_on_idle_locked(Notifier *n, void *opaque) { aio_wait_kick(); } @@ -370,7 +371,8 @@ static void block_job_iostatus_set_err(BlockJob *job, int error) } } -static void block_job_event_cancelled(Notifier *n, void *opaque) +/* Called with job_mutex lock held. */ +static void block_job_event_cancelled_locked(Notifier *n, void *opaque) { BlockJob *job = opaque; uint64_t progress_current, progress_total; @@ -389,7 +391,8 @@ static void block_job_event_cancelled(Notifier *n, void *opaque) job->speed); } -static void block_job_event_completed(Notifier *n, void *opaque) +/* Called with job_mutex lock held. */ +static void block_job_event_completed_locked(Notifier *n, void *opaque) { BlockJob *job = opaque; const char *msg = NULL; @@ -415,7 +418,8 @@ static void block_job_event_completed(Notifier *n, void *opaque) msg); } -static void block_job_event_pending(Notifier *n, void *opaque) +/* Called with job_mutex lock held. */ +static void block_job_event_pending_locked(Notifier *n, void *opaque) { BlockJob *job = opaque; @@ -427,7 +431,8 @@ static void block_job_event_pending(Notifier *n, void *opaque) job->job.id); } -static void block_job_event_ready(Notifier *n, void *opaque) +/* Called with job_mutex lock held. */ +static void block_job_event_ready_locked(Notifier *n, void *opaque) { BlockJob *job = opaque; uint64_t progress_current, progress_total; @@ -472,11 +477,11 @@ void *block_job_create(const char *job_id, const BlockJobDriver *driver, ratelimit_init(&job->limit); - job->finalize_cancelled_notifier.notify = block_job_event_cancelled; - job->finalize_completed_notifier.notify = block_job_event_completed; - job->pending_notifier.notify = block_job_event_pending; - job->ready_notifier.notify = block_job_event_ready; - job->idle_notifier.notify = block_job_on_idle; + job->finalize_cancelled_notifier.notify = block_job_event_cancelled_locked; + job->finalize_completed_notifier.notify = block_job_event_completed_locked; + job->pending_notifier.notify = block_job_event_pending_locked; + job->ready_notifier.notify = block_job_event_ready_locked; + job->idle_notifier.notify = block_job_on_idle_locked; WITH_JOB_LOCK_GUARD() { notifier_list_add(&job->job.on_finalize_cancelled, From d59cb66de32c27443b12b774147b611f8e459e9b Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:09 -0400 Subject: [PATCH 0930/1020] blockjob: protect iostatus field in BlockJob struct iostatus is the only field (together with .job) that needs protection using the job mutex. It is set in the main loop (GLOBAL_STATE functions) but read in I/O code (block_job_error_action). In order to protect it, change block_job_iostatus_set_err to block_job_iostatus_set_err_locked(), always called under job lock. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220926093214.506243-17-eesposit@redhat.com> [kwolf: Fixed up type of iostatus] Signed-off-by: Kevin Wolf --- block/mirror.c | 6 +++++- blockjob.c | 5 +++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/block/mirror.c b/block/mirror.c index c6bf7f40ce..80c0109d39 100644 --- a/block/mirror.c +++ b/block/mirror.c @@ -894,6 +894,7 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) BlockDriverState *bs = s->mirror_top_bs->backing->bs; BlockDriverState *target_bs = blk_bs(s->target); bool need_drain = true; + BlockDeviceIoStatus iostatus; int64_t length; int64_t target_length; BlockDriverInfo bdi; @@ -1016,8 +1017,11 @@ static int coroutine_fn mirror_run(Job *job, Error **errp) * We do so every BLKOCK_JOB_SLICE_TIME nanoseconds, or when there is * an error, or when the source is clean, whichever comes first. */ delta = qemu_clock_get_ns(QEMU_CLOCK_REALTIME) - s->last_pause_ns; + WITH_JOB_LOCK_GUARD() { + iostatus = s->common.iostatus; + } if (delta < BLOCK_JOB_SLICE_TIME && - s->common.iostatus == BLOCK_DEVICE_IO_STATUS_OK) { + iostatus == BLOCK_DEVICE_IO_STATUS_OK) { if (s->in_flight >= MAX_IN_FLIGHT || s->buf_free_count == 0 || (cnt == 0 && s->in_flight > 0)) { trace_mirror_yield(s, cnt, s->buf_free_count, s->in_flight); diff --git a/blockjob.c b/blockjob.c index d8fb5311c7..d04f804001 100644 --- a/blockjob.c +++ b/blockjob.c @@ -363,7 +363,8 @@ BlockJobInfo *block_job_query(BlockJob *job, Error **errp) return block_job_query_locked(job, errp); } -static void block_job_iostatus_set_err(BlockJob *job, int error) +/* Called with job lock held */ +static void block_job_iostatus_set_err_locked(BlockJob *job, int error) { if (job->iostatus == BLOCK_DEVICE_IO_STATUS_OK) { job->iostatus = error == ENOSPC ? BLOCK_DEVICE_IO_STATUS_NOSPACE : @@ -577,8 +578,8 @@ BlockErrorAction block_job_error_action(BlockJob *job, BlockdevOnError on_err, */ job->job.user_paused = true; } + block_job_iostatus_set_err_locked(job, error); } - block_job_iostatus_set_err(job, error); } return action; } From 2fc3bdc3843d2d8bde54c2be4d4f4cc8a9ffcf50 Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:10 -0400 Subject: [PATCH 0931/1020] job.h: categorize JobDriver callbacks that need the AioContext lock Some callbacks implementation use bdrv_* APIs that assume the AioContext lock is held. Make sure this invariant is documented. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220926093214.506243-18-eesposit@redhat.com> Reviewed-by: Kevin Wolf Signed-off-by: Kevin Wolf --- include/qemu/job.h | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/include/qemu/job.h b/include/qemu/job.h index c96387069d..b943d90e8f 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -65,7 +65,11 @@ typedef struct Job { /** True if this job should automatically dismiss itself */ bool auto_dismiss; - /** The completion function that will be called when the job completes. */ + /** + * The completion function that will be called when the job completes. + * Called with AioContext lock held, since many callback implementations + * use bdrv_* functions that require to hold the lock. + */ BlockCompletionFunc *cb; /** The opaque value that is passed to the completion function. */ @@ -260,6 +264,9 @@ struct JobDriver { * * This callback will not be invoked if the job has already failed. * If it fails, abort and then clean will be called. + * + * Called with AioContext lock held, since many callbacs implementations + * use bdrv_* functions that require to hold the lock. */ int (*prepare)(Job *job); @@ -270,6 +277,9 @@ struct JobDriver { * * All jobs will complete with a call to either .commit() or .abort() but * never both. + * + * Called with AioContext lock held, since many callback implementations + * use bdrv_* functions that require to hold the lock. */ void (*commit)(Job *job); @@ -280,6 +290,9 @@ struct JobDriver { * * All jobs will complete with a call to either .commit() or .abort() but * never both. + * + * Called with AioContext lock held, since many callback implementations + * use bdrv_* functions that require to hold the lock. */ void (*abort)(Job *job); @@ -288,6 +301,9 @@ struct JobDriver { * .commit() or .abort(). Regardless of which callback is invoked after * completion, .clean() will always be called, even if the job does not * belong to a transaction group. + * + * Called with AioContext lock held, since many callbacs implementations + * use bdrv_* functions that require to hold the lock. */ void (*clean)(Job *job); @@ -302,11 +318,18 @@ struct JobDriver { * READY). * (If the callback is NULL, the job is assumed to terminate * without I/O.) + * + * Called with AioContext lock held, since many callback implementations + * use bdrv_* functions that require to hold the lock. */ bool (*cancel)(Job *job, bool force); - /** Called when the job is freed */ + /** + * Called when the job is freed. + * Called with AioContext lock held, since many callback implementations + * use bdrv_* functions that require to hold the lock. + */ void (*free)(Job *job); }; From 6f592e5aca1a27fe1c1f661cfe68b35b90850acf Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:11 -0400 Subject: [PATCH 0932/1020] job.c: enable job lock/unlock and remove Aiocontext locks Change the job_{lock/unlock} and macros to use job_mutex. Now that they are not nop anymore, remove the aiocontext to avoid deadlocks. Therefore: - when possible, remove completely the aiocontext lock/unlock pair - if it is used by some other function too, reduce the locking section as much as possible, leaving the job API outside. - change AIO_WAIT_WHILE in AIO_WAIT_WHILE_UNLOCKED, since we are not using the aiocontext lock anymore The only functions that still need the aiocontext lock are: - the JobDriver callbacks, already documented in job.h - job_cancel_sync() in replication.c is called with aio_context_lock taken, but now job is using AIO_WAIT_WHILE_UNLOCKED so we need to release the lock. Reduce the locking section to only cover the callback invocation and document the functions that take the AioContext lock, to avoid taking it twice. Also remove real_job_{lock/unlock}, as they are replaced by the public functions. Signed-off-by: Emanuele Giuseppe Esposito Message-Id: <20220926093214.506243-19-eesposit@redhat.com> Reviewed-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- block/replication.c | 2 + blockdev.c | 72 +++----------------- include/qemu/job.h | 17 ++--- job-qmp.c | 46 +++---------- job.c | 111 +++++++++---------------------- qemu-img.c | 2 - tests/unit/test-bdrv-drain.c | 4 +- tests/unit/test-block-iothread.c | 2 +- tests/unit/test-blockjob.c | 19 +++--- 9 files changed, 72 insertions(+), 203 deletions(-) diff --git a/block/replication.c b/block/replication.c index 5977f7a833..c67f931f37 100644 --- a/block/replication.c +++ b/block/replication.c @@ -727,7 +727,9 @@ static void replication_stop(ReplicationState *rs, bool failover, Error **errp) * disk, secondary disk in backup_job_completed(). */ if (s->backup_job) { + aio_context_release(aio_context); job_cancel_sync(&s->backup_job->job, true); + aio_context_acquire(aio_context); } if (!failover) { diff --git a/blockdev.c b/blockdev.c index 46090bb0aa..a32bafc07a 100644 --- a/blockdev.c +++ b/blockdev.c @@ -155,12 +155,7 @@ void blockdev_mark_auto_del(BlockBackend *blk) for (job = block_job_next_locked(NULL); job; job = block_job_next_locked(job)) { if (block_job_has_bdrv(job, blk_bs(blk))) { - AioContext *aio_context = job->job.aio_context; - aio_context_acquire(aio_context); - job_cancel_locked(&job->job, false); - - aio_context_release(aio_context); } } @@ -1847,14 +1842,7 @@ static void drive_backup_abort(BlkActionState *common) DriveBackupState *state = DO_UPCAST(DriveBackupState, common, common); if (state->job) { - AioContext *aio_context; - - aio_context = bdrv_get_aio_context(state->bs); - aio_context_acquire(aio_context); - job_cancel_sync(&state->job->job, true); - - aio_context_release(aio_context); } } @@ -1948,14 +1936,7 @@ static void blockdev_backup_abort(BlkActionState *common) BlockdevBackupState *state = DO_UPCAST(BlockdevBackupState, common, common); if (state->job) { - AioContext *aio_context; - - aio_context = bdrv_get_aio_context(state->bs); - aio_context_acquire(aio_context); - job_cancel_sync(&state->job->job, true); - - aio_context_release(aio_context); } } @@ -3317,19 +3298,14 @@ out: } /* - * Get a block job using its ID and acquire its AioContext. - * Called with job_mutex held. + * Get a block job using its ID. Called with job_mutex held. */ -static BlockJob *find_block_job_locked(const char *id, - AioContext **aio_context, - Error **errp) +static BlockJob *find_block_job_locked(const char *id, Error **errp) { BlockJob *job; assert(id != NULL); - *aio_context = NULL; - job = block_job_get_locked(id); if (!job) { @@ -3338,36 +3314,30 @@ static BlockJob *find_block_job_locked(const char *id, return NULL; } - *aio_context = block_job_get_aio_context(job); - aio_context_acquire(*aio_context); - return job; } void qmp_block_job_set_speed(const char *device, int64_t speed, Error **errp) { - AioContext *aio_context; BlockJob *job; JOB_LOCK_GUARD(); - job = find_block_job_locked(device, &aio_context, errp); + job = find_block_job_locked(device, errp); if (!job) { return; } block_job_set_speed_locked(job, speed, errp); - aio_context_release(aio_context); } void qmp_block_job_cancel(const char *device, bool has_force, bool force, Error **errp) { - AioContext *aio_context; BlockJob *job; JOB_LOCK_GUARD(); - job = find_block_job_locked(device, &aio_context, errp); + job = find_block_job_locked(device, errp); if (!job) { return; @@ -3380,22 +3350,19 @@ void qmp_block_job_cancel(const char *device, if (job_user_paused_locked(&job->job) && !force) { error_setg(errp, "The block job for device '%s' is currently paused", device); - goto out; + return; } trace_qmp_block_job_cancel(job); job_user_cancel_locked(&job->job, force, errp); -out: - aio_context_release(aio_context); } void qmp_block_job_pause(const char *device, Error **errp) { - AioContext *aio_context; BlockJob *job; JOB_LOCK_GUARD(); - job = find_block_job_locked(device, &aio_context, errp); + job = find_block_job_locked(device, errp); if (!job) { return; @@ -3403,16 +3370,14 @@ void qmp_block_job_pause(const char *device, Error **errp) trace_qmp_block_job_pause(job); job_user_pause_locked(&job->job, errp); - aio_context_release(aio_context); } void qmp_block_job_resume(const char *device, Error **errp) { - AioContext *aio_context; BlockJob *job; JOB_LOCK_GUARD(); - job = find_block_job_locked(device, &aio_context, errp); + job = find_block_job_locked(device, errp); if (!job) { return; @@ -3420,16 +3385,14 @@ void qmp_block_job_resume(const char *device, Error **errp) trace_qmp_block_job_resume(job); job_user_resume_locked(&job->job, errp); - aio_context_release(aio_context); } void qmp_block_job_complete(const char *device, Error **errp) { - AioContext *aio_context; BlockJob *job; JOB_LOCK_GUARD(); - job = find_block_job_locked(device, &aio_context, errp); + job = find_block_job_locked(device, errp); if (!job) { return; @@ -3437,16 +3400,14 @@ void qmp_block_job_complete(const char *device, Error **errp) trace_qmp_block_job_complete(job); job_complete_locked(&job->job, errp); - aio_context_release(aio_context); } void qmp_block_job_finalize(const char *id, Error **errp) { - AioContext *aio_context; BlockJob *job; JOB_LOCK_GUARD(); - job = find_block_job_locked(id, &aio_context, errp); + job = find_block_job_locked(id, errp); if (!job) { return; @@ -3456,24 +3417,16 @@ void qmp_block_job_finalize(const char *id, Error **errp) job_ref_locked(&job->job); job_finalize_locked(&job->job, errp); - /* - * Job's context might have changed via job_finalize (and job_txn_apply - * automatically acquires the new one), so make sure we release the correct - * one. - */ - aio_context = block_job_get_aio_context(job); job_unref_locked(&job->job); - aio_context_release(aio_context); } void qmp_block_job_dismiss(const char *id, Error **errp) { - AioContext *aio_context; BlockJob *bjob; Job *job; JOB_LOCK_GUARD(); - bjob = find_block_job_locked(id, &aio_context, errp); + bjob = find_block_job_locked(id, errp); if (!bjob) { return; @@ -3482,7 +3435,6 @@ void qmp_block_job_dismiss(const char *id, Error **errp) trace_qmp_block_job_dismiss(bjob); job = &bjob->job; job_dismiss_locked(&job, errp); - aio_context_release(aio_context); } void qmp_change_backing_file(const char *device, @@ -3764,15 +3716,11 @@ BlockJobInfoList *qmp_query_block_jobs(Error **errp) for (job = block_job_next_locked(NULL); job; job = block_job_next_locked(job)) { BlockJobInfo *value; - AioContext *aio_context; if (block_job_is_internal(job)) { continue; } - aio_context = block_job_get_aio_context(job); - aio_context_acquire(aio_context); value = block_job_query_locked(job, errp); - aio_context_release(aio_context); if (!value) { qapi_free_BlockJobInfoList(head); return NULL; diff --git a/include/qemu/job.h b/include/qemu/job.h index b943d90e8f..a54fb83887 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -88,7 +88,7 @@ typedef struct Job { AioContext *aio_context; - /** Protected by AioContext lock */ + /** Protected by job_mutex */ /** Reference count of the block job */ int refcnt; @@ -111,7 +111,7 @@ typedef struct Job { /** * Set to false by the job while the coroutine has yielded and may be * re-entered by job_enter(). There may still be I/O or event loop activity - * pending. Accessed under block_job_mutex (in blockjob.c). + * pending. Accessed under job_mutex. * * When the job is deferred to the main loop, busy is true as long as the * bottom half is still pending. @@ -346,9 +346,9 @@ typedef enum JobCreateFlags { extern QemuMutex job_mutex; -#define JOB_LOCK_GUARD() /* QEMU_LOCK_GUARD(&job_mutex) */ +#define JOB_LOCK_GUARD() QEMU_LOCK_GUARD(&job_mutex) -#define WITH_JOB_LOCK_GUARD() /* WITH_QEMU_LOCK_GUARD(&job_mutex) */ +#define WITH_JOB_LOCK_GUARD() WITH_QEMU_LOCK_GUARD(&job_mutex) /** * job_lock: @@ -422,6 +422,8 @@ void job_ref_locked(Job *job); /** * Release a reference that was previously acquired with job_ref() or * job_create(). If it's the last reference to the object, it will be freed. + * + * Takes AioContext lock internally to invoke a job->driver callback. */ void job_unref(Job *job); @@ -696,7 +698,7 @@ void job_user_cancel_locked(Job *job, bool force, Error **errp); * Returns the return value from the job if the job actually completed * during the call, or -ECANCELED if it was canceled. * - * Callers must hold the AioContext lock of job->aio_context. + * Called with job_lock *not* held. */ int job_cancel_sync(Job *job, bool force); @@ -721,8 +723,7 @@ void job_cancel_sync_all(void); * function). * * Returns the return value from the job. - * - * Callers must hold the AioContext lock of job->aio_context. + * Called with job_lock *not* held. */ int job_complete_sync(Job *job, Error **errp); @@ -758,7 +759,7 @@ void job_dismiss_locked(Job **job, Error **errp); * Returns 0 if the job is successfully completed, -ECANCELED if the job was * cancelled before completing, and -errno in other error cases. * - * Callers must hold the AioContext lock of job->aio_context. + * Called with job_lock *not* held. */ int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp); diff --git a/job-qmp.c b/job-qmp.c index 393d3a5b81..d498fc89c0 100644 --- a/job-qmp.c +++ b/job-qmp.c @@ -30,36 +30,27 @@ #include "trace/trace-root.h" /* - * Get a job using its ID and acquire its AioContext. - * Called with job_mutex held. + * Get a job using its ID. Called with job_mutex held. */ -static Job *find_job_locked(const char *id, - AioContext **aio_context, - Error **errp) +static Job *find_job_locked(const char *id, Error **errp) { Job *job; - *aio_context = NULL; - job = job_get_locked(id); if (!job) { error_setg(errp, "Job not found"); return NULL; } - *aio_context = job->aio_context; - aio_context_acquire(*aio_context); - return job; } void qmp_job_cancel(const char *id, Error **errp) { - AioContext *aio_context; Job *job; JOB_LOCK_GUARD(); - job = find_job_locked(id, &aio_context, errp); + job = find_job_locked(id, errp); if (!job) { return; @@ -67,16 +58,14 @@ void qmp_job_cancel(const char *id, Error **errp) trace_qmp_job_cancel(job); job_user_cancel_locked(job, true, errp); - aio_context_release(aio_context); } void qmp_job_pause(const char *id, Error **errp) { - AioContext *aio_context; Job *job; JOB_LOCK_GUARD(); - job = find_job_locked(id, &aio_context, errp); + job = find_job_locked(id, errp); if (!job) { return; @@ -84,16 +73,14 @@ void qmp_job_pause(const char *id, Error **errp) trace_qmp_job_pause(job); job_user_pause_locked(job, errp); - aio_context_release(aio_context); } void qmp_job_resume(const char *id, Error **errp) { - AioContext *aio_context; Job *job; JOB_LOCK_GUARD(); - job = find_job_locked(id, &aio_context, errp); + job = find_job_locked(id, errp); if (!job) { return; @@ -101,16 +88,14 @@ void qmp_job_resume(const char *id, Error **errp) trace_qmp_job_resume(job); job_user_resume_locked(job, errp); - aio_context_release(aio_context); } void qmp_job_complete(const char *id, Error **errp) { - AioContext *aio_context; Job *job; JOB_LOCK_GUARD(); - job = find_job_locked(id, &aio_context, errp); + job = find_job_locked(id, errp); if (!job) { return; @@ -118,16 +103,14 @@ void qmp_job_complete(const char *id, Error **errp) trace_qmp_job_complete(job); job_complete_locked(job, errp); - aio_context_release(aio_context); } void qmp_job_finalize(const char *id, Error **errp) { - AioContext *aio_context; Job *job; JOB_LOCK_GUARD(); - job = find_job_locked(id, &aio_context, errp); + job = find_job_locked(id, errp); if (!job) { return; @@ -137,23 +120,15 @@ void qmp_job_finalize(const char *id, Error **errp) job_ref_locked(job); job_finalize_locked(job, errp); - /* - * Job's context might have changed via job_finalize (and job_txn_apply - * automatically acquires the new one), so make sure we release the correct - * one. - */ - aio_context = job->aio_context; job_unref_locked(job); - aio_context_release(aio_context); } void qmp_job_dismiss(const char *id, Error **errp) { - AioContext *aio_context; Job *job; JOB_LOCK_GUARD(); - job = find_job_locked(id, &aio_context, errp); + job = find_job_locked(id, errp); if (!job) { return; @@ -161,7 +136,6 @@ void qmp_job_dismiss(const char *id, Error **errp) trace_qmp_job_dismiss(job); job_dismiss_locked(&job, errp); - aio_context_release(aio_context); } /* Called with job_mutex held. */ @@ -199,15 +173,11 @@ JobInfoList *qmp_query_jobs(Error **errp) for (job = job_next_locked(NULL); job; job = job_next_locked(job)) { JobInfo *value; - AioContext *aio_context; if (job_is_internal(job)) { continue; } - aio_context = job->aio_context; - aio_context_acquire(aio_context); value = job_query_single_locked(job, errp); - aio_context_release(aio_context); if (!value) { qapi_free_JobInfoList(head); return NULL; diff --git a/job.c b/job.c index 3e6f61c523..76c6d7f79d 100644 --- a/job.c +++ b/job.c @@ -44,8 +44,6 @@ * * The second includes functions used by the job drivers and sometimes * by the core block layer. These delegate the locking to the callee instead. - * - * TODO Actually make this true */ /* @@ -98,21 +96,11 @@ struct JobTxn { }; void job_lock(void) -{ - /* nop */ -} - -void job_unlock(void) -{ - /* nop */ -} - -static void real_job_lock(void) { qemu_mutex_lock(&job_mutex); } -static void real_job_unlock(void) +void job_unlock(void) { qemu_mutex_unlock(&job_mutex); } @@ -187,7 +175,6 @@ static void job_txn_del_job_locked(Job *job) /* Called with job_mutex held, but releases it temporarily. */ static int job_txn_apply_locked(Job *job, int fn(Job *)) { - AioContext *inner_ctx; Job *other_job, *next; JobTxn *txn = job->txn; int rc = 0; @@ -199,23 +186,14 @@ static int job_txn_apply_locked(Job *job, int fn(Job *)) * break AIO_WAIT_WHILE from within fn. */ job_ref_locked(job); - aio_context_release(job->aio_context); QLIST_FOREACH_SAFE(other_job, &txn->jobs, txn_list, next) { - inner_ctx = other_job->aio_context; - aio_context_acquire(inner_ctx); rc = fn(other_job); - aio_context_release(inner_ctx); if (rc) { break; } } - /* - * Note that job->aio_context might have been changed by calling fn, so we - * can't use a local variable to cache it. - */ - aio_context_acquire(job->aio_context); job_unref_locked(job); return rc; } @@ -503,8 +481,12 @@ void job_unref_locked(Job *job) assert(!job->txn); if (job->driver->free) { + AioContext *aio_context = job->aio_context; job_unlock(); + /* FIXME: aiocontext lock is required because cb calls blk_unref */ + aio_context_acquire(aio_context); job->driver->free(job); + aio_context_release(aio_context); job_lock(); } @@ -583,21 +565,17 @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job)) return; } - real_job_lock(); if (job->busy) { - real_job_unlock(); return; } if (fn && !fn(job)) { - real_job_unlock(); return; } assert(!job->deferred_to_main_loop); timer_del(&job->sleep_timer); job->busy = true; - real_job_unlock(); job_unlock(); aio_co_wake(job->co); job_lock(); @@ -628,13 +606,11 @@ static void coroutine_fn job_do_yield_locked(Job *job, uint64_t ns) { AioContext *next_aio_context; - real_job_lock(); if (ns != -1) { timer_mod(&job->sleep_timer, ns); } job->busy = false; job_event_idle_locked(job); - real_job_unlock(); job_unlock(); qemu_coroutine_yield(); job_lock(); @@ -920,10 +896,14 @@ static void job_clean(Job *job) } } -/* Called with job_mutex held, but releases it temporarily */ +/* + * Called with job_mutex held, but releases it temporarily. + * Takes AioContext lock internally to invoke a job->driver callback. + */ static int job_finalize_single_locked(Job *job) { int job_ret; + AioContext *ctx = job->aio_context; assert(job_is_completed_locked(job)); @@ -932,6 +912,7 @@ static int job_finalize_single_locked(Job *job) job_ret = job->ret; job_unlock(); + aio_context_acquire(ctx); if (!job_ret) { job_commit(job); @@ -940,15 +921,13 @@ static int job_finalize_single_locked(Job *job) } job_clean(job); - job_lock(); - if (job->cb) { - job_ret = job->ret; - job_unlock(); job->cb(job->opaque, job_ret); - job_lock(); } + aio_context_release(ctx); + job_lock(); + /* Emit events only if we actually started */ if (job_started_locked(job)) { if (job_is_cancelled_locked(job)) { @@ -963,13 +942,19 @@ static int job_finalize_single_locked(Job *job) return 0; } -/* Called with job_mutex held, but releases it temporarily */ +/* + * Called with job_mutex held, but releases it temporarily. + * Takes AioContext lock internally to invoke a job->driver callback. + */ static void job_cancel_async_locked(Job *job, bool force) { + AioContext *ctx = job->aio_context; GLOBAL_STATE_CODE(); if (job->driver->cancel) { job_unlock(); + aio_context_acquire(ctx); force = job->driver->cancel(job, force); + aio_context_release(ctx); job_lock(); } else { /* No .cancel() means the job will behave as if force-cancelled */ @@ -1002,10 +987,12 @@ static void job_cancel_async_locked(Job *job, bool force) } } -/* Called with job_mutex held, but releases it temporarily. */ +/* + * Called with job_mutex held, but releases it temporarily. + * Takes AioContext lock internally to invoke a job->driver callback. + */ static void job_completed_txn_abort_locked(Job *job) { - AioContext *ctx; JobTxn *txn = job->txn; Job *other_job; @@ -1018,54 +1005,31 @@ static void job_completed_txn_abort_locked(Job *job) txn->aborting = true; job_txn_ref_locked(txn); - /* - * We can only hold the single job's AioContext lock while calling - * job_finalize_single() because the finalization callbacks can involve - * calls of AIO_WAIT_WHILE(), which could deadlock otherwise. - * Note that the job's AioContext may change when it is finalized. - */ job_ref_locked(job); - aio_context_release(job->aio_context); /* Other jobs are effectively cancelled by us, set the status for * them; this job, however, may or may not be cancelled, depending * on the caller, so leave it. */ QLIST_FOREACH(other_job, &txn->jobs, txn_list) { if (other_job != job) { - ctx = other_job->aio_context; - aio_context_acquire(ctx); /* * This is a transaction: If one job failed, no result will matter. * Therefore, pass force=true to terminate all other jobs as quickly * as possible. */ job_cancel_async_locked(other_job, true); - aio_context_release(ctx); } } while (!QLIST_EMPTY(&txn->jobs)) { other_job = QLIST_FIRST(&txn->jobs); - /* - * The job's AioContext may change, so store it in @ctx so we - * release the same context that we have acquired before. - */ - ctx = other_job->aio_context; - aio_context_acquire(ctx); if (!job_is_completed_locked(other_job)) { assert(job_cancel_requested_locked(other_job)); job_finish_sync_locked(other_job, NULL, NULL); } job_finalize_single_locked(other_job); - aio_context_release(ctx); } - /* - * Use job_ref()/job_unref() so we can read the AioContext here - * even if the job went away during job_finalize_single(). - */ - aio_context_acquire(job->aio_context); job_unref_locked(job); - job_txn_unref_locked(txn); } @@ -1073,15 +1037,20 @@ static void job_completed_txn_abort_locked(Job *job) static int job_prepare_locked(Job *job) { int ret; + AioContext *ctx = job->aio_context; GLOBAL_STATE_CODE(); + if (job->ret == 0 && job->driver->prepare) { job_unlock(); + aio_context_acquire(ctx); ret = job->driver->prepare(job); + aio_context_release(ctx); job_lock(); job->ret = ret; job_update_rc_locked(job); } + return job->ret; } @@ -1186,11 +1155,8 @@ static void job_completed_locked(Job *job) static void job_exit(void *opaque) { Job *job = (Job *)opaque; - AioContext *ctx; JOB_LOCK_GUARD(); - job_ref_locked(job); - aio_context_acquire(job->aio_context); /* This is a lie, we're not quiescent, but still doing the completion * callbacks. However, completion callbacks tend to involve operations that @@ -1200,16 +1166,7 @@ static void job_exit(void *opaque) job_event_idle_locked(job); job_completed_locked(job); - - /* - * Note that calling job_completed can move the job to a different - * aio_context, so we cannot cache from above. job_txn_apply takes care of - * acquiring the new lock, and we ref/unref to avoid job_completed freeing - * the job underneath us. - */ - ctx = job->aio_context; job_unref_locked(job); - aio_context_release(ctx); } /** @@ -1337,14 +1294,10 @@ int job_cancel_sync(Job *job, bool force) void job_cancel_sync_all(void) { Job *job; - AioContext *aio_context; JOB_LOCK_GUARD(); while ((job = job_next_locked(NULL))) { - aio_context = job->aio_context; - aio_context_acquire(aio_context); job_cancel_sync_locked(job, true); - aio_context_release(aio_context); } } @@ -1404,8 +1357,8 @@ int job_finish_sync_locked(Job *job, } job_unlock(); - AIO_WAIT_WHILE(job->aio_context, - (job_enter(job), !job_is_completed(job))); + AIO_WAIT_WHILE_UNLOCKED(job->aio_context, + (job_enter(job), !job_is_completed(job))); job_lock(); ret = (job_is_cancelled_locked(job) && job->ret == 0) diff --git a/qemu-img.c b/qemu-img.c index e0a30b1f4c..ace3adf8ae 100644 --- a/qemu-img.c +++ b/qemu-img.c @@ -911,7 +911,6 @@ static void run_block_job(BlockJob *job, Error **errp) AioContext *aio_context = block_job_get_aio_context(job); int ret = 0; - aio_context_acquire(aio_context); job_lock(); job_ref_locked(&job->job); do { @@ -936,7 +935,6 @@ static void run_block_job(BlockJob *job, Error **errp) } job_unref_locked(&job->job); job_unlock(); - aio_context_release(aio_context); /* publish completion progress only when success */ if (!ret) { diff --git a/tests/unit/test-bdrv-drain.c b/tests/unit/test-bdrv-drain.c index 0db056ea63..4924ceb562 100644 --- a/tests/unit/test-bdrv-drain.c +++ b/tests/unit/test-bdrv-drain.c @@ -930,9 +930,9 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, tjob->prepare_ret = -EIO; break; } + aio_context_release(ctx); job_start(&job->job); - aio_context_release(ctx); if (use_iothread) { /* job_co_entry() is run in the I/O thread, wait for the actual job @@ -1016,12 +1016,12 @@ static void test_blockjob_common_drain_node(enum drain_type drain_type, g_assert_true(job->job.busy); /* We're in qemu_co_sleep_ns() */ } - aio_context_acquire(ctx); WITH_JOB_LOCK_GUARD() { ret = job_complete_sync_locked(&job->job, &error_abort); } g_assert_cmpint(ret, ==, (result == TEST_JOB_SUCCESS ? 0 : -EIO)); + aio_context_acquire(ctx); if (use_iothread) { blk_set_aio_context(blk_src, qemu_get_aio_context(), &error_abort); assert(blk_get_aio_context(blk_target) == qemu_get_aio_context()); diff --git a/tests/unit/test-block-iothread.c b/tests/unit/test-block-iothread.c index 96fd21c00a..def0709b2b 100644 --- a/tests/unit/test-block-iothread.c +++ b/tests/unit/test-block-iothread.c @@ -582,10 +582,10 @@ static void test_attach_blockjob(void) aio_poll(qemu_get_aio_context(), false); } - aio_context_acquire(ctx); WITH_JOB_LOCK_GUARD() { job_complete_sync_locked(&tjob->common.job, &error_abort); } + aio_context_acquire(ctx); blk_set_aio_context(blk, qemu_get_aio_context(), &error_abort); aio_context_release(ctx); diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c index e4f126bb6d..f88e10e356 100644 --- a/tests/unit/test-blockjob.c +++ b/tests/unit/test-blockjob.c @@ -228,10 +228,7 @@ static void cancel_common(CancelJob *s) BlockJob *job = &s->common; BlockBackend *blk = s->blk; JobStatus sts = job->job.status; - AioContext *ctx; - - ctx = job->job.aio_context; - aio_context_acquire(ctx); + AioContext *ctx = job->job.aio_context; job_cancel_sync(&job->job, true); WITH_JOB_LOCK_GUARD() { @@ -242,9 +239,11 @@ static void cancel_common(CancelJob *s) assert(job->job.status == JOB_STATUS_NULL); job_unref_locked(&job->job); } - destroy_blk(blk); + aio_context_acquire(ctx); + destroy_blk(blk); aio_context_release(ctx); + } static void test_cancel_created(void) @@ -384,12 +383,10 @@ static void test_cancel_concluded(void) aio_poll(qemu_get_aio_context(), true); assert_job_status_is(job, JOB_STATUS_PENDING); - aio_context_acquire(job->aio_context); WITH_JOB_LOCK_GUARD() { job_finalize_locked(job, &error_abort); + assert(job->status == JOB_STATUS_CONCLUDED); } - aio_context_release(job->aio_context); - assert_job_status_is(job, JOB_STATUS_CONCLUDED); cancel_common(s); } @@ -481,13 +478,11 @@ static void test_complete_in_standby(void) /* Wait for the job to become READY */ job_start(job); - aio_context_acquire(ctx); /* * Here we are waiting for the status to change, so don't bother * protecting the read every time. */ - AIO_WAIT_WHILE(ctx, job->status != JOB_STATUS_READY); - aio_context_release(ctx); + AIO_WAIT_WHILE_UNLOCKED(ctx, job->status != JOB_STATUS_READY); /* Begin the drained section, pausing the job */ bdrv_drain_all_begin(); @@ -497,6 +492,7 @@ static void test_complete_in_standby(void) aio_context_acquire(ctx); /* This will schedule the job to resume it */ bdrv_drain_all_end(); + aio_context_release(ctx); WITH_JOB_LOCK_GUARD() { /* But the job cannot run, so it will remain on standby */ @@ -515,6 +511,7 @@ static void test_complete_in_standby(void) job_dismiss_locked(&job, &error_abort); } + aio_context_acquire(ctx); destroy_blk(blk); aio_context_release(ctx); iothread_join(iothread); From fca26318a09962645351152a83dfa11d782a645d Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:12 -0400 Subject: [PATCH 0933/1020] block_job_query: remove atomic read Not sure what the atomic here was supposed to do, since job.busy is protected by the job lock. Since the whole function is called under job_mutex, just remove the atomic. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Vladimir Sementsov-Ogievskiy Reviewed-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf Message-Id: <20220926093214.506243-20-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- blockjob.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blockjob.c b/blockjob.c index d04f804001..120c1b7ead 100644 --- a/blockjob.c +++ b/blockjob.c @@ -338,7 +338,7 @@ BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp) info = g_new0(BlockJobInfo, 1); info->type = g_strdup(job_type_str(&job->job)); info->device = g_strdup(job->job.id); - info->busy = qatomic_read(&job->job.busy); + info->busy = job->job.busy; info->paused = job->job.pause_count > 0; info->offset = progress_current; info->len = progress_total; From ba6a91005270c8e199d739c2e2afb49372ba0f7f Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:13 -0400 Subject: [PATCH 0934/1020] blockjob: remove unused functions These public functions are not used anywhere, thus can be dropped. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf Reviewed-by: Vladimir Sementsov-Ogievskiy Message-Id: <20220926093214.506243-21-eesposit@redhat.com> Signed-off-by: Kevin Wolf --- blockjob.c | 16 ++-------------- include/block/blockjob.h | 31 ++++++++++++------------------- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/blockjob.c b/blockjob.c index 120c1b7ead..bdf20a0e35 100644 --- a/blockjob.c +++ b/blockjob.c @@ -56,12 +56,6 @@ BlockJob *block_job_next_locked(BlockJob *bjob) return job ? container_of(job, BlockJob, job) : NULL; } -BlockJob *block_job_next(BlockJob *bjob) -{ - JOB_LOCK_GUARD(); - return block_job_next_locked(bjob); -} - BlockJob *block_job_get_locked(const char *id) { Job *job = job_get_locked(id); @@ -308,7 +302,7 @@ bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp) return true; } -bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) +static bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp) { JOB_LOCK_GUARD(); return block_job_set_speed_locked(job, speed, errp); @@ -357,12 +351,6 @@ BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp) return info; } -BlockJobInfo *block_job_query(BlockJob *job, Error **errp) -{ - JOB_LOCK_GUARD(); - return block_job_query_locked(job, errp); -} - /* Called with job lock held */ static void block_job_iostatus_set_err_locked(BlockJob *job, int error) { @@ -525,7 +513,7 @@ void block_job_iostatus_reset_locked(BlockJob *job) job->iostatus = BLOCK_DEVICE_IO_STATUS_OK; } -void block_job_iostatus_reset(BlockJob *job) +static void block_job_iostatus_reset(BlockJob *job) { JOB_LOCK_GUARD(); block_job_iostatus_reset_locked(job); diff --git a/include/block/blockjob.h b/include/block/blockjob.h index 10c24e240a..03032b2eca 100644 --- a/include/block/blockjob.h +++ b/include/block/blockjob.h @@ -102,17 +102,15 @@ typedef struct BlockJob { */ /** - * block_job_next: + * block_job_next_locked: * @job: A block job, or %NULL. * * Get the next element from the list of block jobs after @job, or the * first one if @job is %NULL. * * Returns the requested job, or %NULL if there are no more jobs left. + * Called with job lock held. */ -BlockJob *block_job_next(BlockJob *job); - -/* Same as block_job_next(), but called with job lock held. */ BlockJob *block_job_next_locked(BlockJob *job); /** @@ -122,6 +120,7 @@ BlockJob *block_job_next_locked(BlockJob *job); * Get the block job identified by @id (which must not be %NULL). * * Returns the requested job, or %NULL if it doesn't exist. + * Called with job lock *not* held. */ BlockJob *block_job_get(const char *id); @@ -161,43 +160,37 @@ void block_job_remove_all_bdrv(BlockJob *job); bool block_job_has_bdrv(BlockJob *job, BlockDriverState *bs); /** - * block_job_set_speed: + * block_job_set_speed_locked: * @job: The job to set the speed for. * @speed: The new value * @errp: Error object. * * Set a rate-limiting parameter for the job; the actual meaning may * vary depending on the job type. - */ -bool block_job_set_speed(BlockJob *job, int64_t speed, Error **errp); - -/* - * Same as block_job_set_speed(), but called with job lock held. - * Might release the lock temporarily. + * + * Called with job lock held, but might release it temporarily. */ bool block_job_set_speed_locked(BlockJob *job, int64_t speed, Error **errp); /** - * block_job_query: + * block_job_query_locked: * @job: The job to get information about. * * Return information about a job. + * + * Called with job lock held. */ -BlockJobInfo *block_job_query(BlockJob *job, Error **errp); - -/* Same as block_job_query(), but called with job lock held. */ BlockJobInfo *block_job_query_locked(BlockJob *job, Error **errp); /** - * block_job_iostatus_reset: + * block_job_iostatus_reset_locked: * @job: The job whose I/O status should be reset. * * Reset I/O status on @job and on BlockDriverState objects it uses, * other than job->blk. + * + * Called with job lock held. */ -void block_job_iostatus_reset(BlockJob *job); - -/* Same as block_job_iostatus_reset(), but called with job lock held. */ void block_job_iostatus_reset_locked(BlockJob *job); /* From 9bd4d3c2e3d2e1df979e818ff0a5c05ca455721a Mon Sep 17 00:00:00 2001 From: Emanuele Giuseppe Esposito Date: Mon, 26 Sep 2022 05:32:14 -0400 Subject: [PATCH 0935/1020] job: remove unused functions These public functions are not used anywhere, thus can be dropped. Also, since this is the final job API that doesn't use AioContext lock and replaces it with job_lock, adjust all remaining function documentation to clearly specify if the job lock is taken or not. Also document the locking requirements for a few functions where the second version is not removed. Signed-off-by: Emanuele Giuseppe Esposito Reviewed-by: Stefan Hajnoczi Reviewed-by: Kevin Wolf Message-Id: <20220926093214.506243-22-eesposit@redhat.com> Reviewed-by: Vladimir Sementsov-Ogievskiy Signed-off-by: Kevin Wolf --- include/qemu/job.h | 110 +++++++++++++------------------------ job.c | 107 ++---------------------------------- tests/unit/test-blockjob.c | 4 +- 3 files changed, 46 insertions(+), 175 deletions(-) diff --git a/include/qemu/job.h b/include/qemu/job.h index a54fb83887..e502787dd8 100644 --- a/include/qemu/job.h +++ b/include/qemu/job.h @@ -384,6 +384,8 @@ JobTxn *job_txn_new(void); /** * Release a reference that was previously acquired with job_txn_add_job or * job_txn_new. If it's the last reference to the object, it will be freed. + * + * Called with job lock *not* held. */ void job_txn_unref(JobTxn *txn); @@ -413,21 +415,18 @@ void *job_create(const char *job_id, const JobDriver *driver, JobTxn *txn, /** * Add a reference to Job refcnt, it will be decreased with job_unref, and then * be freed if it comes to be the last reference. + * + * Called with job lock held. */ -void job_ref(Job *job); - -/* Same as job_ref(), but called with job lock held. */ void job_ref_locked(Job *job); /** - * Release a reference that was previously acquired with job_ref() or + * Release a reference that was previously acquired with job_ref_locked() or * job_create(). If it's the last reference to the object, it will be freed. * * Takes AioContext lock internally to invoke a job->driver callback. + * Called with job lock held. */ -void job_unref(Job *job); - -/* Same as job_unref(), but called with job lock held. */ void job_unref_locked(Job *job); /** @@ -473,12 +472,8 @@ void job_progress_increase_remaining(Job *job, uint64_t delta); * Conditionally enter the job coroutine if the job is ready to run, not * already busy and fn() returns true. fn() is called while under the job_lock * critical section. - */ -void job_enter_cond(Job *job, bool(*fn)(Job *job)); - -/* - * Same as job_enter_cond(), but called with job lock held. - * Might release the lock temporarily. + * + * Called with job lock held, but might release it temporarily. */ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job)); @@ -557,11 +552,8 @@ bool job_cancel_requested(Job *job); /** * Returns whether the job is in a completed state. - * Called with job_mutex *not* held. + * Called with job lock held. */ -bool job_is_completed(Job *job); - -/* Same as job_is_completed(), but called with job lock held. */ bool job_is_completed_locked(Job *job); /** @@ -576,14 +568,16 @@ bool job_is_ready_locked(Job *job); /** * Request @job to pause at the next pause point. Must be paired with * job_resume(). If the job is supposed to be resumed by user action, call - * job_user_pause() instead. + * job_user_pause_locked() instead. + * + * Called with job lock *not* held. */ void job_pause(Job *job); /* Same as job_pause(), but called with job lock held. */ void job_pause_locked(Job *job); -/** Resumes a @job paused with job_pause. */ +/** Resumes a @job paused with job_pause. Called with job lock *not* held. */ void job_resume(Job *job); /* @@ -595,27 +589,20 @@ void job_resume_locked(Job *job); /** * Asynchronously pause the specified @job. * Do not allow a resume until a matching call to job_user_resume. + * Called with job lock held. */ -void job_user_pause(Job *job, Error **errp); - -/* Same as job_user_pause(), but called with job lock held. */ void job_user_pause_locked(Job *job, Error **errp); -/** Returns true if the job is user-paused. */ -bool job_user_paused(Job *job); - -/* Same as job_user_paused(), but called with job lock held. */ +/** + * Returns true if the job is user-paused. + * Called with job lock held. + */ bool job_user_paused_locked(Job *job); /** * Resume the specified @job. - * Must be paired with a preceding job_user_pause. - */ -void job_user_resume(Job *job, Error **errp); - -/* - * Same as job_user_resume(), but called with job lock held. - * Might release the lock temporarily. + * Must be paired with a preceding job_user_pause_locked. + * Called with job lock held, but might release it temporarily. */ void job_user_resume_locked(Job *job, Error **errp); @@ -624,6 +611,7 @@ void job_user_resume_locked(Job *job, Error **errp); * first one if @job is %NULL. * * Returns the requested job, or %NULL if there are no more jobs left. + * Called with job lock *not* held. */ Job *job_next(Job *job); @@ -634,20 +622,17 @@ Job *job_next_locked(Job *job); * Get the job identified by @id (which must not be %NULL). * * Returns the requested job, or %NULL if it doesn't exist. + * Called with job lock held. */ -Job *job_get(const char *id); - -/* Same as job_get(), but called with job lock held. */ Job *job_get_locked(const char *id); /** * Check whether the verb @verb can be applied to @job in its current state. * Returns 0 if the verb can be applied; otherwise errp is set and -EPERM * returned. + * + * Called with job lock held. */ -int job_apply_verb(Job *job, JobVerb verb, Error **errp); - -/* Same as job_apply_verb, but called with job lock held. */ int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp); /** @@ -662,31 +647,24 @@ void job_early_fail(Job *job); */ void job_transition_to_ready(Job *job); -/** Asynchronously complete the specified @job. */ -void job_complete(Job *job, Error **errp); - -/* - * Same as job_complete(), but called with job lock held. - * Might release the lock temporarily. +/** + * Asynchronously complete the specified @job. + * Called with job lock held, but might release it temporarily. */ void job_complete_locked(Job *job, Error **errp); /** * Asynchronously cancel the specified @job. If @force is true, the job should * be cancelled immediately without waiting for a consistent state. + * Called with job lock held. */ -void job_cancel(Job *job, bool force); - -/* Same as job_cancel(), but called with job lock held. */ void job_cancel_locked(Job *job, bool force); /** - * Cancels the specified job like job_cancel(), but may refuse to do so if the - * operation isn't meaningful in the current state of the job. + * Cancels the specified job like job_cancel_locked(), but may refuse + * to do so if the operation isn't meaningful in the current state of the job. + * Called with job lock held. */ -void job_user_cancel(Job *job, bool force, Error **errp); - -/* Same as job_user_cancel(), but called with job lock held. */ void job_user_cancel_locked(Job *job, bool force, Error **errp); /** @@ -714,7 +692,7 @@ void job_cancel_sync_all(void); /** * @job: The job to be completed. - * @errp: Error object which may be set by job_complete(); this is not + * @errp: Error object which may be set by job_complete_locked(); this is not * necessarily set on every error, the job return value has to be * checked as well. * @@ -723,11 +701,8 @@ void job_cancel_sync_all(void); * function). * * Returns the return value from the job. - * Called with job_lock *not* held. + * Called with job_lock held. */ -int job_complete_sync(Job *job, Error **errp); - -/* Same as job_complete_sync, but called with job lock held. */ int job_complete_sync_locked(Job *job, Error **errp); /** @@ -737,19 +712,17 @@ int job_complete_sync_locked(Job *job, Error **errp); * FIXME: Make the below statement universally true: * For jobs that support the manual workflow mode, all graph changes that occur * as a result will occur after this command and before a successful reply. + * + * Called with job lock held. */ -void job_finalize(Job *job, Error **errp); - -/* Same as job_finalize(), but called with job lock held. */ void job_finalize_locked(Job *job, Error **errp); /** * Remove the concluded @job from the query list and resets the passed pointer * to %NULL. Returns an error if the job is not actually concluded. + * + * Called with job lock held. */ -void job_dismiss(Job **job, Error **errp); - -/* Same as job_dismiss(), but called with job lock held. */ void job_dismiss_locked(Job **job, Error **errp); /** @@ -759,14 +732,7 @@ void job_dismiss_locked(Job **job, Error **errp); * Returns 0 if the job is successfully completed, -ECANCELED if the job was * cancelled before completing, and -errno in other error cases. * - * Called with job_lock *not* held. - */ -int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), - Error **errp); - -/* - * Same as job_finish_sync(), but called with job lock held. - * Might release the lock temporarily. + * Called with job_lock held, but might release it temporarily. */ int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp), Error **errp); diff --git a/job.c b/job.c index 76c6d7f79d..78feae05fb 100644 --- a/job.c +++ b/job.c @@ -233,12 +233,6 @@ int job_apply_verb_locked(Job *job, JobVerb verb, Error **errp) return -EPERM; } -int job_apply_verb(Job *job, JobVerb verb, Error **errp) -{ - JOB_LOCK_GUARD(); - return job_apply_verb_locked(job, verb, errp); -} - JobType job_type(const Job *job) { return job->driver->job_type; @@ -324,7 +318,7 @@ bool job_is_completed_locked(Job *job) return false; } -bool job_is_completed(Job *job) +static bool job_is_completed(Job *job) { JOB_LOCK_GUARD(); return job_is_completed_locked(job); @@ -368,12 +362,6 @@ Job *job_get_locked(const char *id) return NULL; } -Job *job_get(const char *id) -{ - JOB_LOCK_GUARD(); - return job_get_locked(id); -} - void job_set_aio_context(Job *job, AioContext *ctx) { /* protect against read in job_finish_sync_locked and job_start */ @@ -465,12 +453,6 @@ void job_ref_locked(Job *job) ++job->refcnt; } -void job_ref(Job *job) -{ - JOB_LOCK_GUARD(); - job_ref_locked(job); -} - void job_unref_locked(Job *job) { GLOBAL_STATE_CODE(); @@ -499,12 +481,6 @@ void job_unref_locked(Job *job) } } -void job_unref(Job *job) -{ - JOB_LOCK_GUARD(); - job_unref_locked(job); -} - void job_progress_update(Job *job, uint64_t done) { progress_work_done(&job->progress, done); @@ -581,12 +557,6 @@ void job_enter_cond_locked(Job *job, bool(*fn)(Job *job)) job_lock(); } -void job_enter_cond(Job *job, bool(*fn)(Job *job)) -{ - JOB_LOCK_GUARD(); - job_enter_cond_locked(job, fn); -} - void job_enter(Job *job) { JOB_LOCK_GUARD(); @@ -674,8 +644,9 @@ void coroutine_fn job_pause_point(Job *job) job_pause_point_locked(job); } -static void coroutine_fn job_yield_locked(Job *job) +void coroutine_fn job_yield(Job *job) { + JOB_LOCK_GUARD(); assert(job->busy); /* Check cancellation *before* setting busy = false, too! */ @@ -690,12 +661,6 @@ static void coroutine_fn job_yield_locked(Job *job) job_pause_point_locked(job); } -void coroutine_fn job_yield(Job *job) -{ - JOB_LOCK_GUARD(); - job_yield_locked(job); -} - void coroutine_fn job_sleep_ns(Job *job, int64_t ns) { JOB_LOCK_GUARD(); @@ -764,23 +729,11 @@ void job_user_pause_locked(Job *job, Error **errp) job_pause_locked(job); } -void job_user_pause(Job *job, Error **errp) -{ - JOB_LOCK_GUARD(); - job_user_pause_locked(job, errp); -} - bool job_user_paused_locked(Job *job) { return job->user_paused; } -bool job_user_paused(Job *job) -{ - JOB_LOCK_GUARD(); - return job_user_paused_locked(job); -} - void job_user_resume_locked(Job *job, Error **errp) { assert(job); @@ -801,12 +754,6 @@ void job_user_resume_locked(Job *job, Error **errp) job_resume_locked(job); } -void job_user_resume(Job *job, Error **errp) -{ - JOB_LOCK_GUARD(); - job_user_resume_locked(job, errp); -} - /* Called with job_mutex held, but releases it temporarily. */ static void job_do_dismiss_locked(Job *job) { @@ -834,12 +781,6 @@ void job_dismiss_locked(Job **jobptr, Error **errp) *jobptr = NULL; } -void job_dismiss(Job **jobptr, Error **errp) -{ - JOB_LOCK_GUARD(); - job_dismiss_locked(jobptr, errp); -} - void job_early_fail(Job *job) { JOB_LOCK_GUARD(); @@ -1084,12 +1025,6 @@ void job_finalize_locked(Job *job, Error **errp) job_do_finalize_locked(job); } -void job_finalize(Job *job, Error **errp) -{ - JOB_LOCK_GUARD(); - job_finalize_locked(job, errp); -} - /* Called with job_mutex held. */ static int job_transition_to_pending_locked(Job *job) { @@ -1236,12 +1171,6 @@ void job_cancel_locked(Job *job, bool force) } } -void job_cancel(Job *job, bool force) -{ - JOB_LOCK_GUARD(); - job_cancel_locked(job, force); -} - void job_user_cancel_locked(Job *job, bool force, Error **errp) { if (job_apply_verb_locked(job, JOB_VERB_CANCEL, errp)) { @@ -1250,15 +1179,9 @@ void job_user_cancel_locked(Job *job, bool force, Error **errp) job_cancel_locked(job, force); } -void job_user_cancel(Job *job, bool force, Error **errp) -{ - JOB_LOCK_GUARD(); - job_user_cancel_locked(job, force, errp); -} - -/* A wrapper around job_cancel() taking an Error ** parameter so it may be - * used with job_finish_sync() without the need for (rather nasty) function - * pointer casts there. +/* A wrapper around job_cancel_locked() taking an Error ** parameter so it may + * be used with job_finish_sync_locked() without the need for (rather nasty) + * function pointer casts there. * * Called with job_mutex held. */ @@ -1306,12 +1229,6 @@ int job_complete_sync_locked(Job *job, Error **errp) return job_finish_sync_locked(job, job_complete_locked, errp); } -int job_complete_sync(Job *job, Error **errp) -{ - JOB_LOCK_GUARD(); - return job_complete_sync_locked(job, errp); -} - void job_complete_locked(Job *job, Error **errp) { /* Should not be reachable via external interface for internal jobs */ @@ -1331,12 +1248,6 @@ void job_complete_locked(Job *job, Error **errp) job_lock(); } -void job_complete(Job *job, Error **errp) -{ - JOB_LOCK_GUARD(); - job_complete_locked(job, errp); -} - int job_finish_sync_locked(Job *job, void (*finish)(Job *, Error **errp), Error **errp) @@ -1366,9 +1277,3 @@ int job_finish_sync_locked(Job *job, job_unref_locked(job); return ret; } - -int job_finish_sync(Job *job, void (*finish)(Job *, Error **errp), Error **errp) -{ - JOB_LOCK_GUARD(); - return job_finish_sync_locked(job, finish, errp); -} diff --git a/tests/unit/test-blockjob.c b/tests/unit/test-blockjob.c index f88e10e356..c0426bd10c 100644 --- a/tests/unit/test-blockjob.c +++ b/tests/unit/test-blockjob.c @@ -432,7 +432,7 @@ static const BlockJobDriver test_yielding_driver = { }; /* - * Test that job_complete() works even on jobs that are in a paused + * Test that job_complete_locked() works even on jobs that are in a paused * state (i.e., STANDBY). * * To do this, run YieldingJob in an IO thread, get it into the READY @@ -440,7 +440,7 @@ static const BlockJobDriver test_yielding_driver = { * acquire the context so the job will not be entered and will thus * remain on STANDBY. * - * job_complete() should still work without error. + * job_complete_locked() should still work without error. * * Note that on the QMP interface, it is impossible to lock an IO * thread before a drained section ends. In practice, the From a7ca2eb488ff149c898f43abe103f8bd8e3ca3c4 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Fri, 23 Sep 2022 16:28:38 +0200 Subject: [PATCH 0936/1020] file-posix: Remove unused s->discard_zeroes The field is unused (only ever set, but never read) since commit ac9185603. Additionally, the commit message of commit 34fa110e already explained earlier why it's unreliable. Remove it. Signed-off-by: Kevin Wolf Message-Id: <20220923142838.91043-1-kwolf@redhat.com> Signed-off-by: Kevin Wolf --- block/file-posix.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/block/file-posix.c b/block/file-posix.c index ad3021938b..23acffb9a4 100644 --- a/block/file-posix.c +++ b/block/file-posix.c @@ -154,7 +154,6 @@ typedef struct BDRVRawState { bool has_discard:1; bool has_write_zeroes:1; - bool discard_zeroes:1; bool use_linux_aio:1; bool use_linux_io_uring:1; int page_cache_inconsistent; /* errno from fdatasync failure */ @@ -755,7 +754,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, ret = -EINVAL; goto fail; } else { - s->discard_zeroes = true; s->has_fallocate = true; } } else { @@ -769,19 +767,12 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, } if (S_ISBLK(st.st_mode)) { -#ifdef BLKDISCARDZEROES - unsigned int arg; - if (ioctl(s->fd, BLKDISCARDZEROES, &arg) == 0 && arg) { - s->discard_zeroes = true; - } -#endif #ifdef __linux__ /* On Linux 3.10, BLKDISCARD leaves stale data in the page cache. Do * not rely on the contents of discarded blocks unless using O_DIRECT. * Same for BLKZEROOUT. */ if (!(bs->open_flags & BDRV_O_NOCACHE)) { - s->discard_zeroes = false; s->has_write_zeroes = false; } #endif From 02b61f38d3574900fb4cc4c450b17c75956a6a04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:49:49 +0100 Subject: [PATCH 0937/1020] hw/virtio: incorporate backend features in features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are some extra bits used over a vhost-user connection which are hidden from the device itself. We need to set them here to ensure we enable things like the protocol extensions. Currently net/vhost-user.c has it's own inscrutable way of persisting this data but it really should live in the core vhost_user code. Signed-off-by: Alex Bennée Message-Id: <20220726192150.2435175-7-alex.bennee@linaro.org> Message-Id: <20220802095010.3330793-2-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé --- hw/virtio/vhost-user.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 70748e61e0..0b7e41ffe8 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -1460,7 +1460,14 @@ static int vhost_user_set_features(struct vhost_dev *dev, */ bool log_enabled = features & (0x1ULL << VHOST_F_LOG_ALL); - return vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES, features, + /* + * We need to include any extra backend only feature bits that + * might be needed by our device. Currently this includes the + * VHOST_USER_F_PROTOCOL_FEATURES bit for enabling protocol + * features. + */ + return vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES, + features | dev->backend_features, log_enabled); } From ea5d6ea7788c83216547fe72874033d4bf693182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:49:53 +0100 Subject: [PATCH 0938/1020] include/hw/virtio: more comment for VIRTIO_F_BAD_FEATURE MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When debugging a new vhost user you may be surprised to see VHOST_USER_F_PROTOCOL getting squashed in the maze of backend_features, acked_features and guest_features. Expand the description here to help the next poor soul trying to work through this. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-6-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/virtio.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index db1c0ddf6b..9bb2485415 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -24,7 +24,12 @@ #include "qom/object.h" #include "hw/virtio/vhost.h" -/* A guest should never accept this. It implies negotiation is broken. */ +/* + * A guest should never accept this. It implies negotiation is broken + * between the driver frontend and the device. This bit is re-used for + * vhost-user to advertise VHOST_USER_F_PROTOCOL_FEATURES between QEMU + * and a vhost-user backend. + */ #define VIRTIO_F_BAD_FEATURE 30 #define VIRTIO_LEGACY_FEATURES ((0x1ULL << VIRTIO_F_BAD_FEATURE) | \ From c7066f2d30d6d9c7f83cf741afb2f489e0cdd16d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:49:54 +0100 Subject: [PATCH 0939/1020] include/hw: document vhost_dev feature life-cycle MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Try and explicitly document the various state of feature bits as related to the vhost_dev structure. Importantly the backend_features can advertise things like VHOST_USER_F_PROTOCOL_FEATURES which is never exposed to the driver and is only present in the vhost-user feature negotiation. Signed-off-by: Alex Bennée Acked-by: Jason Wang Message-Id: <20220802095010.3330793-7-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé --- include/hw/virtio/vhost.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index a346f23d13..586c5457e2 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -86,8 +86,11 @@ struct vhost_dev { /* if non-zero, minimum required value for max_queues */ int num_queues; uint64_t features; + /** @acked_features: final set of negotiated features */ uint64_t acked_features; + /** @backend_features: backend specific feature bits */ uint64_t backend_features; + /** @protocol_features: final negotiated protocol features */ uint64_t protocol_features; uint64_t max_queues; uint64_t backend_cap; From c97c76b3e75496e8d63ca6b754727446c4e74768 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:49:55 +0100 Subject: [PATCH 0940/1020] hw/virtio: fix some coding style issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Alex Bennée Acked-by: Jason Wang Message-Id: <20220802095010.3330793-8-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé --- hw/virtio/vhost-user.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index 0b7e41ffe8..03415b6c95 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -200,7 +200,7 @@ typedef struct { VhostUserRequest request; #define VHOST_USER_VERSION_MASK (0x3) -#define VHOST_USER_REPLY_MASK (0x1<<2) +#define VHOST_USER_REPLY_MASK (0x1 << 2) #define VHOST_USER_NEED_REPLY_MASK (0x1 << 3) uint32_t flags; uint32_t size; /* the following payload size */ @@ -208,7 +208,7 @@ typedef struct { typedef union { #define VHOST_USER_VRING_IDX_MASK (0xff) -#define VHOST_USER_VRING_NOFD_MASK (0x1<<8) +#define VHOST_USER_VRING_NOFD_MASK (0x1 << 8) uint64_t u64; struct vhost_vring_state state; struct vhost_vring_addr addr; @@ -248,7 +248,8 @@ struct vhost_user { size_t region_rb_len; /* RAMBlock associated with a given region */ RAMBlock **region_rb; - /* The offset from the start of the RAMBlock to the start of the + /* + * The offset from the start of the RAMBlock to the start of the * vhost region. */ ram_addr_t *region_rb_offset; From 8d11c10d0699d9ee9745b4b5bc138e573d852c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:49:56 +0100 Subject: [PATCH 0941/1020] hw/virtio: log potentially buggy guest drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the guest driver attempts to use the UNUSED(30) bit it is potentially buggy as 6.3 Legacy Interface: Reserved Feature Bits states it "SHOULD NOT be negotiated". For now just log this guest error. Signed-off-by: Alex Bennée Acked-by: Jason Wang Message-Id: <20220802095010.3330793-9-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 5d607aeaa0..97a6307c0f 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -2980,6 +2980,13 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val) if (vdev->status & VIRTIO_CONFIG_S_FEATURES_OK) { return -EINVAL; } + + if (val & (1ull << VIRTIO_F_BAD_FEATURE)) { + qemu_log_mask(LOG_GUEST_ERROR, + "%s: guest driver for %s has enabled UNUSED(30) feature bit!\n", + __func__, vdev->name); + } + ret = virtio_set_features_nocheck(vdev, val); if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) { /* VIRTIO_RING_F_EVENT_IDX changes the size of the caches. */ From a27612311988aff8f29a68ed5eaecde3bf6cdf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:49:57 +0100 Subject: [PATCH 0942/1020] hw/virtio: add some vhost-user trace events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These are useful for tracing the lifetime of vhost-user connections. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-10-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé --- hw/virtio/trace-events | 4 ++++ hw/virtio/vhost.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 20af2e7ebd..887ca7afa8 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -8,6 +8,10 @@ vhost_region_add_section_aligned(const char *name, uint64_t gpa, uint64_t size, vhost_section(const char *name) "%s" vhost_reject_section(const char *name, int d) "%s:%d" vhost_iotlb_miss(void *dev, int step) "%p step %d" +vhost_dev_cleanup(void *dev) "%p" +vhost_dev_start(void *dev, const char *name) "%p:%s" +vhost_dev_stop(void *dev, const char *name) "%p:%s" + # vhost-user.c vhost_user_postcopy_end_entry(void) "" diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index f758f177bb..5185c15295 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1477,6 +1477,8 @@ void vhost_dev_cleanup(struct vhost_dev *hdev) { int i; + trace_vhost_dev_cleanup(hdev); + for (i = 0; i < hdev->nvqs; ++i) { vhost_virtqueue_cleanup(hdev->vqs + i); } @@ -1783,6 +1785,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) /* should only be called after backend is connected */ assert(hdev->vhost_ops); + trace_vhost_dev_start(hdev, vdev->name); + vdev->vhost_started = true; hdev->started = true; hdev->vdev = vdev; @@ -1869,6 +1873,8 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) /* should only be called after backend is connected */ assert(hdev->vhost_ops); + trace_vhost_dev_stop(hdev, vdev->name); + if (hdev->vhost_ops->vhost_dev_start) { hdev->vhost_ops->vhost_dev_start(hdev, false); } From 9f6bcfd99f46377888059d8539befec9505f57fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:49:58 +0100 Subject: [PATCH 0943/1020] hw/virtio: move vm_running check to virtio_device_started MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the boilerplate virtio code does the same thing (or should at least) of checking to see if the VM is running before attempting to start VirtIO. Push the logic up to the common function to avoid getting a copy and paste wrong. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-11-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/vhost-user-fs.c | 6 +----- hw/virtio/vhost-user-i2c.c | 6 +----- hw/virtio/vhost-user-rng.c | 6 +----- hw/virtio/vhost-user-vsock.c | 6 +----- hw/virtio/vhost-vsock.c | 6 +----- include/hw/virtio/virtio.h | 5 +++++ 6 files changed, 10 insertions(+), 25 deletions(-) diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index e513e4fdda..d2bebba785 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -122,11 +122,7 @@ static void vuf_stop(VirtIODevice *vdev) static void vuf_set_status(VirtIODevice *vdev, uint8_t status) { VHostUserFS *fs = VHOST_USER_FS(vdev); - bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; - - if (!vdev->vm_running) { - should_start = false; - } + bool should_start = virtio_device_started(vdev, status); if (fs->vhost_dev.started == should_start) { return; diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c index 6020eee093..b930cf6d5e 100644 --- a/hw/virtio/vhost-user-i2c.c +++ b/hw/virtio/vhost-user-i2c.c @@ -93,11 +93,7 @@ static void vu_i2c_stop(VirtIODevice *vdev) static void vu_i2c_set_status(VirtIODevice *vdev, uint8_t status) { VHostUserI2C *i2c = VHOST_USER_I2C(vdev); - bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; - - if (!vdev->vm_running) { - should_start = false; - } + bool should_start = virtio_device_started(vdev, status); if (i2c->vhost_dev.started == should_start) { return; diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c index 3a7bf8e32d..a9c1c4bc79 100644 --- a/hw/virtio/vhost-user-rng.c +++ b/hw/virtio/vhost-user-rng.c @@ -90,11 +90,7 @@ static void vu_rng_stop(VirtIODevice *vdev) static void vu_rng_set_status(VirtIODevice *vdev, uint8_t status) { VHostUserRNG *rng = VHOST_USER_RNG(vdev); - bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; - - if (!vdev->vm_running) { - should_start = false; - } + bool should_start = virtio_device_started(vdev, status); if (rng->vhost_dev.started == should_start) { return; diff --git a/hw/virtio/vhost-user-vsock.c b/hw/virtio/vhost-user-vsock.c index 0f8ff99f85..22c1616ebd 100644 --- a/hw/virtio/vhost-user-vsock.c +++ b/hw/virtio/vhost-user-vsock.c @@ -55,11 +55,7 @@ const VhostDevConfigOps vsock_ops = { static void vuv_set_status(VirtIODevice *vdev, uint8_t status) { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); - bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; - - if (!vdev->vm_running) { - should_start = false; - } + bool should_start = virtio_device_started(vdev, status); if (vvc->vhost_dev.started == should_start) { return; diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index 0338de892f..8031c164a5 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -70,13 +70,9 @@ static int vhost_vsock_set_running(VirtIODevice *vdev, int start) static void vhost_vsock_set_status(VirtIODevice *vdev, uint8_t status) { VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); - bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; + bool should_start = virtio_device_started(vdev, status); int ret; - if (!vdev->vm_running) { - should_start = false; - } - if (vvc->vhost_dev.started == should_start) { return; } diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 9bb2485415..74e7ad5a92 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -100,6 +100,7 @@ struct VirtIODevice VirtQueue *vq; MemoryListener listener; uint16_t device_id; + /* @vm_running: current VM running state via virtio_vmstate_change() */ bool vm_running; bool broken; /* device in invalid state, needs reset */ bool use_disabled_flag; /* allow use of 'disable' flag when needed */ @@ -376,6 +377,10 @@ static inline bool virtio_device_started(VirtIODevice *vdev, uint8_t status) return vdev->started; } + if (!vdev->vm_running) { + return false; + } + return status & VIRTIO_CONFIG_S_DRIVER_OK; } From b8f3e6a18de6ad5cb668c5430b4933f1e40783cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:49:59 +0100 Subject: [PATCH 0944/1020] hw/virtio: move vhd->started check into helper and add FIXME MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `started` field is manipulated internally within the vhost code except for one place, vhost-user-blk via f5b22d06fb (vhost: recheck dev state in the vhost_migration_log routine). Mark that as a FIXME because it introduces a potential race. I think the referenced fix should be tracking its state locally. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-12-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Raphael Norwitz --- hw/block/vhost-user-blk.c | 10 ++++++++-- hw/scsi/vhost-scsi.c | 4 ++-- hw/scsi/vhost-user-scsi.c | 2 +- hw/virtio/vhost-user-fs.c | 3 ++- hw/virtio/vhost-user-i2c.c | 4 ++-- hw/virtio/vhost-user-rng.c | 4 ++-- hw/virtio/vhost-user-vsock.c | 2 +- hw/virtio/vhost-vsock-common.c | 3 ++- hw/virtio/vhost-vsock.c | 2 +- include/hw/virtio/vhost.h | 12 ++++++++++++ 10 files changed, 33 insertions(+), 13 deletions(-) diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 9117222456..2bba42478d 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -229,7 +229,7 @@ static void vhost_user_blk_set_status(VirtIODevice *vdev, uint8_t status) return; } - if (s->dev.started == should_start) { + if (vhost_dev_is_started(&s->dev) == should_start) { return; } @@ -286,7 +286,7 @@ static void vhost_user_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq) return; } - if (s->dev.started) { + if (vhost_dev_is_started(&s->dev)) { return; } @@ -415,6 +415,12 @@ static void vhost_user_blk_event(void *opaque, QEMUChrEvent event) * the vhost migration code. If disconnect was caught there is an * option for the general vhost code to get the dev state without * knowing its type (in this case vhost-user). + * + * FIXME: this is sketchy to be reaching into vhost_dev + * now because we are forcing something that implies we + * have executed vhost_dev_stop() but that won't happen + * until vhost_user_blk_stop() gets called from the bh. + * Really this state check should be tracked locally. */ s->dev.started = false; } diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index 3059068175..bdf337a7a2 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -120,7 +120,7 @@ static void vhost_scsi_set_status(VirtIODevice *vdev, uint8_t val) start = false; } - if (vsc->dev.started == start) { + if (vhost_dev_is_started(&vsc->dev) == start) { return; } @@ -147,7 +147,7 @@ static int vhost_scsi_pre_save(void *opaque) /* At this point, backend must be stopped, otherwise * it might keep writing to memory. */ - assert(!vsc->dev.started); + assert(!vhost_dev_is_started(&vsc->dev)); return 0; } diff --git a/hw/scsi/vhost-user-scsi.c b/hw/scsi/vhost-user-scsi.c index 1b2f7eed98..bc37317d55 100644 --- a/hw/scsi/vhost-user-scsi.c +++ b/hw/scsi/vhost-user-scsi.c @@ -49,7 +49,7 @@ static void vhost_user_scsi_set_status(VirtIODevice *vdev, uint8_t status) VHostSCSICommon *vsc = VHOST_SCSI_COMMON(s); bool start = (status & VIRTIO_CONFIG_S_DRIVER_OK) && vdev->vm_running; - if (vsc->dev.started == start) { + if (vhost_dev_is_started(&vsc->dev) == start) { return; } diff --git a/hw/virtio/vhost-user-fs.c b/hw/virtio/vhost-user-fs.c index d2bebba785..ad0f91c607 100644 --- a/hw/virtio/vhost-user-fs.c +++ b/hw/virtio/vhost-user-fs.c @@ -20,6 +20,7 @@ #include "hw/virtio/virtio-bus.h" #include "hw/virtio/virtio-access.h" #include "qemu/error-report.h" +#include "hw/virtio/vhost.h" #include "hw/virtio/vhost-user-fs.h" #include "monitor/monitor.h" #include "sysemu/sysemu.h" @@ -124,7 +125,7 @@ static void vuf_set_status(VirtIODevice *vdev, uint8_t status) VHostUserFS *fs = VHOST_USER_FS(vdev); bool should_start = virtio_device_started(vdev, status); - if (fs->vhost_dev.started == should_start) { + if (vhost_dev_is_started(&fs->vhost_dev) == should_start) { return; } diff --git a/hw/virtio/vhost-user-i2c.c b/hw/virtio/vhost-user-i2c.c index b930cf6d5e..bc58b6c0d1 100644 --- a/hw/virtio/vhost-user-i2c.c +++ b/hw/virtio/vhost-user-i2c.c @@ -95,7 +95,7 @@ static void vu_i2c_set_status(VirtIODevice *vdev, uint8_t status) VHostUserI2C *i2c = VHOST_USER_I2C(vdev); bool should_start = virtio_device_started(vdev, status); - if (i2c->vhost_dev.started == should_start) { + if (vhost_dev_is_started(&i2c->vhost_dev) == should_start) { return; } @@ -174,7 +174,7 @@ static void vu_i2c_disconnect(DeviceState *dev) } i2c->connected = false; - if (i2c->vhost_dev.started) { + if (vhost_dev_is_started(&i2c->vhost_dev)) { vu_i2c_stop(vdev); } } diff --git a/hw/virtio/vhost-user-rng.c b/hw/virtio/vhost-user-rng.c index a9c1c4bc79..bc1f36c5ac 100644 --- a/hw/virtio/vhost-user-rng.c +++ b/hw/virtio/vhost-user-rng.c @@ -92,7 +92,7 @@ static void vu_rng_set_status(VirtIODevice *vdev, uint8_t status) VHostUserRNG *rng = VHOST_USER_RNG(vdev); bool should_start = virtio_device_started(vdev, status); - if (rng->vhost_dev.started == should_start) { + if (vhost_dev_is_started(&rng->vhost_dev) == should_start) { return; } @@ -160,7 +160,7 @@ static void vu_rng_disconnect(DeviceState *dev) rng->connected = false; - if (rng->vhost_dev.started) { + if (vhost_dev_is_started(&rng->vhost_dev)) { vu_rng_stop(vdev); } } diff --git a/hw/virtio/vhost-user-vsock.c b/hw/virtio/vhost-user-vsock.c index 22c1616ebd..7b67e29d83 100644 --- a/hw/virtio/vhost-user-vsock.c +++ b/hw/virtio/vhost-user-vsock.c @@ -57,7 +57,7 @@ static void vuv_set_status(VirtIODevice *vdev, uint8_t status) VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); bool should_start = virtio_device_started(vdev, status); - if (vvc->vhost_dev.started == should_start) { + if (vhost_dev_is_started(&vvc->vhost_dev) == should_start) { return; } diff --git a/hw/virtio/vhost-vsock-common.c b/hw/virtio/vhost-vsock-common.c index 7394818e00..29b9ab4f72 100644 --- a/hw/virtio/vhost-vsock-common.c +++ b/hw/virtio/vhost-vsock-common.c @@ -14,6 +14,7 @@ #include "hw/virtio/virtio-access.h" #include "qemu/error-report.h" #include "hw/qdev-properties.h" +#include "hw/virtio/vhost.h" #include "hw/virtio/vhost-vsock.h" #include "qemu/iov.h" #include "monitor/monitor.h" @@ -199,7 +200,7 @@ int vhost_vsock_common_pre_save(void *opaque) * At this point, backend must be stopped, otherwise * it might keep writing to memory. */ - assert(!vvc->vhost_dev.started); + assert(!vhost_dev_is_started(&vvc->vhost_dev)); return 0; } diff --git a/hw/virtio/vhost-vsock.c b/hw/virtio/vhost-vsock.c index 8031c164a5..7dc3c73931 100644 --- a/hw/virtio/vhost-vsock.c +++ b/hw/virtio/vhost-vsock.c @@ -73,7 +73,7 @@ static void vhost_vsock_set_status(VirtIODevice *vdev, uint8_t status) bool should_start = virtio_device_started(vdev, status); int ret; - if (vvc->vhost_dev.started == should_start) { + if (vhost_dev_is_started(&vvc->vhost_dev) == should_start) { return; } diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 586c5457e2..61b957e927 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -94,6 +94,7 @@ struct vhost_dev { uint64_t protocol_features; uint64_t max_queues; uint64_t backend_cap; + /* @started: is the vhost device started? */ bool started; bool log_enabled; uint64_t log_size; @@ -165,6 +166,17 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); */ void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); +/** + * vhost_dev_is_started() - report status of vhost device + * @hdev: common vhost_dev structure + * + * Return the started status of the vhost device + */ +static inline bool vhost_dev_is_started(struct vhost_dev *hdev) +{ + return hdev->started; +} + /** * vhost_dev_start() - start the vhost device * @hdev: common vhost_dev structure From 27ba7b027f0f06479091bcfbcd308a6b272563a4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 2 Aug 2022 10:50:00 +0100 Subject: [PATCH 0945/1020] hw/virtio: add boilerplate for vhost-user-gpio device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This creates the QEMU side of the vhost-user-gpio device which connects to the remote daemon. It is based of vhost-user-i2c code. Signed-off-by: Viresh Kumar Reviewed-by: Alex Bennée Message-Id: <5390324a748194a21bc99b1538e19761a8c64092.1641987128.git.viresh.kumar@linaro.org> [AJB: fixes for qtest, tweaks to feature bits] Signed-off-by: Alex Bennée Cc: Vincent Whitchurch Message-Id: <20220802095010.3330793-13-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 7 + hw/virtio/Kconfig | 5 + hw/virtio/meson.build | 1 + hw/virtio/trace-events | 5 + hw/virtio/vhost-user-gpio.c | 411 ++++++++++++++++++++++++++++ include/hw/virtio/vhost-user-gpio.h | 35 +++ 6 files changed, 464 insertions(+) create mode 100644 hw/virtio/vhost-user-gpio.c create mode 100644 include/hw/virtio/vhost-user-gpio.h diff --git a/MAINTAINERS b/MAINTAINERS index e1530b51a2..66d519fe35 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2098,6 +2098,13 @@ F: hw/virtio/vhost-user-rng-pci.c F: include/hw/virtio/vhost-user-rng.h F: tools/vhost-user-rng/* +vhost-user-gpio +M: Alex Bennée +R: Viresh Kumar +S: Maintained +F: hw/virtio/vhost-user-gpio.c +F: include/hw/virtio/vhost-user-gpio.h + virtio-crypto M: Gonglei S: Supported diff --git a/hw/virtio/Kconfig b/hw/virtio/Kconfig index e9ecae1f50..cbfd8c7173 100644 --- a/hw/virtio/Kconfig +++ b/hw/virtio/Kconfig @@ -80,3 +80,8 @@ config VHOST_USER_FS bool default y depends on VIRTIO && VHOST_USER + +config VHOST_USER_GPIO + bool + default y + depends on VIRTIO && VHOST_USER diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build index 7e8877fd64..33c8e71fab 100644 --- a/hw/virtio/meson.build +++ b/hw/virtio/meson.build @@ -29,6 +29,7 @@ virtio_ss.add(when: 'CONFIG_VIRTIO_IOMMU', if_true: files('virtio-iommu.c')) virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c')) virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c')) virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c')) +virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c')) virtio_pci_ss = ss.source_set() virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c')) diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 887ca7afa8..820dadc26c 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -144,3 +144,8 @@ virtio_mem_state_response(uint16_t state) "state=%" PRIu16 virtio_pmem_flush_request(void) "flush request" virtio_pmem_response(void) "flush response" virtio_pmem_flush_done(int type) "fsync return=%d" + +# virtio-gpio.c +virtio_gpio_start(void) "start" +virtio_gpio_stop(void) "stop" +virtio_gpio_set_status(uint8_t status) "0x%x" diff --git a/hw/virtio/vhost-user-gpio.c b/hw/virtio/vhost-user-gpio.c new file mode 100644 index 0000000000..8b40fe450c --- /dev/null +++ b/hw/virtio/vhost-user-gpio.c @@ -0,0 +1,411 @@ +/* + * Vhost-user GPIO virtio device + * + * Copyright (c) 2022 Viresh Kumar + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/qdev-properties.h" +#include "hw/virtio/virtio-bus.h" +#include "hw/virtio/vhost-user-gpio.h" +#include "qemu/error-report.h" +#include "standard-headers/linux/virtio_ids.h" +#include "trace.h" + +#define REALIZE_CONNECTION_RETRIES 3 + +/* Features required from VirtIO */ +static const int feature_bits[] = { + VIRTIO_F_VERSION_1, + VIRTIO_F_NOTIFY_ON_EMPTY, + VIRTIO_RING_F_INDIRECT_DESC, + VIRTIO_RING_F_EVENT_IDX, + VIRTIO_GPIO_F_IRQ, + VHOST_INVALID_FEATURE_BIT +}; + +static void vu_gpio_get_config(VirtIODevice *vdev, uint8_t *config) +{ + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + + memcpy(config, &gpio->config, sizeof(gpio->config)); +} + +static int vu_gpio_config_notifier(struct vhost_dev *dev) +{ + VHostUserGPIO *gpio = VHOST_USER_GPIO(dev->vdev); + + memcpy(dev->vdev->config, &gpio->config, sizeof(gpio->config)); + virtio_notify_config(dev->vdev); + + return 0; +} + +const VhostDevConfigOps gpio_ops = { + .vhost_dev_config_notifier = vu_gpio_config_notifier, +}; + +static int vu_gpio_start(VirtIODevice *vdev) +{ + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + struct vhost_dev *vhost_dev = &gpio->vhost_dev; + int ret, i; + + if (!k->set_guest_notifiers) { + error_report("binding does not support guest notifiers"); + return -ENOSYS; + } + + ret = vhost_dev_enable_notifiers(vhost_dev, vdev); + if (ret < 0) { + error_report("Error enabling host notifiers: %d", ret); + return ret; + } + + ret = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, true); + if (ret < 0) { + error_report("Error binding guest notifier: %d", ret); + goto err_host_notifiers; + } + + /* + * Before we start up we need to ensure we have the final feature + * set needed for the vhost configuration. The backend may also + * apply backend_features when the feature set is sent. + */ + vhost_ack_features(&gpio->vhost_dev, feature_bits, vdev->guest_features); + + ret = vhost_dev_start(&gpio->vhost_dev, vdev); + if (ret < 0) { + error_report("Error starting vhost-user-gpio: %d", ret); + goto err_guest_notifiers; + } + + /* + * guest_notifier_mask/pending not used yet, so just unmask + * everything here. virtio-pci will do the right thing by + * enabling/disabling irqfd. + */ + for (i = 0; i < gpio->vhost_dev.nvqs; i++) { + vhost_virtqueue_mask(&gpio->vhost_dev, vdev, i, false); + } + + /* + * As we must have VHOST_USER_F_PROTOCOL_FEATURES (because + * VHOST_USER_GET_CONFIG requires it) we need to explicitly enable + * the vrings. + */ + g_assert(vhost_dev->vhost_ops && + vhost_dev->vhost_ops->vhost_set_vring_enable); + ret = vhost_dev->vhost_ops->vhost_set_vring_enable(vhost_dev, true); + if (ret == 0) { + return 0; + } + + error_report("Failed to start vrings for vhost-user-gpio: %d", ret); + +err_guest_notifiers: + k->set_guest_notifiers(qbus->parent, gpio->vhost_dev.nvqs, false); +err_host_notifiers: + vhost_dev_disable_notifiers(&gpio->vhost_dev, vdev); + + return ret; +} + +static void vu_gpio_stop(VirtIODevice *vdev) +{ + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); + VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); + struct vhost_dev *vhost_dev = &gpio->vhost_dev; + int ret; + + if (!k->set_guest_notifiers) { + return; + } + + /* + * We can call vu_gpio_stop multiple times, for example from + * vm_state_notify and the final object finalisation. Check we + * aren't already stopped before doing so. + */ + if (!vhost_dev_is_started(vhost_dev)) { + return; + } + + vhost_dev_stop(vhost_dev, vdev); + + ret = k->set_guest_notifiers(qbus->parent, vhost_dev->nvqs, false); + if (ret < 0) { + error_report("vhost guest notifier cleanup failed: %d", ret); + return; + } + + vhost_dev_disable_notifiers(vhost_dev, vdev); +} + +static void vu_gpio_set_status(VirtIODevice *vdev, uint8_t status) +{ + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + bool should_start = virtio_device_started(vdev, status); + + trace_virtio_gpio_set_status(status); + + if (!gpio->connected) { + return; + } + + if (vhost_dev_is_started(&gpio->vhost_dev) == should_start) { + return; + } + + if (should_start) { + if (vu_gpio_start(vdev)) { + qemu_chr_fe_disconnect(&gpio->chardev); + } + } else { + vu_gpio_stop(vdev); + } +} + +static uint64_t vu_gpio_get_features(VirtIODevice *vdev, uint64_t features, + Error **errp) +{ + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + + return vhost_get_features(&gpio->vhost_dev, feature_bits, features); +} + +static void vu_gpio_handle_output(VirtIODevice *vdev, VirtQueue *vq) +{ + /* + * Not normally called; it's the daemon that handles the queue; + * however virtio's cleanup path can call this. + */ +} + +static void vu_gpio_guest_notifier_mask(VirtIODevice *vdev, int idx, bool mask) +{ + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + + vhost_virtqueue_mask(&gpio->vhost_dev, vdev, idx, mask); +} + +static void do_vhost_user_cleanup(VirtIODevice *vdev, VHostUserGPIO *gpio) +{ + virtio_delete_queue(gpio->command_vq); + virtio_delete_queue(gpio->interrupt_vq); + g_free(gpio->vhost_dev.vqs); + gpio->vhost_dev.vqs = NULL; + virtio_cleanup(vdev); + vhost_user_cleanup(&gpio->vhost_user); +} + +static int vu_gpio_connect(DeviceState *dev, Error **errp) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + struct vhost_dev *vhost_dev = &gpio->vhost_dev; + int ret; + + if (gpio->connected) { + return 0; + } + gpio->connected = true; + + vhost_dev_set_config_notifier(vhost_dev, &gpio_ops); + gpio->vhost_user.supports_config = true; + + ret = vhost_dev_init(vhost_dev, &gpio->vhost_user, + VHOST_BACKEND_TYPE_USER, 0, errp); + if (ret < 0) { + return ret; + } + + /* restore vhost state */ + if (virtio_device_started(vdev, vdev->status)) { + vu_gpio_start(vdev); + } + + return 0; +} + +static void vu_gpio_disconnect(DeviceState *dev) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + + if (!gpio->connected) { + return; + } + gpio->connected = false; + + vu_gpio_stop(vdev); + vhost_dev_cleanup(&gpio->vhost_dev); +} + +static void vu_gpio_event(void *opaque, QEMUChrEvent event) +{ + DeviceState *dev = opaque; + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserGPIO *gpio = VHOST_USER_GPIO(vdev); + Error *local_err = NULL; + + switch (event) { + case CHR_EVENT_OPENED: + if (vu_gpio_connect(dev, &local_err) < 0) { + qemu_chr_fe_disconnect(&gpio->chardev); + return; + } + break; + case CHR_EVENT_CLOSED: + vu_gpio_disconnect(dev); + break; + case CHR_EVENT_BREAK: + case CHR_EVENT_MUX_IN: + case CHR_EVENT_MUX_OUT: + /* Ignore */ + break; + } +} + +static int vu_gpio_realize_connect(VHostUserGPIO *gpio, Error **errp) +{ + VirtIODevice *vdev = &gpio->parent_obj; + DeviceState *dev = &vdev->parent_obj; + struct vhost_dev *vhost_dev = &gpio->vhost_dev; + int ret; + + ret = qemu_chr_fe_wait_connected(&gpio->chardev, errp); + if (ret < 0) { + return ret; + } + + /* + * vu_gpio_connect() may have already connected (via the event + * callback) in which case it will just report success. + */ + ret = vu_gpio_connect(dev, errp); + if (ret < 0) { + qemu_chr_fe_disconnect(&gpio->chardev); + return ret; + } + g_assert(gpio->connected); + + ret = vhost_dev_get_config(vhost_dev, (uint8_t *)&gpio->config, + sizeof(gpio->config), errp); + + if (ret < 0) { + error_report("vhost-user-gpio: get config failed"); + + qemu_chr_fe_disconnect(&gpio->chardev); + vhost_dev_cleanup(vhost_dev); + return ret; + } + + return 0; +} + +static void vu_gpio_device_realize(DeviceState *dev, Error **errp) +{ + ERRP_GUARD(); + + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserGPIO *gpio = VHOST_USER_GPIO(dev); + int retries, ret; + + if (!gpio->chardev.chr) { + error_setg(errp, "vhost-user-gpio: chardev is mandatory"); + return; + } + + if (!vhost_user_init(&gpio->vhost_user, &gpio->chardev, errp)) { + return; + } + + virtio_init(vdev, VIRTIO_ID_GPIO, sizeof(gpio->config)); + + gpio->vhost_dev.nvqs = 2; + gpio->command_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output); + gpio->interrupt_vq = virtio_add_queue(vdev, 256, vu_gpio_handle_output); + gpio->vhost_dev.vqs = g_new0(struct vhost_virtqueue, gpio->vhost_dev.nvqs); + + gpio->connected = false; + + qemu_chr_fe_set_handlers(&gpio->chardev, NULL, NULL, vu_gpio_event, NULL, + dev, NULL, true); + + retries = REALIZE_CONNECTION_RETRIES; + g_assert(!*errp); + do { + if (*errp) { + error_prepend(errp, "Reconnecting after error: "); + error_report_err(*errp); + *errp = NULL; + } + ret = vu_gpio_realize_connect(gpio, errp); + } while (ret < 0 && retries--); + + if (ret < 0) { + do_vhost_user_cleanup(vdev, gpio); + } + + return; +} + +static void vu_gpio_device_unrealize(DeviceState *dev) +{ + VirtIODevice *vdev = VIRTIO_DEVICE(dev); + VHostUserGPIO *gpio = VHOST_USER_GPIO(dev); + + vu_gpio_set_status(vdev, 0); + qemu_chr_fe_set_handlers(&gpio->chardev, NULL, NULL, NULL, NULL, NULL, NULL, + false); + vhost_dev_cleanup(&gpio->vhost_dev); + do_vhost_user_cleanup(vdev, gpio); +} + +static const VMStateDescription vu_gpio_vmstate = { + .name = "vhost-user-gpio", + .unmigratable = 1, +}; + +static Property vu_gpio_properties[] = { + DEFINE_PROP_CHR("chardev", VHostUserGPIO, chardev), + DEFINE_PROP_END_OF_LIST(), +}; + +static void vu_gpio_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); + + device_class_set_props(dc, vu_gpio_properties); + dc->vmsd = &vu_gpio_vmstate; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + vdc->realize = vu_gpio_device_realize; + vdc->unrealize = vu_gpio_device_unrealize; + vdc->get_features = vu_gpio_get_features; + vdc->get_config = vu_gpio_get_config; + vdc->set_status = vu_gpio_set_status; + vdc->guest_notifier_mask = vu_gpio_guest_notifier_mask; +} + +static const TypeInfo vu_gpio_info = { + .name = TYPE_VHOST_USER_GPIO, + .parent = TYPE_VIRTIO_DEVICE, + .instance_size = sizeof(VHostUserGPIO), + .class_init = vu_gpio_class_init, +}; + +static void vu_gpio_register_types(void) +{ + type_register_static(&vu_gpio_info); +} + +type_init(vu_gpio_register_types) diff --git a/include/hw/virtio/vhost-user-gpio.h b/include/hw/virtio/vhost-user-gpio.h new file mode 100644 index 0000000000..4fe9aeecc0 --- /dev/null +++ b/include/hw/virtio/vhost-user-gpio.h @@ -0,0 +1,35 @@ +/* + * Vhost-user GPIO virtio device + * + * Copyright (c) 2021 Viresh Kumar + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef _QEMU_VHOST_USER_GPIO_H +#define _QEMU_VHOST_USER_GPIO_H + +#include "hw/virtio/virtio.h" +#include "hw/virtio/vhost.h" +#include "hw/virtio/vhost-user.h" +#include "standard-headers/linux/virtio_gpio.h" +#include "chardev/char-fe.h" + +#define TYPE_VHOST_USER_GPIO "vhost-user-gpio-device" +OBJECT_DECLARE_SIMPLE_TYPE(VHostUserGPIO, VHOST_USER_GPIO); + +struct VHostUserGPIO { + /*< private >*/ + VirtIODevice parent_obj; + CharBackend chardev; + struct virtio_gpio_config config; + struct vhost_virtqueue *vhost_vq; + struct vhost_dev vhost_dev; + VhostUserState vhost_user; + VirtQueue *command_vq; + VirtQueue *interrupt_vq; + bool connected; + /*< public >*/ +}; + +#endif /* _QEMU_VHOST_USER_GPIO_H */ From 25c60a4612dd30976dc2c471ebe050dd5f6635a4 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 2 Aug 2022 10:50:01 +0100 Subject: [PATCH 0946/1020] hw/virtio: add vhost-user-gpio-pci boilerplate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows is to instantiate a vhost-user-gpio device as part of a PCI bus. It is mostly boilerplate which looks pretty similar to the vhost-user-fs-pci device. Signed-off-by: Viresh Kumar Reviewed-by: Alex Bennée Message-Id: <5f560cab92d0d789b1c94295ec74b9952907d69d.1641987128.git.viresh.kumar@linaro.org> Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-14-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 2 +- hw/virtio/meson.build | 1 + hw/virtio/vhost-user-gpio-pci.c | 69 +++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 hw/virtio/vhost-user-gpio-pci.c diff --git a/MAINTAINERS b/MAINTAINERS index 66d519fe35..beccce4a7a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2102,7 +2102,7 @@ vhost-user-gpio M: Alex Bennée R: Viresh Kumar S: Maintained -F: hw/virtio/vhost-user-gpio.c +F: hw/virtio/vhost-user-gpio* F: include/hw/virtio/vhost-user-gpio.h virtio-crypto diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build index 33c8e71fab..c14e3db10a 100644 --- a/hw/virtio/meson.build +++ b/hw/virtio/meson.build @@ -30,6 +30,7 @@ virtio_ss.add(when: 'CONFIG_VIRTIO_MEM', if_true: files('virtio-mem.c')) virtio_ss.add(when: 'CONFIG_VHOST_USER_I2C', if_true: files('vhost-user-i2c.c')) virtio_ss.add(when: 'CONFIG_VHOST_USER_RNG', if_true: files('vhost-user-rng.c')) virtio_ss.add(when: 'CONFIG_VHOST_USER_GPIO', if_true: files('vhost-user-gpio.c')) +virtio_ss.add(when: ['CONFIG_VIRTIO_PCI', 'CONFIG_VHOST_USER_GPIO'], if_true: files('vhost-user-gpio-pci.c')) virtio_pci_ss = ss.source_set() virtio_pci_ss.add(when: 'CONFIG_VHOST_VSOCK', if_true: files('vhost-vsock-pci.c')) diff --git a/hw/virtio/vhost-user-gpio-pci.c b/hw/virtio/vhost-user-gpio-pci.c new file mode 100644 index 0000000000..b3028a24a1 --- /dev/null +++ b/hw/virtio/vhost-user-gpio-pci.c @@ -0,0 +1,69 @@ +/* + * Vhost-user gpio virtio device PCI glue + * + * Copyright (c) 2022 Viresh Kumar + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "hw/qdev-properties.h" +#include "hw/virtio/vhost-user-gpio.h" +#include "hw/virtio/virtio-pci.h" + +struct VHostUserGPIOPCI { + VirtIOPCIProxy parent_obj; + VHostUserGPIO vdev; +}; + +typedef struct VHostUserGPIOPCI VHostUserGPIOPCI; + +#define TYPE_VHOST_USER_GPIO_PCI "vhost-user-gpio-pci-base" + +DECLARE_INSTANCE_CHECKER(VHostUserGPIOPCI, VHOST_USER_GPIO_PCI, + TYPE_VHOST_USER_GPIO_PCI) + +static void vhost_user_gpio_pci_realize(VirtIOPCIProxy *vpci_dev, Error **errp) +{ + VHostUserGPIOPCI *dev = VHOST_USER_GPIO_PCI(vpci_dev); + DeviceState *vdev = DEVICE(&dev->vdev); + + vpci_dev->nvectors = 1; + qdev_realize(vdev, BUS(&vpci_dev->bus), errp); +} + +static void vhost_user_gpio_pci_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass); + PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass); + k->realize = vhost_user_gpio_pci_realize; + set_bit(DEVICE_CATEGORY_INPUT, dc->categories); + pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + pcidev_k->device_id = 0; /* Set by virtio-pci based on virtio id */ + pcidev_k->revision = 0x00; + pcidev_k->class_id = PCI_CLASS_COMMUNICATION_OTHER; +} + +static void vhost_user_gpio_pci_instance_init(Object *obj) +{ + VHostUserGPIOPCI *dev = VHOST_USER_GPIO_PCI(obj); + + virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev), + TYPE_VHOST_USER_GPIO); +} + +static const VirtioPCIDeviceTypeInfo vhost_user_gpio_pci_info = { + .base_name = TYPE_VHOST_USER_GPIO_PCI, + .non_transitional_name = "vhost-user-gpio-pci", + .instance_size = sizeof(VHostUserGPIOPCI), + .instance_init = vhost_user_gpio_pci_instance_init, + .class_init = vhost_user_gpio_pci_class_init, +}; + +static void vhost_user_gpio_pci_register(void) +{ + virtio_pci_types_register(&vhost_user_gpio_pci_info); +} + +type_init(vhost_user_gpio_pci_register); From bbd971153745ca2aa9a26b7d6370374ef559a328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:02 +0100 Subject: [PATCH 0947/1020] tests/qtest: pass stdout/stderr down to subtests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When trying to work out what the virtio-net-tests where doing it was hard because the g_test_trap_subprocess redirects all output to /dev/null. Lift this restriction by using the appropriate flags so you can see something similar to what the vhost-user-blk tests show when running. Signed-off-by: Alex Bennée Acked-by: Thomas Huth Message-Id: <20220407150042.2338562-1-alex.bennee@linaro.org> Message-Id: <20220802095010.3330793-15-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/qos-test.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c index 831db5cf2a..33cdada380 100644 --- a/tests/qtest/qos-test.c +++ b/tests/qtest/qos-test.c @@ -185,7 +185,9 @@ static void run_one_test(const void *arg) static void subprocess_run_one_test(const void *arg) { const gchar *path = arg; - g_test_trap_subprocess(path, 0, 0); + g_test_trap_subprocess(path, 0, + G_TEST_SUBPROCESS_INHERIT_STDOUT | + G_TEST_SUBPROCESS_INHERIT_STDERR); g_test_trap_assert_passed(); } From ebaa07083b57aab2d2dabf86d9bf172f43bad7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:03 +0100 Subject: [PATCH 0948/1020] tests/qtest: add a timeout for subprocess_run_one_test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hangs have been observed in the tests and currently we don't timeout if a subprocess hangs. Rectify that. Signed-off-by: Alex Bennée Reviewed-by: Thomas Huth Message-Id: <20220802095010.3330793-16-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Philippe Mathieu-Daudé --- tests/qtest/qos-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c index 33cdada380..566cb3b00b 100644 --- a/tests/qtest/qos-test.c +++ b/tests/qtest/qos-test.c @@ -185,7 +185,7 @@ static void run_one_test(const void *arg) static void subprocess_run_one_test(const void *arg) { const gchar *path = arg; - g_test_trap_subprocess(path, 0, + g_test_trap_subprocess(path, 180 * G_USEC_PER_SEC, G_TEST_SUBPROCESS_INHERIT_STDOUT | G_TEST_SUBPROCESS_INHERIT_STDERR); g_test_trap_assert_passed(); From 30ea13e9d97dcbd4ea541ddf9e8857fa1d5cb30f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:04 +0100 Subject: [PATCH 0949/1020] tests/qtest: use qos_printf instead of g_test_message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vhost-user tests respawn qos-test as a standalone process. As a result the gtester framework squashes all messages coming out of it which make it hard to debug. As the test does not care about asserting certain messages just convert the tests to use the direct qos_printf. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-17-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/qos-test.c | 5 +++++ tests/qtest/vhost-user-test.c | 13 +++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c index 566cb3b00b..5da4091ec3 100644 --- a/tests/qtest/qos-test.c +++ b/tests/qtest/qos-test.c @@ -321,6 +321,11 @@ static void walk_path(QOSGraphNode *orig_path, int len) int main(int argc, char **argv, char** envp) { g_test_init(&argc, &argv, NULL); + + if (g_test_subprocess()) { + qos_printf("qos_test running single test in subprocess\n"); + } + if (g_test_verbose()) { qos_printf("ENVIRONMENT VARIABLES: {\n"); for (char **env = envp; *env != 0; env++) { diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 84498941a6..99dc6080e5 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -26,6 +26,7 @@ #include "libqos/virtio-pci.h" #include "libqos/malloc-pc.h" +#include "libqos/qgraph_internal.h" #include "hw/virtio/virtio-net.h" #include "standard-headers/linux/vhost_types.h" @@ -316,7 +317,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) } if (size != VHOST_USER_HDR_SIZE) { - g_test_message("Wrong message size received %d", size); + qos_printf("%s: Wrong message size received %d\n", __func__, size); return; } @@ -327,8 +328,8 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) p += VHOST_USER_HDR_SIZE; size = qemu_chr_fe_read_all(chr, p, msg.size); if (size != msg.size) { - g_test_message("Wrong message size received %d != %d", - size, msg.size); + qos_printf("%s: Wrong message size received %d != %d\n", + __func__, size, msg.size); return; } } @@ -450,7 +451,7 @@ static const char *init_hugepagefs(void) } if (access(path, R_OK | W_OK | X_OK)) { - g_test_message("access on path (%s): %s", path, strerror(errno)); + qos_printf("access on path (%s): %s", path, strerror(errno)); g_test_fail(); return NULL; } @@ -460,13 +461,13 @@ static const char *init_hugepagefs(void) } while (ret != 0 && errno == EINTR); if (ret != 0) { - g_test_message("statfs on path (%s): %s", path, strerror(errno)); + qos_printf("statfs on path (%s): %s", path, strerror(errno)); g_test_fail(); return NULL; } if (fs.f_type != HUGETLBFS_MAGIC) { - g_test_message("Warning: path not on HugeTLBFS: %s", path); + qos_printf("Warning: path not on HugeTLBFS: %s", path); g_test_fail(); return NULL; } From 20a4127fbd4f54ab5ff2e0f3538c2b8e89011bce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:05 +0100 Subject: [PATCH 0950/1020] tests/qtest: catch unhandled vhost-user messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't need to action every message but lets document the ones we are expecting to consume so future tests don't get confused about unhandled bits. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-18-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/vhost-user-test.c | 43 +++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 99dc6080e5..8d2d4ba535 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -358,12 +358,44 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) } break; + case VHOST_USER_SET_OWNER: + /* + * We don't need to do anything here, the remote is just + * letting us know it is in charge. Just log it. + */ + qos_printf("set_owner: start of session\n"); + break; + case VHOST_USER_GET_PROTOCOL_FEATURES: if (s->vu_ops->get_protocol_features) { s->vu_ops->get_protocol_features(s, chr, &msg); } break; + case VHOST_USER_SET_PROTOCOL_FEATURES: + /* + * We did set VHOST_USER_F_PROTOCOL_FEATURES so its valid for + * the remote end to send this. There is no handshake reply so + * just log the details for debugging. + */ + qos_printf("set_protocol_features: 0x%"PRIx64 "\n", msg.payload.u64); + break; + + /* + * A real vhost-user backend would actually set the size and + * address of the vrings but we can simply report them. + */ + case VHOST_USER_SET_VRING_NUM: + qos_printf("set_vring_num: %d/%d\n", + msg.payload.state.index, msg.payload.state.num); + break; + case VHOST_USER_SET_VRING_ADDR: + qos_printf("set_vring_addr: 0x%"PRIx64"/0x%"PRIx64"/0x%"PRIx64"\n", + msg.payload.addr.avail_user_addr, + msg.payload.addr.desc_user_addr, + msg.payload.addr.used_user_addr); + break; + case VHOST_USER_GET_VRING_BASE: /* send back vring base to qemu */ msg.flags |= VHOST_USER_REPLY_MASK; @@ -428,7 +460,18 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size); break; + case VHOST_USER_SET_VRING_ENABLE: + /* + * Another case we ignore as we don't need to respond. With a + * fully functioning vhost-user we would enable/disable the + * vring monitoring. + */ + qos_printf("set_vring(%d)=%s\n", msg.payload.state.index, + msg.payload.state.num ? "enabled" : "disabled"); + break; + default: + qos_printf("vhost-user: un-handled message: %d\n", msg.request); break; } From f48d994fb50c49093dd1dfe64c0d7314c6b62faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:06 +0100 Subject: [PATCH 0951/1020] tests/qtest: plain g_assert for VHOST_USER_F_PROTOCOL_FEATURES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit checkpatch.pl warns that non-plain asserts should be avoided so convert the check to a plain g_assert. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-19-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/vhost-user-test.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 8d2d4ba535..a99f55ed84 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -985,8 +985,7 @@ static void test_multiqueue(void *obj, void *arg, QGuestAllocator *alloc) static void vu_net_set_features(TestServer *s, CharBackend *chr, VhostUserMsg *msg) { - g_assert_cmpint(msg->payload.u64 & - (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES), !=, 0ULL); + g_assert(msg->payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES)); if (s->test_flags == TEST_FLAGS_DISCONNECT) { qemu_chr_fe_disconnect(chr); s->test_flags = TEST_FLAGS_BAD; From 3bd869f36e3bec51969c8cdb0e3637312d85eb1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:07 +0100 Subject: [PATCH 0952/1020] tests/qtest: add assert to catch bad features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No device driver (which is what the qvirtio_ access functions represent) should be setting UNUSED(30) in the feature space. Although existing libqos users mask it out lets ensure nothing sneaks through. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-20-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/libqos/virtio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/qtest/libqos/virtio.c b/tests/qtest/libqos/virtio.c index 09ec09b655..03056e5187 100644 --- a/tests/qtest/libqos/virtio.c +++ b/tests/qtest/libqos/virtio.c @@ -101,6 +101,8 @@ uint64_t qvirtio_get_features(QVirtioDevice *d) void qvirtio_set_features(QVirtioDevice *d, uint64_t features) { + g_assert(!(features & QVIRTIO_F_BAD_FEATURE)); + d->features = features; d->bus->set_features(d, features); From ff070f602af6163b6ef4d803d5c3bde735035fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:08 +0100 Subject: [PATCH 0953/1020] tests/qtest: implement stub for VHOST_USER_GET_CONFIG MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't implement the full solution because frankly none of the tests need to at the moment. We may end up re-implementing libvhostuser in the end. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-21-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/vhost-user-test.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index a99f55ed84..3052386634 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -79,6 +79,8 @@ typedef enum VhostUserRequest { VHOST_USER_SET_PROTOCOL_FEATURES = 16, VHOST_USER_GET_QUEUE_NUM = 17, VHOST_USER_SET_VRING_ENABLE = 18, + VHOST_USER_GET_CONFIG = 24, + VHOST_USER_SET_CONFIG = 25, VHOST_USER_MAX } VhostUserRequest; @@ -372,6 +374,17 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) } break; + case VHOST_USER_GET_CONFIG: + /* + * Treat GET_CONFIG as a NOP and just reply and let the guest + * consider we have updated its memory. Tests currently don't + * require working configs. + */ + msg.flags |= VHOST_USER_REPLY_MASK; + p = (uint8_t *) &msg; + qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size); + break; + case VHOST_USER_SET_PROTOCOL_FEATURES: /* * We did set VHOST_USER_F_PROTOCOL_FEATURES so its valid for From 19d55a19a4b9151f15eb5e2b5d0610aa2a738c7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:09 +0100 Subject: [PATCH 0954/1020] tests/qtest: add a get_features op to vhost-user-test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As we expand this test for more virtio devices we will need to support different feature sets. Add a mandatory op field to fetch the list of features needed for the test itself. Signed-off-by: Alex Bennée Message-Id: <20220802095010.3330793-22-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/vhost-user-test.c | 37 +++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 3052386634..4f4fcc09f5 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -171,10 +171,11 @@ struct vhost_user_ops { const char *chr_opts); /* VHOST-USER commands. */ + uint64_t (*get_features)(TestServer *s); void (*set_features)(TestServer *s, CharBackend *chr, - VhostUserMsg *msg); + VhostUserMsg *msg); void (*get_protocol_features)(TestServer *s, - CharBackend *chr, VhostUserMsg *msg); + CharBackend *chr, VhostUserMsg *msg); }; static const char *init_hugepagefs(void); @@ -338,20 +339,22 @@ static void chr_read(void *opaque, const uint8_t *buf, int size) switch (msg.request) { case VHOST_USER_GET_FEATURES: + /* Mandatory for tests to define get_features */ + g_assert(s->vu_ops->get_features); + /* send back features to qemu */ msg.flags |= VHOST_USER_REPLY_MASK; msg.size = sizeof(m.payload.u64); - msg.payload.u64 = 0x1ULL << VHOST_F_LOG_ALL | - 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES; - if (s->queues > 1) { - msg.payload.u64 |= 0x1ULL << VIRTIO_NET_F_MQ; - } + if (s->test_flags >= TEST_FLAGS_BAD) { msg.payload.u64 = 0; s->test_flags = TEST_FLAGS_END; + } else { + msg.payload.u64 = s->vu_ops->get_features(s); } - p = (uint8_t *) &msg; - qemu_chr_fe_write_all(chr, p, VHOST_USER_HDR_SIZE + msg.size); + + qemu_chr_fe_write_all(chr, (uint8_t *) &msg, + VHOST_USER_HDR_SIZE + msg.size); break; case VHOST_USER_SET_FEATURES: @@ -995,8 +998,21 @@ static void test_multiqueue(void *obj, void *arg, QGuestAllocator *alloc) wait_for_rings_started(s, s->queues * 2); } + +static uint64_t vu_net_get_features(TestServer *s) +{ + uint64_t features = 0x1ULL << VHOST_F_LOG_ALL | + 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES; + + if (s->queues > 1) { + features |= 0x1ULL << VIRTIO_NET_F_MQ; + } + + return features; +} + static void vu_net_set_features(TestServer *s, CharBackend *chr, - VhostUserMsg *msg) + VhostUserMsg *msg) { g_assert(msg->payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES)); if (s->test_flags == TEST_FLAGS_DISCONNECT) { @@ -1025,6 +1041,7 @@ static struct vhost_user_ops g_vu_net_ops = { .append_opts = append_vhost_net_opts, + .get_features = vu_net_get_features, .set_features = vu_net_set_features, .get_protocol_features = vu_net_get_protocol_features, }; From 8fcfc8235e43649cd4045c815abdaac078cff9c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 2 Aug 2022 10:50:10 +0100 Subject: [PATCH 0955/1020] tests/qtest: enable tests for virtio-gpio MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We don't have a virtio-gpio implementation in QEMU and only support a vhost-user backend. The QEMU side of the code is minimal so it should be enough to instantiate the device and pass some vhost-user messages over the control socket. To do this we hook into the existing vhost-user-test code and just add the bits required for gpio. Signed-off-by: Alex Bennée Cc: Viresh Kumar Cc: Paolo Bonzini Cc: Eric Auger Message-Id: <20220408155704.2777166-1-alex.bennee@linaro.org> Message-Id: <20220802095010.3330793-23-alex.bennee@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 1 + tests/qtest/libqos/meson.build | 1 + tests/qtest/libqos/virtio-gpio.c | 171 +++++++++++++++++++++++++++++++ tests/qtest/libqos/virtio-gpio.h | 35 +++++++ tests/qtest/libqos/virtio.c | 2 +- tests/qtest/vhost-user-test.c | 66 ++++++++++++ 6 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 tests/qtest/libqos/virtio-gpio.c create mode 100644 tests/qtest/libqos/virtio-gpio.h diff --git a/MAINTAINERS b/MAINTAINERS index beccce4a7a..d0c0c8a55b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2104,6 +2104,7 @@ R: Viresh Kumar S: Maintained F: hw/virtio/vhost-user-gpio* F: include/hw/virtio/vhost-user-gpio.h +F: tests/qtest/libqos/virtio-gpio.* virtio-crypto M: Gonglei diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build index cff83c86d9..a5b6d5197a 100644 --- a/tests/qtest/libqos/meson.build +++ b/tests/qtest/libqos/meson.build @@ -45,6 +45,7 @@ libqos_srcs = files( 'virtio-scsi.c', 'virtio-serial.c', 'virtio-iommu.c', + 'virtio-gpio.c', 'generic-pcihost.c', # qgraph machines: diff --git a/tests/qtest/libqos/virtio-gpio.c b/tests/qtest/libqos/virtio-gpio.c new file mode 100644 index 0000000000..762aa6695b --- /dev/null +++ b/tests/qtest/libqos/virtio-gpio.c @@ -0,0 +1,171 @@ +/* + * virtio-gpio nodes for testing + * + * Copyright (c) 2022 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "standard-headers/linux/virtio_config.h" +#include "../libqtest.h" +#include "qemu/module.h" +#include "qgraph.h" +#include "virtio-gpio.h" + +static QGuestAllocator *alloc; + +static void virtio_gpio_cleanup(QVhostUserGPIO *gpio) +{ + QVirtioDevice *vdev = gpio->vdev; + int i; + + for (i = 0; i < 2; i++) { + qvirtqueue_cleanup(vdev->bus, gpio->queues[i], alloc); + } + g_free(gpio->queues); +} + +/* + * This handles the VirtIO setup from the point of view of the driver + * frontend and therefor doesn't present any vhost specific features + * and in fact masks of the re-used bit. + */ +static void virtio_gpio_setup(QVhostUserGPIO *gpio) +{ + QVirtioDevice *vdev = gpio->vdev; + uint64_t features; + int i; + + features = qvirtio_get_features(vdev); + features &= ~QVIRTIO_F_BAD_FEATURE; + qvirtio_set_features(vdev, features); + + gpio->queues = g_new(QVirtQueue *, 2); + for (i = 0; i < 2; i++) { + gpio->queues[i] = qvirtqueue_setup(vdev, alloc, i); + } + qvirtio_set_driver_ok(vdev); +} + +static void *qvirtio_gpio_get_driver(QVhostUserGPIO *v_gpio, + const char *interface) +{ + if (!g_strcmp0(interface, "vhost-user-gpio")) { + return v_gpio; + } + if (!g_strcmp0(interface, "virtio")) { + return v_gpio->vdev; + } + + g_assert_not_reached(); +} + +static void *qvirtio_gpio_device_get_driver(void *object, + const char *interface) +{ + QVhostUserGPIODevice *v_gpio = object; + return qvirtio_gpio_get_driver(&v_gpio->gpio, interface); +} + +/* virtio-gpio (mmio) */ +static void qvirtio_gpio_device_destructor(QOSGraphObject *obj) +{ + QVhostUserGPIODevice *gpio_dev = (QVhostUserGPIODevice *) obj; + virtio_gpio_cleanup(&gpio_dev->gpio); +} + +static void qvirtio_gpio_device_start_hw(QOSGraphObject *obj) +{ + QVhostUserGPIODevice *gpio_dev = (QVhostUserGPIODevice *) obj; + virtio_gpio_setup(&gpio_dev->gpio); +} + +static void *virtio_gpio_device_create(void *virtio_dev, + QGuestAllocator *t_alloc, + void *addr) +{ + QVhostUserGPIODevice *virtio_device = g_new0(QVhostUserGPIODevice, 1); + QVhostUserGPIO *interface = &virtio_device->gpio; + + interface->vdev = virtio_dev; + alloc = t_alloc; + + virtio_device->obj.get_driver = qvirtio_gpio_device_get_driver; + virtio_device->obj.start_hw = qvirtio_gpio_device_start_hw; + virtio_device->obj.destructor = qvirtio_gpio_device_destructor; + + return &virtio_device->obj; +} + +/* virtio-gpio-pci */ +static void qvirtio_gpio_pci_destructor(QOSGraphObject *obj) +{ + QVhostUserGPIOPCI *gpio_pci = (QVhostUserGPIOPCI *) obj; + QOSGraphObject *pci_vobj = &gpio_pci->pci_vdev.obj; + + virtio_gpio_cleanup(&gpio_pci->gpio); + qvirtio_pci_destructor(pci_vobj); +} + +static void qvirtio_gpio_pci_start_hw(QOSGraphObject *obj) +{ + QVhostUserGPIOPCI *gpio_pci = (QVhostUserGPIOPCI *) obj; + QOSGraphObject *pci_vobj = &gpio_pci->pci_vdev.obj; + + qvirtio_pci_start_hw(pci_vobj); + virtio_gpio_setup(&gpio_pci->gpio); +} + +static void *qvirtio_gpio_pci_get_driver(void *object, const char *interface) +{ + QVhostUserGPIOPCI *v_gpio = object; + + if (!g_strcmp0(interface, "pci-device")) { + return v_gpio->pci_vdev.pdev; + } + return qvirtio_gpio_get_driver(&v_gpio->gpio, interface); +} + +static void *virtio_gpio_pci_create(void *pci_bus, QGuestAllocator *t_alloc, + void *addr) +{ + QVhostUserGPIOPCI *virtio_spci = g_new0(QVhostUserGPIOPCI, 1); + QVhostUserGPIO *interface = &virtio_spci->gpio; + QOSGraphObject *obj = &virtio_spci->pci_vdev.obj; + + virtio_pci_init(&virtio_spci->pci_vdev, pci_bus, addr); + interface->vdev = &virtio_spci->pci_vdev.vdev; + alloc = t_alloc; + + obj->get_driver = qvirtio_gpio_pci_get_driver; + obj->start_hw = qvirtio_gpio_pci_start_hw; + obj->destructor = qvirtio_gpio_pci_destructor; + + return obj; +} + +static void virtio_gpio_register_nodes(void) +{ + QPCIAddress addr = { + .devfn = QPCI_DEVFN(4, 0), + }; + + QOSGraphEdgeOptions edge_opts = { }; + + /* vhost-user-gpio-device */ + edge_opts.extra_device_opts = "id=gpio0,chardev=chr-vhost-user-test"; + qos_node_create_driver("vhost-user-gpio-device", + virtio_gpio_device_create); + qos_node_consumes("vhost-user-gpio-device", "virtio-bus", &edge_opts); + qos_node_produces("vhost-user-gpio-device", "vhost-user-gpio"); + + /* virtio-gpio-pci */ + edge_opts.extra_device_opts = "id=gpio0,addr=04.0,chardev=chr-vhost-user-test"; + add_qpci_address(&edge_opts, &addr); + qos_node_create_driver("vhost-user-gpio-pci", virtio_gpio_pci_create); + qos_node_consumes("vhost-user-gpio-pci", "pci-bus", &edge_opts); + qos_node_produces("vhost-user-gpio-pci", "vhost-user-gpio"); +} + +libqos_init(virtio_gpio_register_nodes); diff --git a/tests/qtest/libqos/virtio-gpio.h b/tests/qtest/libqos/virtio-gpio.h new file mode 100644 index 0000000000..f11d41bd19 --- /dev/null +++ b/tests/qtest/libqos/virtio-gpio.h @@ -0,0 +1,35 @@ +/* + * virtio-gpio structures + * + * Copyright (c) 2022 Linaro Ltd + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef TESTS_LIBQOS_VIRTIO_GPIO_H +#define TESTS_LIBQOS_VIRTIO_GPIO_H + +#include "qgraph.h" +#include "virtio.h" +#include "virtio-pci.h" + +typedef struct QVhostUserGPIO QVhostUserGPIO; +typedef struct QVhostUserGPIOPCI QVhostUserGPIOPCI; +typedef struct QVhostUserGPIODevice QVhostUserGPIODevice; + +struct QVhostUserGPIO { + QVirtioDevice *vdev; + QVirtQueue **queues; +}; + +struct QVhostUserGPIOPCI { + QVirtioPCIDevice pci_vdev; + QVhostUserGPIO gpio; +}; + +struct QVhostUserGPIODevice { + QOSGraphObject obj; + QVhostUserGPIO gpio; +}; + +#endif diff --git a/tests/qtest/libqos/virtio.c b/tests/qtest/libqos/virtio.c index 03056e5187..410513225f 100644 --- a/tests/qtest/libqos/virtio.c +++ b/tests/qtest/libqos/virtio.c @@ -110,7 +110,7 @@ void qvirtio_set_features(QVirtioDevice *d, uint64_t features) * This could be a separate function for drivers that want to access * configuration space before setting FEATURES_OK, but no existing users * need that and it's less code for callers if this is done implicitly. - */ + */ if (features & (1ull << VIRTIO_F_VERSION_1)) { uint8_t status = d->bus->get_status(d) | VIRTIO_CONFIG_S_FEATURES_OK; diff --git a/tests/qtest/vhost-user-test.c b/tests/qtest/vhost-user-test.c index 4f4fcc09f5..e8d2da7228 100644 --- a/tests/qtest/vhost-user-test.c +++ b/tests/qtest/vhost-user-test.c @@ -32,6 +32,7 @@ #include "standard-headers/linux/vhost_types.h" #include "standard-headers/linux/virtio_ids.h" #include "standard-headers/linux/virtio_net.h" +#include "standard-headers/linux/virtio_gpio.h" #ifdef CONFIG_LINUX #include @@ -53,9 +54,12 @@ #define VHOST_MAX_VIRTQUEUES 0x100 #define VHOST_USER_F_PROTOCOL_FEATURES 30 +#define VIRTIO_F_VERSION_1 32 + #define VHOST_USER_PROTOCOL_F_MQ 0 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1 #define VHOST_USER_PROTOCOL_F_CROSS_ENDIAN 6 +#define VHOST_USER_PROTOCOL_F_CONFIG 9 #define VHOST_LOG_PAGE 0x1000 @@ -140,6 +144,7 @@ enum { enum { VHOST_USER_NET, + VHOST_USER_GPIO, }; typedef struct TestServer { @@ -198,6 +203,19 @@ static void append_vhost_net_opts(TestServer *s, GString *cmd_line, chr_opts, s->chr_name); } +/* + * For GPIO there are no other magic devices we need to add (like + * block or netdev) so all we need to worry about is the vhost-user + * chardev socket. + */ +static void append_vhost_gpio_opts(TestServer *s, GString *cmd_line, + const char *chr_opts) +{ + g_string_append_printf(cmd_line, QEMU_CMD_CHR, + s->chr_name, s->socket_path, + chr_opts); +} + static void append_mem_opts(TestServer *server, GString *cmd_line, int size, enum test_memfd memfd) { @@ -1090,3 +1108,51 @@ static void register_vhost_user_test(void) test_multiqueue, &opts); } libqos_init(register_vhost_user_test); + +static uint64_t vu_gpio_get_features(TestServer *s) +{ + return 0x1ULL << VIRTIO_F_VERSION_1 | + 0x1ULL << VIRTIO_GPIO_F_IRQ | + 0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES; +} + +/* + * This stub can't handle all the message types but we should reply + * that we support VHOST_USER_PROTOCOL_F_CONFIG as gpio would use it + * talking to a read vhost-user daemon. + */ +static void vu_gpio_get_protocol_features(TestServer *s, CharBackend *chr, + VhostUserMsg *msg) +{ + /* send back features to qemu */ + msg->flags |= VHOST_USER_REPLY_MASK; + msg->size = sizeof(m.payload.u64); + msg->payload.u64 = 1ULL << VHOST_USER_PROTOCOL_F_CONFIG; + + qemu_chr_fe_write_all(chr, (uint8_t *)msg, VHOST_USER_HDR_SIZE + msg->size); +} + +static struct vhost_user_ops g_vu_gpio_ops = { + .type = VHOST_USER_GPIO, + + .append_opts = append_vhost_gpio_opts, + + .get_features = vu_gpio_get_features, + .set_features = vu_net_set_features, + .get_protocol_features = vu_gpio_get_protocol_features, +}; + +static void register_vhost_gpio_test(void) +{ + QOSGraphTestOptions opts = { + .before = vhost_user_test_setup, + .subprocess = true, + .arg = &g_vu_gpio_ops, + }; + + qemu_add_opts(&qemu_chardev_opts); + + qos_add_test("read-guest-mem/memfile", + "vhost-user-gpio", test_read_guest_mem, &opts); +} +libqos_init(register_vhost_gpio_test); From d74c30c81159d703fb4e1caa0ec6772ff89dd02f Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Tue, 6 Sep 2022 10:31:07 +0300 Subject: [PATCH 0956/1020] virtio: introduce VirtIOConfigSizeParams & virtio_get_config_size This is the first step towards moving all device config size calculation logic into the virtio core code. In particular, this adds a struct that contains all the necessary information for common virtio code to be able to calculate the final config size for a device. This is expected to be used with the new virtio_get_config_size helper, which calculates the final length based on the provided host features. This builds on top of already existing code like VirtIOFeature and virtio_feature_get_config_size(), but adds additional fields, as well as sanity checking so that device-specifc code doesn't have to duplicate it. An example usage would be: static const VirtIOFeature dev_features[] = { {.flags = 1ULL << FEATURE_1_BIT, .end = endof(struct virtio_dev_config, feature_1)}, {.flags = 1ULL << FEATURE_2_BIT, .end = endof(struct virtio_dev_config, feature_2)}, {} }; static const VirtIOConfigSizeParams dev_cfg_size_params = { .min_size = DEV_BASE_CONFIG_SIZE, .max_size = sizeof(struct virtio_dev_config), .feature_sizes = dev_features }; // code inside my_dev_device_realize() size_t config_size = virtio_get_config_size(&dev_cfg_size_params, host_features); virtio_init(vdev, VIRTIO_ID_MYDEV, config_size); Currently every device is expected to write its own boilerplate from the example above in device_realize(), however, the next step of this transition is moving VirtIOConfigSizeParams into VirtioDeviceClass, so that it can be done automatically by the virtio initialization code. All of the users of virtio_feature_get_config_size have been converted to use virtio_get_config_size so it's no longer needed and is removed with this commit. Signed-off-by: Daniil Tatianin Message-Id: <20220906073111.353245-2-d-tatianin@yandex-team.ru> Reviewed-by: Raphael Norwitz Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/block/virtio-blk.c | 16 +++++++--------- hw/net/virtio-net.c | 9 +++++++-- hw/virtio/virtio.c | 10 ++++++---- include/hw/virtio/virtio.h | 10 ++++++++-- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index e9ba752f6b..10c47c2934 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -49,13 +49,11 @@ static const VirtIOFeature feature_sizes[] = { {} }; -static void virtio_blk_set_config_size(VirtIOBlock *s, uint64_t host_features) -{ - s->config_size = MAX(VIRTIO_BLK_CFG_SIZE, - virtio_feature_get_config_size(feature_sizes, host_features)); - - assert(s->config_size <= sizeof(struct virtio_blk_config)); -} +static const VirtIOConfigSizeParams cfg_size_params = { + .min_size = VIRTIO_BLK_CFG_SIZE, + .max_size = sizeof(struct virtio_blk_config), + .feature_sizes = feature_sizes +}; static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq, VirtIOBlockReq *req) @@ -1204,8 +1202,8 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) return; } - virtio_blk_set_config_size(s, s->host_features); - + s->config_size = virtio_get_config_size(&cfg_size_params, + s->host_features); virtio_init(vdev, VIRTIO_ID_BLOCK, s->config_size); s->blk = conf->conf.blk; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 63a8332cd0..e9f696b4cf 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -106,6 +106,12 @@ static const VirtIOFeature feature_sizes[] = { {} }; +static const VirtIOConfigSizeParams cfg_size_params = { + .min_size = endof(struct virtio_net_config, mac), + .max_size = sizeof(struct virtio_net_config), + .feature_sizes = feature_sizes +}; + static VirtIONetQueue *virtio_net_get_subqueue(NetClientState *nc) { VirtIONet *n = qemu_get_nic_opaque(nc); @@ -3241,8 +3247,7 @@ static void virtio_net_set_config_size(VirtIONet *n, uint64_t host_features) { virtio_add_feature(&host_features, VIRTIO_NET_F_MAC); - n->config_size = virtio_feature_get_config_size(feature_sizes, - host_features); + n->config_size = virtio_get_config_size(&cfg_size_params, host_features); } void virtio_net_set_netclient_name(VirtIONet *n, const char *name, diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 97a6307c0f..2cc1d7d24a 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3006,11 +3006,12 @@ int virtio_set_features(VirtIODevice *vdev, uint64_t val) return ret; } -size_t virtio_feature_get_config_size(const VirtIOFeature *feature_sizes, - uint64_t host_features) +size_t virtio_get_config_size(const VirtIOConfigSizeParams *params, + uint64_t host_features) { - size_t config_size = 0; - int i; + size_t config_size = params->min_size; + const VirtIOFeature *feature_sizes = params->feature_sizes; + size_t i; for (i = 0; feature_sizes[i].flags != 0; i++) { if (host_features & feature_sizes[i].flags) { @@ -3018,6 +3019,7 @@ size_t virtio_feature_get_config_size(const VirtIOFeature *feature_sizes, } } + assert(config_size <= params->max_size); return config_size; } diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 74e7ad5a92..cecfb7c552 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -49,8 +49,14 @@ typedef struct VirtIOFeature { size_t end; } VirtIOFeature; -size_t virtio_feature_get_config_size(const VirtIOFeature *features, - uint64_t host_features); +typedef struct VirtIOConfigSizeParams { + size_t min_size; + size_t max_size; + const VirtIOFeature *feature_sizes; +} VirtIOConfigSizeParams; + +size_t virtio_get_config_size(const VirtIOConfigSizeParams *params, + uint64_t host_features); typedef struct VirtQueue VirtQueue; From d9cf55a86d315efc9fa07daad72f74f769555183 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Tue, 6 Sep 2022 10:31:08 +0300 Subject: [PATCH 0957/1020] virtio-blk: move config size params to virtio-blk-common This way we can reuse it for other virtio-blk devices, e.g vhost-user-blk, which currently does not control its config space size dynamically. Signed-off-by: Daniil Tatianin Reviewed-by: Raphael Norwitz Message-Id: <20220906073111.353245-3-d-tatianin@yandex-team.ru> Reviewed-by: Raphael Norwitz Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 2 ++ hw/block/meson.build | 2 +- hw/block/virtio-blk-common.c | 39 +++++++++++++++++++++++++++ hw/block/virtio-blk.c | 24 ++--------------- include/hw/virtio/virtio-blk-common.h | 20 ++++++++++++++ 5 files changed, 64 insertions(+), 23 deletions(-) create mode 100644 hw/block/virtio-blk-common.c create mode 100644 include/hw/virtio/virtio-blk-common.h diff --git a/MAINTAINERS b/MAINTAINERS index d0c0c8a55b..05b75805eb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2030,8 +2030,10 @@ virtio-blk M: Stefan Hajnoczi L: qemu-block@nongnu.org S: Supported +F: hw/block/virtio-blk-common.c F: hw/block/virtio-blk.c F: hw/block/dataplane/* +F: include/hw/virtio/virtio-blk-common.h F: tests/qtest/virtio-blk-test.c T: git https://github.com/stefanha/qemu.git block diff --git a/hw/block/meson.build b/hw/block/meson.build index 2389326112..8ee1f1f850 100644 --- a/hw/block/meson.build +++ b/hw/block/meson.build @@ -16,7 +16,7 @@ softmmu_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c')) softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen-block.c')) softmmu_ss.add(when: 'CONFIG_TC58128', if_true: files('tc58128.c')) -specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c')) +specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c', 'virtio-blk-common.c')) specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c')) subdir('dataplane') diff --git a/hw/block/virtio-blk-common.c b/hw/block/virtio-blk-common.c new file mode 100644 index 0000000000..ac52d7c176 --- /dev/null +++ b/hw/block/virtio-blk-common.c @@ -0,0 +1,39 @@ +/* + * Virtio Block Device common helpers + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#include "qemu/osdep.h" + +#include "standard-headers/linux/virtio_blk.h" +#include "hw/virtio/virtio.h" +#include "hw/virtio/virtio-blk-common.h" + +/* Config size before the discard support (hide associated config fields) */ +#define VIRTIO_BLK_CFG_SIZE offsetof(struct virtio_blk_config, \ + max_discard_sectors) + +/* + * Starting from the discard feature, we can use this array to properly + * set the config size depending on the features enabled. + */ +static const VirtIOFeature feature_sizes[] = { + {.flags = 1ULL << VIRTIO_BLK_F_DISCARD, + .end = endof(struct virtio_blk_config, discard_sector_alignment)}, + {.flags = 1ULL << VIRTIO_BLK_F_WRITE_ZEROES, + .end = endof(struct virtio_blk_config, write_zeroes_may_unmap)}, + {} +}; + +const VirtIOConfigSizeParams virtio_blk_cfg_size_params = { + .min_size = VIRTIO_BLK_CFG_SIZE, + .max_size = sizeof(struct virtio_blk_config), + .feature_sizes = feature_sizes +}; diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 10c47c2934..8131ec2dbc 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -32,29 +32,9 @@ #include "hw/virtio/virtio-bus.h" #include "migration/qemu-file-types.h" #include "hw/virtio/virtio-access.h" +#include "hw/virtio/virtio-blk-common.h" #include "qemu/coroutine.h" -/* Config size before the discard support (hide associated config fields) */ -#define VIRTIO_BLK_CFG_SIZE offsetof(struct virtio_blk_config, \ - max_discard_sectors) -/* - * Starting from the discard feature, we can use this array to properly - * set the config size depending on the features enabled. - */ -static const VirtIOFeature feature_sizes[] = { - {.flags = 1ULL << VIRTIO_BLK_F_DISCARD, - .end = endof(struct virtio_blk_config, discard_sector_alignment)}, - {.flags = 1ULL << VIRTIO_BLK_F_WRITE_ZEROES, - .end = endof(struct virtio_blk_config, write_zeroes_may_unmap)}, - {} -}; - -static const VirtIOConfigSizeParams cfg_size_params = { - .min_size = VIRTIO_BLK_CFG_SIZE, - .max_size = sizeof(struct virtio_blk_config), - .feature_sizes = feature_sizes -}; - static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq, VirtIOBlockReq *req) { @@ -1202,7 +1182,7 @@ static void virtio_blk_device_realize(DeviceState *dev, Error **errp) return; } - s->config_size = virtio_get_config_size(&cfg_size_params, + s->config_size = virtio_get_config_size(&virtio_blk_cfg_size_params, s->host_features); virtio_init(vdev, VIRTIO_ID_BLOCK, s->config_size); diff --git a/include/hw/virtio/virtio-blk-common.h b/include/hw/virtio/virtio-blk-common.h new file mode 100644 index 0000000000..31daada3e3 --- /dev/null +++ b/include/hw/virtio/virtio-blk-common.h @@ -0,0 +1,20 @@ +/* + * Virtio Block Device common helpers + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + */ + +#ifndef VIRTIO_BLK_COMMON_H +#define VIRTIO_BLK_COMMON_H + +#include "hw/virtio/virtio.h" + +extern const VirtIOConfigSizeParams virtio_blk_cfg_size_params; + +#endif From 246db16d43b664d7fbf1993858fe193feb712978 Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Tue, 6 Sep 2022 10:31:09 +0300 Subject: [PATCH 0958/1020] vhost-user-blk: make it possible to disable write-zeroes/discard It is useful to have the ability to disable these features for compatibility with older VMs that don't have these implemented. Signed-off-by: Daniil Tatianin Reviewed-by: Raphael Norwitz Message-Id: <20220906073111.353245-4-d-tatianin@yandex-team.ru> Reviewed-by: Raphael Norwitz Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/block/vhost-user-blk.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 2bba42478d..92bfe56b45 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -259,8 +259,6 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev, virtio_add_feature(&features, VIRTIO_BLK_F_BLK_SIZE); virtio_add_feature(&features, VIRTIO_BLK_F_FLUSH); virtio_add_feature(&features, VIRTIO_BLK_F_RO); - virtio_add_feature(&features, VIRTIO_BLK_F_DISCARD); - virtio_add_feature(&features, VIRTIO_BLK_F_WRITE_ZEROES); if (s->config_wce) { virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE); @@ -598,6 +596,10 @@ static Property vhost_user_blk_properties[] = { VHOST_USER_BLK_AUTO_NUM_QUEUES), DEFINE_PROP_UINT32("queue-size", VHostUserBlk, queue_size, 128), DEFINE_PROP_BIT("config-wce", VHostUserBlk, config_wce, 0, true), + DEFINE_PROP_BIT64("discard", VHostUserBlk, parent_obj.host_features, + VIRTIO_BLK_F_DISCARD, true), + DEFINE_PROP_BIT64("write-zeroes", VHostUserBlk, parent_obj.host_features, + VIRTIO_BLK_F_WRITE_ZEROES, true), DEFINE_PROP_END_OF_LIST(), }; From f1c25f295dc784a2e8270d94c8d12d8a55a0882c Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Tue, 6 Sep 2022 10:31:10 +0300 Subject: [PATCH 0959/1020] vhost-user-blk: make 'config_wce' part of 'host_features' No reason to have this be a separate field. This also makes it more akin to what the virtio-blk device does. Signed-off-by: Daniil Tatianin Reviewed-by: Raphael Norwitz Message-Id: <20220906073111.353245-5-d-tatianin@yandex-team.ru> Reviewed-by: Raphael Norwitz Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/block/vhost-user-blk.c | 6 ++---- include/hw/virtio/vhost-user-blk.h | 1 - 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index 92bfe56b45..aa4831f27a 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -260,9 +260,6 @@ static uint64_t vhost_user_blk_get_features(VirtIODevice *vdev, virtio_add_feature(&features, VIRTIO_BLK_F_FLUSH); virtio_add_feature(&features, VIRTIO_BLK_F_RO); - if (s->config_wce) { - virtio_add_feature(&features, VIRTIO_BLK_F_CONFIG_WCE); - } if (s->num_queues > 1) { virtio_add_feature(&features, VIRTIO_BLK_F_MQ); } @@ -595,7 +592,8 @@ static Property vhost_user_blk_properties[] = { DEFINE_PROP_UINT16("num-queues", VHostUserBlk, num_queues, VHOST_USER_BLK_AUTO_NUM_QUEUES), DEFINE_PROP_UINT32("queue-size", VHostUserBlk, queue_size, 128), - DEFINE_PROP_BIT("config-wce", VHostUserBlk, config_wce, 0, true), + DEFINE_PROP_BIT64("config-wce", VHostUserBlk, parent_obj.host_features, + VIRTIO_BLK_F_CONFIG_WCE, true), DEFINE_PROP_BIT64("discard", VHostUserBlk, parent_obj.host_features, VIRTIO_BLK_F_DISCARD, true), DEFINE_PROP_BIT64("write-zeroes", VHostUserBlk, parent_obj.host_features, diff --git a/include/hw/virtio/vhost-user-blk.h b/include/hw/virtio/vhost-user-blk.h index 7c91f15040..ea085ee1ed 100644 --- a/include/hw/virtio/vhost-user-blk.h +++ b/include/hw/virtio/vhost-user-blk.h @@ -34,7 +34,6 @@ struct VHostUserBlk { struct virtio_blk_config blkcfg; uint16_t num_queues; uint32_t queue_size; - uint32_t config_wce; struct vhost_dev dev; struct vhost_inflight *inflight; VhostUserState vhost_user; From 8edd56735baa7f58aa504d0f2c4ed6f893630cce Mon Sep 17 00:00:00 2001 From: Daniil Tatianin Date: Tue, 6 Sep 2022 10:31:11 +0300 Subject: [PATCH 0960/1020] vhost-user-blk: dynamically resize config space based on features Make vhost-user-blk backwards compatible when migrating from older VMs running with modern features turned off, the same way it was done for virtio-blk in 20764be0421c ("virtio-blk: set config size depending on the features enabled") It's currently impossible to migrate from an older VM with vhost-user-blk (with disable-legacy=off) because of errors like this: qemu-system-x86_64: get_pci_config_device: Bad config data: i=0x10 read: 41 device: 1 cmask: ff wmask: 80 w1cmask:0 qemu-system-x86_64: Failed to load PCIDevice:config qemu-system-x86_64: Failed to load virtio-blk:virtio qemu-system-x86_64: error while loading state for instance 0x0 of device '0000:00:05.0:00.0:02.0/virtio-blk' qemu-system-x86_64: load of migration failed: Invalid argument This is caused by the newer (destination) VM requiring a bigger BAR0 alignment because it has to cover a bigger configuration space, which isn't actually needed since those additional config fields are not active (write-zeroes/discard). Signed-off-by: Daniil Tatianin Reviewed-by: Raphael Norwitz Message-Id: <20220906073111.353245-6-d-tatianin@yandex-team.ru> Reviewed-by: Raphael Norwitz Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- MAINTAINERS | 2 ++ hw/block/meson.build | 2 +- hw/block/vhost-user-blk.c | 17 ++++++++++------- 3 files changed, 13 insertions(+), 8 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index 05b75805eb..8ae2e43c83 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2281,11 +2281,13 @@ S: Maintained F: contrib/vhost-user-blk/ F: contrib/vhost-user-scsi/ F: hw/block/vhost-user-blk.c +F: hw/block/virtio-blk-common.c F: hw/scsi/vhost-user-scsi.c F: hw/virtio/vhost-user-blk-pci.c F: hw/virtio/vhost-user-scsi-pci.c F: include/hw/virtio/vhost-user-blk.h F: include/hw/virtio/vhost-user-scsi.h +F: include/hw/virtio/virtio-blk-common.h vhost-user-gpu M: Marc-André Lureau diff --git a/hw/block/meson.build b/hw/block/meson.build index 8ee1f1f850..1908abd45c 100644 --- a/hw/block/meson.build +++ b/hw/block/meson.build @@ -17,6 +17,6 @@ softmmu_ss.add(when: 'CONFIG_XEN', if_true: files('xen-block.c')) softmmu_ss.add(when: 'CONFIG_TC58128', if_true: files('tc58128.c')) specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c', 'virtio-blk-common.c')) -specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c')) +specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c', 'virtio-blk-common.c')) subdir('dataplane') diff --git a/hw/block/vhost-user-blk.c b/hw/block/vhost-user-blk.c index aa4831f27a..84902dde17 100644 --- a/hw/block/vhost-user-blk.c +++ b/hw/block/vhost-user-blk.c @@ -23,6 +23,7 @@ #include "hw/qdev-core.h" #include "hw/qdev-properties.h" #include "hw/qdev-properties-system.h" +#include "hw/virtio/virtio-blk-common.h" #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-user-blk.h" #include "hw/virtio/virtio.h" @@ -63,7 +64,7 @@ static void vhost_user_blk_update_config(VirtIODevice *vdev, uint8_t *config) /* Our num_queues overrides the device backend */ virtio_stw_p(vdev, &s->blkcfg.num_queues, s->num_queues); - memcpy(config, &s->blkcfg, sizeof(struct virtio_blk_config)); + memcpy(config, &s->blkcfg, vdev->config_len); } static void vhost_user_blk_set_config(VirtIODevice *vdev, const uint8_t *config) @@ -92,12 +93,12 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev) { int ret; struct virtio_blk_config blkcfg; + VirtIODevice *vdev = dev->vdev; VHostUserBlk *s = VHOST_USER_BLK(dev->vdev); Error *local_err = NULL; ret = vhost_dev_get_config(dev, (uint8_t *)&blkcfg, - sizeof(struct virtio_blk_config), - &local_err); + vdev->config_len, &local_err); if (ret < 0) { error_report_err(local_err); return ret; @@ -106,7 +107,7 @@ static int vhost_user_blk_handle_config_change(struct vhost_dev *dev) /* valid for resize only */ if (blkcfg.capacity != s->blkcfg.capacity) { s->blkcfg.capacity = blkcfg.capacity; - memcpy(dev->vdev->config, &s->blkcfg, sizeof(struct virtio_blk_config)); + memcpy(dev->vdev->config, &s->blkcfg, vdev->config_len); virtio_notify_config(dev->vdev); } @@ -448,7 +449,7 @@ static int vhost_user_blk_realize_connect(VHostUserBlk *s, Error **errp) assert(s->connected); ret = vhost_dev_get_config(&s->dev, (uint8_t *)&s->blkcfg, - sizeof(struct virtio_blk_config), errp); + s->parent_obj.config_len, errp); if (ret < 0) { qemu_chr_fe_disconnect(&s->chardev); vhost_dev_cleanup(&s->dev); @@ -463,6 +464,7 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) ERRP_GUARD(); VirtIODevice *vdev = VIRTIO_DEVICE(dev); VHostUserBlk *s = VHOST_USER_BLK(vdev); + size_t config_size; int retries; int i, ret; @@ -493,8 +495,9 @@ static void vhost_user_blk_device_realize(DeviceState *dev, Error **errp) return; } - virtio_init(vdev, VIRTIO_ID_BLOCK, - sizeof(struct virtio_blk_config)); + config_size = virtio_get_config_size(&virtio_blk_cfg_size_params, + vdev->host_features); + virtio_init(vdev, VIRTIO_ID_BLOCK, config_size); s->virtqs = g_new(VirtQueue *, s->num_queues); for (i = 0; i < s->num_queues; i++) { From b1b146f53cad89ed51956f67bc5b672348753777 Mon Sep 17 00:00:00 2001 From: Miguel Luis Date: Tue, 20 Sep 2022 16:21:35 +0000 Subject: [PATCH 0961/1020] tests/acpi: virt: allow acpi GTDT changes Step 3 from bios-tables-test.c documented procedure. Signed-off-by: Miguel Luis Message-Id: <20220920162137.75239-2-miguel.luis@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Acked-by: Ani Sinha --- tests/qtest/bios-tables-test-allowed-diff.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..957bd1b4f6 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/virt/GTDT", +"tests/data/acpi/virt/GTDT.memhp", +"tests/data/acpi/virt/GTDT.numamem", From 5dbc9a27856b7b345c6cbd47eba0d730d9852ce1 Mon Sep 17 00:00:00 2001 From: Miguel Luis Date: Tue, 20 Sep 2022 16:21:36 +0000 Subject: [PATCH 0962/1020] acpi: arm/virt: build_gtdt: fix invalid 64-bit physical addresses Per the ACPI 6.5 specification, on the GTDT Table Structure, the Counter Control Block Address and Counter Read Block Address fields of the GTDT table should be set to 0xFFFFFFFFFFFFFFFF if not provided, rather than 0x0. Fixes: 41041e57085 ("acpi: arm/virt: build_gtdt: use acpi_table_begin()/acpi_table_end() instead of build_header()") Signed-off-by: Miguel Luis Message-Id: <20220920162137.75239-3-miguel.luis@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Ani Sinha --- hw/arm/virt-acpi-build.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 9b3aee01bf..13c6e3e468 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -592,8 +592,7 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_table_begin(&table, table_data); /* CntControlBase Physical Address */ - /* FIXME: invalid value, should be 0xFFFFFFFFFFFFFFFF if not impl. ? */ - build_append_int_noprefix(table_data, 0, 8); + build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8); build_append_int_noprefix(table_data, 0, 4); /* Reserved */ /* * FIXME: clarify comment: @@ -618,7 +617,7 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) /* Non-Secure EL2 timer Flags */ build_append_int_noprefix(table_data, irqflags, 4); /* CntReadBase Physical address */ - build_append_int_noprefix(table_data, 0, 8); + build_append_int_noprefix(table_data, 0xFFFFFFFFFFFFFFFF, 8); /* Platform Timer Count */ build_append_int_noprefix(table_data, 0, 4); /* Platform Timer Offset */ From 0a17270761e7d90a67edadb19c7f6871387931be Mon Sep 17 00:00:00 2001 From: Miguel Luis Date: Tue, 20 Sep 2022 16:21:37 +0000 Subject: [PATCH 0963/1020] tests/acpi: virt: update ACPI GTDT binaries Step 6 & 7 of the bios-tables-test.c documented procedure. Differences between disassembled ASL files for GTDT: @@ -13,14 +13,14 @@ [000h 0000 4] Signature : "GTDT" [Generic Timer Description Table] [004h 0004 4] Table Length : 00000060 [008h 0008 1] Revision : 02 -[009h 0009 1] Checksum : 8C +[009h 0009 1] Checksum : 9C [00Ah 0010 6] Oem ID : "BOCHS " [010h 0016 8] Oem Table ID : "BXPC " [018h 0024 4] Oem Revision : 00000001 [01Ch 0028 4] Asl Compiler ID : "BXPC" [020h 0032 4] Asl Compiler Revision : 00000001 -[024h 0036 8] Counter Block Address : 0000000000000000 +[024h 0036 8] Counter Block Address : FFFFFFFFFFFFFFFF [02Ch 0044 4] Reserved : 00000000 [030h 0048 4] Secure EL1 Interrupt : 0000001D @@ -46,16 +46,16 @@ Trigger Mode : 0 Polarity : 0 Always On : 0 -[050h 0080 8] Counter Read Block Address : 0000000000000000 +[050h 0080 8] Counter Read Block Address : FFFFFFFFFFFFFFFF [058h 0088 4] Platform Timer Count : 00000000 [05Ch 0092 4] Platform Timer Offset : 00000000 Raw Table Data: Length 96 (0x60) - 0000: 47 54 44 54 60 00 00 00 02 8C 42 4F 43 48 53 20 // GTDT`.....BOCHS + 0000: 47 54 44 54 60 00 00 00 02 9C 42 4F 43 48 53 20 // GTDT`.....BOCHS 0010: 42 58 50 43 20 20 20 20 01 00 00 00 42 58 50 43 // BXPC ....BXPC - 0020: 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ + 0020: 01 00 00 00 FF FF FF FF FF FF FF FF 00 00 00 00 // ................ 0030: 1D 00 00 00 00 00 00 00 1E 00 00 00 04 00 00 00 // ................ 0040: 1B 00 00 00 00 00 00 00 1A 00 00 00 00 00 00 00 // ................ - 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // ................ + 0050: FF FF FF FF FF FF FF FF 00 00 00 00 00 00 00 00 // ................ Signed-off-by: Miguel Luis Message-Id: <20220920162137.75239-4-miguel.luis@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Acked-by: Ani Sinha --- tests/data/acpi/virt/GTDT | Bin 96 -> 96 bytes tests/data/acpi/virt/GTDT.memhp | Bin 96 -> 96 bytes tests/data/acpi/virt/GTDT.numamem | Bin 96 -> 96 bytes tests/qtest/bios-tables-test-allowed-diff.h | 3 --- 4 files changed, 3 deletions(-) diff --git a/tests/data/acpi/virt/GTDT b/tests/data/acpi/virt/GTDT index 9408b71b59c0e0f2991c0053562280155b47bc0b..6f8cb9b8f30b55f4c93fe515982621e3db50feb2 100644 GIT binary patch delta 45 kcmYdD;BpUf2}xjJU|^avkxPo>KNL*VQ4xT#fs$YV0LH=;ng9R* delta 45 jcmYdD;BpUf2}xjJU|{N*$R))AWPrg$9Tfo>8%6^Foy!E8 diff --git a/tests/data/acpi/virt/GTDT.memhp b/tests/data/acpi/virt/GTDT.memhp index 9408b71b59c0e0f2991c0053562280155b47bc0b..6f8cb9b8f30b55f4c93fe515982621e3db50feb2 100644 GIT binary patch delta 45 kcmYdD;BpUf2}xjJU|^avkxPo>KNL*VQ4xT#fs$YV0LH=;ng9R* delta 45 jcmYdD;BpUf2}xjJU|{N*$R))AWPrg$9Tfo>8%6^Foy!E8 diff --git a/tests/data/acpi/virt/GTDT.numamem b/tests/data/acpi/virt/GTDT.numamem index 9408b71b59c0e0f2991c0053562280155b47bc0b..6f8cb9b8f30b55f4c93fe515982621e3db50feb2 100644 GIT binary patch delta 45 kcmYdD;BpUf2}xjJU|^avkxPo>KNL*VQ4xT#fs$YV0LH=;ng9R* delta 45 jcmYdD;BpUf2}xjJU|{N*$R))AWPrg$9Tfo>8%6^Foy!E8 diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 957bd1b4f6..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,4 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/virt/GTDT", -"tests/data/acpi/virt/GTDT.memhp", -"tests/data/acpi/virt/GTDT.numamem", From 9c769e04465118601dea96b02c27887bd46cce25 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Fri, 23 Sep 2022 17:18:35 +0100 Subject: [PATCH 0964/1020] mem/cxl-type3: Add sn option to provide serial number for PCI ecap The Device Serial Number Extended Capability PCI r6.0 sec 7.9.3 provides a standard way to provide a device serial number as an IEEE defined 64-bit extended unique identifier EUI-64. CXL 2.0 section 8.1.12.2 Memory Device PCIe Capabilities and Extended Capabilities requires this to be used to uniquely identify CXL memory devices. Signed-off-by: Jonathan Cameron Message-Id: <20220923161835.9805-1-Jonathan.Cameron@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Ben Widawsky --- hw/mem/cxl_type3.c | 14 +++++++++++++- include/hw/cxl/cxl_device.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c index ada2108fac..a71bf1afeb 100644 --- a/hw/mem/cxl_type3.c +++ b/hw/mem/cxl_type3.c @@ -14,6 +14,12 @@ #include "sysemu/hostmem.h" #include "hw/cxl/cxl.h" +/* + * Null value of all Fs suggested by IEEE RA guidelines for use of + * EU, OUI and CID + */ +#define UI64_NULL ~(0ULL) + static void build_dvsecs(CXLType3Dev *ct3d) { CXLComponentState *cxl_cstate = &ct3d->cxl_cstate; @@ -149,7 +155,12 @@ static void ct3_realize(PCIDevice *pci_dev, Error **errp) pci_config_set_class(pci_conf, PCI_CLASS_MEMORY_CXL); pcie_endpoint_cap_init(pci_dev, 0x80); - cxl_cstate->dvsec_offset = 0x100; + if (ct3d->sn != UI64_NULL) { + pcie_dev_ser_num_init(pci_dev, 0x100, ct3d->sn); + cxl_cstate->dvsec_offset = 0x100 + 0x0c; + } else { + cxl_cstate->dvsec_offset = 0x100; + } ct3d->cxl_cstate.pdev = pci_dev; build_dvsecs(ct3d); @@ -275,6 +286,7 @@ static Property ct3_props[] = { HostMemoryBackend *), DEFINE_PROP_LINK("lsa", CXLType3Dev, lsa, TYPE_MEMORY_BACKEND, HostMemoryBackend *), + DEFINE_PROP_UINT64("sn", CXLType3Dev, sn, UI64_NULL), DEFINE_PROP_END_OF_LIST(), }; diff --git a/include/hw/cxl/cxl_device.h b/include/hw/cxl/cxl_device.h index 1e141b6621..e4d221cdb3 100644 --- a/include/hw/cxl/cxl_device.h +++ b/include/hw/cxl/cxl_device.h @@ -237,6 +237,7 @@ struct CXLType3Dev { /* Properties */ HostMemoryBackend *hostmem; HostMemoryBackend *lsa; + uint64_t sn; /* State */ AddressSpace hostmem_as; From 20ca47429e96df84e7b2e741f740bfce8a813fb2 Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Mon, 26 Sep 2022 11:32:06 -0400 Subject: [PATCH 0965/1020] Revert "intel_iommu: Fix irqchip / X2APIC configuration checks" It's true that when vcpus<=255 we don't require the length of 32bit APIC IDs. However here since we already have EIM=ON it means the hypervisor will declare the VM as x2apic supported (e.g. VT-d ECAP register will have EIM bit 4 set), so the guest should assume the APIC IDs are 32bits width even if vcpus<=255. In short, commit 77250171bdc breaks any simple cmdline that wants to boot a VM with >=9 but <=255 vcpus with: -device intel-iommu,intremap=on For anyone who does not want to enable x2apic, we can use eim=off in the intel-iommu parameters to skip enabling KVM x2apic. This partly reverts commit 77250171bdc02aee106083fd2a068147befa1a38, while keeping the valid bit on checking split irqchip, but revert the other change. One thing to mention is that this patch may break migration compatibility of such VM, however that's probably the best thing we can do, because the old behavior was simply wrong and not working for >8 vcpus. For <=8 vcpus, there could be a light guest ABI change (by enabling KVM x2apic after this patch), but logically it shouldn't affect the migration from working. Also, this is not the 1st commit to change x2apic behavior. Igor provided a full history of how this evolved for the past few years: https://lore.kernel.org/qemu-devel/20220922154617.57d1a1fb@redhat.com/ Relevant commits for reference: fb506e701e ("intel_iommu: reject broken EIM", 2016-10-17) c1bb5418e3 ("target/i386: Support up to 32768 CPUs without IRQ remapping", 2020-12-10) 77250171bd ("intel_iommu: Fix irqchip / X2APIC configuration checks", 2022-05-16) dc89f32d92 ("target/i386: Fix sanity check on max APIC ID / X2APIC enablement", 2022-05-16) We may want to have this for stable too (mostly for 7.1.0 only). Adding a fixes tag. Cc: David Woodhouse Cc: Claudio Fontana Cc: Igor Mammedov Fixes: 77250171bd ("intel_iommu: Fix irqchip / X2APIC configuration checks") Signed-off-by: Peter Xu Message-Id: <20220926153206.10881-1-peterx@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Igor Mammedov --- hw/i386/intel_iommu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 05d53a1aa9..6524c2ee32 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -3818,6 +3818,11 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) error_setg(errp, "eim=on requires accel=kvm,kernel-irqchip=split"); return false; } + if (!kvm_enable_x2apic()) { + error_setg(errp, "eim=on requires support on the KVM side" + "(X2APIC_API, first shipped in v4.7)"); + return false; + } } /* Currently only address widths supported are 39 and 48 bits */ From a5ebce385763447d2ab7cb572914713eedea764a Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 11 Aug 2022 08:24:39 -0400 Subject: [PATCH 0966/1020] qmp: add QMP command x-query-virtio This new command lists all the instances of VirtIODevices with their canonical QOM path and name. [Jonah: @virtio_list duplicates information that already exists in the QOM composition tree. However, extracting necessary information from this tree seems to be a bit convoluted. Instead, we still create our own list of realized virtio devices but use @qmp_qom_get with the device's canonical QOM path to confirm that the device exists and is realized. If the device exists but is actually not realized, then we remove it from our list (for synchronicity to the QOM composition tree). Also, the QMP command @x-query-virtio is redundant as @qom-list and @qom-get are sufficient to search '/machine/' for realized virtio devices. However, @x-query-virtio is much more convenient in listing realized virtio devices.] Signed-off-by: Laurent Vivier Signed-off-by: Jonah Palmer Message-Id: <1660220684-24909-2-git-send-email-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/meson.build | 2 ++ hw/virtio/virtio-stub.c | 14 ++++++++ hw/virtio/virtio.c | 44 ++++++++++++++++++++++++ include/hw/virtio/virtio.h | 1 + qapi/meson.build | 1 + qapi/qapi-schema.json | 1 + qapi/virtio.json | 68 ++++++++++++++++++++++++++++++++++++++ tests/qtest/qmp-cmd-test.c | 1 + 8 files changed, 132 insertions(+) create mode 100644 hw/virtio/virtio-stub.c create mode 100644 qapi/virtio.json diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build index c14e3db10a..dfed1e7af5 100644 --- a/hw/virtio/meson.build +++ b/hw/virtio/meson.build @@ -62,4 +62,6 @@ virtio_ss.add_all(when: 'CONFIG_VIRTIO_PCI', if_true: virtio_pci_ss) specific_ss.add_all(when: 'CONFIG_VIRTIO', if_true: virtio_ss) softmmu_ss.add_all(when: 'CONFIG_VIRTIO', if_true: softmmu_virtio_ss) softmmu_ss.add(when: 'CONFIG_VIRTIO', if_false: files('vhost-stub.c')) +softmmu_ss.add(when: 'CONFIG_VIRTIO', if_false: files('virtio-stub.c')) softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('vhost-stub.c')) +softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('virtio-stub.c')) diff --git a/hw/virtio/virtio-stub.c b/hw/virtio/virtio-stub.c new file mode 100644 index 0000000000..05a81edc92 --- /dev/null +++ b/hw/virtio/virtio-stub.c @@ -0,0 +1,14 @@ +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qapi/qapi-commands-virtio.h" + +static void *qmp_virtio_unsupported(Error **errp) +{ + error_setg(errp, "Virtio is disabled"); + return NULL; +} + +VirtioInfoList *qmp_x_query_virtio(Error **errp) +{ + return qmp_virtio_unsupported(errp); +} diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 2cc1d7d24a..4fc7c80d3f 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -13,12 +13,18 @@ #include "qemu/osdep.h" #include "qapi/error.h" +#include "qapi/qmp/qdict.h" +#include "qapi/qapi-commands-virtio.h" +#include "qapi/qapi-commands-qom.h" +#include "qapi/qapi-visit-virtio.h" +#include "qapi/qmp/qjson.h" #include "cpu.h" #include "trace.h" #include "qemu/error-report.h" #include "qemu/log.h" #include "qemu/main-loop.h" #include "qemu/module.h" +#include "qom/object_interfaces.h" #include "hw/virtio/virtio.h" #include "migration/qemu-file-types.h" #include "qemu/atomic.h" @@ -29,6 +35,9 @@ #include "sysemu/runstate.h" #include "standard-headers/linux/virtio_ids.h" +/* QAPI list of realized VirtIODevices */ +static QTAILQ_HEAD(, VirtIODevice) virtio_list; + /* * The alignment to use between consumer and producer parts of vring. * x86 pagesize again. This is the default, used by transports like PCI @@ -3707,6 +3716,7 @@ static void virtio_device_realize(DeviceState *dev, Error **errp) vdev->listener.commit = virtio_memory_listener_commit; vdev->listener.name = "virtio"; memory_listener_register(&vdev->listener, vdev->dma_as); + QTAILQ_INSERT_TAIL(&virtio_list, vdev, next); } static void virtio_device_unrealize(DeviceState *dev) @@ -3721,6 +3731,7 @@ static void virtio_device_unrealize(DeviceState *dev) vdc->unrealize(dev); } + QTAILQ_REMOVE(&virtio_list, vdev, next); g_free(vdev->bus_name); vdev->bus_name = NULL; } @@ -3894,6 +3905,8 @@ static void virtio_device_class_init(ObjectClass *klass, void *data) vdc->stop_ioeventfd = virtio_device_stop_ioeventfd_impl; vdc->legacy_features |= VIRTIO_LEGACY_FEATURES; + + QTAILQ_INIT(&virtio_list); } bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev) @@ -3904,6 +3917,37 @@ bool virtio_device_ioeventfd_enabled(VirtIODevice *vdev) return virtio_bus_ioeventfd_enabled(vbus); } +VirtioInfoList *qmp_x_query_virtio(Error **errp) +{ + VirtioInfoList *list = NULL; + VirtioInfoList *node; + VirtIODevice *vdev; + + QTAILQ_FOREACH(vdev, &virtio_list, next) { + DeviceState *dev = DEVICE(vdev); + Error *err = NULL; + QObject *obj = qmp_qom_get(dev->canonical_path, "realized", &err); + + if (err == NULL) { + GString *is_realized = qobject_to_json_pretty(obj, true); + /* virtio device is NOT realized, remove it from list */ + if (!strncmp(is_realized->str, "false", 4)) { + QTAILQ_REMOVE(&virtio_list, vdev, next); + } else { + node = g_new0(VirtioInfoList, 1); + node->value = g_new(VirtioInfo, 1); + node->value->path = g_strdup(dev->canonical_path); + node->value->name = g_strdup(vdev->name); + QAPI_LIST_PREPEND(list, node->value); + } + g_string_free(is_realized, true); + } + qobject_unref(obj); + } + + return list; +} + static const TypeInfo virtio_device_info = { .name = TYPE_VIRTIO_DEVICE, .parent = TYPE_DEVICE, diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index cecfb7c552..9eeb958e39 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -122,6 +122,7 @@ struct VirtIODevice bool use_guest_notifier_mask; AddressSpace *dma_as; QLIST_HEAD(, VirtQueue) *vector_queues; + QTAILQ_ENTRY(VirtIODevice) next; }; struct VirtioDeviceClass { diff --git a/qapi/meson.build b/qapi/meson.build index 840f1b0e19..9a36c15c04 100644 --- a/qapi/meson.build +++ b/qapi/meson.build @@ -49,6 +49,7 @@ qapi_all_modules = [ 'stats', 'trace', 'transaction', + 'virtio', 'yank', ] if have_system diff --git a/qapi/qapi-schema.json b/qapi/qapi-schema.json index 92d7ecc52c..f000b90744 100644 --- a/qapi/qapi-schema.json +++ b/qapi/qapi-schema.json @@ -94,3 +94,4 @@ { 'include': 'acpi.json' } { 'include': 'pci.json' } { 'include': 'stats.json' } +{ 'include': 'virtio.json' } diff --git a/qapi/virtio.json b/qapi/virtio.json new file mode 100644 index 0000000000..03896e423f --- /dev/null +++ b/qapi/virtio.json @@ -0,0 +1,68 @@ +# -*- Mode: Python -*- +# vim: filetype=python +# + +## +# = Virtio devices +## + +## +# @VirtioInfo: +# +# Basic information about a given VirtIODevice +# +# @path: The VirtIODevice's canonical QOM path +# +# @name: Name of the VirtIODevice +# +# Since: 7.1 +# +## +{ 'struct': 'VirtioInfo', + 'data': { 'path': 'str', + 'name': 'str' } } + +## +# @x-query-virtio: +# +# Returns a list of all realized VirtIODevices +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: List of gathered VirtIODevices +# +# Since: 7.1 +# +# Example: +# +# -> { "execute": "x-query-virtio" } +# <- { "return": [ +# { +# "name": "virtio-input", +# "path": "/machine/peripheral-anon/device[4]/virtio-backend" +# }, +# { +# "name": "virtio-crypto", +# "path": "/machine/peripheral/crypto0/virtio-backend" +# }, +# { +# "name": "virtio-scsi", +# "path": "/machine/peripheral-anon/device[2]/virtio-backend" +# }, +# { +# "name": "virtio-net", +# "path": "/machine/peripheral-anon/device[1]/virtio-backend" +# }, +# { +# "name": "virtio-serial", +# "path": "/machine/peripheral-anon/device[0]/virtio-backend" +# } +# ] +# } +# +## + +{ 'command': 'x-query-virtio', + 'returns': [ 'VirtioInfo' ], + 'features': [ 'unstable' ] } diff --git a/tests/qtest/qmp-cmd-test.c b/tests/qtest/qmp-cmd-test.c index af00712458..897e4e937b 100644 --- a/tests/qtest/qmp-cmd-test.c +++ b/tests/qtest/qmp-cmd-test.c @@ -103,6 +103,7 @@ static bool query_is_ignored(const char *cmd) "query-gic-capabilities", /* arm */ /* Success depends on target-specific build configuration: */ "query-pci", /* CONFIG_PCI */ + "x-query-virtio", /* CONFIG_VIRTIO */ /* Success depends on launching SEV guest */ "query-sev-launch-measure", /* Success depends on Host or Hypervisor SEV support */ From 90c066cd6822fb5e892e3daedd0a72b40e33dc30 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 11 Aug 2022 08:24:40 -0400 Subject: [PATCH 0967/1020] qmp: add QMP command x-query-virtio-status This new command shows the status of a VirtIODevice, including its corresponding vhost device's status (if active). Next patch will improve output by decoding feature bits, including vhost device's feature bits (backend, protocol, acked, and features). Also will decode status bits of a VirtIODevice. [Jonah: From patch v12; added a check to @virtio_device_find to ensure synchronicity between @virtio_list and the devices in the QOM composition tree.] Signed-off-by: Laurent Vivier Signed-off-by: Jonah Palmer Message-Id: <1660220684-24909-3-git-send-email-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-stub.c | 5 + hw/virtio/virtio.c | 104 +++++++++++++++++++ qapi/virtio.json | 222 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 331 insertions(+) diff --git a/hw/virtio/virtio-stub.c b/hw/virtio/virtio-stub.c index 05a81edc92..0b432e8de7 100644 --- a/hw/virtio/virtio-stub.c +++ b/hw/virtio/virtio-stub.c @@ -12,3 +12,8 @@ VirtioInfoList *qmp_x_query_virtio(Error **errp) { return qmp_virtio_unsupported(errp); } + +VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) +{ + return qmp_virtio_unsupported(errp); +} diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 4fc7c80d3f..696e19126a 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3948,6 +3948,110 @@ VirtioInfoList *qmp_x_query_virtio(Error **errp) return list; } +static VirtIODevice *virtio_device_find(const char *path) +{ + VirtIODevice *vdev; + + QTAILQ_FOREACH(vdev, &virtio_list, next) { + DeviceState *dev = DEVICE(vdev); + + if (strcmp(dev->canonical_path, path) != 0) { + continue; + } + + Error *err = NULL; + QObject *obj = qmp_qom_get(dev->canonical_path, "realized", &err); + if (err == NULL) { + GString *is_realized = qobject_to_json_pretty(obj, true); + /* virtio device is NOT realized, remove it from list */ + if (!strncmp(is_realized->str, "false", 4)) { + g_string_free(is_realized, true); + qobject_unref(obj); + QTAILQ_REMOVE(&virtio_list, vdev, next); + return NULL; + } + g_string_free(is_realized, true); + } else { + /* virtio device doesn't exist in QOM tree */ + QTAILQ_REMOVE(&virtio_list, vdev, next); + qobject_unref(obj); + return NULL; + } + /* device exists in QOM tree & is realized */ + qobject_unref(obj); + return vdev; + } + return NULL; +} + +VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) +{ + VirtIODevice *vdev; + VirtioStatus *status; + + vdev = virtio_device_find(path); + if (vdev == NULL) { + error_setg(errp, "Path %s is not a VirtIODevice", path); + return NULL; + } + + status = g_new0(VirtioStatus, 1); + status->name = g_strdup(vdev->name); + status->device_id = vdev->device_id; + status->vhost_started = vdev->vhost_started; + status->guest_features = vdev->guest_features; + status->host_features = vdev->host_features; + status->backend_features = vdev->backend_features; + + switch (vdev->device_endian) { + case VIRTIO_DEVICE_ENDIAN_LITTLE: + status->device_endian = g_strdup("little"); + break; + case VIRTIO_DEVICE_ENDIAN_BIG: + status->device_endian = g_strdup("big"); + break; + default: + status->device_endian = g_strdup("unknown"); + break; + } + + status->num_vqs = virtio_get_num_queues(vdev); + status->status = vdev->status; + status->isr = vdev->isr; + status->queue_sel = vdev->queue_sel; + status->vm_running = vdev->vm_running; + status->broken = vdev->broken; + status->disabled = vdev->disabled; + status->use_started = vdev->use_started; + status->started = vdev->started; + status->start_on_kick = vdev->start_on_kick; + status->disable_legacy_check = vdev->disable_legacy_check; + status->bus_name = g_strdup(vdev->bus_name); + status->use_guest_notifier_mask = vdev->use_guest_notifier_mask; + status->has_vhost_dev = vdev->vhost_started; + + if (vdev->vhost_started) { + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); + struct vhost_dev *hdev = vdc->get_vhost(vdev); + + status->vhost_dev = g_new0(VhostStatus, 1); + status->vhost_dev->n_mem_sections = hdev->n_mem_sections; + status->vhost_dev->n_tmp_sections = hdev->n_tmp_sections; + status->vhost_dev->nvqs = hdev->nvqs; + status->vhost_dev->vq_index = hdev->vq_index; + status->vhost_dev->features = hdev->features; + status->vhost_dev->acked_features = hdev->acked_features; + status->vhost_dev->backend_features = hdev->backend_features; + status->vhost_dev->protocol_features = hdev->protocol_features; + status->vhost_dev->max_queues = hdev->max_queues; + status->vhost_dev->backend_cap = hdev->backend_cap; + status->vhost_dev->log_enabled = hdev->log_enabled; + status->vhost_dev->log_size = hdev->log_size; + } + + return status; +} + static const TypeInfo virtio_device_info = { .name = TYPE_VIRTIO_DEVICE, .parent = TYPE_DEVICE, diff --git a/qapi/virtio.json b/qapi/virtio.json index 03896e423f..c86b3bc635 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -66,3 +66,225 @@ { 'command': 'x-query-virtio', 'returns': [ 'VirtioInfo' ], 'features': [ 'unstable' ] } + +## +# @VhostStatus: +# +# Information about a vhost device. This information will only be +# displayed if the vhost device is active. +# +# @n-mem-sections: vhost_dev n_mem_sections +# +# @n-tmp-sections: vhost_dev n_tmp_sections +# +# @nvqs: vhost_dev nvqs (number of virtqueues being used) +# +# @vq-index: vhost_dev vq_index +# +# @features: vhost_dev features +# +# @acked-features: vhost_dev acked_features +# +# @backend-features: vhost_dev backend_features +# +# @protocol-features: vhost_dev protocol_features +# +# @max-queues: vhost_dev max_queues +# +# @backend-cap: vhost_dev backend_cap +# +# @log-enabled: vhost_dev log_enabled flag +# +# @log-size: vhost_dev log_size +# +# Since: 7.1 +# +## + +{ 'struct': 'VhostStatus', + 'data': { 'n-mem-sections': 'int', + 'n-tmp-sections': 'int', + 'nvqs': 'uint32', + 'vq-index': 'int', + 'features': 'uint64', + 'acked-features': 'uint64', + 'backend-features': 'uint64', + 'protocol-features': 'uint64', + 'max-queues': 'uint64', + 'backend-cap': 'uint64', + 'log-enabled': 'bool', + 'log-size': 'uint64' } } + +## +# @VirtioStatus: +# +# Full status of the virtio device with most VirtIODevice members. +# Also includes the full status of the corresponding vhost device +# if the vhost device is active. +# +# @name: VirtIODevice name +# +# @device-id: VirtIODevice ID +# +# @vhost-started: VirtIODevice vhost_started flag +# +# @guest-features: VirtIODevice guest_features +# +# @host-features: VirtIODevice host_features +# +# @backend-features: VirtIODevice backend_features +# +# @device-endian: VirtIODevice device_endian +# +# @num-vqs: VirtIODevice virtqueue count. This is the number of active +# virtqueues being used by the VirtIODevice. +# +# @status: VirtIODevice configuration status (VirtioDeviceStatus) +# +# @isr: VirtIODevice ISR +# +# @queue-sel: VirtIODevice queue_sel +# +# @vm-running: VirtIODevice vm_running flag +# +# @broken: VirtIODevice broken flag +# +# @disabled: VirtIODevice disabled flag +# +# @use-started: VirtIODevice use_started flag +# +# @started: VirtIODevice started flag +# +# @start-on-kick: VirtIODevice start_on_kick flag +# +# @disable-legacy-check: VirtIODevice disabled_legacy_check flag +# +# @bus-name: VirtIODevice bus_name +# +# @use-guest-notifier-mask: VirtIODevice use_guest_notifier_mask flag +# +# @vhost-dev: Corresponding vhost device info for a given VirtIODevice. +# Present if the given VirtIODevice has an active vhost +# device. +# +# Since: 7.1 +# +## + +{ 'struct': 'VirtioStatus', + 'data': { 'name': 'str', + 'device-id': 'uint16', + 'vhost-started': 'bool', + 'device-endian': 'str', + 'guest-features': 'uint64', + 'host-features': 'uint64', + 'backend-features': 'uint64', + 'num-vqs': 'int', + 'status': 'uint8', + 'isr': 'uint8', + 'queue-sel': 'uint16', + 'vm-running': 'bool', + 'broken': 'bool', + 'disabled': 'bool', + 'use-started': 'bool', + 'started': 'bool', + 'start-on-kick': 'bool', + 'disable-legacy-check': 'bool', + 'bus-name': 'str', + 'use-guest-notifier-mask': 'bool', + '*vhost-dev': 'VhostStatus' } } + +## +# @x-query-virtio-status: +# +# Poll for a comprehensive status of a given virtio device +# +# @path: Canonical QOM path of the VirtIODevice +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: VirtioStatus of the virtio device +# +# Since: 7.1 +# +# Examples: +# +# 1. Poll for the status of virtio-crypto (no vhost-crypto active) +# +# -> { "execute": "x-query-virtio-status", +# "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend" } +# } +# <- { "return": { +# "device-endian": "little", +# "bus-name": "", +# "disable-legacy-check": false, +# "name": "virtio-crypto", +# "started": true, +# "device-id": 20, +# "backend-features": 0, +# "start-on-kick": false, +# "isr": 1, +# "broken": false, +# "status": 15, +# "num-vqs": 2, +# "guest-features": 5100273664, +# "host-features": 6325010432, +# "use-guest-notifier-mask": true, +# "vm-running": true, +# "queue-sel": 1, +# "disabled": false, +# "vhost-started": false, +# "use-started": true +# } +# } +# +# 2. Poll for the status of virtio-net (vhost-net is active) +# +# -> { "execute": "x-query-virtio-status", +# "arguments": { "path": "/machine/peripheral-anon/device[1]/virtio-backend" } +# } +# <- { "return": { +# "device-endian": "little", +# "bus-name": "", +# "disabled-legacy-check": false, +# "name": "virtio-net", +# "started": true, +# "device-id": 1, +# "vhost-dev": { +# "n-tmp-sections": 4, +# "n-mem-sections": 4, +# "max-queues": 1, +# "backend-cap": 2, +# "log-size": 0, +# "backend-features": 0, +# "nvqs": 2, +# "protocol-features": 0, +# "vq-index": 0, +# "log-enabled": false, +# "acked-features": 5100306432, +# "features": 13908344832 +# }, +# "backend-features": 6337593319, +# "start-on-kick": false, +# "isr": 1, +# "broken": false, +# "status": 15, +# "num-vqs": 3, +# "guest-features": 5111807911, +# "host-features": 6337593319, +# "use-guest-notifier-mask": true, +# "vm-running": true, +# "queue-sel": 2, +# "disabled": false, +# "vhost-started": true, +# "use-started": true +# } +# } +# +## + +{ 'command': 'x-query-virtio-status', + 'data': { 'path': 'str' }, + 'returns': 'VirtioStatus', + 'features': [ 'unstable' ] } From f3034ad71fcd0a6a58bc37830f182b307f089159 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 11 Aug 2022 08:24:41 -0400 Subject: [PATCH 0968/1020] qmp: decode feature & status bits in virtio-status Display feature names instead of bitmaps for host, guest, and backend for VirtIODevices. Display status names instead of bitmaps for VirtIODevices. Display feature names instead of bitmaps for backend, protocol, acked, and features (hdev->features) for vhost devices. Decode features according to device ID. Decode statuses according to configuration status bitmap (config_status_map). Decode vhost user protocol features according to vhost user protocol bitmap (vhost_user_protocol_map). Transport features are on the first line. Undecoded bits (if any) are stored in a separate field. [Jonah: Several changes made to this patch from prev. version (v14): - Moved all device features mappings to hw/virtio/virtio.c - Renamed device features mappings (less generic) - Generalized @FEATURE_ENTRY macro for all device mappings - Virtio device feature map definitions include descriptions of feature bits - Moved @VHOST_USER_F_PROTOCOL_FEATURES feature bit from transport feature map to vhost-user-supported device feature mappings (blk, fs, i2c, rng, net, gpu, input, scsi, vsock) - New feature bit added for virtio-vsock: @VIRTIO_VSOCK_F_SEQPACKET - New feature bit added for virtio-iommu: @VIRTIO_IOMMU_F_BYPASS_CONFIG - New feature bit added for virtio-mem: @VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE - New virtio transport feature bit added: @VIRTIO_F_IN_ORDER - Added device feature map definition for virtio-rng ] Signed-off-by: Laurent Vivier Signed-off-by: Jonah Palmer Message-Id: <1660220684-24909-4-git-send-email-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio.c | 643 ++++++++++++++++++++++++++++++++++++- include/hw/virtio/vhost.h | 3 + include/hw/virtio/virtio.h | 5 + qapi/virtio.json | 251 +++++++++++++-- 4 files changed, 874 insertions(+), 28 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 696e19126a..6c530567b0 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -34,10 +34,433 @@ #include "sysemu/dma.h" #include "sysemu/runstate.h" #include "standard-headers/linux/virtio_ids.h" +#include "standard-headers/linux/vhost_types.h" +#include "standard-headers/linux/virtio_blk.h" +#include "standard-headers/linux/virtio_console.h" +#include "standard-headers/linux/virtio_gpu.h" +#include "standard-headers/linux/virtio_net.h" +#include "standard-headers/linux/virtio_scsi.h" +#include "standard-headers/linux/virtio_i2c.h" +#include "standard-headers/linux/virtio_balloon.h" +#include "standard-headers/linux/virtio_iommu.h" +#include "standard-headers/linux/virtio_mem.h" +#include "standard-headers/linux/virtio_vsock.h" +#include CONFIG_DEVICES /* QAPI list of realized VirtIODevices */ static QTAILQ_HEAD(, VirtIODevice) virtio_list; +/* + * Maximum size of virtio device config space + */ +#define VHOST_USER_MAX_CONFIG_SIZE 256 + +#define FEATURE_ENTRY(name, desc) (qmp_virtio_feature_map_t) \ + { .virtio_bit = name, .feature_desc = desc } + +enum VhostUserProtocolFeature { + VHOST_USER_PROTOCOL_F_MQ = 0, + VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1, + VHOST_USER_PROTOCOL_F_RARP = 2, + VHOST_USER_PROTOCOL_F_REPLY_ACK = 3, + VHOST_USER_PROTOCOL_F_NET_MTU = 4, + VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, + VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6, + VHOST_USER_PROTOCOL_F_CRYPTO_SESSION = 7, + VHOST_USER_PROTOCOL_F_PAGEFAULT = 8, + VHOST_USER_PROTOCOL_F_CONFIG = 9, + VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD = 10, + VHOST_USER_PROTOCOL_F_HOST_NOTIFIER = 11, + VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD = 12, + VHOST_USER_PROTOCOL_F_RESET_DEVICE = 13, + VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS = 14, + VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS = 15, + VHOST_USER_PROTOCOL_F_MAX +}; + +/* Virtio transport features mapping */ +static qmp_virtio_feature_map_t virtio_transport_map[] = { + /* Virtio device transport features */ +#ifndef VIRTIO_CONFIG_NO_LEGACY + FEATURE_ENTRY(VIRTIO_F_NOTIFY_ON_EMPTY, \ + "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. " + "descs. on VQ"), + FEATURE_ENTRY(VIRTIO_F_ANY_LAYOUT, \ + "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts"), +#endif /* !VIRTIO_CONFIG_NO_LEGACY */ + FEATURE_ENTRY(VIRTIO_F_VERSION_1, \ + "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)"), + FEATURE_ENTRY(VIRTIO_F_IOMMU_PLATFORM, \ + "VIRTIO_F_IOMMU_PLATFORM: Device can be used on IOMMU platform"), + FEATURE_ENTRY(VIRTIO_F_RING_PACKED, \ + "VIRTIO_F_RING_PACKED: Device supports packed VQ layout"), + FEATURE_ENTRY(VIRTIO_F_IN_ORDER, \ + "VIRTIO_F_IN_ORDER: Device uses buffers in same order as made " + "available by driver"), + FEATURE_ENTRY(VIRTIO_F_ORDER_PLATFORM, \ + "VIRTIO_F_ORDER_PLATFORM: Memory accesses ordered by platform"), + FEATURE_ENTRY(VIRTIO_F_SR_IOV, \ + "VIRTIO_F_SR_IOV: Device supports single root I/O virtualization"), + /* Virtio ring transport features */ + FEATURE_ENTRY(VIRTIO_RING_F_INDIRECT_DESC, \ + "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported"), + FEATURE_ENTRY(VIRTIO_RING_F_EVENT_IDX, \ + "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled"), + { -1, "" } +}; + +/* Vhost-user protocol features mapping */ +static qmp_virtio_feature_map_t vhost_user_protocol_map[] = { + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_MQ, \ + "VHOST_USER_PROTOCOL_F_MQ: Multiqueue protocol supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_LOG_SHMFD, \ + "VHOST_USER_PROTOCOL_F_LOG_SHMFD: Shared log memory fd supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RARP, \ + "VHOST_USER_PROTOCOL_F_RARP: Vhost-user back-end RARP broadcasting " + "supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_REPLY_ACK, \ + "VHOST_USER_PROTOCOL_F_REPLY_ACK: Requested operation status ack. " + "supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_NET_MTU, \ + "VHOST_USER_PROTOCOL_F_NET_MTU: Expose host MTU to guest supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_REQ, \ + "VHOST_USER_PROTOCOL_F_SLAVE_REQ: Socket fd for back-end initiated " + "requests supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CROSS_ENDIAN, \ + "VHOST_USER_PROTOCOL_F_CROSS_ENDIAN: Endianness of VQs for legacy " + "devices supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CRYPTO_SESSION, \ + "VHOST_USER_PROTOCOL_F_CRYPTO_SESSION: Session creation for crypto " + "operations supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_PAGEFAULT, \ + "VHOST_USER_PROTOCOL_F_PAGEFAULT: Request servicing on userfaultfd " + "for accessed pages supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIG, \ + "VHOST_USER_PROTOCOL_F_CONFIG: Vhost-user messaging for virtio " + "device configuration space supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD, \ + "VHOST_USER_PROTOCOL_F_SLAVE_SEND_FD: Slave fd communication " + "channel supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_HOST_NOTIFIER, \ + "VHOST_USER_PROTOCOL_F_HOST_NOTIFIER: Host notifiers for specified " + "VQs supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD, \ + "VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD: Shared inflight I/O buffers " + "supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_RESET_DEVICE, \ + "VHOST_USER_PROTOCOL_F_RESET_DEVICE: Disabling all rings and " + "resetting internal device state supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS, \ + "VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS: In-band messaging " + "supported"), + FEATURE_ENTRY(VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS, \ + "VHOST_USER_PROTOCOL_F_CONFIGURE_MEM_SLOTS: Configuration for " + "memory slots supported"), + { -1, "" } +}; + +/* virtio device configuration statuses */ +static qmp_virtio_feature_map_t virtio_config_status_map[] = { + FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER_OK, \ + "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_FEATURES_OK, \ + "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_DRIVER, \ + "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_NEEDS_RESET, \ + "VIRTIO_CONFIG_S_NEEDS_RESET: Irrecoverable error, device needs " + "reset"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_FAILED, \ + "VIRTIO_CONFIG_S_FAILED: Error in guest, device failed"), + FEATURE_ENTRY(VIRTIO_CONFIG_S_ACKNOWLEDGE, \ + "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found"), + { -1, "" } +}; + +/* virtio-blk features mapping */ +qmp_virtio_feature_map_t virtio_blk_feature_map[] = { + FEATURE_ENTRY(VIRTIO_BLK_F_SIZE_MAX, \ + "VIRTIO_BLK_F_SIZE_MAX: Max segment size is size_max"), + FEATURE_ENTRY(VIRTIO_BLK_F_SEG_MAX, \ + "VIRTIO_BLK_F_SEG_MAX: Max segments in a request is seg_max"), + FEATURE_ENTRY(VIRTIO_BLK_F_GEOMETRY, \ + "VIRTIO_BLK_F_GEOMETRY: Legacy geometry available"), + FEATURE_ENTRY(VIRTIO_BLK_F_RO, \ + "VIRTIO_BLK_F_RO: Device is read-only"), + FEATURE_ENTRY(VIRTIO_BLK_F_BLK_SIZE, \ + "VIRTIO_BLK_F_BLK_SIZE: Block size of disk available"), + FEATURE_ENTRY(VIRTIO_BLK_F_TOPOLOGY, \ + "VIRTIO_BLK_F_TOPOLOGY: Topology information available"), + FEATURE_ENTRY(VIRTIO_BLK_F_MQ, \ + "VIRTIO_BLK_F_MQ: Multiqueue supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_DISCARD, \ + "VIRTIO_BLK_F_DISCARD: Discard command supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_WRITE_ZEROES, \ + "VIRTIO_BLK_F_WRITE_ZEROES: Write zeroes command supported"), +#ifndef VIRTIO_BLK_NO_LEGACY + FEATURE_ENTRY(VIRTIO_BLK_F_BARRIER, \ + "VIRTIO_BLK_F_BARRIER: Request barriers supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_SCSI, \ + "VIRTIO_BLK_F_SCSI: SCSI packet commands supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_FLUSH, \ + "VIRTIO_BLK_F_FLUSH: Flush command supported"), + FEATURE_ENTRY(VIRTIO_BLK_F_CONFIG_WCE, \ + "VIRTIO_BLK_F_CONFIG_WCE: Cache writeback and writethrough modes " + "supported"), +#endif /* !VIRTIO_BLK_NO_LEGACY */ + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + +/* virtio-serial features mapping */ +qmp_virtio_feature_map_t virtio_serial_feature_map[] = { + FEATURE_ENTRY(VIRTIO_CONSOLE_F_SIZE, \ + "VIRTIO_CONSOLE_F_SIZE: Host providing console size"), + FEATURE_ENTRY(VIRTIO_CONSOLE_F_MULTIPORT, \ + "VIRTIO_CONSOLE_F_MULTIPORT: Multiple ports for device supported"), + FEATURE_ENTRY(VIRTIO_CONSOLE_F_EMERG_WRITE, \ + "VIRTIO_CONSOLE_F_EMERG_WRITE: Emergency write supported"), + { -1, "" } +}; + +/* virtio-gpu features mapping */ +qmp_virtio_feature_map_t virtio_gpu_feature_map[] = { + FEATURE_ENTRY(VIRTIO_GPU_F_VIRGL, \ + "VIRTIO_GPU_F_VIRGL: Virgl 3D mode supported"), + FEATURE_ENTRY(VIRTIO_GPU_F_EDID, \ + "VIRTIO_GPU_F_EDID: EDID metadata supported"), + FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_UUID, \ + "VIRTIO_GPU_F_RESOURCE_UUID: Resource UUID assigning supported"), + FEATURE_ENTRY(VIRTIO_GPU_F_RESOURCE_BLOB, \ + "VIRTIO_GPU_F_RESOURCE_BLOB: Size-based blob resources supported"), + FEATURE_ENTRY(VIRTIO_GPU_F_CONTEXT_INIT, \ + "VIRTIO_GPU_F_CONTEXT_INIT: Context types and synchronization " + "timelines supported"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + +/* virtio-input features mapping */ +qmp_virtio_feature_map_t virtio_input_feature_map[] = { + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + +/* virtio-net features mapping */ +qmp_virtio_feature_map_t virtio_net_feature_map[] = { + FEATURE_ENTRY(VIRTIO_NET_F_CSUM, \ + "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum " + "supported"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_CSUM, \ + "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial " + "checksum supported"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_GUEST_OFFLOADS, \ + "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading " + "reconfig. supported"), + FEATURE_ENTRY(VIRTIO_NET_F_MTU, \ + "VIRTIO_NET_F_MTU: Device max MTU reporting supported"), + FEATURE_ENTRY(VIRTIO_NET_F_MAC, \ + "VIRTIO_NET_F_MAC: Device has given MAC address"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO4, \ + "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_TSO6, \ + "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ECN, \ + "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_UFO, \ + "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO"), + FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO4, \ + "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4"), + FEATURE_ENTRY(VIRTIO_NET_F_HOST_TSO6, \ + "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6"), + FEATURE_ENTRY(VIRTIO_NET_F_HOST_ECN, \ + "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN"), + FEATURE_ENTRY(VIRTIO_NET_F_HOST_UFO, \ + "VIRTIO_NET_F_HOST_UFO: Device can receive UFO"), + FEATURE_ENTRY(VIRTIO_NET_F_MRG_RXBUF, \ + "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers"), + FEATURE_ENTRY(VIRTIO_NET_F_STATUS, \ + "VIRTIO_NET_F_STATUS: Configuration status field available"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VQ, \ + "VIRTIO_NET_F_CTRL_VQ: Control channel available"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX, \ + "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_VLAN, \ + "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_RX_EXTRA, \ + "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported"), + FEATURE_ENTRY(VIRTIO_NET_F_GUEST_ANNOUNCE, \ + "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets " + "supported"), + FEATURE_ENTRY(VIRTIO_NET_F_MQ, \ + "VIRTIO_NET_F_MQ: Multiqueue with automatic receive steering " + "supported"), + FEATURE_ENTRY(VIRTIO_NET_F_CTRL_MAC_ADDR, \ + "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control " + "channel"), + FEATURE_ENTRY(VIRTIO_NET_F_HASH_REPORT, \ + "VIRTIO_NET_F_HASH_REPORT: Hash reporting supported"), + FEATURE_ENTRY(VIRTIO_NET_F_RSS, \ + "VIRTIO_NET_F_RSS: RSS RX steering supported"), + FEATURE_ENTRY(VIRTIO_NET_F_RSC_EXT, \ + "VIRTIO_NET_F_RSC_EXT: Extended coalescing info supported"), + FEATURE_ENTRY(VIRTIO_NET_F_STANDBY, \ + "VIRTIO_NET_F_STANDBY: Device acting as standby for primary " + "device with same MAC addr. supported"), + FEATURE_ENTRY(VIRTIO_NET_F_SPEED_DUPLEX, \ + "VIRTIO_NET_F_SPEED_DUPLEX: Device set linkspeed and duplex"), +#ifndef VIRTIO_NET_NO_LEGACY + FEATURE_ENTRY(VIRTIO_NET_F_GSO, \ + "VIRTIO_NET_F_GSO: Handling GSO-type packets supported"), +#endif /* !VIRTIO_NET_NO_LEGACY */ + FEATURE_ENTRY(VHOST_NET_F_VIRTIO_NET_HDR, \ + "VHOST_NET_F_VIRTIO_NET_HDR: Virtio-net headers for RX and TX " + "packets supported"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + +/* virtio-scsi features mapping */ +qmp_virtio_feature_map_t virtio_scsi_feature_map[] = { + FEATURE_ENTRY(VIRTIO_SCSI_F_INOUT, \ + "VIRTIO_SCSI_F_INOUT: Requests including read and writable data " + "buffers suppoted"), + FEATURE_ENTRY(VIRTIO_SCSI_F_HOTPLUG, \ + "VIRTIO_SCSI_F_HOTPLUG: Reporting and handling hot-plug events " + "supported"), + FEATURE_ENTRY(VIRTIO_SCSI_F_CHANGE, \ + "VIRTIO_SCSI_F_CHANGE: Reporting and handling LUN changes " + "supported"), + FEATURE_ENTRY(VIRTIO_SCSI_F_T10_PI, \ + "VIRTIO_SCSI_F_T10_PI: T10 info included in request header"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + +/* virtio/vhost-user-fs features mapping */ +qmp_virtio_feature_map_t virtio_fs_feature_map[] = { + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + +/* virtio/vhost-user-i2c features mapping */ +qmp_virtio_feature_map_t virtio_i2c_feature_map[] = { + FEATURE_ENTRY(VIRTIO_I2C_F_ZERO_LENGTH_REQUEST, \ + "VIRTIO_I2C_F_ZERO_LEGNTH_REQUEST: Zero length requests supported"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + +/* virtio/vhost-vsock features mapping */ +qmp_virtio_feature_map_t virtio_vsock_feature_map[] = { + FEATURE_ENTRY(VIRTIO_VSOCK_F_SEQPACKET, \ + "VIRTIO_VSOCK_F_SEQPACKET: SOCK_SEQPACKET supported"), + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + +/* virtio-balloon features mapping */ +qmp_virtio_feature_map_t virtio_balloon_feature_map[] = { + FEATURE_ENTRY(VIRTIO_BALLOON_F_MUST_TELL_HOST, \ + "VIRTIO_BALLOON_F_MUST_TELL_HOST: Tell host before reclaiming " + "pages"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_STATS_VQ, \ + "VIRTIO_BALLOON_F_STATS_VQ: Guest memory stats VQ available"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_DEFLATE_ON_OOM, \ + "VIRTIO_BALLOON_F_DEFLATE_ON_OOM: Deflate balloon when guest OOM"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_FREE_PAGE_HINT, \ + "VIRTIO_BALLOON_F_FREE_PAGE_HINT: VQ reporting free pages enabled"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_PAGE_POISON, \ + "VIRTIO_BALLOON_F_PAGE_POISON: Guest page poisoning enabled"), + FEATURE_ENTRY(VIRTIO_BALLOON_F_REPORTING, \ + "VIRTIO_BALLOON_F_REPORTING: Page reporting VQ enabled"), + { -1, "" } +}; + +/* virtio-crypto features mapping */ +qmp_virtio_feature_map_t virtio_crypto_feature_map[] = { + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + { -1, "" } +}; + +/* virtio-iommu features mapping */ +qmp_virtio_feature_map_t virtio_iommu_feature_map[] = { + FEATURE_ENTRY(VIRTIO_IOMMU_F_INPUT_RANGE, \ + "VIRTIO_IOMMU_F_INPUT_RANGE: Range of available virtual addrs. " + "available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_DOMAIN_RANGE, \ + "VIRTIO_IOMMU_F_DOMAIN_RANGE: Number of supported domains " + "available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_MAP_UNMAP, \ + "VIRTIO_IOMMU_F_MAP_UNMAP: Map and unmap requests available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS, \ + "VIRTIO_IOMMU_F_BYPASS: Endpoints not attached to domains are in " + "bypass mode"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_PROBE, \ + "VIRTIO_IOMMU_F_PROBE: Probe requests available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_MMIO, \ + "VIRTIO_IOMMU_F_MMIO: VIRTIO_IOMMU_MAP_F_MMIO flag available"), + FEATURE_ENTRY(VIRTIO_IOMMU_F_BYPASS_CONFIG, \ + "VIRTIO_IOMMU_F_BYPASS_CONFIG: Bypass field of IOMMU config " + "available"), + { -1, "" } +}; + +/* virtio-mem features mapping */ +qmp_virtio_feature_map_t virtio_mem_feature_map[] = { +#ifndef CONFIG_ACPI + FEATURE_ENTRY(VIRTIO_MEM_F_ACPI_PXM, \ + "VIRTIO_MEM_F_ACPI_PXM: node_id is an ACPI PXM and is valid"), +#endif /* !CONFIG_ACPI */ + FEATURE_ENTRY(VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE, \ + "VIRTIO_MEM_F_UNPLUGGED_INACCESSIBLE: Unplugged memory cannot be " + "accessed"), + { -1, "" } +}; + +/* virtio-rng features mapping */ +qmp_virtio_feature_map_t virtio_rng_feature_map[] = { + FEATURE_ENTRY(VHOST_F_LOG_ALL, \ + "VHOST_F_LOG_ALL: Logging write descriptors supported"), + FEATURE_ENTRY(VHOST_USER_F_PROTOCOL_FEATURES, \ + "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features " + "negotiation supported"), + { -1, "" } +}; + /* * The alignment to use between consumer and producer parts of vring. * x86 pagesize again. This is the default, used by transports like PCI @@ -3984,6 +4407,203 @@ static VirtIODevice *virtio_device_find(const char *path) return NULL; } +#define CONVERT_FEATURES(type, map, is_status, bitmap) \ + ({ \ + type *list = NULL; \ + type *node; \ + for (i = 0; map[i].virtio_bit != -1; i++) { \ + if (is_status) { \ + bit = map[i].virtio_bit; \ + } \ + else { \ + bit = 1ULL << map[i].virtio_bit; \ + } \ + if ((bitmap & bit) == 0) { \ + continue; \ + } \ + node = g_new0(type, 1); \ + node->value = g_strdup(map[i].feature_desc); \ + node->next = list; \ + list = node; \ + bitmap ^= bit; \ + } \ + list; \ + }) + +static VirtioDeviceStatus *qmp_decode_status(uint8_t bitmap) +{ + VirtioDeviceStatus *status; + uint8_t bit; + int i; + + status = g_new0(VirtioDeviceStatus, 1); + status->statuses = CONVERT_FEATURES(strList, virtio_config_status_map, + 1, bitmap); + status->has_unknown_statuses = bitmap != 0; + if (status->has_unknown_statuses) { + status->unknown_statuses = bitmap; + } + + return status; +} + +static VhostDeviceProtocols *qmp_decode_protocols(uint64_t bitmap) +{ + VhostDeviceProtocols *vhu_protocols; + uint64_t bit; + int i; + + vhu_protocols = g_new0(VhostDeviceProtocols, 1); + vhu_protocols->protocols = + CONVERT_FEATURES(strList, + vhost_user_protocol_map, 0, bitmap); + vhu_protocols->has_unknown_protocols = bitmap != 0; + if (vhu_protocols->has_unknown_protocols) { + vhu_protocols->unknown_protocols = bitmap; + } + + return vhu_protocols; +} + +static VirtioDeviceFeatures *qmp_decode_features(uint16_t device_id, + uint64_t bitmap) +{ + VirtioDeviceFeatures *features; + uint64_t bit; + int i; + + features = g_new0(VirtioDeviceFeatures, 1); + features->has_dev_features = true; + + /* transport features */ + features->transports = CONVERT_FEATURES(strList, virtio_transport_map, 0, + bitmap); + + /* device features */ + switch (device_id) { +#ifdef CONFIG_VIRTIO_SERIAL + case VIRTIO_ID_CONSOLE: + features->dev_features = + CONVERT_FEATURES(strList, virtio_serial_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_BLK + case VIRTIO_ID_BLOCK: + features->dev_features = + CONVERT_FEATURES(strList, virtio_blk_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_GPU + case VIRTIO_ID_GPU: + features->dev_features = + CONVERT_FEATURES(strList, virtio_gpu_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_NET + case VIRTIO_ID_NET: + features->dev_features = + CONVERT_FEATURES(strList, virtio_net_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_SCSI + case VIRTIO_ID_SCSI: + features->dev_features = + CONVERT_FEATURES(strList, virtio_scsi_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_BALLOON + case VIRTIO_ID_BALLOON: + features->dev_features = + CONVERT_FEATURES(strList, virtio_balloon_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_IOMMU + case VIRTIO_ID_IOMMU: + features->dev_features = + CONVERT_FEATURES(strList, virtio_iommu_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_INPUT + case VIRTIO_ID_INPUT: + features->dev_features = + CONVERT_FEATURES(strList, virtio_input_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VHOST_USER_FS + case VIRTIO_ID_FS: + features->dev_features = + CONVERT_FEATURES(strList, virtio_fs_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VHOST_VSOCK + case VIRTIO_ID_VSOCK: + features->dev_features = + CONVERT_FEATURES(strList, virtio_vsock_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_CRYPTO + case VIRTIO_ID_CRYPTO: + features->dev_features = + CONVERT_FEATURES(strList, virtio_crypto_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_MEM + case VIRTIO_ID_MEM: + features->dev_features = + CONVERT_FEATURES(strList, virtio_mem_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_I2C_ADAPTER + case VIRTIO_ID_I2C_ADAPTER: + features->dev_features = + CONVERT_FEATURES(strList, virtio_i2c_feature_map, 0, bitmap); + break; +#endif +#ifdef CONFIG_VIRTIO_RNG + case VIRTIO_ID_RNG: + features->dev_features = + CONVERT_FEATURES(strList, virtio_rng_feature_map, 0, bitmap); + break; +#endif + /* No features */ + case VIRTIO_ID_9P: + case VIRTIO_ID_PMEM: + case VIRTIO_ID_IOMEM: + case VIRTIO_ID_RPMSG: + case VIRTIO_ID_CLOCK: + case VIRTIO_ID_MAC80211_WLAN: + case VIRTIO_ID_MAC80211_HWSIM: + case VIRTIO_ID_RPROC_SERIAL: + case VIRTIO_ID_MEMORY_BALLOON: + case VIRTIO_ID_CAIF: + case VIRTIO_ID_SIGNAL_DIST: + case VIRTIO_ID_PSTORE: + case VIRTIO_ID_SOUND: + case VIRTIO_ID_BT: + case VIRTIO_ID_RPMB: + case VIRTIO_ID_VIDEO_ENCODER: + case VIRTIO_ID_VIDEO_DECODER: + case VIRTIO_ID_SCMI: + case VIRTIO_ID_NITRO_SEC_MOD: + case VIRTIO_ID_WATCHDOG: + case VIRTIO_ID_CAN: + case VIRTIO_ID_DMABUF: + case VIRTIO_ID_PARAM_SERV: + case VIRTIO_ID_AUDIO_POLICY: + case VIRTIO_ID_GPIO: + break; + default: + g_assert_not_reached(); + } + + features->has_unknown_dev_features = bitmap != 0; + if (features->has_unknown_dev_features) { + features->unknown_dev_features = bitmap; + } + + return features; +} + VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) { VirtIODevice *vdev; @@ -3999,9 +4619,12 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) status->name = g_strdup(vdev->name); status->device_id = vdev->device_id; status->vhost_started = vdev->vhost_started; - status->guest_features = vdev->guest_features; - status->host_features = vdev->host_features; - status->backend_features = vdev->backend_features; + status->guest_features = qmp_decode_features(vdev->device_id, + vdev->guest_features); + status->host_features = qmp_decode_features(vdev->device_id, + vdev->host_features); + status->backend_features = qmp_decode_features(vdev->device_id, + vdev->backend_features); switch (vdev->device_endian) { case VIRTIO_DEVICE_ENDIAN_LITTLE: @@ -4016,7 +4639,7 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) } status->num_vqs = virtio_get_num_queues(vdev); - status->status = vdev->status; + status->status = qmp_decode_status(vdev->status); status->isr = vdev->isr; status->queue_sel = vdev->queue_sel; status->vm_running = vdev->vm_running; @@ -4039,10 +4662,14 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) status->vhost_dev->n_tmp_sections = hdev->n_tmp_sections; status->vhost_dev->nvqs = hdev->nvqs; status->vhost_dev->vq_index = hdev->vq_index; - status->vhost_dev->features = hdev->features; - status->vhost_dev->acked_features = hdev->acked_features; - status->vhost_dev->backend_features = hdev->backend_features; - status->vhost_dev->protocol_features = hdev->protocol_features; + status->vhost_dev->features = + qmp_decode_features(vdev->device_id, hdev->features); + status->vhost_dev->acked_features = + qmp_decode_features(vdev->device_id, hdev->acked_features); + status->vhost_dev->backend_features = + qmp_decode_features(vdev->device_id, hdev->backend_features); + status->vhost_dev->protocol_features = + qmp_decode_protocols(hdev->protocol_features); status->vhost_dev->max_queues = hdev->max_queues; status->vhost_dev->backend_cap = hdev->backend_cap; status->vhost_dev->log_enabled = hdev->log_enabled; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 61b957e927..d7eb557885 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -5,6 +5,9 @@ #include "hw/virtio/virtio.h" #include "exec/memory.h" +#define VHOST_F_DEVICE_IOTLB 63 +#define VHOST_USER_F_PROTOCOL_FEATURES 30 + /* Generic structures common for any vhost based device. */ struct vhost_inflight { diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 9eeb958e39..f41b4a7e64 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -82,6 +82,11 @@ typedef struct VirtQueueElement #define TYPE_VIRTIO_DEVICE "virtio-device" OBJECT_DECLARE_TYPE(VirtIODevice, VirtioDeviceClass, VIRTIO_DEVICE) +typedef struct { + int virtio_bit; + const char *feature_desc; +} qmp_virtio_feature_map_t; + enum virtio_device_endian { VIRTIO_DEVICE_ENDIAN_UNKNOWN, VIRTIO_DEVICE_ENDIAN_LITTLE, diff --git a/qapi/virtio.json b/qapi/virtio.json index c86b3bc635..c9c8201e66 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -106,10 +106,10 @@ 'n-tmp-sections': 'int', 'nvqs': 'uint32', 'vq-index': 'int', - 'features': 'uint64', - 'acked-features': 'uint64', - 'backend-features': 'uint64', - 'protocol-features': 'uint64', + 'features': 'VirtioDeviceFeatures', + 'acked-features': 'VirtioDeviceFeatures', + 'backend-features': 'VirtioDeviceFeatures', + 'protocol-features': 'VhostDeviceProtocols', 'max-queues': 'uint64', 'backend-cap': 'uint64', 'log-enabled': 'bool', @@ -176,11 +176,11 @@ 'device-id': 'uint16', 'vhost-started': 'bool', 'device-endian': 'str', - 'guest-features': 'uint64', - 'host-features': 'uint64', - 'backend-features': 'uint64', + 'guest-features': 'VirtioDeviceFeatures', + 'host-features': 'VirtioDeviceFeatures', + 'backend-features': 'VirtioDeviceFeatures', 'num-vqs': 'int', - 'status': 'uint8', + 'status': 'VirtioDeviceStatus', 'isr': 'uint8', 'queue-sel': 'uint16', 'vm-running': 'bool', @@ -222,14 +222,41 @@ # "name": "virtio-crypto", # "started": true, # "device-id": 20, -# "backend-features": 0, +# "backend-features": { +# "transports": [], +# "dev-features": [] +# }, # "start-on-kick": false, # "isr": 1, # "broken": false, -# "status": 15, +# "status": { +# "statuses": [ +# "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found", +# "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device", +# "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete", +# "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready" +# ] +# }, # "num-vqs": 2, -# "guest-features": 5100273664, -# "host-features": 6325010432, +# "guest-features": { +# "dev-features": [], +# "transports": [ +# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", +# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", +# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)" +# ] +# }, +# "host-features": { +# "unknown-dev-features": 1073741824, +# "dev-features": [], +# "transports": [ +# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", +# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", +# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)", +# "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts", +# "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. descs. on VQ" +# ] +# }, # "use-guest-notifier-mask": true, # "vm-running": true, # "queue-sel": 1, @@ -257,22 +284,147 @@ # "max-queues": 1, # "backend-cap": 2, # "log-size": 0, -# "backend-features": 0, +# "backend-features": { +# "dev-features": [], +# "transports": [] +# }, # "nvqs": 2, -# "protocol-features": 0, +# "protocol-features": { +# "protocols": [] +# }, # "vq-index": 0, # "log-enabled": false, -# "acked-features": 5100306432, -# "features": 13908344832 +# "acked-features": { +# "dev-features": [ +# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers" +# ], +# "transports": [ +# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", +# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", +# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)" +# ] +# }, +# "features": { +# "dev-features": [ +# "VHOST_F_LOG_ALL: Logging write descriptors supported", +# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers" +# ], +# "transports": [ +# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", +# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", +# "VIRTIO_F_IOMMU_PLATFORM: Device can be used on IOMMU platform", +# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)", +# "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts", +# "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. descs. on VQ" +# ] +# } +# }, +# "backend-features": { +# "dev-features": [ +# "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features negotation supported", +# "VIRTIO_NET_F_GSO: Handling GSO-type packets supported", +# "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control channel", +# "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets supported", +# "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported", +# "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported", +# "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported", +# "VIRTIO_NET_F_CTRL_VQ: Control channel available", +# "VIRTIO_NET_F_STATUS: Configuration status field available", +# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers", +# "VIRTIO_NET_F_HOST_UFO: Device can receive UFO", +# "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN", +# "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6", +# "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4", +# "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO", +# "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN", +# "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6", +# "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4", +# "VIRTIO_NET_F_MAC: Device has given MAC address", +# "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading reconfig. supported", +# "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial checksum supported", +# "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum supported" +# ], +# "transports": [ +# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", +# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", +# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)", +# "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts", +# "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. descs. on VQ" +# ] # }, -# "backend-features": 6337593319, # "start-on-kick": false, # "isr": 1, # "broken": false, -# "status": 15, +# "status": { +# "statuses": [ +# "VIRTIO_CONFIG_S_ACKNOWLEDGE: Valid virtio device found", +# "VIRTIO_CONFIG_S_DRIVER: Guest OS compatible with device", +# "VIRTIO_CONFIG_S_FEATURES_OK: Feature negotiation complete", +# "VIRTIO_CONFIG_S_DRIVER_OK: Driver setup and ready" +# ] +# }, # "num-vqs": 3, -# "guest-features": 5111807911, -# "host-features": 6337593319, +# "guest-features": { +# "dev-features": [ +# "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control channel", +# "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets supported", +# "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported", +# "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported", +# "VIRTIO_NET_F_CTRL_VQ: Control channel available", +# "VIRTIO_NET_F_STATUS: Configuration status field available", +# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers", +# "VIRTIO_NET_F_HOST_UFO: Device can receive UFO", +# "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN", +# "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6", +# "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4", +# "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO", +# "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN", +# "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6", +# "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4", +# "VIRTIO_NET_F_MAC: Device has given MAC address", +# "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading reconfig. supported", +# "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial checksum supported", +# "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum supported" +# ], +# "transports": [ +# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", +# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", +# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)" +# ] +# }, +# "host-features": { +# "dev-features": [ +# "VHOST_USER_F_PROTOCOL_FEATURES: Vhost-user protocol features negotation supported", +# "VIRTIO_NET_F_GSO: Handling GSO-type packets supported", +# "VIRTIO_NET_F_CTRL_MAC_ADDR: MAC address set through control channel", +# "VIRTIO_NET_F_GUEST_ANNOUNCE: Driver sending gratuitous packets supported", +# "VIRTIO_NET_F_CTRL_RX_EXTRA: Extra RX mode control supported", +# "VIRTIO_NET_F_CTRL_VLAN: Control channel VLAN filtering supported", +# "VIRTIO_NET_F_CTRL_RX: Control channel RX mode supported", +# "VIRTIO_NET_F_CTRL_VQ: Control channel available", +# "VIRTIO_NET_F_STATUS: Configuration status field available", +# "VIRTIO_NET_F_MRG_RXBUF: Driver can merge receive buffers", +# "VIRTIO_NET_F_HOST_UFO: Device can receive UFO", +# "VIRTIO_NET_F_HOST_ECN: Device can receive TSO with ECN", +# "VIRTIO_NET_F_HOST_TSO6: Device can receive TSOv6", +# "VIRTIO_NET_F_HOST_TSO4: Device can receive TSOv4", +# "VIRTIO_NET_F_GUEST_UFO: Driver can receive UFO", +# "VIRTIO_NET_F_GUEST_ECN: Driver can receive TSO with ECN", +# "VIRTIO_NET_F_GUEST_TSO6: Driver can receive TSOv6", +# "VIRTIO_NET_F_GUEST_TSO4: Driver can receive TSOv4", +# "VIRTIO_NET_F_MAC: Device has given MAC address", +# "VIRTIO_NET_F_CTRL_GUEST_OFFLOADS: Control channel offloading reconfig. supported", +# "VIRTIO_NET_F_GUEST_CSUM: Driver handling packets with partial checksum supported", +# "VIRTIO_NET_F_CSUM: Device handling packets with partial checksum supported" +# ], +# "transports": [ +# "VIRTIO_RING_F_EVENT_IDX: Used & avail. event fields enabled", +# "VIRTIO_RING_F_INDIRECT_DESC: Indirect descriptors supported", +# "VIRTIO_F_VERSION_1: Device compliant for v1 spec (legacy)", +# "VIRTIO_F_ANY_LAYOUT: Device accepts arbitrary desc. layouts", +# "VIRTIO_F_NOTIFY_ON_EMPTY: Notify when device runs out of avail. descs. on VQ" +# ] +# }, # "use-guest-notifier-mask": true, # "vm-running": true, # "queue-sel": 2, @@ -288,3 +440,62 @@ 'data': { 'path': 'str' }, 'returns': 'VirtioStatus', 'features': [ 'unstable' ] } + +## +# @VirtioDeviceStatus: +# +# A structure defined to list the configuration statuses of a virtio +# device +# +# @statuses: List of decoded configuration statuses of the virtio +# device +# +# @unknown-statuses: Virtio device statuses bitmap that have not been decoded +# +# Since: 7.1 +## + +{ 'struct': 'VirtioDeviceStatus', + 'data': { 'statuses': [ 'str' ], + '*unknown-statuses': 'uint8' } } + +## +# @VhostDeviceProtocols: +# +# A structure defined to list the vhost user protocol features of a +# Vhost User device +# +# @protocols: List of decoded vhost user protocol features of a vhost +# user device +# +# @unknown-protocols: Vhost user device protocol features bitmap that +# have not been decoded +# +# Since: 7.1 +## + +{ 'struct': 'VhostDeviceProtocols', + 'data': { 'protocols': [ 'str' ], + '*unknown-protocols': 'uint64' } } + +## +# @VirtioDeviceFeatures: +# +# The common fields that apply to most Virtio devices. Some devices +# may not have their own device-specific features (e.g. virtio-rng). +# +# @transports: List of transport features of the virtio device +# +# @dev-features: List of device-specific features (if the device has +# unique features) +# +# @unknown-dev-features: Virtio device features bitmap that have not +# been decoded +# +# Since: 7.1 +## + +{ 'struct': 'VirtioDeviceFeatures', + 'data': { 'transports': [ 'str' ], + '*dev-features': [ 'str' ], + '*unknown-dev-features': 'uint64' } } From 07536ddda73a07bba6da8087fed5dd5a02320b11 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 11 Aug 2022 08:24:42 -0400 Subject: [PATCH 0969/1020] qmp: add QMP commands for virtio/vhost queue-status These new commands show the internal status of a VirtIODevice's VirtQueue and a vhost device's vhost_virtqueue (if active). Signed-off-by: Laurent Vivier Signed-off-by: Jonah Palmer Message-Id: <1660220684-24909-5-git-send-email-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-stub.c | 14 +++ hw/virtio/virtio.c | 103 ++++++++++++++++ qapi/virtio.json | 256 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 373 insertions(+) diff --git a/hw/virtio/virtio-stub.c b/hw/virtio/virtio-stub.c index 0b432e8de7..13e5f93652 100644 --- a/hw/virtio/virtio-stub.c +++ b/hw/virtio/virtio-stub.c @@ -17,3 +17,17 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) { return qmp_virtio_unsupported(errp); } + +VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path, + uint16_t queue, + Error **errp) +{ + return qmp_virtio_unsupported(errp); +} + +VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path, + uint16_t queue, + Error **errp) +{ + return qmp_virtio_unsupported(errp); +} diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 6c530567b0..da869e7b51 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -4679,6 +4679,109 @@ VirtioStatus *qmp_x_query_virtio_status(const char *path, Error **errp) return status; } +VirtVhostQueueStatus *qmp_x_query_virtio_vhost_queue_status(const char *path, + uint16_t queue, + Error **errp) +{ + VirtIODevice *vdev; + VirtVhostQueueStatus *status; + + vdev = virtio_device_find(path); + if (vdev == NULL) { + error_setg(errp, "Path %s is not a VirtIODevice", path); + return NULL; + } + + if (!vdev->vhost_started) { + error_setg(errp, "Error: vhost device has not started yet"); + return NULL; + } + + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); + struct vhost_dev *hdev = vdc->get_vhost(vdev); + + if (queue < hdev->vq_index || queue >= hdev->vq_index + hdev->nvqs) { + error_setg(errp, "Invalid vhost virtqueue number %d", queue); + return NULL; + } + + status = g_new0(VirtVhostQueueStatus, 1); + status->name = g_strdup(vdev->name); + status->kick = hdev->vqs[queue].kick; + status->call = hdev->vqs[queue].call; + status->desc = (uintptr_t)hdev->vqs[queue].desc; + status->avail = (uintptr_t)hdev->vqs[queue].avail; + status->used = (uintptr_t)hdev->vqs[queue].used; + status->num = hdev->vqs[queue].num; + status->desc_phys = hdev->vqs[queue].desc_phys; + status->desc_size = hdev->vqs[queue].desc_size; + status->avail_phys = hdev->vqs[queue].avail_phys; + status->avail_size = hdev->vqs[queue].avail_size; + status->used_phys = hdev->vqs[queue].used_phys; + status->used_size = hdev->vqs[queue].used_size; + + return status; +} + +VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path, + uint16_t queue, + Error **errp) +{ + VirtIODevice *vdev; + VirtQueueStatus *status; + + vdev = virtio_device_find(path); + if (vdev == NULL) { + error_setg(errp, "Path %s is not a VirtIODevice", path); + return NULL; + } + + if (queue >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, queue)) { + error_setg(errp, "Invalid virtqueue number %d", queue); + return NULL; + } + + status = g_new0(VirtQueueStatus, 1); + status->name = g_strdup(vdev->name); + status->queue_index = vdev->vq[queue].queue_index; + status->inuse = vdev->vq[queue].inuse; + status->vring_num = vdev->vq[queue].vring.num; + status->vring_num_default = vdev->vq[queue].vring.num_default; + status->vring_align = vdev->vq[queue].vring.align; + status->vring_desc = vdev->vq[queue].vring.desc; + status->vring_avail = vdev->vq[queue].vring.avail; + status->vring_used = vdev->vq[queue].vring.used; + status->used_idx = vdev->vq[queue].used_idx; + status->signalled_used = vdev->vq[queue].signalled_used; + status->signalled_used_valid = vdev->vq[queue].signalled_used_valid; + + if (vdev->vhost_started) { + VirtioDeviceClass *vdc = VIRTIO_DEVICE_GET_CLASS(vdev); + struct vhost_dev *hdev = vdc->get_vhost(vdev); + + /* check if vq index exists for vhost as well */ + if (queue >= hdev->vq_index && queue < hdev->vq_index + hdev->nvqs) { + status->has_last_avail_idx = true; + + int vhost_vq_index = + hdev->vhost_ops->vhost_get_vq_index(hdev, queue); + struct vhost_vring_state state = { + .index = vhost_vq_index, + }; + + status->last_avail_idx = + hdev->vhost_ops->vhost_get_vring_base(hdev, &state); + } + } else { + status->has_shadow_avail_idx = true; + status->has_last_avail_idx = true; + status->last_avail_idx = vdev->vq[queue].last_avail_idx; + status->shadow_avail_idx = vdev->vq[queue].shadow_avail_idx; + } + + return status; +} + static const TypeInfo virtio_device_info = { .name = TYPE_VIRTIO_DEVICE, .parent = TYPE_DEVICE, diff --git a/qapi/virtio.json b/qapi/virtio.json index c9c8201e66..d9050f3584 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -499,3 +499,259 @@ 'data': { 'transports': [ 'str' ], '*dev-features': [ 'str' ], '*unknown-dev-features': 'uint64' } } + +## +# @VirtQueueStatus: +# +# Information of a VirtIODevice VirtQueue, including most members of +# the VirtQueue data structure. +# +# @name: Name of the VirtIODevice that uses this VirtQueue +# +# @queue-index: VirtQueue queue_index +# +# @inuse: VirtQueue inuse +# +# @vring-num: VirtQueue vring.num +# +# @vring-num-default: VirtQueue vring.num_default +# +# @vring-align: VirtQueue vring.align +# +# @vring-desc: VirtQueue vring.desc (descriptor area) +# +# @vring-avail: VirtQueue vring.avail (driver area) +# +# @vring-used: VirtQueue vring.used (device area) +# +# @last-avail-idx: VirtQueue last_avail_idx or return of vhost_dev +# vhost_get_vring_base (if vhost active) +# +# @shadow-avail-idx: VirtQueue shadow_avail_idx +# +# @used-idx: VirtQueue used_idx +# +# @signalled-used: VirtQueue signalled_used +# +# @signalled-used-valid: VirtQueue signalled_used_valid flag +# +# Since: 7.1 +# +## + +{ 'struct': 'VirtQueueStatus', + 'data': { 'name': 'str', + 'queue-index': 'uint16', + 'inuse': 'uint32', + 'vring-num': 'uint32', + 'vring-num-default': 'uint32', + 'vring-align': 'uint32', + 'vring-desc': 'uint64', + 'vring-avail': 'uint64', + 'vring-used': 'uint64', + '*last-avail-idx': 'uint16', + '*shadow-avail-idx': 'uint16', + 'used-idx': 'uint16', + 'signalled-used': 'uint16', + 'signalled-used-valid': 'bool' } } + +## +# @x-query-virtio-queue-status: +# +# Return the status of a given VirtIODevice's VirtQueue +# +# @path: VirtIODevice canonical QOM path +# +# @queue: VirtQueue index to examine +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: VirtQueueStatus of the VirtQueue +# +# Notes: last_avail_idx will not be displayed in the case where +# the selected VirtIODevice has a running vhost device and +# the VirtIODevice VirtQueue index (queue) does not exist for +# the corresponding vhost device vhost_virtqueue. Also, +# shadow_avail_idx will not be displayed in the case where +# the selected VirtIODevice has a running vhost device. +# +# Since: 7.1 +# +# Examples: +# +# 1. Get VirtQueueStatus for virtio-vsock (vhost-vsock running) +# +# -> { "execute": "x-query-virtio-queue-status", +# "arguments": { "path": "/machine/peripheral/vsock0/virtio-backend", +# "queue": 1 } +# } +# <- { "return": { +# "signalled-used": 0, +# "inuse": 0, +# "name": "vhost-vsock", +# "vring-align": 4096, +# "vring-desc": 5217370112, +# "signalled-used-valid": false, +# "vring-num-default": 128, +# "vring-avail": 5217372160, +# "queue-index": 1, +# "last-avail-idx": 0, +# "vring-used": 5217372480, +# "used-idx": 0, +# "vring-num": 128 +# } +# } +# +# 2. Get VirtQueueStatus for virtio-serial (no vhost) +# +# -> { "execute": "x-query-virtio-queue-status", +# "arguments": { "path": "/machine/peripheral-anon/device[0]/virtio-backend", +# "queue": 20 } +# } +# <- { "return": { +# "signalled-used": 0, +# "inuse": 0, +# "name": "virtio-serial", +# "vring-align": 4096, +# "vring-desc": 5182074880, +# "signalled-used-valid": false, +# "vring-num-default": 128, +# "vring-avail": 5182076928, +# "queue-index": 20, +# "last-avail-idx": 0, +# "vring-used": 5182077248, +# "used-idx": 0, +# "shadow-avail-idx": 0, +# "vring-num": 128 +# } +# } +# +## + +{ 'command': 'x-query-virtio-queue-status', + 'data': { 'path': 'str', 'queue': 'uint16' }, + 'returns': 'VirtQueueStatus', + 'features': [ 'unstable' ] } + +## +# @VirtVhostQueueStatus: +# +# Information of a vhost device's vhost_virtqueue, including most +# members of the vhost_dev vhost_virtqueue data structure. +# +# @name: Name of the VirtIODevice that uses this vhost_virtqueue +# +# @kick: vhost_virtqueue kick +# +# @call: vhost_virtqueue call +# +# @desc: vhost_virtqueue desc +# +# @avail: vhost_virtqueue avail +# +# @used: vhost_virtqueue used +# +# @num: vhost_virtqueue num +# +# @desc-phys: vhost_virtqueue desc_phys (descriptor area phys. addr.) +# +# @desc-size: vhost_virtqueue desc_size +# +# @avail-phys: vhost_virtqueue avail_phys (driver area phys. addr.) +# +# @avail-size: vhost_virtqueue avail_size +# +# @used-phys: vhost_virtqueue used_phys (device area phys. addr.) +# +# @used-size: vhost_virtqueue used_size +# +# Since: 7.1 +# +## + +{ 'struct': 'VirtVhostQueueStatus', + 'data': { 'name': 'str', + 'kick': 'int', + 'call': 'int', + 'desc': 'uint64', + 'avail': 'uint64', + 'used': 'uint64', + 'num': 'int', + 'desc-phys': 'uint64', + 'desc-size': 'uint32', + 'avail-phys': 'uint64', + 'avail-size': 'uint32', + 'used-phys': 'uint64', + 'used-size': 'uint32' } } + +## +# @x-query-virtio-vhost-queue-status: +# +# Return information of a given vhost device's vhost_virtqueue +# +# @path: VirtIODevice canonical QOM path +# +# @queue: vhost_virtqueue index to examine +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: VirtVhostQueueStatus of the vhost_virtqueue +# +# Since: 7.1 +# +# Examples: +# +# 1. Get vhost_virtqueue status for vhost-crypto +# +# -> { "execute": "x-query-virtio-vhost-queue-status", +# "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend", +# "queue": 0 } +# } +# <- { "return": { +# "avail-phys": 5216124928, +# "name": "virtio-crypto", +# "used-phys": 5216127040, +# "avail-size": 2054, +# "desc-size": 16384, +# "used-size": 8198, +# "desc": 140141447430144, +# "num": 1024, +# "call": 0, +# "avail": 140141447446528, +# "desc-phys": 5216108544, +# "used": 140141447448640, +# "kick": 0 +# } +# } +# +# 2. Get vhost_virtqueue status for vhost-vsock +# +# -> { "execute": "x-query-virtio-vhost-queue-status", +# "arguments": { "path": "/machine/peripheral/vsock0/virtio-backend", +# "queue": 0 } +# } +# <- { "return": { +# "avail-phys": 5182261248, +# "name": "vhost-vsock", +# "used-phys": 5182261568, +# "avail-size": 262, +# "desc-size": 2048, +# "used-size": 1030, +# "desc": 140141413580800, +# "num": 128, +# "call": 0, +# "avail": 140141413582848, +# "desc-phys": 5182259200, +# "used": 140141413583168, +# "kick": 0 +# } +# } +# +## + +{ 'command': 'x-query-virtio-vhost-queue-status', + 'data': { 'path': 'str', 'queue': 'uint16' }, + 'returns': 'VirtVhostQueueStatus', + 'features': [ 'unstable' ] } From 1ee7bb5befaa24d2dfe8b32a437050209298c983 Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 11 Aug 2022 08:24:43 -0400 Subject: [PATCH 0970/1020] qmp: add QMP command x-query-virtio-queue-element This new command shows the information of a VirtQueue element. [Note: Up until v10 of this patch series, virtio.json had many (15+) enums defined (e.g. decoded device features, statuses, etc.). In v10 most of these enums were removed and replaced with string literals. By doing this we get (1) simpler schema, (2) smaller generated code, and (3) less maintenance burden for when new things are added (e.g. devices, device features, etc.).] Signed-off-by: Laurent Vivier Signed-off-by: Jonah Palmer Message-Id: <1660220684-24909-6-git-send-email-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/virtio/virtio-stub.c | 9 ++ hw/virtio/virtio.c | 154 +++++++++++++++++++++++++++++++ qapi/virtio.json | 197 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 360 insertions(+) diff --git a/hw/virtio/virtio-stub.c b/hw/virtio/virtio-stub.c index 13e5f93652..7ddb22cc5e 100644 --- a/hw/virtio/virtio-stub.c +++ b/hw/virtio/virtio-stub.c @@ -31,3 +31,12 @@ VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path, { return qmp_virtio_unsupported(errp); } + +VirtioQueueElement *qmp_x_query_virtio_queue_element(const char *path, + uint16_t queue, + bool has_index, + uint16_t index, + Error **errp) +{ + return qmp_virtio_unsupported(errp); +} diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index da869e7b51..808446b4c9 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -823,6 +823,19 @@ static inline void vring_used_write(VirtQueue *vq, VRingUsedElem *uelem, address_space_cache_invalidate(&caches->used, pa, sizeof(VRingUsedElem)); } +/* Called within rcu_read_lock(). */ +static inline uint16_t vring_used_flags(VirtQueue *vq) +{ + VRingMemoryRegionCaches *caches = vring_get_region_caches(vq); + hwaddr pa = offsetof(VRingUsed, flags); + + if (!caches) { + return 0; + } + + return virtio_lduw_phys_cached(vq->vdev, &caches->used, pa); +} + /* Called within rcu_read_lock(). */ static uint16_t vring_used_idx(VirtQueue *vq) { @@ -4782,6 +4795,147 @@ VirtQueueStatus *qmp_x_query_virtio_queue_status(const char *path, return status; } +static strList *qmp_decode_vring_desc_flags(uint16_t flags) +{ + strList *list = NULL; + strList *node; + int i; + + struct { + uint16_t flag; + const char *value; + } map[] = { + { VRING_DESC_F_NEXT, "next" }, + { VRING_DESC_F_WRITE, "write" }, + { VRING_DESC_F_INDIRECT, "indirect" }, + { 1 << VRING_PACKED_DESC_F_AVAIL, "avail" }, + { 1 << VRING_PACKED_DESC_F_USED, "used" }, + { 0, "" } + }; + + for (i = 0; map[i].flag; i++) { + if ((map[i].flag & flags) == 0) { + continue; + } + node = g_malloc0(sizeof(strList)); + node->value = g_strdup(map[i].value); + node->next = list; + list = node; + } + + return list; +} + +VirtioQueueElement *qmp_x_query_virtio_queue_element(const char *path, + uint16_t queue, + bool has_index, + uint16_t index, + Error **errp) +{ + VirtIODevice *vdev; + VirtQueue *vq; + VirtioQueueElement *element = NULL; + + vdev = virtio_device_find(path); + if (vdev == NULL) { + error_setg(errp, "Path %s is not a VirtIO device", path); + return NULL; + } + + if (queue >= VIRTIO_QUEUE_MAX || !virtio_queue_get_num(vdev, queue)) { + error_setg(errp, "Invalid virtqueue number %d", queue); + return NULL; + } + vq = &vdev->vq[queue]; + + if (virtio_vdev_has_feature(vdev, VIRTIO_F_RING_PACKED)) { + error_setg(errp, "Packed ring not supported"); + return NULL; + } else { + unsigned int head, i, max; + VRingMemoryRegionCaches *caches; + MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID; + MemoryRegionCache *desc_cache; + VRingDesc desc; + VirtioRingDescList *list = NULL; + VirtioRingDescList *node; + int rc; int ndescs; + + RCU_READ_LOCK_GUARD(); + + max = vq->vring.num; + + if (!has_index) { + head = vring_avail_ring(vq, vq->last_avail_idx % vq->vring.num); + } else { + head = vring_avail_ring(vq, index % vq->vring.num); + } + i = head; + + caches = vring_get_region_caches(vq); + if (!caches) { + error_setg(errp, "Region caches not initialized"); + return NULL; + } + if (caches->desc.len < max * sizeof(VRingDesc)) { + error_setg(errp, "Cannot map descriptor ring"); + return NULL; + } + + desc_cache = &caches->desc; + vring_split_desc_read(vdev, &desc, desc_cache, i); + if (desc.flags & VRING_DESC_F_INDIRECT) { + int64_t len; + len = address_space_cache_init(&indirect_desc_cache, vdev->dma_as, + desc.addr, desc.len, false); + desc_cache = &indirect_desc_cache; + if (len < desc.len) { + error_setg(errp, "Cannot map indirect buffer"); + goto done; + } + + max = desc.len / sizeof(VRingDesc); + i = 0; + vring_split_desc_read(vdev, &desc, desc_cache, i); + } + + element = g_new0(VirtioQueueElement, 1); + element->avail = g_new0(VirtioRingAvail, 1); + element->used = g_new0(VirtioRingUsed, 1); + element->name = g_strdup(vdev->name); + element->index = head; + element->avail->flags = vring_avail_flags(vq); + element->avail->idx = vring_avail_idx(vq); + element->avail->ring = head; + element->used->flags = vring_used_flags(vq); + element->used->idx = vring_used_idx(vq); + ndescs = 0; + + do { + /* A buggy driver may produce an infinite loop */ + if (ndescs >= max) { + break; + } + node = g_new0(VirtioRingDescList, 1); + node->value = g_new0(VirtioRingDesc, 1); + node->value->addr = desc.addr; + node->value->len = desc.len; + node->value->flags = qmp_decode_vring_desc_flags(desc.flags); + node->next = list; + list = node; + + ndescs++; + rc = virtqueue_split_read_next_desc(vdev, &desc, desc_cache, + max, &i); + } while (rc == VIRTQUEUE_READ_DESC_MORE); + element->descs = list; +done: + address_space_cache_destroy(&indirect_desc_cache); + } + + return element; +} + static const TypeInfo virtio_device_info = { .name = TYPE_VIRTIO_DEVICE, .parent = TYPE_DEVICE, diff --git a/qapi/virtio.json b/qapi/virtio.json index d9050f3584..e47a8fb2e0 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -755,3 +755,200 @@ 'data': { 'path': 'str', 'queue': 'uint16' }, 'returns': 'VirtVhostQueueStatus', 'features': [ 'unstable' ] } + +## +# @VirtioRingDesc: +# +# Information regarding the vring descriptor area +# +# @addr: Guest physical address of the descriptor area +# +# @len: Length of the descriptor area +# +# @flags: List of descriptor flags +# +# Since: 7.1 +# +## + +{ 'struct': 'VirtioRingDesc', + 'data': { 'addr': 'uint64', + 'len': 'uint32', + 'flags': [ 'str' ] } } + +## +# @VirtioRingAvail: +# +# Information regarding the avail vring (a.k.a. driver area) +# +# @flags: VRingAvail flags +# +# @idx: VRingAvail index +# +# @ring: VRingAvail ring[] entry at provided index +# +# Since: 7.1 +# +## + +{ 'struct': 'VirtioRingAvail', + 'data': { 'flags': 'uint16', + 'idx': 'uint16', + 'ring': 'uint16' } } + +## +# @VirtioRingUsed: +# +# Information regarding the used vring (a.k.a. device area) +# +# @flags: VRingUsed flags +# +# @idx: VRingUsed index +# +# Since: 7.1 +# +## + +{ 'struct': 'VirtioRingUsed', + 'data': { 'flags': 'uint16', + 'idx': 'uint16' } } + +## +# @VirtioQueueElement: +# +# Information regarding a VirtQueue's VirtQueueElement including +# descriptor, driver, and device areas +# +# @name: Name of the VirtIODevice that uses this VirtQueue +# +# @index: Index of the element in the queue +# +# @descs: List of descriptors (VirtioRingDesc) +# +# @avail: VRingAvail info +# +# @used: VRingUsed info +# +# Since: 7.1 +# +## + +{ 'struct': 'VirtioQueueElement', + 'data': { 'name': 'str', + 'index': 'uint32', + 'descs': [ 'VirtioRingDesc' ], + 'avail': 'VirtioRingAvail', + 'used': 'VirtioRingUsed' } } + +## +# @x-query-virtio-queue-element: +# +# Return the information about a VirtQueue's VirtQueueElement +# +# @path: VirtIODevice canonical QOM path +# +# @queue: VirtQueue index to examine +# +# @index: Index of the element in the queue +# (default: head of the queue) +# +# Features: +# @unstable: This command is meant for debugging. +# +# Returns: VirtioQueueElement information +# +# Since: 7.1 +# +# Examples: +# +# 1. Introspect on virtio-net's VirtQueue 0 at index 5 +# +# -> { "execute": "x-query-virtio-queue-element", +# "arguments": { "path": "/machine/peripheral-anon/device[1]/virtio-backend", +# "queue": 0, +# "index": 5 } +# } +# <- { "return": { +# "index": 5, +# "name": "virtio-net", +# "descs": [ +# { +# "flags": ["write"], +# "len": 1536, +# "addr": 5257305600 +# } +# ], +# "avail": { +# "idx": 256, +# "flags": 0, +# "ring": 5 +# }, +# "used": { +# "idx": 13, +# "flags": 0 +# } +# } +# } +# +# 2. Introspect on virtio-crypto's VirtQueue 1 at head +# +# -> { "execute": "x-query-virtio-queue-element", +# "arguments": { "path": "/machine/peripheral/crypto0/virtio-backend", +# "queue": 1 } +# } +# <- { "return": { +# "index": 0, +# "name": "virtio-crypto", +# "descs": [ +# { +# "flags": [], +# "len": 0, +# "addr": 8080268923184214134 +# } +# ], +# "avail": { +# "idx": 280, +# "flags": 0, +# "ring": 0 +# }, +# "used": { +# "idx": 280, +# "flags": 0 +# } +# } +# } +# +# 3. Introspect on virtio-scsi's VirtQueue 2 at head +# +# -> { "execute": "x-query-virtio-queue-element", +# "arguments": { "path": "/machine/peripheral-anon/device[2]/virtio-backend", +# "queue": 2 } +# } +# <- { "return": { +# "index": 19, +# "name": "virtio-scsi", +# "descs": [ +# { +# "flags": ["used", "indirect", "write"], +# "len": 4099327944, +# "addr": 12055409292258155293 +# } +# ], +# "avail": { +# "idx": 1147, +# "flags": 0, +# "ring": 19 +# }, +# "used": { +# "idx": 280, +# "flags": 0 +# } +# } +# } +# +## + +{ 'command': 'x-query-virtio-queue-element', + 'data': { 'path': 'str', 'queue': 'uint16', '*index': 'uint16' }, + 'returns': 'VirtioQueueElement', + 'features': [ 'unstable' ] } From 8a8287981d1169f534894d983ecfd3b70b71918b Mon Sep 17 00:00:00 2001 From: Laurent Vivier Date: Thu, 11 Aug 2022 08:24:44 -0400 Subject: [PATCH 0971/1020] hmp: add virtio commands This patch implements the HMP versions of the virtio QMP commands. [Jonah: Adjusted hmp monitor output format for features / statuses with their descriptions.] Signed-off-by: Laurent Vivier Signed-off-by: Jonah Palmer Message-Id: <1660220684-24909-7-git-send-email-jonah.palmer@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hmp-commands-info.hx | 70 ++++++++++ include/monitor/hmp.h | 5 + monitor/hmp-cmds.c | 310 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 385 insertions(+) diff --git a/hmp-commands-info.hx b/hmp-commands-info.hx index e012035541..754b1e8408 100644 --- a/hmp-commands-info.hx +++ b/hmp-commands-info.hx @@ -923,3 +923,73 @@ SRST ``stats`` Show runtime-collected statistics ERST + + { + .name = "virtio", + .args_type = "", + .params = "", + .help = "List all available virtio devices", + .cmd = hmp_virtio_query, + .flags = "p", + }, + +SRST + ``info virtio`` + List all available virtio devices +ERST + + { + .name = "virtio-status", + .args_type = "path:s", + .params = "path", + .help = "Display status of a given virtio device", + .cmd = hmp_virtio_status, + .flags = "p", + }, + +SRST + ``info virtio-status`` *path* + Display status of a given virtio device +ERST + + { + .name = "virtio-queue-status", + .args_type = "path:s,queue:i", + .params = "path queue", + .help = "Display status of a given virtio queue", + .cmd = hmp_virtio_queue_status, + .flags = "p", + }, + +SRST + ``info virtio-queue-status`` *path* *queue* + Display status of a given virtio queue +ERST + + { + .name = "virtio-vhost-queue-status", + .args_type = "path:s,queue:i", + .params = "path queue", + .help = "Display status of a given vhost queue", + .cmd = hmp_vhost_queue_status, + .flags = "p", + }, + +SRST + ``info virtio-vhost-queue-status`` *path* *queue* + Display status of a given vhost queue +ERST + + { + .name = "virtio-queue-element", + .args_type = "path:s,queue:i,index:i?", + .params = "path queue [index]", + .help = "Display element of a given virtio queue", + .cmd = hmp_virtio_queue_element, + .flags = "p", + }, + +SRST + ``info virtio-queue-element`` *path* *queue* [*index*] + Display element of a given virtio queue +ERST diff --git a/include/monitor/hmp.h b/include/monitor/hmp.h index a618eb1e4e..a9cf064ee8 100644 --- a/include/monitor/hmp.h +++ b/include/monitor/hmp.h @@ -95,6 +95,11 @@ void hmp_qom_list(Monitor *mon, const QDict *qdict); void hmp_qom_get(Monitor *mon, const QDict *qdict); void hmp_qom_set(Monitor *mon, const QDict *qdict); void hmp_info_qom_tree(Monitor *mon, const QDict *dict); +void hmp_virtio_query(Monitor *mon, const QDict *qdict); +void hmp_virtio_status(Monitor *mon, const QDict *qdict); +void hmp_virtio_queue_status(Monitor *mon, const QDict *qdict); +void hmp_vhost_queue_status(Monitor *mon, const QDict *qdict); +void hmp_virtio_queue_element(Monitor *mon, const QDict *qdict); void object_add_completion(ReadLineState *rs, int nb_args, const char *str); void object_del_completion(ReadLineState *rs, int nb_args, const char *str); void device_add_completion(ReadLineState *rs, int nb_args, const char *str); diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c index f90eea8d01..bab86c5537 100644 --- a/monitor/hmp-cmds.c +++ b/monitor/hmp-cmds.c @@ -43,6 +43,8 @@ #include "qapi/qapi-commands-stats.h" #include "qapi/qapi-commands-tpm.h" #include "qapi/qapi-commands-ui.h" +#include "qapi/qapi-commands-virtio.h" +#include "qapi/qapi-visit-virtio.h" #include "qapi/qapi-visit-net.h" #include "qapi/qapi-visit-migration.h" #include "qapi/qmp/qdict.h" @@ -2472,3 +2474,311 @@ exit: exit_no_print: error_free(err); } + +static void hmp_virtio_dump_protocols(Monitor *mon, + VhostDeviceProtocols *pcol) +{ + strList *pcol_list = pcol->protocols; + while (pcol_list) { + monitor_printf(mon, "\t%s", pcol_list->value); + pcol_list = pcol_list->next; + if (pcol_list != NULL) { + monitor_printf(mon, ",\n"); + } + } + monitor_printf(mon, "\n"); + if (pcol->has_unknown_protocols) { + monitor_printf(mon, " unknown-protocols(0x%016"PRIx64")\n", + pcol->unknown_protocols); + } +} + +static void hmp_virtio_dump_status(Monitor *mon, + VirtioDeviceStatus *status) +{ + strList *status_list = status->statuses; + while (status_list) { + monitor_printf(mon, "\t%s", status_list->value); + status_list = status_list->next; + if (status_list != NULL) { + monitor_printf(mon, ",\n"); + } + } + monitor_printf(mon, "\n"); + if (status->has_unknown_statuses) { + monitor_printf(mon, " unknown-statuses(0x%016"PRIx32")\n", + status->unknown_statuses); + } +} + +static void hmp_virtio_dump_features(Monitor *mon, + VirtioDeviceFeatures *features) +{ + strList *transport_list = features->transports; + while (transport_list) { + monitor_printf(mon, "\t%s", transport_list->value); + transport_list = transport_list->next; + if (transport_list != NULL) { + monitor_printf(mon, ",\n"); + } + } + + monitor_printf(mon, "\n"); + strList *list = features->dev_features; + if (list) { + while (list) { + monitor_printf(mon, "\t%s", list->value); + list = list->next; + if (list != NULL) { + monitor_printf(mon, ",\n"); + } + } + monitor_printf(mon, "\n"); + } + + if (features->has_unknown_dev_features) { + monitor_printf(mon, " unknown-features(0x%016"PRIx64")\n", + features->unknown_dev_features); + } +} + +void hmp_virtio_query(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + VirtioInfoList *list = qmp_x_query_virtio(&err); + VirtioInfoList *node; + + if (err != NULL) { + hmp_handle_error(mon, err); + return; + } + + if (list == NULL) { + monitor_printf(mon, "No VirtIO devices\n"); + return; + } + + node = list; + while (node) { + monitor_printf(mon, "%s [%s]\n", node->value->path, + node->value->name); + node = node->next; + } + qapi_free_VirtioInfoList(list); +} + +void hmp_virtio_status(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + const char *path = qdict_get_try_str(qdict, "path"); + VirtioStatus *s = qmp_x_query_virtio_status(path, &err); + + if (err != NULL) { + hmp_handle_error(mon, err); + return; + } + + monitor_printf(mon, "%s:\n", path); + monitor_printf(mon, " device_name: %s %s\n", + s->name, s->has_vhost_dev ? "(vhost)" : ""); + monitor_printf(mon, " device_id: %d\n", s->device_id); + monitor_printf(mon, " vhost_started: %s\n", + s->vhost_started ? "true" : "false"); + monitor_printf(mon, " bus_name: %s\n", s->bus_name); + monitor_printf(mon, " broken: %s\n", + s->broken ? "true" : "false"); + monitor_printf(mon, " disabled: %s\n", + s->disabled ? "true" : "false"); + monitor_printf(mon, " disable_legacy_check: %s\n", + s->disable_legacy_check ? "true" : "false"); + monitor_printf(mon, " started: %s\n", + s->started ? "true" : "false"); + monitor_printf(mon, " use_started: %s\n", + s->use_started ? "true" : "false"); + monitor_printf(mon, " start_on_kick: %s\n", + s->start_on_kick ? "true" : "false"); + monitor_printf(mon, " use_guest_notifier_mask: %s\n", + s->use_guest_notifier_mask ? "true" : "false"); + monitor_printf(mon, " vm_running: %s\n", + s->vm_running ? "true" : "false"); + monitor_printf(mon, " num_vqs: %"PRId64"\n", s->num_vqs); + monitor_printf(mon, " queue_sel: %d\n", + s->queue_sel); + monitor_printf(mon, " isr: %d\n", s->isr); + monitor_printf(mon, " endianness: %s\n", + s->device_endian); + monitor_printf(mon, " status:\n"); + hmp_virtio_dump_status(mon, s->status); + monitor_printf(mon, " Guest features:\n"); + hmp_virtio_dump_features(mon, s->guest_features); + monitor_printf(mon, " Host features:\n"); + hmp_virtio_dump_features(mon, s->host_features); + monitor_printf(mon, " Backend features:\n"); + hmp_virtio_dump_features(mon, s->backend_features); + + if (s->has_vhost_dev) { + monitor_printf(mon, " VHost:\n"); + monitor_printf(mon, " nvqs: %d\n", + s->vhost_dev->nvqs); + monitor_printf(mon, " vq_index: %"PRId64"\n", + s->vhost_dev->vq_index); + monitor_printf(mon, " max_queues: %"PRId64"\n", + s->vhost_dev->max_queues); + monitor_printf(mon, " n_mem_sections: %"PRId64"\n", + s->vhost_dev->n_mem_sections); + monitor_printf(mon, " n_tmp_sections: %"PRId64"\n", + s->vhost_dev->n_tmp_sections); + monitor_printf(mon, " backend_cap: %"PRId64"\n", + s->vhost_dev->backend_cap); + monitor_printf(mon, " log_enabled: %s\n", + s->vhost_dev->log_enabled ? "true" : "false"); + monitor_printf(mon, " log_size: %"PRId64"\n", + s->vhost_dev->log_size); + monitor_printf(mon, " Features:\n"); + hmp_virtio_dump_features(mon, s->vhost_dev->features); + monitor_printf(mon, " Acked features:\n"); + hmp_virtio_dump_features(mon, s->vhost_dev->acked_features); + monitor_printf(mon, " Backend features:\n"); + hmp_virtio_dump_features(mon, s->vhost_dev->backend_features); + monitor_printf(mon, " Protocol features:\n"); + hmp_virtio_dump_protocols(mon, s->vhost_dev->protocol_features); + } + + qapi_free_VirtioStatus(s); +} + +void hmp_vhost_queue_status(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + const char *path = qdict_get_try_str(qdict, "path"); + int queue = qdict_get_int(qdict, "queue"); + VirtVhostQueueStatus *s = + qmp_x_query_virtio_vhost_queue_status(path, queue, &err); + + if (err != NULL) { + hmp_handle_error(mon, err); + return; + } + + monitor_printf(mon, "%s:\n", path); + monitor_printf(mon, " device_name: %s (vhost)\n", + s->name); + monitor_printf(mon, " kick: %"PRId64"\n", s->kick); + monitor_printf(mon, " call: %"PRId64"\n", s->call); + monitor_printf(mon, " VRing:\n"); + monitor_printf(mon, " num: %"PRId64"\n", s->num); + monitor_printf(mon, " desc: 0x%016"PRIx64"\n", s->desc); + monitor_printf(mon, " desc_phys: 0x%016"PRIx64"\n", + s->desc_phys); + monitor_printf(mon, " desc_size: %"PRId32"\n", s->desc_size); + monitor_printf(mon, " avail: 0x%016"PRIx64"\n", s->avail); + monitor_printf(mon, " avail_phys: 0x%016"PRIx64"\n", + s->avail_phys); + monitor_printf(mon, " avail_size: %"PRId32"\n", s->avail_size); + monitor_printf(mon, " used: 0x%016"PRIx64"\n", s->used); + monitor_printf(mon, " used_phys: 0x%016"PRIx64"\n", + s->used_phys); + monitor_printf(mon, " used_size: %"PRId32"\n", s->used_size); + + qapi_free_VirtVhostQueueStatus(s); +} + +void hmp_virtio_queue_status(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + const char *path = qdict_get_try_str(qdict, "path"); + int queue = qdict_get_int(qdict, "queue"); + VirtQueueStatus *s = qmp_x_query_virtio_queue_status(path, queue, &err); + + if (err != NULL) { + hmp_handle_error(mon, err); + return; + } + + monitor_printf(mon, "%s:\n", path); + monitor_printf(mon, " device_name: %s\n", s->name); + monitor_printf(mon, " queue_index: %d\n", s->queue_index); + monitor_printf(mon, " inuse: %d\n", s->inuse); + monitor_printf(mon, " used_idx: %d\n", s->used_idx); + monitor_printf(mon, " signalled_used: %d\n", + s->signalled_used); + monitor_printf(mon, " signalled_used_valid: %s\n", + s->signalled_used_valid ? "true" : "false"); + if (s->has_last_avail_idx) { + monitor_printf(mon, " last_avail_idx: %d\n", + s->last_avail_idx); + } + if (s->has_shadow_avail_idx) { + monitor_printf(mon, " shadow_avail_idx: %d\n", + s->shadow_avail_idx); + } + monitor_printf(mon, " VRing:\n"); + monitor_printf(mon, " num: %"PRId32"\n", s->vring_num); + monitor_printf(mon, " num_default: %"PRId32"\n", + s->vring_num_default); + monitor_printf(mon, " align: %"PRId32"\n", + s->vring_align); + monitor_printf(mon, " desc: 0x%016"PRIx64"\n", + s->vring_desc); + monitor_printf(mon, " avail: 0x%016"PRIx64"\n", + s->vring_avail); + monitor_printf(mon, " used: 0x%016"PRIx64"\n", + s->vring_used); + + qapi_free_VirtQueueStatus(s); +} + +void hmp_virtio_queue_element(Monitor *mon, const QDict *qdict) +{ + Error *err = NULL; + const char *path = qdict_get_try_str(qdict, "path"); + int queue = qdict_get_int(qdict, "queue"); + int index = qdict_get_try_int(qdict, "index", -1); + VirtioQueueElement *e; + VirtioRingDescList *list; + + e = qmp_x_query_virtio_queue_element(path, queue, index != -1, + index, &err); + if (err != NULL) { + hmp_handle_error(mon, err); + return; + } + + monitor_printf(mon, "%s:\n", path); + monitor_printf(mon, " device_name: %s\n", e->name); + monitor_printf(mon, " index: %d\n", e->index); + monitor_printf(mon, " desc:\n"); + monitor_printf(mon, " descs:\n"); + + list = e->descs; + while (list) { + monitor_printf(mon, " addr 0x%"PRIx64" len %d", + list->value->addr, list->value->len); + if (list->value->flags) { + strList *flag = list->value->flags; + monitor_printf(mon, " ("); + while (flag) { + monitor_printf(mon, "%s", flag->value); + flag = flag->next; + if (flag) { + monitor_printf(mon, ", "); + } + } + monitor_printf(mon, ")"); + } + list = list->next; + if (list) { + monitor_printf(mon, ",\n"); + } + } + monitor_printf(mon, "\n"); + monitor_printf(mon, " avail:\n"); + monitor_printf(mon, " flags: %d\n", e->avail->flags); + monitor_printf(mon, " idx: %d\n", e->avail->idx); + monitor_printf(mon, " ring: %d\n", e->avail->ring); + monitor_printf(mon, " used:\n"); + monitor_printf(mon, " flags: %d\n", e->used->flags); + monitor_printf(mon, " idx: %d\n", e->used->idx); + + qapi_free_VirtioQueueElement(e); +} From 31e039e76d60fab708d49444ba40effc3037670d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Aug 2022 14:54:20 +0100 Subject: [PATCH 0972/1020] pci: Remove unused pci_get_*_by_mask() functions The helper functions pci_get_{byte,word,long,quad}_by_mask() were added in 2012 in commit c9f50cea70a1596. In the decade since we have never added a single use of them. The helpers clearly aren't that helpful, so drop them rather than carrying around dead code. Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-Id: <20220818135421.2515257-2-peter.maydell@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Paolo Bonzini --- include/hw/pci/pci.h | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index b54b6ef88f..c79144bc5e 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -692,13 +692,6 @@ pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg) pci_set_byte(config, (~mask & val) | (mask & rval)); } -static inline uint8_t -pci_get_byte_by_mask(uint8_t *config, uint8_t mask) -{ - uint8_t val = pci_get_byte(config); - return (val & mask) >> ctz32(mask); -} - static inline void pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg) { @@ -707,13 +700,6 @@ pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg) pci_set_word(config, (~mask & val) | (mask & rval)); } -static inline uint16_t -pci_get_word_by_mask(uint8_t *config, uint16_t mask) -{ - uint16_t val = pci_get_word(config); - return (val & mask) >> ctz32(mask); -} - static inline void pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg) { @@ -722,13 +708,6 @@ pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg) pci_set_long(config, (~mask & val) | (mask & rval)); } -static inline uint32_t -pci_get_long_by_mask(uint8_t *config, uint32_t mask) -{ - uint32_t val = pci_get_long(config); - return (val & mask) >> ctz32(mask); -} - static inline void pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg) { @@ -737,13 +716,6 @@ pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg) pci_set_quad(config, (~mask & val) | (mask & rval)); } -static inline uint64_t -pci_get_quad_by_mask(uint8_t *config, uint64_t mask) -{ - uint64_t val = pci_get_quad(config); - return (val & mask) >> ctz32(mask); -} - PCIDevice *pci_new_multifunction(int devfn, bool multifunction, const char *name); PCIDevice *pci_new(int devfn, const char *name); From 775cc426a986742fb252dd3aa865763c10cdb438 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Thu, 18 Aug 2022 14:54:21 +0100 Subject: [PATCH 0973/1020] pci: Sanity check mask argument to pci_set_*_by_mask() Coverity complains that in functions like pci_set_word_by_mask() we might end up shifting by more than 31 bits. This is true, but only if the caller passes in a zero mask. Help Coverity out by asserting that the mask argument is valid. Fixes: CID 1487168 Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-Id: <20220818135421.2515257-3-peter.maydell@linaro.org> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Paolo Bonzini --- include/hw/pci/pci.h | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index c79144bc5e..97937cc922 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -688,7 +688,10 @@ static inline void pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg) { uint8_t val = pci_get_byte(config); - uint8_t rval = reg << ctz32(mask); + uint8_t rval; + + assert(mask); + rval = reg << ctz32(mask); pci_set_byte(config, (~mask & val) | (mask & rval)); } @@ -696,7 +699,10 @@ static inline void pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg) { uint16_t val = pci_get_word(config); - uint16_t rval = reg << ctz32(mask); + uint16_t rval; + + assert(mask); + rval = reg << ctz32(mask); pci_set_word(config, (~mask & val) | (mask & rval)); } @@ -704,7 +710,10 @@ static inline void pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg) { uint32_t val = pci_get_long(config); - uint32_t rval = reg << ctz32(mask); + uint32_t rval; + + assert(mask); + rval = reg << ctz32(mask); pci_set_long(config, (~mask & val) | (mask & rval)); } @@ -712,7 +721,10 @@ static inline void pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg) { uint64_t val = pci_get_quad(config); - uint64_t rval = reg << ctz32(mask); + uint64_t rval; + + assert(mask); + rval = reg << ctz32(mask); pci_set_quad(config, (~mask & val) | (mask & rval)); } From fd8caa253c56ed126c09d3b9cc682753ff12218f Mon Sep 17 00:00:00 2001 From: Hal Martin Date: Fri, 12 Aug 2022 15:51:53 +0200 Subject: [PATCH 0974/1020] hw/smbios: support for type 8 (port connector) PATCH v1: add support for SMBIOS type 8 to qemu PATCH v2: incorporate patch v1 feedback and add smbios type=8 to qemu-options internal_reference: internal reference designator external_reference: external reference designator connector_type: hex value for port connector type (see SMBIOS 7.9.2) port_type: hex value for port type (see SMBIOS 7.9.3) After studying various vendor implementationsi (Dell, Lenovo, MSI), the value of internal connector type was hard-coded to 0x0 (None). Example usage: -smbios type=8,internal_reference=JUSB1,external_reference=USB1,connector_type=0x12,port_type=0x10 \ -smbios type=8,internal_reference=JAUD1,external_reference="Audio Jack",connector_type=0x1f,port_type=0x1d \ -smbios type=8,internal_reference=LAN,external_reference=Ethernet,connector_type=0x0b,port_type=0x1f \ -smbios type=8,internal_reference=PS2,external_reference=Mouse,connector_type=0x0f,port_type=0x0e \ -smbios type=8,internal_reference=PS2,external_reference=Keyboard,connector_type=0x0f,port_type=0x0d Signed-off-by: Hal Martin Message-Id: <20220812135153.17859-1-hal.martin@gmail.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/smbios/smbios.c | 63 ++++++++++++++++++++++++++++++++++++ include/hw/firmware/smbios.h | 10 ++++++ qemu-options.hx | 2 ++ 3 files changed, 75 insertions(+) diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c index 4c9f664830..51437ca09f 100644 --- a/hw/smbios/smbios.c +++ b/hw/smbios/smbios.c @@ -111,6 +111,13 @@ static struct { .processor_id = 0, }; +struct type8_instance { + const char *internal_reference, *external_reference; + uint8_t connector_type, port_type; + QTAILQ_ENTRY(type8_instance) next; +}; +static QTAILQ_HEAD(, type8_instance) type8 = QTAILQ_HEAD_INITIALIZER(type8); + static struct { size_t nvalues; char **values; @@ -337,6 +344,29 @@ static const QemuOptDesc qemu_smbios_type4_opts[] = { { /* end of list */ } }; +static const QemuOptDesc qemu_smbios_type8_opts[] = { + { + .name = "internal_reference", + .type = QEMU_OPT_STRING, + .help = "internal reference designator", + }, + { + .name = "external_reference", + .type = QEMU_OPT_STRING, + .help = "external reference designator", + }, + { + .name = "connector_type", + .type = QEMU_OPT_NUMBER, + .help = "connector type", + }, + { + .name = "port_type", + .type = QEMU_OPT_NUMBER, + .help = "port type", + }, +}; + static const QemuOptDesc qemu_smbios_type11_opts[] = { { .name = "value", @@ -718,6 +748,26 @@ static void smbios_build_type_4_table(MachineState *ms, unsigned instance) smbios_type4_count++; } +static void smbios_build_type_8_table(void) +{ + unsigned instance = 0; + struct type8_instance *t8; + + QTAILQ_FOREACH(t8, &type8, next) { + SMBIOS_BUILD_TABLE_PRE(8, T0_BASE + instance, true); + + SMBIOS_TABLE_SET_STR(8, internal_reference_str, t8->internal_reference); + SMBIOS_TABLE_SET_STR(8, external_reference_str, t8->external_reference); + /* most vendors seem to set this to None */ + t->internal_connector_type = 0x0; + t->external_connector_type = t8->connector_type; + t->port_type = t8->port_type; + + SMBIOS_BUILD_TABLE_POST; + instance++; + } +} + static void smbios_build_type_11_table(void) { char count_str[128]; @@ -1030,6 +1080,7 @@ void smbios_get_tables(MachineState *ms, smbios_build_type_4_table(ms, i); } + smbios_build_type_8_table(); smbios_build_type_11_table(); #define MAX_DIMM_SZ (16 * GiB) @@ -1348,6 +1399,18 @@ void smbios_entry_add(QemuOpts *opts, Error **errp) UINT16_MAX); } return; + case 8: + if (!qemu_opts_validate(opts, qemu_smbios_type8_opts, errp)) { + return; + } + struct type8_instance *t; + t = g_new0(struct type8_instance, 1); + save_opt(&t->internal_reference, opts, "internal_reference"); + save_opt(&t->external_reference, opts, "external_reference"); + t->connector_type = qemu_opt_get_number(opts, "connector_type", 0); + t->port_type = qemu_opt_get_number(opts, "port_type", 0); + QTAILQ_INSERT_TAIL(&type8, t, next); + return; case 11: if (!qemu_opts_validate(opts, qemu_smbios_type11_opts, errp)) { return; diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h index 4b7ad77a44..e7d386f7c8 100644 --- a/include/hw/firmware/smbios.h +++ b/include/hw/firmware/smbios.h @@ -189,6 +189,16 @@ struct smbios_type_4 { uint16_t processor_family2; } QEMU_PACKED; +/* SMBIOS type 8 - Port Connector Information */ +struct smbios_type_8 { + struct smbios_structure_header header; + uint8_t internal_reference_str; + uint8_t internal_connector_type; + uint8_t external_reference_str; + uint8_t external_connector_type; + uint8_t port_type; +} QEMU_PACKED; + /* SMBIOS type 11 - OEM strings */ struct smbios_type_11 { struct smbios_structure_header header; diff --git a/qemu-options.hx b/qemu-options.hx index 95b998a13b..c0bb74655c 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2572,6 +2572,8 @@ DEF("smbios", HAS_ARG, QEMU_OPTION_smbios, " [,asset=str][,part=str][,max-speed=%d][,current-speed=%d]\n" " [,processor-id=%d]\n" " specify SMBIOS type 4 fields\n" + "-smbios type=8[,external_reference=str][,internal_reference=str][,connector_type=%d][,port_type=%d]\n" + " specify SMBIOS type 8 fields\n" "-smbios type=11[,value=str][,path=filename]\n" " specify SMBIOS type 11 fields\n" "-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]\n" From beec628c80bbc9475b05f4465fe36188de14999e Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:34:59 -0400 Subject: [PATCH 0975/1020] tests: acpi: whitelist pc/q35 DSDT due to HPET AML move Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-2-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test-allowed-diff.h | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..a7aa428fab 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,33 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/pc/DSDT", +"tests/data/acpi/pc/DSDT.acpierst", +"tests/data/acpi/pc/DSDT.acpihmat", +"tests/data/acpi/pc/DSDT.bridge", +"tests/data/acpi/pc/DSDT.cphp", +"tests/data/acpi/pc/DSDT.dimmpxm", +"tests/data/acpi/pc/DSDT.hpbridge", +"tests/data/acpi/pc/DSDT.hpbrroot", +"tests/data/acpi/pc/DSDT.ipmikcs", +"tests/data/acpi/pc/DSDT.memhp", +"tests/data/acpi/pc/DSDT.numamem", +"tests/data/acpi/pc/DSDT.roothp", +"tests/data/acpi/q35/DSDT", +"tests/data/acpi/q35/DSDT.acpierst", +"tests/data/acpi/q35/DSDT.acpihmat", +"tests/data/acpi/q35/DSDT.applesmc", +"tests/data/acpi/q35/DSDT.bridge", +"tests/data/acpi/q35/DSDT.cphp", +"tests/data/acpi/q35/DSDT.cxl", +"tests/data/acpi/q35/DSDT.dimmpxm", +"tests/data/acpi/q35/DSDT.ipmibt", +"tests/data/acpi/q35/DSDT.ipmismbus", +"tests/data/acpi/q35/DSDT.ivrs", +"tests/data/acpi/q35/DSDT.memhp", +"tests/data/acpi/q35/DSDT.mmio64", +"tests/data/acpi/q35/DSDT.multi-bridge", +"tests/data/acpi/q35/DSDT.numamem", +"tests/data/acpi/q35/DSDT.pvpanic-isa", +"tests/data/acpi/q35/DSDT.tis.tpm12", +"tests/data/acpi/q35/DSDT.tis.tpm2", +"tests/data/acpi/q35/DSDT.viot", +"tests/data/acpi/q35/DSDT.xapic", From e05acc360e50626e253ddfa185561b0383a8f3e0 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:00 -0400 Subject: [PATCH 0976/1020] acpi: x86: deduplicate HPET AML building HPET AML doesn't depend on piix4 nor q35, move code buiding it to common scope to avoid duplication. Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-3-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 0355bd3dda..67b532f5a5 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -1467,9 +1467,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(sb_scope, dev); aml_append(dsdt, sb_scope); - if (misc->has_hpet) { - build_hpet_aml(dsdt); - } build_piix4_isa_bridge(dsdt); if (pm->pcihp_bridge_en || pm->pcihp_root_en) { build_x86_acpi_pci_hotplug(dsdt, pm->pcihp_io_base); @@ -1515,9 +1512,6 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, aml_append(dsdt, sb_scope); - if (misc->has_hpet) { - build_hpet_aml(dsdt); - } build_q35_isa_bridge(dsdt); if (pm->pcihp_bridge_en) { build_x86_acpi_pci_hotplug(dsdt, pm->pcihp_io_base); @@ -1528,6 +1522,10 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, } } + if (misc->has_hpet) { + build_hpet_aml(dsdt); + } + if (vmbus_bridge) { sb_scope = aml_scope("_SB"); aml_append(sb_scope, build_vmbus_device_aml(vmbus_bridge)); From 4609296d0601f24899863d5a6895f31be6e4b897 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:01 -0400 Subject: [PATCH 0977/1020] tests: acpi: update expected blobs after HPET move HPET AML moved after PCI host bridge description (no functional change) diff example for PC machine: @@ -54,47 +54,6 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) } } - Scope (_SB) - { - Device (HPET) - { - Name (_HID, EisaId ("PNP0103") /* HPET System Timer */) // _HID: Hardware ID - Name (_UID, Zero) // _UID: Unique ID - OperationRegion (HPTM, SystemMemory, 0xFED00000, 0x0400) - Field (HPTM, DWordAcc, Lock, Preserve) - { - VEND, 32, - PRD, 32 - } - - Method (_STA, 0, NotSerialized) // _STA: Status - { - Local0 = VEND /* \_SB_.HPET.VEND */ - Local1 = PRD /* \_SB_.HPET.PRD_ */ - Local0 >>= 0x10 - If (((Local0 == Zero) || (Local0 == 0xFFFF))) - { - Return (Zero) - } - - If (((Local1 == Zero) || (Local1 > 0x05F5E100))) - { - Return (Zero) - } - - Return (0x0F) - } - - Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings - { - Memory32Fixed (ReadOnly, - 0xFED00000, // Address Base - 0x00000400, // Address Length - ) - }) - } - } - Scope (_SB.PCI0) { Device (ISA) @@ -529,6 +488,47 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) } } + Scope (_SB) + { + Device (HPET) + { + Name (_HID, EisaId ("PNP0103") /* HPET System Timer */) // _HID: Hardware ID + Name (_UID, Zero) // _UID: Unique ID + OperationRegion (HPTM, SystemMemory, 0xFED00000, 0x0400) + Field (HPTM, DWordAcc, Lock, Preserve) + { + VEND, 32, + PRD, 32 + } + + Method (_STA, 0, NotSerialized) // _STA: Status + { + Local0 = VEND /* \_SB_.HPET.VEND */ + Local1 = PRD /* \_SB_.HPET.PRD_ */ + Local0 >>= 0x10 + If (((Local0 == Zero) || (Local0 == 0xFFFF))) + { + Return (Zero) + } + + If (((Local1 == Zero) || (Local1 > 0x05F5E100))) + { + Return (Zero) + } + + Return (0x0F) + } + + Name (_CRS, ResourceTemplate () // _CRS: Current Resource Settings + { + Memory32Fixed (ReadOnly, + 0xFED00000, // Address Base + 0x00000400, // Address Length + ) + }) + } + } + Scope (_SB) { Device (\_SB.PCI0.PRES) Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-4-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/pc/DSDT | Bin 5987 -> 5987 bytes tests/data/acpi/pc/DSDT.acpierst | Bin 5954 -> 5954 bytes tests/data/acpi/pc/DSDT.acpihmat | Bin 7312 -> 7312 bytes tests/data/acpi/pc/DSDT.bridge | Bin 8653 -> 8653 bytes tests/data/acpi/pc/DSDT.cphp | Bin 6451 -> 6451 bytes tests/data/acpi/pc/DSDT.dimmpxm | Bin 7641 -> 7641 bytes tests/data/acpi/pc/DSDT.hpbridge | Bin 5954 -> 5954 bytes tests/data/acpi/pc/DSDT.hpbrroot | Bin 3069 -> 3069 bytes tests/data/acpi/pc/DSDT.ipmikcs | Bin 6059 -> 6059 bytes tests/data/acpi/pc/DSDT.memhp | Bin 7346 -> 7346 bytes tests/data/acpi/pc/DSDT.numamem | Bin 5993 -> 5993 bytes tests/data/acpi/pc/DSDT.roothp | Bin 6195 -> 6195 bytes tests/data/acpi/q35/DSDT | Bin 8274 -> 8274 bytes tests/data/acpi/q35/DSDT.acpierst | Bin 8291 -> 8291 bytes tests/data/acpi/q35/DSDT.acpihmat | Bin 9599 -> 9599 bytes tests/data/acpi/q35/DSDT.applesmc | Bin 8320 -> 8320 bytes tests/data/acpi/q35/DSDT.bridge | Bin 10988 -> 10988 bytes tests/data/acpi/q35/DSDT.cphp | Bin 8738 -> 8738 bytes tests/data/acpi/q35/DSDT.cxl | Bin 9600 -> 9600 bytes tests/data/acpi/q35/DSDT.dimmpxm | Bin 9928 -> 9928 bytes tests/data/acpi/q35/DSDT.ipmibt | Bin 8349 -> 8349 bytes tests/data/acpi/q35/DSDT.ipmismbus | Bin 8363 -> 8363 bytes tests/data/acpi/q35/DSDT.ivrs | Bin 8291 -> 8291 bytes tests/data/acpi/q35/DSDT.memhp | Bin 9633 -> 9633 bytes tests/data/acpi/q35/DSDT.mmio64 | Bin 9404 -> 9404 bytes tests/data/acpi/q35/DSDT.multi-bridge | Bin 8568 -> 8568 bytes tests/data/acpi/q35/DSDT.numamem | Bin 8280 -> 8280 bytes tests/data/acpi/q35/DSDT.pvpanic-isa | Bin 8375 -> 8375 bytes tests/data/acpi/q35/DSDT.tis.tpm12 | Bin 8880 -> 8880 bytes tests/data/acpi/q35/DSDT.tis.tpm2 | Bin 8906 -> 8906 bytes tests/data/acpi/q35/DSDT.viot | Bin 9383 -> 9383 bytes tests/data/acpi/q35/DSDT.xapic | Bin 35637 -> 35637 bytes tests/qtest/bios-tables-test-allowed-diff.h | 32 -------------------- 33 files changed, 32 deletions(-) diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT index e80bef30317b5ef3bf0d2fb7aaabd6def109adb6..2d543fbf94e42f03814019c146b49f94e76bf15d 100644 GIT binary patch delta 19 bcmaE?_gHVjq|FM9s%#S{^=)=#mlFU0Q=bPS delta 19 bcmaE?_gHVjq{-Xa`Zi8dW!vn^E++s0T|@`I diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst index d5a2ca51652dfc3637a817bac4a02d6ff6dc8ac2..798349aa3f85e0803396471237e94604d00a1f90 100644 GIT binary patch delta 19 bcmX@4cSvu-q|FM9s%#S{^=)=#|H}^mP`C%a delta 19 bcmX@4cSvu-q{-Xa`Zi8dW!vn^{+AyBT3rZQ diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat index f86c743c4d64041c7fbd9999cc700e88416770b7..2b0fd3433b586fd7665b9a0b5b2f8bb3fcc09b44 100644 GIT binary patch delta 19 bcmbPWIl*$mq|FM9s%#S{^=)=#_Z9^JNyrAo delta 19 bcmbPWIl*$mq{-Xa`Zi8dW!vn^?kx%cQ*8%e diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge index 14ed0d995a9f6540deae5a25a7853ed4493a6e06..56398fc0147c9ab9d59947e24cddb08380b6a13e 100644 GIT binary patch delta 19 bcmX@>eAaowq|FM9s%#S{^=)=#?~nojR4)gV delta 19 bcmX@>eAaowq{-Xa`Zi8dW!vn^-XR45UDOCL diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp index c653302a84a42d063a74a22c6adf910beeba7c60..38cb47c675edb6d4797b008d2deae656739230ef 100644 GIT binary patch delta 19 bcmdmNwApCFq|FM9s%#S{^=)=#e{#Sg$q|FM9Y^)O}^=(#TyUq##Q{o4f delta 19 bcmew>{#Sg$q{%Z_`!-HuW8JLAcAXUfTxbXq diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs index f0d9e75841ea3d69fed9384e439bc4e94c7a4c4e..be7f22f1c29f25351bcb5620dcfe8f955bd083d7 100644 GIT binary patch delta 19 bcmZ3jzgmC7q|FM9xoi_B^=Hq)$ diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge index d820098355e0b79dc69d714817fe906064852f4d..40457ec74d272f4ce971b66a1b19a397ed9af770 100644 GIT binary patch delta 21 dcmaD8`X+QkDC6eGjEoYKLmB%vKau1R1ORKJ2zdYi delta 21 dcmaD8`X+QkDC6WX$-d2@jEoYSpGa~D0sv@b2m}BC diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/q35/DSDT.cphp index ac8456a43d54209d77917163b282954d7429b331..fe87e060d5cf41b20cf1a37928ed31ca9b15ed66 100644 GIT binary patch delta 21 dcmZ4FvdCpaDC6eGjEoYKLmB%vKasTK003R^2k-y@ delta 21 dcmZ4FvdCpaDC6WX$-d2@jEoYSpGewq003ID2YUbj diff --git a/tests/data/acpi/q35/DSDT.cxl b/tests/data/acpi/q35/DSDT.cxl index 369ae90196113ec666a4acec7bb7a93be5b60e75..82d7563a73f6b7a4ead15ca0933d0e57ae8be48e 100644 GIT binary patch delta 21 dcmZqhZt&g^%DDM4BcsIRP{zK^PbBAX0{~iS2pa$Z delta 21 ccmZqhZt&g^$~ZYpvTt)JBcsITCz5lx0aq&rrT_o{ diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/q35/DSDT.dimmpxm index bb0eadf869fe366fc139f8b0fd2ed811d3b16814..304c8229d81e333ed7564423cf50ad2b963b0a2e 100644 GIT binary patch delta 21 dcmX@%d%|}^DC6eGjEoYKLmB%vKaqUG0{~`*2>1X1 delta 21 dcmX@%d%|}^DC6WX$-d2@jEoYSpGZF80RUr22!j9s diff --git a/tests/data/acpi/q35/DSDT.ipmibt b/tests/data/acpi/q35/DSDT.ipmibt index bb258279506e78b50545f6f9030bd25afe433c29..b9a5ae240c62f29d952d94a280bc97d608b3c2e5 100644 GIT binary patch delta 21 dcmbR1IM;DQDC6eGj6M>RLmB%v>r3Ua0RUZm2c-Z2 delta 21 dcmbR1IM;DQDC6XXl6{*)8GR%+>r3Ua0RUX#2YUbj diff --git a/tests/data/acpi/q35/DSDT.ipmismbus b/tests/data/acpi/q35/DSDT.ipmismbus index 15000c357fdabf1bceef6f860bd35e9a33024927..a0eeae95c07fe3708509c3e652c3aeff9c21ac82 100644 GIT binary patch delta 21 dcmZ4OxY}_;DC6eGj8PJkLmB%v+e+oJ0RUir2i*Vw delta 21 dcmZ4OxY}_;DC6Yyl6{*)8KWdN+e+oJ0RUiO2f+XU diff --git a/tests/data/acpi/q35/DSDT.ivrs b/tests/data/acpi/q35/DSDT.ivrs index 0bc5de80652ae7328fdc07ccda34afff39ade56f..f768380c1c2aa8fcd6ff6bc1048e0ccd2037eb2c 100644 GIT binary patch delta 21 dcmaFt@YrEPDC6eGjEoYKLmB%vKas3w0|00M2&n)7 delta 21 dcmaFt@YrEPDC6WX$-d2@jEoYSpGelT0RUve2s8iy diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp index 663456fc0d3c71a51b541f5ab952e05c9dac01e6..b4a9f5a0fe5cf3b44ebe7659a2bf3687e1073482 100644 GIT binary patch delta 21 dcmZ4Jz0i9@DC6eGjEoYKLmB%vKat$a4FF%$2z~$n delta 21 dcmZ4Jz0i9@DC6WX$-d2@jEoYSpGfZI1^`@@2nhfH diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/q35/DSDT.mmio64 index 91afd01d598c7c2c733387dfb5140d0fcad54adb..3af5ef2ea473322d8697281d3a20f7282f3238ac 100644 GIT binary patch delta 21 dcmdnvxyN%uDC6eGjEoYKLmB%vKasq_1ps682+9Be delta 21 dcmdnvxyN%uDC6WX$-d2@jEoYSpGe-|0svsP2vq<8 diff --git a/tests/data/acpi/q35/DSDT.multi-bridge b/tests/data/acpi/q35/DSDT.multi-bridge index afde339a181628ae9153251eee026b437ab685bc..238668b95f33e831d66e2e2fa5e952f00ea7260b 100644 GIT binary patch delta 21 dcmez2^uuXGDC6eGjEoYKLmB%vKarfm4ghPv2<-p> delta 21 dcmez2^uuXGDC6WX$-d2@jEoYSpGZz&2LNb+2zUSh diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/q35/DSDT.numamem index e537669949a07adbaa4255021ea14bb4a9dc672f..37fa4c3a45b0d7db0d3d368df5e027e7e1acf9d2 100644 GIT binary patch delta 21 dcmccNaKm9kDC6eGjEoYKLmB%vKanh90{~_+2#5dx delta 21 dcmccNaKm9kDC6WX$-d2@jEoYSpGcOl0RUq32onGR diff --git a/tests/data/acpi/q35/DSDT.pvpanic-isa b/tests/data/acpi/q35/DSDT.pvpanic-isa index cc545b5d2505246d33f83d2482273968aa1be032..8705309748d1d7352c6623b32c28eab7fbbce2a4 100644 GIT binary patch delta 21 dcmdn)xZQC>DC6eGjA;^+LmB%vdrIZ80RUqX2n_%L delta 21 dcmdn)xZQC>DC6Yal6{*)8Pg;-drIZ80RUrR2mJs5 diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 b/tests/data/acpi/q35/DSDT.tis.tpm12 index a97d884c50485f848054c6ac95ecfa055ff59e5b..7408f03e4b571c352f9fdf2afc8718aa7b37da06 100644 GIT binary patch delta 21 dcmdnsy1{irDC6eGjKNZqLmB%vo5@tM0RUmA2k`&^ delta 21 dcmdnsy1{irDC6W6(tVpl8H1%Zo5@tM0RUlJ2hacj diff --git a/tests/data/acpi/q35/DSDT.tis.tpm2 b/tests/data/acpi/q35/DSDT.tis.tpm2 index 1f5392919b5ea69696b49ff13aab5c37d0615919..134c2fbccacd0e9383df094f9b4deb03b4e46abb 100644 GIT binary patch delta 21 dcmX@*ddhV}DC6eGjJZ;iLmB%w2g+2k0RU%32wDID delta 21 dcmX@*ddhV}DC6Wq(*2vm7;~gH2gp>h0RU&{2vYz6 diff --git a/tests/data/acpi/q35/DSDT.viot b/tests/data/acpi/q35/DSDT.viot index e20e4ee5e92e11ccf890a18fbdd78181c43f3b5c..be4a254e93a9cb360f42a25121c5fcefbd47480f 100644 GIT binary patch delta 21 dcmZ4Px!iL@DC6eGjEoYKLmB%vKao7l1pr`z2#Wv! delta 21 dcmZ4Px!iL@DC6WX$-d2@jEoYSpGY3&0svh^2o?YU diff --git a/tests/data/acpi/q35/DSDT.xapic b/tests/data/acpi/q35/DSDT.xapic index 3cab5956eee60363251a6fab0cc981bbbda64443..2327152da1b7d777c1f3da358ae5ae1406384d11 100644 GIT binary patch delta 23 fcmdlwjcMyNrVXKtn;$bWN=y!A?A!cAGO!Q;anuPq delta 23 fcmdlwjcMyNrVXKtlfxwYHit4YN^E{28CVDaZk7ne diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index a7aa428fab..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,33 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/pc/DSDT", -"tests/data/acpi/pc/DSDT.acpierst", -"tests/data/acpi/pc/DSDT.acpihmat", -"tests/data/acpi/pc/DSDT.bridge", -"tests/data/acpi/pc/DSDT.cphp", -"tests/data/acpi/pc/DSDT.dimmpxm", -"tests/data/acpi/pc/DSDT.hpbridge", -"tests/data/acpi/pc/DSDT.hpbrroot", -"tests/data/acpi/pc/DSDT.ipmikcs", -"tests/data/acpi/pc/DSDT.memhp", -"tests/data/acpi/pc/DSDT.numamem", -"tests/data/acpi/pc/DSDT.roothp", -"tests/data/acpi/q35/DSDT", -"tests/data/acpi/q35/DSDT.acpierst", -"tests/data/acpi/q35/DSDT.acpihmat", -"tests/data/acpi/q35/DSDT.applesmc", -"tests/data/acpi/q35/DSDT.bridge", -"tests/data/acpi/q35/DSDT.cphp", -"tests/data/acpi/q35/DSDT.cxl", -"tests/data/acpi/q35/DSDT.dimmpxm", -"tests/data/acpi/q35/DSDT.ipmibt", -"tests/data/acpi/q35/DSDT.ipmismbus", -"tests/data/acpi/q35/DSDT.ivrs", -"tests/data/acpi/q35/DSDT.memhp", -"tests/data/acpi/q35/DSDT.mmio64", -"tests/data/acpi/q35/DSDT.multi-bridge", -"tests/data/acpi/q35/DSDT.numamem", -"tests/data/acpi/q35/DSDT.pvpanic-isa", -"tests/data/acpi/q35/DSDT.tis.tpm12", -"tests/data/acpi/q35/DSDT.tis.tpm2", -"tests/data/acpi/q35/DSDT.viot", -"tests/data/acpi/q35/DSDT.xapic", From 31b5dd03908e0c78fe8ad27e10be630cec5d4a93 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:02 -0400 Subject: [PATCH 0978/1020] tests: acpi: whitelist pc/q35 DSDT due to HPET AML move Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-5-imammedo@redhat.com> --- tests/qtest/bios-tables-test-allowed-diff.h | 34 +++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..452145badd 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,35 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/pc/DSDT", +"tests/data/acpi/pc/DSDT.acpierst", +"tests/data/acpi/pc/DSDT.acpihmat", +"tests/data/acpi/pc/DSDT.bridge", +"tests/data/acpi/pc/DSDT.cphp", +"tests/data/acpi/pc/DSDT.dimmpxm", +"tests/data/acpi/pc/DSDT.hpbridge", +"tests/data/acpi/pc/DSDT.hpbrroot", +"tests/data/acpi/pc/DSDT.ipmikcs", +"tests/data/acpi/pc/DSDT.memhp", +"tests/data/acpi/pc/DSDT.numamem", +"tests/data/acpi/pc/DSDT.roothp", +"tests/data/acpi/q35/DSDT", +"tests/data/acpi/q35/DSDT.acpierst", +"tests/data/acpi/q35/DSDT.acpihmat", +"tests/data/acpi/q35/DSDT.applesmc", +"tests/data/acpi/q35/DSDT.bridge", +"tests/data/acpi/q35/DSDT.cphp", +"tests/data/acpi/q35/DSDT.cxl", +"tests/data/acpi/q35/DSDT.dimmpxm", +"tests/data/acpi/q35/DSDT.ipmibt", +"tests/data/acpi/q35/DSDT.ipmismbus", +"tests/data/acpi/q35/DSDT.ivrs", +"tests/data/acpi/q35/DSDT.memhp", +"tests/data/acpi/q35/DSDT.mmio64", +"tests/data/acpi/q35/DSDT.multi-bridge", +"tests/data/acpi/q35/DSDT.numamem", +"tests/data/acpi/q35/DSDT.pvpanic-isa", +"tests/data/acpi/q35/DSDT.tis.tpm12", +"tests/data/acpi/q35/DSDT.tis.tpm2", +"tests/data/acpi/q35/DSDT.viot", +"tests/data/acpi/q35/DSDT.xapic", +"tests/data/acpi/q35/DSDT.nohpet", +"tests/data/acpi/pc/DSDT.nohpet", From a12cf6923ce121633d877cf3ec53b2bcc85763ca Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:03 -0400 Subject: [PATCH 0979/1020] acpi: x86: refactor PDSM method to reduce nesting .., it will help with code readability and make easier to extend method in followup patches Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-6-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 139 ++++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 62 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 67b532f5a5..6d02eed12c 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -574,9 +574,12 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, Aml *aml_pci_device_dsm(void) { - Aml *method, *UUID, *ifctx, *ifctx1, *ifctx2, *ifctx3, *elsectx; - Aml *acpi_index = aml_local(0); + Aml *method, *UUID, *ifctx, *ifctx1; + Aml *ret = aml_local(0); + Aml *caps = aml_local(1); + Aml *acpi_index = aml_local(2); Aml *zero = aml_int(0); + Aml *one = aml_int(1); Aml *bnum = aml_arg(4); Aml *func = aml_arg(2); Aml *rev = aml_arg(1); @@ -584,73 +587,85 @@ Aml *aml_pci_device_dsm(void) method = aml_method("PDSM", 6, AML_SERIALIZED); - /* - * PCI Firmware Specification 3.1 - * 4.6. _DSM Definitions for PCI - */ - UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); - ifctx = aml_if(aml_equal(aml_arg(0), UUID)); + /* get supported functions */ + ifctx = aml_if(aml_equal(func, zero)); { - aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sunum), acpi_index)); - ifctx1 = aml_if(aml_equal(func, zero)); + uint8_t byte_list[1] = { 0 }; /* nothing supported yet */ + aml_append(ifctx, aml_store(aml_buffer(1, byte_list), ret)); + aml_append(ifctx, aml_store(zero, caps)); + + /* + * PCI Firmware Specification 3.1 + * 4.6. _DSM Definitions for PCI + */ + UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D"); + ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(0), UUID))); { - uint8_t byte_list[1]; + /* call is for unsupported UUID, bail out */ + aml_append(ifctx1, aml_return(ret)); + } + aml_append(ifctx, ifctx1); - ifctx2 = aml_if(aml_equal(rev, aml_int(2))); - { - /* - * advertise function 7 if device has acpi-index - * acpi_index values: - * 0: not present (default value) - * FFFFFFFF: not supported (old QEMU without PIDX reg) - * other: device's acpi-index - */ - ifctx3 = aml_if(aml_lnot( - aml_or(aml_equal(acpi_index, zero), - aml_equal(acpi_index, aml_int(0xFFFFFFFF)), NULL) - )); - { - byte_list[0] = - 1 /* have supported functions */ | - 1 << 7 /* support for function 7 */ - ; - aml_append(ifctx3, aml_return(aml_buffer(1, byte_list))); - } - aml_append(ifctx2, ifctx3); - } - aml_append(ifctx1, ifctx2); + ifctx1 = aml_if(aml_lless(rev, aml_int(2))); + { + /* call is for unsupported REV, bail out */ + aml_append(ifctx1, aml_return(ret)); + } + aml_append(ifctx, ifctx1); - byte_list[0] = 0; /* nothing supported */ - aml_append(ifctx1, aml_return(aml_buffer(1, byte_list))); - } - aml_append(ifctx, ifctx1); - elsectx = aml_else(); - /* - * PCI Firmware Specification 3.1 - * 4.6.7. _DSM for Naming a PCI or PCI Express Device Under - * Operating Systems - */ - ifctx1 = aml_if(aml_equal(func, aml_int(7))); - { - Aml *pkg = aml_package(2); - Aml *ret = aml_local(1); + aml_append(ifctx, + aml_store(aml_call2("AIDX", bnum, sunum), acpi_index)); + /* + * advertise function 7 if device has acpi-index + * acpi_index values: + * 0: not present (default value) + * FFFFFFFF: not supported (old QEMU without PIDX reg) + * other: device's acpi-index + */ + ifctx1 = aml_if(aml_lnot( + aml_or(aml_equal(acpi_index, zero), + aml_equal(acpi_index, aml_int(0xFFFFFFFF)), NULL) + )); + { + /* have supported functions */ + aml_append(ifctx1, aml_or(caps, one, caps)); + /* support for function 7 */ + aml_append(ifctx1, + aml_or(caps, aml_shiftleft(one, aml_int(7)), caps)); + } + aml_append(ifctx, ifctx1); - aml_append(pkg, zero); - /* - * optional, if not impl. should return null string - */ - aml_append(pkg, aml_string("%s", "")); - aml_append(ifctx1, aml_store(pkg, ret)); - /* - * update acpi-index to actual value - */ - aml_append(ifctx1, aml_store(acpi_index, aml_index(ret, zero))); - aml_append(ifctx1, aml_return(ret)); - } - aml_append(elsectx, ifctx1); - aml_append(ifctx, elsectx); + aml_append(ifctx, aml_store(caps, aml_index(ret, zero))); + aml_append(ifctx, aml_return(ret)); } aml_append(method, ifctx); + + /* handle specific functions requests */ + /* + * PCI Firmware Specification 3.1 + * 4.6.7. _DSM for Naming a PCI or PCI Express Device Under + * Operating Systems + */ + ifctx = aml_if(aml_equal(func, aml_int(7))); + { + Aml *pkg = aml_package(2); + + aml_append(pkg, zero); + /* + * optional, if not impl. should return null string + */ + aml_append(pkg, aml_string("%s", "")); + aml_append(ifctx, aml_store(pkg, ret)); + + aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sunum), acpi_index)); + /* + * update acpi-index to actual value + */ + aml_append(ifctx, aml_store(acpi_index, aml_index(ret, zero))); + } + + aml_append(method, ifctx); + aml_append(method, aml_return(ret)); return method; } From 467d099a2985c1e1bd41b234529d7f2262fd2e27 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:04 -0400 Subject: [PATCH 0980/1020] x86: acpi: _DSM: use Package to pass parameters Numer of possible arguments to pass to a method is limited in ACPI. The following patches will need to pass over more parameters to PDSM method, will hit that limit. Prepare for this by passing structure (Package) to method, which let us workaround arguments limitation. Pass to PDSM all standard arguments of _DSM as is, and pack custom parameters into Package that is passed as the last argument to PDSM. Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-7-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6d02eed12c..a19900c4e4 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -431,11 +431,17 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, ); aml_append(dev, method); method = aml_method("_DSM", 4, AML_SERIALIZED); - aml_append(method, - aml_return(aml_call6("PDSM", aml_arg(0), aml_arg(1), - aml_arg(2), aml_arg(3), - aml_name("BSEL"), aml_name("_SUN"))) - ); + { + Aml *params = aml_local(0); + Aml *pkg = aml_package(2); + aml_append(pkg, aml_name("BSEL")); + aml_append(pkg, aml_name("_SUN")); + aml_append(method, aml_store(pkg, params)); + aml_append(method, + aml_return(aml_call5("PDSM", aml_arg(0), aml_arg(1), + aml_arg(2), aml_arg(3), params)) + ); + } aml_append(dev, method); aml_append(parent_scope, dev); @@ -480,10 +486,17 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, */ aml_append(dev, aml_name_decl("ASUN", aml_int(slot))); method = aml_method("_DSM", 4, AML_SERIALIZED); - aml_append(method, aml_return( - aml_call6("PDSM", aml_arg(0), aml_arg(1), aml_arg(2), - aml_arg(3), aml_name("BSEL"), aml_name("ASUN")) - )); + { + Aml *params = aml_local(0); + Aml *pkg = aml_package(2); + aml_append(pkg, aml_name("BSEL")); + aml_append(pkg, aml_name("ASUN")); + aml_append(method, aml_store(pkg, params)); + aml_append(method, aml_return( + aml_call5("PDSM", aml_arg(0), aml_arg(1), aml_arg(2), + aml_arg(3), params) + )); + } aml_append(dev, method); } @@ -580,12 +593,13 @@ Aml *aml_pci_device_dsm(void) Aml *acpi_index = aml_local(2); Aml *zero = aml_int(0); Aml *one = aml_int(1); - Aml *bnum = aml_arg(4); Aml *func = aml_arg(2); Aml *rev = aml_arg(1); - Aml *sunum = aml_arg(5); + Aml *params = aml_arg(4); + Aml *bnum = aml_derefof(aml_index(params, aml_int(0))); + Aml *sunum = aml_derefof(aml_index(params, aml_int(1))); - method = aml_method("PDSM", 6, AML_SERIALIZED); + method = aml_method("PDSM", 5, AML_SERIALIZED); /* get supported functions */ ifctx = aml_if(aml_equal(func, zero)); @@ -662,10 +676,10 @@ Aml *aml_pci_device_dsm(void) * update acpi-index to actual value */ aml_append(ifctx, aml_store(acpi_index, aml_index(ret, zero))); + aml_append(ifctx, aml_return(ret)); } aml_append(method, ifctx); - aml_append(method, aml_return(ret)); return method; } From 13508ea26a978e1326424ca80a1346c0492f3813 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:05 -0400 Subject: [PATCH 0981/1020] tests: acpi: update expected blobs An intermediate blobs update to keep changes (last 2 patches) reviewable. Includes refactored PDSM that uses Package argument for custom parameters. ===== PDSM taking package as arguments Return (Local0) } - Method (PDSM, 6, Serialized) + Method (PDSM, 5, Serialized) { - If ((Arg0 == ToUUID ("e5c937d0-3553-4d7a-9117-ea4d19c3434d") /* Device Labeling Interface */)) + If ((Arg2 == Zero)) { - Local0 = AIDX (Arg4, Arg5) - If ((Arg2 == Zero)) - { - If ((Arg1 == 0x02)) + Local0 = Buffer (One) { - If (!((Local0 == Zero) | (Local0 == 0xFFFFFFFF))) - { - Return (Buffer (One) - { - 0x81 // . - }) - } + 0x00 // . } + Local1 = Zero + If ((Arg0 != ToUUID ("e5c937d0-3553-4d7a-9117-ea4d19c3434d") /* Device Labeling Interface */)) + { + Return (Local0) + } - Return (Buffer (One) - { - 0x00 // . - }) + If ((Arg1 < 0x02)) + { + Return (Local0) } - ElseIf ((Arg2 == 0x07)) + + Local2 = AIDX (DerefOf (Arg4 [Zero]), DerefOf (Arg4 [One] + )) + If (!((Local2 == Zero) | (Local2 == 0xFFFFFFFF))) { - Local1 = Package (0x02) - { - Zero, - "" - } - Local1 [Zero] = Local0 - Return (Local1) + Local1 |= One + Local1 |= (One << 0x07) } + + Local0 [Zero] = Local1 + Return (Local0) + } + + If ((Arg2 == 0x07)) + { + Local0 = Package (0x02) + { + Zero, + "" + } + Local2 = AIDX (DerefOf (Arg4 [Zero]), DerefOf (Arg4 [One] + )) + Local0 [Zero] = Local2 + Return (Local0) } } } ===== PCI slot using Package to pass arguments to _DSM Name (ASUN, Zero) Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method { - Return (PDSM (Arg0, Arg1, Arg2, Arg3, BSEL, ASUN)) + Local0 = Package (0x02) + { + BSEL, + ASUN + } + Return (PDSM (Arg0, Arg1, Arg2, Arg3, Local0)) } } ===== hotpluggable PCI slot using Package to pass arguments to _DSM Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method { - Return (PDSM (Arg0, Arg1, Arg2, Arg3, BSEL, _SUN)) + Local0 = Package (0x02) + { + BSEL, + _SUN + } + Return (PDSM (Arg0, Arg1, Arg2, Arg3, Local0)) } } Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-8-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/data/acpi/pc/DSDT | Bin 5987 -> 6219 bytes tests/data/acpi/pc/DSDT.acpierst | Bin 5954 -> 6186 bytes tests/data/acpi/pc/DSDT.acpihmat | Bin 7312 -> 7544 bytes tests/data/acpi/pc/DSDT.bridge | Bin 8653 -> 9078 bytes tests/data/acpi/pc/DSDT.cphp | Bin 6451 -> 6683 bytes tests/data/acpi/pc/DSDT.dimmpxm | Bin 7641 -> 7873 bytes tests/data/acpi/pc/DSDT.hpbridge | Bin 5954 -> 6186 bytes tests/data/acpi/pc/DSDT.ipmikcs | Bin 6059 -> 6291 bytes tests/data/acpi/pc/DSDT.memhp | Bin 7346 -> 7578 bytes tests/data/acpi/pc/DSDT.nohpet | Bin 5845 -> 6077 bytes tests/data/acpi/pc/DSDT.numamem | Bin 5993 -> 6225 bytes tests/data/acpi/pc/DSDT.roothp | Bin 6195 -> 6434 bytes tests/data/acpi/q35/DSDT | Bin 8274 -> 8320 bytes tests/data/acpi/q35/DSDT.acpierst | Bin 8291 -> 8337 bytes tests/data/acpi/q35/DSDT.acpihmat | Bin 9599 -> 9645 bytes tests/data/acpi/q35/DSDT.applesmc | Bin 8320 -> 8366 bytes tests/data/acpi/q35/DSDT.bridge | Bin 10988 -> 11227 bytes tests/data/acpi/q35/DSDT.cphp | Bin 8738 -> 8784 bytes tests/data/acpi/q35/DSDT.cxl | Bin 9600 -> 9646 bytes tests/data/acpi/q35/DSDT.dimmpxm | Bin 9928 -> 9974 bytes tests/data/acpi/q35/DSDT.ipmibt | Bin 8349 -> 8395 bytes tests/data/acpi/q35/DSDT.ipmismbus | Bin 8363 -> 8409 bytes tests/data/acpi/q35/DSDT.ivrs | Bin 8291 -> 8337 bytes tests/data/acpi/q35/DSDT.memhp | Bin 9633 -> 9679 bytes tests/data/acpi/q35/DSDT.mmio64 | Bin 9404 -> 9450 bytes tests/data/acpi/q35/DSDT.multi-bridge | Bin 8568 -> 8628 bytes tests/data/acpi/q35/DSDT.nohpet | Bin 8132 -> 8178 bytes tests/data/acpi/q35/DSDT.numamem | Bin 8280 -> 8326 bytes tests/data/acpi/q35/DSDT.pvpanic-isa | Bin 8375 -> 8421 bytes tests/data/acpi/q35/DSDT.tis.tpm12 | Bin 8880 -> 8926 bytes tests/data/acpi/q35/DSDT.tis.tpm2 | Bin 8906 -> 8952 bytes tests/data/acpi/q35/DSDT.viot | Bin 9383 -> 9429 bytes tests/data/acpi/q35/DSDT.xapic | Bin 35637 -> 35683 bytes tests/qtest/bios-tables-test-allowed-diff.h | 34 -------------------- 34 files changed, 34 deletions(-) diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT index 2d543fbf94e42f03814019c146b49f94e76bf15d..cb718f1a8a591b27ca841f70f40762562c15c837 100644 GIT binary patch delta 1368 zcmaE?ciMo!c zNf2e5-I-aqJe}6Y#0NXY3wW&waP~Cda0+(yVTf+h4>mA}=ZJT731Z-I3=Z{U5Rr`s zx}T>&h>HoN1SFQQ1mvZR%&hE$=q3l&$$h+HvUpWZ-pwn^=rQ>wua*L;x_ETcJSNNX z5uqrN7)48oQS_1+MY{Y%xT%mBMO%qc^phAxwgN=BsgW2(M~P9yDM*BMzQib+NQ|PZ z#3+&!BEn6v#3))wjH0K+DAE)r!cDovDB4JjqOZg#vJ@f0O|`@*I!KHnR#76X^Ay!W OD>Kl_g3Vo`HyHuis-Nrt delta 1204 zcmX?Y@K}$_CDa|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V&k^tF62!pa7#!-yAR-5urOt@-iV-HKoOJbr0O0lbDMzOW(#Xttx`o@O=EzJMl|1i{drh7r*p${L&BcOKXd1 OiQ~v)n~TJ5G6DeTf_9hy diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst index 798349aa3f85e0803396471237e94604d00a1f90..aebb29c2a4ae67b732bef3eb8e72c5665bb3a7b3 100644 GIT binary patch delta 1385 zcmX@4x5|LaCD!c zNf2e5-I-aqJRMiZ#0NXY3wW*yaP~Cda0+(yVTf+h4>mA}=ZJT731Z-I3=Z{U5Rr`s zx}T>&h>HoN1SFQQ1mvZR%&hE$=q3l&$$h+HvUpWZ-pwm(ZW3&00Wq0}fq@xfIu|n` z<2@#G@@XlcnjVkt29L?U#3-6bjH0W=D3atS!cDQnC|XF2qNl_t(i9-VO}WG<+DMF| zuf!;_6ePk;wZteoNQ@#@AtJ2vBt}s$F^Vn{qexVk2scF%qi8NMiXIZ9NL7RgH)Rr| aXe}{{J`$tIR8$MC5JAi4o6AJcFaiL0S)o4w delta 1221 zcmZ2wa7d5KCDNE4JQI_j;ACy49rZ430WQJ5d<%S7Cuax>a|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V&k^tF62!pa7#!-yAR-84*YHsM()004zr-(XER5IgTKv+-@kc(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ zk|4@9yE7Z|*E_9^i4S&)7w}pW;OuF@;S}uZ!w}u1A8cR{&k^tF62!pa7#!-yAR-$N zbU#ml5Em0j2}mqq3CK$snOWHh(M=Al!G=&BJPZs>5M5kM__c{}#7}-LB*o}4nN3(r z0o8_hbQ?S-dl93kj~GRlh*2aaLWG;5h*30;7)6hWQKTkHgqyO6QM8U2MW2XKWF|(0 zo2rOWw2v4?OyWdX=SGa8E@Bj&BSw*s1QBiuBSz6IViesYMv;;v5pGH&M$sx_6ul!x Wk&zS;ZYq<~lEqsVY~C()lMw*;SEL>Q delta 1186 zcmexiHNle0CDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li2{CR@xe~<0^VE!&YlJ$E?n^eK_LtULQD+_ zn&k^tF62!pa7#!-yAR-I4>ojRSi%5e7{M6EAVzeP(_{x>Eh#KI3#U6IVABK9)w?d4u0up_@xb`@Y-F4U-}4sX+CMZhDS(iiQ~v)o99d4 GWCQ>bvvXkp diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge index 56398fc0147c9ab9d59947e24cddb08380b6a13e..e04b5b2035fb665b1e75075d4c47776a51fa77e2 100644 GIT binary patch literal 9078 zcmeHL&2Jmm5ue8oY57P>OKNS&RvZ(ujW$hTla#-L0)@z3N}?rFYcA!aSfN~!3QD;K zvT&jzvS5^^3r8_fpeduGhaMP%xmw2_TcD@j{3oP`UV2Q?*q26~+2x~TN>1cG^&kOS z?aaLQo8QcPZ{DmlLo5I4902=oc1fK#65023HGw}20O+0m%K5+wm`yD^S7BjafSC`% z&O1J`lJa9MyFADK*s%U!Ss#63v8oNVC-Qc!YCqhvYCwb5Yc}WfB2QI}Y{hI%>S{hI zRp#?rB=d~>rAkICfmB(}Yaq{_x=4d)gxShZutMD*m1F!3LPE^M$45{;bilmu5*kI0Z6|%1E=C z+NU^-Xrq7Q!lh{^IPNz9&PL)%r}wC`294{G-2-D(ZEAL<>sUB^M80Kj5#L4(!K`F5Rk zV(lsq^wkEeei7|U85|UA*SW8+$@Vnb@=RMnRg^B;U<-&y}f;_mw&ez1PG{{DwxGF4w(=#}Xx=W`5p zV24HU*1|3B)a4x>F(3SpgbXB9Jy&FEzGyJDRJg^kx+du{%fPRy1q~~BoJRUpBe$5q z;aaAgP$HFlF)!IbO56_9D^Br8LN3W@M%DAlWGYEC+)F&D#MJWa&wL%;ZonfonM|%J z^Fw$wWJ2b-l}myBfl>fe+XvO?%m%A-x;<#15Ntk*HT{5PaiMD|g&>9XdXCs26e1jo zugsoQ4Yeq}A`D3_=H89_c5SHJZ1ss2Z?7^NYbtYU`C{aEZHsN!QDxcnL6=UzgGyYK z&iMAA7MG>|WhaEieiz+*X&+|C3t>=A>u%S#h$9tpWc9_h&XohhoSlKoSLc5FKw{8{ z^VaLs*yRFlXGefFsMC^TY;`krcyI@>kk5MU@H7`f>XK28yduqq@0J7jm^^!JFbSAD zoBIZ}H1zhM5{Dkj&U|>C_B0)206ZSJuca>SZae{nOgR?j5=hjcqIIN#afB%tXsq2< zCh_ph>A6ZSnTFnpr-MX$N?r<($*D-aGnKpw$~!nV1(b+>eQ?{MeF|MII!s?0A*+ge zQt764ThS!4DOTQMwT`e@}FSXig08`+$+EKlzCo`A= zw*ZoUU*&Uq->@5(Q~AEy`D%v+2;@dUpVv!nB3}l(>GrnK0#H9ds@7R~4bcHNLUjE5mvdz}T*>}}hm%zoBo~9tPlm^&I<4an+Ow)_m(*A6uuDcu%5kC~jC-;9hqD15vt)?3Q zQFlLvlz4^i9O~<7Oa(0iP^5Y(ra1&52B^oD3qKB#2Llg4^8q(G2t?hJi{$f))T7k< zV0CiijZ>Nyj5uLW<8lgk~fO4 zA_-0*ffVwHbVYFD0*QM?5}dF=xY30@B3%`nA_6Jm6-jW43Z$qwjIGq(pXI~#lDW1`870bR(c(cLa5j9b3 zoycYbn@$w2_k;in*zLI%i3DMhQNXsswIoOomKhZAa(69F637zWY=p6=dSu`o+mp!C z<-Uzv;a%6Wk*_O#8#%)}r)MK?SNk?{hqb?FBY)S(HoDnxnmClP3JV!KYLxfv*jGO? zup$aOeo~>lXO~IF>Llz5N8Yo~kc^c=*qe^LXLlmTQ!DJ)FF!KWeRhf(Pf*`ZacleR z6glqZzCA(mKKl&HxU>59Cdp`5&e8`P*o^+4O$&`Z|1#^nXxwkMuvI;73$Z8uzHbA} z({WpPv^*WRg-6TNaa(w_JRP@%N6XW3TX?iQ9k+$wnZr{{!R>?|A?K delta 2214 zcmez7cGj88CDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li2{CR@xe~<0^VE!&YlJ$E?n^eK_LtULQD+_ znv7 z8JStxAax*#=q4|gU_+={9tH*`hz?(b8 l8JQTJCXePblp+^WwmD56&1YDHWi+2*4HkU)Y=Po6MgUdmwrT(X diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp index 38cb47c675edb6d4797b008d2deae656739230ef..3e8a202b0f32d585b38d4f8c85247124de5ec73d 100644 GIT binary patch delta 1368 zcmdmNG~0yBCDzaneREc_tc(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ zk|4@9yE9+m_HLQtxtm{>(PQ#Tek}!5b@Aw?c}#vw zj3Pq;B1|eJM$t}U6#XSek)t3HZfYe)(Me(y@d^=PT_7=vrV^v*CNYX+g^6%eA~A}V z5~JuPF^Y6Wh;UOOF^aYlqv$6wifl!Ra8n~OijESah*OLR>wJk(G?5rZSBX(1DXxW9 OW}uY?o1?^UG6Dd56QI=q delta 1204 zcmbPjve}5sCDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li2{CR@xe~<0^VE!&YlJ$E?n^eK_LtULQD+_ zndHxtMTi5aEaqHgsWF!T@3zx$r|-#vq~SCa1}d`L(35 z*cA`9%W1N%0AA^G{L%;UOLGh2H9Qo*^nCo%FY!wo3*oi97Qggy{L+HLcny!nFTE7M z^n3i$mLhoVZpJTt7QeK(C|<)8@k_79FZ~t2w7nQ!yF2kqU&b#jD~{Ljbo|mA@k{>} P*AmB($2L1j+++j*x9fJ^ diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/pc/DSDT.dimmpxm index 06a7aa59465238bfbf715ae83540f68b1f2f3ea5..f7d6ca1448cf0ae3c609fc1e1391cccc2d7221fc 100644 GIT binary patch delta 1387 zcmcac(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ zk|4@9yE9h_)H|(>i4S&)7w}pW;OuF@;S}uZ!w}u1A8cR{&k^tF62!pa7#!-yAR-$N zbU#ml5Em0j2}mqq3CK$snOWHh(M=Al!G=&BJPZs>5M5kM__c{}#7{O6kz(|i>@T9F zfNDcLx(yzaCljOSIx&i*MTxL3o)|@oiBa^N7)9D*M7SxR7)6_jQS_Y{Mb_d(xT&5P zMTdz|#4bUEb>74%>L*6gWnvVGOA_IxXkrx2Cq~g@Vic)M5#gq6Vic_>M$u;*!sObomXi3JHAi3|)&5(WIs;)9*y1-!WeoIMRhT)5%`fdHxtMTi5aEaqHgsWF!T@3zxlFDS;bU}~+$o|Zg~f(= zunkU=FXNY%6~(JN9l!KO{L;ViOS_8UwYwj`^iBNI%Hntp&&4mj9ltcA1YX0v@k>v| zFMS`sw5B9pyNmHl@5L|8E``_dK>X6P@k>9&FRd?)*X~OE(ueU&^UB~gJRHCDLK!V_ M9C>W>3z?gY07V3KG5`Po diff --git a/tests/data/acpi/pc/DSDT.hpbridge b/tests/data/acpi/pc/DSDT.hpbridge index 798349aa3f85e0803396471237e94604d00a1f90..aebb29c2a4ae67b732bef3eb8e72c5665bb3a7b3 100644 GIT binary patch delta 1385 zcmX@4x5|LaCD!c zNf2e5-I-aqJRMiZ#0NXY3wW*yaP~Cda0+(yVTf+h4>mA}=ZJT731Z-I3=Z{U5Rr`s zx}T>&h>HoN1SFQQ1mvZR%&hE$=q3l&$$h+HvUpWZ-pwm(ZW3&00Wq0}fq@xfIu|n` z<2@#G@@XlcnjVkt29L?U#3-6bjH0W=D3atS!cDQnC|XF2qNl_t(i9-VO}WG<+DMF| zuf!;_6ePk;wZteoNQ@#@AtJ2vBt}s$F^Vn{qexVk2scF%qi8NMiXIZ9NL7RgH)Rr| aXe}{{J`$tIR8$MC5JAi4o6AJcFaiL0S)o4w delta 1221 zcmZ2wa7d5KCDNE4JQI_j;ACy49rZ430WQJ5d<%S7Cuax>a|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V&k^tF62!pa7#!-yAR-84*YHsM()004zr-(XER5IgTKv+-@k;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* zBtevI?q_DY(M@6$$qEtSrbJ>CEhR?LOJWr13KQX`LShtcB}UOtViehm i5aFgqViX-EMiHkd5!U$n~VTXH>qd< delta 1167 zcmbPixLTjfCD;*!sObomXi3JHAi3|)&5;yN=ZBHurR>c(}2S%*wu$2 zx=AzGz#yI@-q9t9fx|I4)Q>?#JRayEo+Th>Wn^Y$gVcc}qMN)}f(@Z+c^DX&AnLi8 zaA^?Xhz~Y&VOYWdVi>th_Tl4WbebH^rzM5OhIp_IPLr47mwu05+L9ly;m!D^&*GOB z7r<+HB7W)B_@%$%m$nzgYj-Dp>C5<~Wrgq>o{nF7BYx@M_@!Ni@!H*wU-~9~X=M?- qhUem!-i}|IQ53J?-uR`b;+MXUUs_WPuieFBTH-kJ*ydegHyHsB4Q@aH diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/pc/DSDT.memhp index b81e3dd8ecd89f4690d69a90096df095fe218425..63fdfe8c025f8b2f19411792817cd21b506fa984 100644 GIT binary patch delta 1387 zcmdmFIm?>MCDc(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ zk|4@9yE6y#*E_9^i4S&)7w}pW;OuF@;S}uZ!w}u1A8cR{&k^tF62!pa7#!-yAR-$N zbU#ml5Em0j2}mqq3CK$snOWHh(M=Al!G=&BJPZs>5M5kM__c{}#82iGmSXgntRbwW zfNDcLx(yzabBIy2ffz+!h*4xALWG-Yh*5Na7)30iL|ErRjG`W56kQ-jk%$-(Zi*mA z(HvqFJs?JriZ~H&${J>vHs6%G$p`@bk)nP8 delta 1186 zcmbPby~&cxCDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li2{CR@xe~<0^VE!&YlJ$E?n^eK_LtULQD+_ zn&k^tF62!pa7#!-yAR-yXVmJ}A9@nDmkCa=LS z{SCjgg9u*3yYNe2!7nW*ir4TA{L-87OaH+y?IwoT?g{v%Z{e3#5yxwI9)9T^_@$X7 z@EY!eUwRsT=?D0wwIuP{U4mbFAAV^LDZGXU;g_C+U-}t-X#;7zc2`MjiQ~v)n-5Cg GWCQ@s6m!7< diff --git a/tests/data/acpi/pc/DSDT.nohpet b/tests/data/acpi/pc/DSDT.nohpet index cb7bf7d850f340e12a7237c987f570300fd9c92b..281b0955ca223a1bd2c24f5e58fb8b73ae37a957 100644 GIT binary patch delta 1367 zcmcbryH}sfCD;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* zBtevIc4sc*^mJMq6CdmpFW|K%z}eG)!ztL+hatL2KiI$^o+IATC5VB;F*wwZK}0ql z=zg98AucA65|CKJ5|EcNGPAN1qMIC8C-I8O;#D+Rmsgh2W3o4|mIA7}cyz-&CifGg z=rS>i#QBJ@E}9rc^NCUPm>5Os{6x4Zn;1pwiBa^K7)9m+M7XJ%7)ASuQN%1rgmv!3 zDC#Cg(RpGN2@4V7rf^~u%_c_CePR?T3lrg{bYc{(CPvYFViXyR5aFhBVifHb(LyUT N(8_|%e?)FF0syVjpr`-< delta 1194 zcmdn1e^r;uCDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li2{CR@xe~<0^VE!&YlJ$E?n^eK_LtULQD+_ zn&k^tF62!pa7#!-yAR-!e(CS{r5*Y4+TD#``YL{Dc>%nJXX2OMj9>aMerb0>ymn8- zFMS)ow5kwZ!}IY=@5C?7ER5H1U;NV3@k>9%FRd+t*X~mM();mCbBf|MJQ%<9Tv07? M9C>W>6VaQD0Dwkx9smFU diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/pc/DSDT.numamem index 230aaae37169ec2f78ebeae735ccc905a112d284..34914bf1ed362ebd07f0dbc22434dfddd26d9a82 100644 GIT binary patch delta 1388 zcmaEc(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ zk|4@9yEAif)jO??i4S&)7w}pW;OuF@;S}uZ!w}u1A8cR{&k^tF62!pa7#!-yAR-$N zbU#ml5Em0j2}mqq3CK$snOWHh(M=Al!G=&BJPZs>5M5kM__c{}#7{oLE5+zB`980f z0;&!1=r(vvR^}r@Q93b-RuiM>Ju!-m`H65-IWdZM6Qk%qF^Zf8h;UOoF^WzTqljOS z2a|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V&k^tF62!pa7#!-yAR- LJhr()>?R`sl%I1@ diff --git a/tests/data/acpi/pc/DSDT.roothp b/tests/data/acpi/pc/DSDT.roothp index 7091ee019191d822869f9a9f35ebd635eea4a9eb..bba1612c972948911ca5f5b301b10a380b8d83b7 100644 GIT binary patch delta 1407 zcmdmNu*itZCD!c zNf2e5-I-aqxIA~o#0NXY3pnnY9Lj4i<-aA^&?25A-q9t9hk=2afx{`-)rTRv$(d#H zT3!_e*?6EYcnXBLm_Xw3!J&Q$OF$mW$jr)4h;DM9{F+yjkRp%CdVE@h6%`SqXd5w# zei5U{j-LoOH4&re7%_^t1cDNMsg4*$hlo+cCPIXDUc@NsBSz6BVibvq65*yOVie6IM$sctEm^!p K&t_#Y0VV)Uf2(8w delta 1194 zcmZ2vwAp~mCDa|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!Vt_@!^-msS

>7DqcnFaA0?u%b~I)3Sg_@%Xl@Y-F9UwS`&X-;9hh6m%9o{L}lIeuwF5xjO+ rjrgTci)o4D$iSP0#08iDx-NI% diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/q35/DSDT index a85c608022b9e0878bcedc785b9bdf27e50a760b..3870958969b1c0e29f9dd26a1256359e90897d3e 100644 GIT binary patch delta 179 zcmccQ(BR1B66_MvpuoVu=(Le5o{7mvWO6psj(R7~0GD82-UTjfld~8K1eqBb5(*d+ z7f4N-oFOR8C2+y~;66_KZq`<(ycx@wBJQI_j;N)zk9rZ430WQJ5d<%S7Cuax>a|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* NBtevIZfCwD0|0JNI!yoo delta 159 zcmbQ}_}GEVCDa|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V5i&CX diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/q35/DSDT.acpihmat index 51e79b3b0754224aa6cd1e1257b404182506f1d1..a32e90b5d913d07bc9ed9aca521420305559f357 100644 GIT binary patch delta 179 zcmezGwbq-;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* NBtevIZfE|X2ms6HI`{wp delta 159 zcmZ4M{ojkrCDp4cqS%4!O7W7JL+B70$hT9`4;%FPRV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li5vl*&Tb4MJn=x9u^c(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ Nk|4@9Z)H9$0{|KaIqv`f delta 159 zcmZ4I*x<V(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li5vl*&Tb4MJn=x9u^c(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ zk|4@9w=>tuaCz>Ei4S&)7jWD)nNPu<$$!gae+4lnXO_un3MvY+@jyrO6bNxKIR(4= z#0Q7^B`g8?BO@~_J0ZHseex0oO+t!1CO=ouBCJSTkqAZk#3mCD;*!sObomXi3JHAi3|)&5;+1qo!uBjc;bOHV?hRpC(swk7$58uzxe`l zk_?x}x)=~gz+v5F8wGnwzZJoT2Jsy6jxIqw3=B*R98STmJ`B-KHj}3+s7Q&&10Bq> z1mx_D%&csXTzqh-Uv!h>lg_~}y$!GQBqh9Nd*PR!f?xU`erXM5 zymlAim)?V4noR|-;Q{!iXW^HAf?rxs6|dbD_@xiwm*!E!Yj_xb=>_0emCDc(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ Nk|4@9w=>U{0{|dEIhX(d delta 159 zcmccMvdD$YCDa|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V!c NNf2e5+nIkV0ssJjImiG2 delta 159 zcmZ4I-QdmT66_Mvpvu6&cyA+DJQI_j;N)zk9rZ430WQJ5d<%S7Cuax>a|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* NBtevIZfAB>1^~m2IyC?Q delta 159 zcmez7d%~B?CDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li5vl*&Tb4MJn=x9u^sN$r*yeTml!&Pd*Jct@52H{>oSKu(R)ygazzVGr5?SBosJ$xV(cLv12sVr^n2BNsbEVnJd@0s{k3tLo$|F7^T;Rwf2spfw-^gpo`r NNP;Nae2MwA3;>&(I?(_C delta 131 zcmX@@IM%eTOXb#jKFFqgmu^OH}5 zO{;t-iof!eJnZaS;OOZRk&~OSKzVW&!ve|4nOsZ@geTQbPGFdv!1Esn7?ub!Gd6+< ihK1q_L?>r)u@?xjGBNNnBo-ueBr-58N!-M8S_S}whAYtk diff --git a/tests/data/acpi/q35/DSDT.ipmismbus b/tests/data/acpi/q35/DSDT.ipmismbus index a0eeae95c07fe3708509c3e652c3aeff9c21ac82..479df48cd37af888317d63eac8f565f370201490 100644 GIT binary patch delta 179 zcmZ4Oc+-)~CD;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* NBtevIZf91J1pt!1InDq8 delta 159 zcmccVxZ07+CDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li5vl*&Tb4MJn=x9u^;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* NBtevIZfCwD0|0JNI!yoo delta 159 zcmbQ}_}GEVCDa|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!V5i&CX diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp index b4a9f5a0fe5cf3b44ebe7659a2bf3687e1073482..a5730b8ab8abb2602334633cd6c760f79915e564 100644 GIT binary patch delta 179 zcmZ4JecqePCDc(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ Nk|4@9w=+vA0RS{(IX3_R delta 159 zcmX@_z0jM>CD;*!sObomXi3JHAi3|)&5;+1qo!uBjc;bOHV?hRpC(swk7$58uzxe|5 Ge?;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* NBtevIZf7=C1OVaDI#~b! delta 159 zcmaFmxyO^sCDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li5vl*&Tb4MJn=x9u^;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* zBtevIZfCBQ;c}9Qi4S&)7w{6F%%@<_=r`F51NJQI_j;N)zk9rZ430WQJ5d<%S7Cuax>a|v89KlwD+ zw90p)_$yz@!_K}1j-D$;Grlcv9`;1cu28JpX}!VTm9!VSSbKhUjDc(SdiF}z`y|1syaD~i@iXIm5G5DXbs2!VI&g@ Nk|4@9w=>(y002%mId=d6 delta 159 zcmexlf5e{4CD;*!sObomXi3JHAi3|)&5;+1qo!uBjc;bOHV?hRpC(swk7$58uzxe{Q Gk_-T9Q8HZs diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/q35/DSDT.numamem index 37fa4c3a45b0d7db0d3d368df5e027e7e1acf9d2..414b8af67bdf79238915de0d609ce45e150eb958 100644 GIT binary patch delta 179 zcmccN(B{bH66_Mvroh0!_+}$lJQI_T$mDFM9raF}0WQJ5ybD~|CTB4e2r@G=Bor_t zE|8iuIYUsGOW=a}$)~}lRlXC&U-?QNcJ^J8uz-DPCKuC^gaSuTmx$($90mp;!N`yV z)KWV+iD7aQ&wn6bs7+){tWB(B!c NNf2e5+nF!Q003SRIx7GG delta 159 zcmZp3yy3v*66_KZp}@ev*szf+o{7m%aB?=&j(Qii0GD82z6Cz4lQRT`xdbklpL`l@ zTID-Y{FSfdVQ1e0M^BfCoZN&3%9FDg7D!Ick74p8r6=utboVu@OWt zEEHcLIysAry+DYSiGi0Pu^^!%k%3`JB1eFyvm1j5Pdt!jEXV-y1o|QwD^%e%mZZE_Yvfgm#@LqY*V z;sU8jlQRT`xdbklpL`l@TID-Y{FSfdVQ1eZ2@BY#W^yqtNhomibcty0$YEdr5{wK< zKrOYClNcr^@%#q@hT25N#M;D4MlN=S#Dc_*1O^76R@KQ_T`F830PWJNEzp delta 115 zcmaFrxZRP1CDD^%e%mZZE_Yvfgm#@LqY*V z;sU8jlj~WsN$r*yeTml!&Pd*Jct@52H{>oSKu(R)ygazzVGr5?SBosJ$xV(cLv12sVr^n2BNsbEVnJd@0s{k3tLo$|F7^T;Rwf2spfw-^gpo`r NNP;Na{F(K-3;+_8JFx%& delta 132 zcmez2ddii{CD%eTOXb#jKFFqgmu^OH}5 zO{;t-iof!eJnZaS;OOZRk&~OSKzVW&!ve|4nOsZ@geTQbPGFdv!1Esn7?ub!Gd6+< jhK1q_L?>r)u@?xjGBNNnBo-ueBr-58N!+Z+c3lPl1?w!b diff --git a/tests/data/acpi/q35/DSDT.viot b/tests/data/acpi/q35/DSDT.viot index be4a254e93a9cb360f42a25121c5fcefbd47480f..3f14b57f0797ab13fc4c90dd2949cf4bd6c30896 100644 GIT binary patch delta 179 zcmZ4PdDWB4CD;o1Dc^Ajr(fkWj#o zxIk*sD~d!bm0* NBtevIZf90d1OT<%Is^a! delta 159 zcmccWx!jY>CDV(c!xBMe#zqjq zuuyz~=;SOe_5vYRCI()H#Dav5Li5vl*&Tb4MJn=x9u^{Bzjn3g0IIC{E7G0eOn!osvzd0(yRZeg1pD$W@L`>tAt=lxaKZfK z(_qso--+U{d?gP%`xZEQx=eKG I0`uf{0IEYXmH+?% diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 452145badd..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,35 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/pc/DSDT", -"tests/data/acpi/pc/DSDT.acpierst", -"tests/data/acpi/pc/DSDT.acpihmat", -"tests/data/acpi/pc/DSDT.bridge", -"tests/data/acpi/pc/DSDT.cphp", -"tests/data/acpi/pc/DSDT.dimmpxm", -"tests/data/acpi/pc/DSDT.hpbridge", -"tests/data/acpi/pc/DSDT.hpbrroot", -"tests/data/acpi/pc/DSDT.ipmikcs", -"tests/data/acpi/pc/DSDT.memhp", -"tests/data/acpi/pc/DSDT.numamem", -"tests/data/acpi/pc/DSDT.roothp", -"tests/data/acpi/q35/DSDT", -"tests/data/acpi/q35/DSDT.acpierst", -"tests/data/acpi/q35/DSDT.acpihmat", -"tests/data/acpi/q35/DSDT.applesmc", -"tests/data/acpi/q35/DSDT.bridge", -"tests/data/acpi/q35/DSDT.cphp", -"tests/data/acpi/q35/DSDT.cxl", -"tests/data/acpi/q35/DSDT.dimmpxm", -"tests/data/acpi/q35/DSDT.ipmibt", -"tests/data/acpi/q35/DSDT.ipmismbus", -"tests/data/acpi/q35/DSDT.ivrs", -"tests/data/acpi/q35/DSDT.memhp", -"tests/data/acpi/q35/DSDT.mmio64", -"tests/data/acpi/q35/DSDT.multi-bridge", -"tests/data/acpi/q35/DSDT.numamem", -"tests/data/acpi/q35/DSDT.pvpanic-isa", -"tests/data/acpi/q35/DSDT.tis.tpm12", -"tests/data/acpi/q35/DSDT.tis.tpm2", -"tests/data/acpi/q35/DSDT.viot", -"tests/data/acpi/q35/DSDT.xapic", -"tests/data/acpi/q35/DSDT.nohpet", -"tests/data/acpi/pc/DSDT.nohpet", From 18a31b8d3e75f5bb727826dfe6a0c762536bf408 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:06 -0400 Subject: [PATCH 0982/1020] tests: acpi: whitelist pc/q35 DSDT before switching _DSM to use ASUN Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-9-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test-allowed-diff.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..1983fa596b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,15 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/pc/DSDT", +"tests/data/acpi/pc/DSDT.acpierst", +"tests/data/acpi/pc/DSDT.acpihmat", +"tests/data/acpi/pc/DSDT.bridge", +"tests/data/acpi/pc/DSDT.cphp", +"tests/data/acpi/pc/DSDT.dimmpxm", +"tests/data/acpi/pc/DSDT.hpbridge", +"tests/data/acpi/pc/DSDT.ipmikcs", +"tests/data/acpi/pc/DSDT.memhp", +"tests/data/acpi/pc/DSDT.nohpet", +"tests/data/acpi/pc/DSDT.numamem", +"tests/data/acpi/pc/DSDT.roothp", +"tests/data/acpi/q35/DSDT.bridge", +"tests/data/acpi/q35/DSDT.multi-bridge", From 5840a16364b8d7b474b2730a4c73ffb4c1dbaf47 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:07 -0400 Subject: [PATCH 0983/1020] x86: acpi: cleanup PCI device _DSM duplication add ASUN variable to hotpluggable slots and use it instead of _SUN which has the same value to reuse _DMS code on both branches (hot- and non-hotpluggable). No functional change. Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-10-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 56 +++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index a19900c4e4..eb92b05197 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -374,6 +374,25 @@ build_facs(GArray *table_data) g_array_append_vals(table_data, reserved, 40); /* Reserved */ } +Aml *aml_pci_device_dsm(void) +{ + Aml *method; + + method = aml_method("_DSM", 4, AML_SERIALIZED); + { + Aml *params = aml_local(0); + Aml *pkg = aml_package(2); + aml_append(pkg, aml_name("BSEL")); + aml_append(pkg, aml_name("ASUN")); + aml_append(method, aml_store(pkg, params)); + aml_append(method, + aml_return(aml_call5("PDSM", aml_arg(0), aml_arg(1), + aml_arg(2), aml_arg(3), params)) + ); + } + return method; +} + static void build_append_pcihp_notify_entry(Aml *method, int slot) { Aml *if_ctx; @@ -423,26 +442,17 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, break; } dev = aml_device("S%.02X", devfn); - aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); + aml_append(dev, aml_name_decl("ASUN", aml_int(slot))); aml_append(dev, aml_name_decl("_ADR", aml_int(adr))); + aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); aml_append(method, aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) ); aml_append(dev, method); - method = aml_method("_DSM", 4, AML_SERIALIZED); - { - Aml *params = aml_local(0); - Aml *pkg = aml_package(2); - aml_append(pkg, aml_name("BSEL")); - aml_append(pkg, aml_name("_SUN")); - aml_append(method, aml_store(pkg, params)); - aml_append(method, - aml_return(aml_call5("PDSM", aml_arg(0), aml_arg(1), - aml_arg(2), aml_arg(3), params)) - ); - } - aml_append(dev, method); + + aml_append(dev, aml_pci_device_dsm()); + aml_append(parent_scope, dev); build_append_pcihp_notify_entry(notify_method, slot); @@ -485,19 +495,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, * enumeration order in linux kernel, so use another variable for it */ aml_append(dev, aml_name_decl("ASUN", aml_int(slot))); - method = aml_method("_DSM", 4, AML_SERIALIZED); - { - Aml *params = aml_local(0); - Aml *pkg = aml_package(2); - aml_append(pkg, aml_name("BSEL")); - aml_append(pkg, aml_name("ASUN")); - aml_append(method, aml_store(pkg, params)); - aml_append(method, aml_return( - aml_call5("PDSM", aml_arg(0), aml_arg(1), aml_arg(2), - aml_arg(3), params) - )); - } - aml_append(dev, method); + aml_append(dev, aml_pci_device_dsm()); } if (pc->class_id == PCI_CLASS_DISPLAY_VGA) { @@ -585,7 +583,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, qobject_unref(bsel); } -Aml *aml_pci_device_dsm(void) +static Aml *aml_pci_pdsm(void) { Aml *method, *UUID, *ifctx, *ifctx1; Aml *ret = aml_local(0); @@ -1368,7 +1366,7 @@ static void build_x86_acpi_pci_hotplug(Aml *table, uint64_t pcihp_addr) aml_append(method, aml_return(aml_local(0))); aml_append(scope, method); - aml_append(scope, aml_pci_device_dsm()); + aml_append(scope, aml_pci_pdsm()); aml_append(table, scope); } From 01766490708273b66e7175c1ff5921edd934348e Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:08 -0400 Subject: [PATCH 0984/1020] tests: acpi: update expected blobs It's expected that hotpluggable slots will, get ASUN variable and use that instead of _SUN with its _DSM method. For example: @@ -979,8 +979,9 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) Device (S18) { - Name (_SUN, 0x03) // _SUN: Slot User Number + Name (ASUN, 0x03) Name (_ADR, 0x00030000) // _ADR: Address + Name (_SUN, 0x03) // _SUN: Slot User Number Method (_EJ0, 1, NotSerialized) // _EJx: Eject Device { PCEJ (BSEL, _SUN) @@ -991,7 +992,7 @@ DefinitionBlock ("", "DSDT", 1, "BOCHS ", "BXPC ", 0x00000001) Local0 = Package (0x02) { BSEL, - _SUN + ASUN } Return (PDSM (Arg0, Arg1, Arg2, Arg3, Local0)) } Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-11-imammedo@redhat.com> --- tests/data/acpi/pc/DSDT | Bin 6219 -> 6422 bytes tests/data/acpi/pc/DSDT.acpierst | Bin 6186 -> 6382 bytes tests/data/acpi/pc/DSDT.acpihmat | Bin 7544 -> 7747 bytes tests/data/acpi/pc/DSDT.bridge | Bin 9078 -> 9496 bytes tests/data/acpi/pc/DSDT.cphp | Bin 6683 -> 6886 bytes tests/data/acpi/pc/DSDT.dimmpxm | Bin 7873 -> 8076 bytes tests/data/acpi/pc/DSDT.hpbridge | Bin 6186 -> 6382 bytes tests/data/acpi/pc/DSDT.ipmikcs | Bin 6291 -> 6494 bytes tests/data/acpi/pc/DSDT.memhp | Bin 7578 -> 7781 bytes tests/data/acpi/pc/DSDT.nohpet | Bin 6077 -> 6280 bytes tests/data/acpi/pc/DSDT.numamem | Bin 6225 -> 6428 bytes tests/data/acpi/pc/DSDT.roothp | Bin 6434 -> 6656 bytes tests/data/acpi/q35/DSDT.bridge | Bin 11227 -> 11449 bytes tests/data/acpi/q35/DSDT.multi-bridge | Bin 8628 -> 8640 bytes tests/qtest/bios-tables-test-allowed-diff.h | 14 -------------- 15 files changed, 14 deletions(-) diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT index cb718f1a8a591b27ca841f70f40762562c15c837..8282d449ceaefd914b419f507a13f3fb7b318aaf 100644 GIT binary patch delta 1170 zcmY++OHRU207l^w3Y0==%cD>pC2<9aFC2o!nHsImOu7UUx8MRCkhlsHV;r#tSKw}p z=0C~3(~~dfd-1mP^CG`bQpc&hfBH{>f3<%si%l7A_q&(iHM?<(!&T|6i-&8!>XqyK zuI)Hg$1DHC?lwHweFX6zTQ0<0m@DR5j9U#>6RVl*h+7?27pq&0TLab*Ynbeqn+Nm6 zJd1H_!kS`Dlbvw$VZNAeF>WnbORQzGQ*LcoTdZv{ZUHP13ru##tpn?bbu7j$goR?E z$yVGVSR@u%j9Uzg#bT44bL+yoVqJ@I>%n?rJ(I1u^w4F>W*1Ol)Sd YOKuq~6U!{dZ4R4@&Bem6=j5mI3(bW3jsO4v delta 1329 zcmaLPIZnd>6aZ0MaT3R|9cQ((OR1cIN|u5%00*Fm#0e;&KpcaE za19nQ<^S#IX`UyaV<$?}P$c5-$$ zOHN(G$Qg@!f3)-)=PxHodUSPtb34Cy_`#F$KeoV@f;s2Gc^R*9E`SRP=3E39WxUSW z2HOheTmqM5yusN4I|}Ap2A5^L$=Lj6qH3f67gX=P$ac+Pc3g+AdH)R}iZh>10<{W}U8Sik8z>$JEx4~^0C!9Orj)FON k!Ce{ea_)h93g+Ag_hr1tc>o?LnDY=k{KIDUu@Zin-wNzyDF6Tf diff --git a/tests/data/acpi/pc/DSDT.acpierst b/tests/data/acpi/pc/DSDT.acpierst index aebb29c2a4ae67b732bef3eb8e72c5665bb3a7b3..9520f3b7303a43091e8c77b64d1f76407e85f1f4 100644 GIT binary patch delta 1131 zcmY++OG?8~07l^y`bck+Cg~$hUn#hP`mV#))R_uKXJVG%B3wdu;Y38x6*zO^M!E(; z{sZ?;4o^B_=NKiJXA2}5qR{6ZSxVuU-mC@|70cr diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat index b7c5de46346d2777b33f7fc464d319bd762fda8d..33169838bed50710495d45e0d9486ac59b4e504c 100644 GIT binary patch delta 1170 zcmY++yGp}g07vl@dr8x@x%Hkl1)spXRb1MpZYmhvgv>sTLsvl`L2>HrQwTnYqbUCa z-?tuqoS*a03okG7yH(~mmB)AQIrgr$4`s0|!}WIa7C&V-)nb2Mx{Koe+S_r~6l}=#L%jiB(}$v8u(m)nGNTn#m5i)nRq9y2ZFPU=6W`$&R?WFjvgA z7`G;@Db_UEF*gt9iFp>|)`GRfS|&T;=EHn3-(uX_u(nv+WT)IZu#Q;AV%!2)AQqTx z&Mkz6Vxh&jMX*RLGT9lo7#54g7UPz{60yW&3vOLlSFCF>Zar8}tY@+%w?3>d*0&h9 z0c;>PFxiUR5H=JWT8!HWHWC||Eax_cjm5?mLNHQC_aJ@ zk@Hc9JG%H<4kOpRe}4XUETzER8ew@M-?y-315vba|9nS$ckK z=d5g;oH~Y)Gv*Ke!s2h7KAt4$(d_c-dU|pDgIAXRaUPskFy{ieAmdfeMQ~BUoJ-)6 zjMq3@U`xTA%iyw%*E!o@Tfv+w;EIelI6GiR!JMn$s*E=|*T6LebFPEyG9Gbu!LEWi zH^2=UZ*lg(o`N|y!A%*DIs0H=!JJ#*mW*T0ZE#z`oC9zm<6X`ja7V$MyWp;j6V5$w oPr;n~;J%FaIEUa+!JH#-B;$R~1Mon>oQL4yA2zeMN%&!Y1Jnj424aS~^|X7iH8VG(`U15^nn5=elAp$d|ZK%F*1NK_!XfewxkaR#oy zQK*@a|C5-hDbtLmc=T4*H~t>IoUu5GuY-+TPI;ZNJIi>QD7R@cOx=e`c5gka!_UmK zkNi_D>Ge{5klbA4^mGtk@sr=PnY*4H+DjT^;jM-PcSdSEfh6Cji4q$6bpa_f&~$7qgVti5-ds(#S&nNU`d2KDC&SZ zL0y6wtBFbqS)_0BjI!h;WFa z2j~&>B#5F9=o9osc#L8I7!V93h++sB5)4Hcqu2y&5^PEk#TH;s4*b(6f#RxDW7)cPtE?}2n7x3fJSJa3P+H!vQgTUv0IX{11xjsIi<^0V56xecp N_)`4q{JgDxDL<$GC>sC( literal 9078 zcmeHL&2Jmm5ue8oY57P>OKNS&RvZ(ujW$hTla#-L0)@z3N}?rFYcA!aSfN~!3QD;K zvT&jzvS5^^3r8_fpeduGhaMP%xmw2_TcD@j{3oP`UV2Q?*q26~+2x~TN>1cG^&kOS z?aaLQo8QcPZ{DmlLo5I4902=oc1fK#65023HGw}20O+0m%K5+wm`yD^S7BjafSC`% z&O1J`lJa9MyFADK*s%U!Ss#63v8oNVC-Qc!YCqhvYCwb5Yc}WfB2QI}Y{hI%>S{hI zRp#?rB=d~>rAkICfmB(}Yaq{_x=4d)gxShZutMD*m1F!3LPE^M$45{;bilmu5*kI0Z6|%1E=C z+NU^-Xrq7Q!lh{^IPNz9&PL)%r}wC`294{G-2-D(ZEAL<>sUB^M80Kj5#L4(!K`F5Rk zV(lsq^wkEeei7|U85|UA*SW8+$@Vnb@=RMnRg^B;U<-&y}f;_mw&ez1PG{{DwxGF4w(=#}Xx=W`5p zV24HU*1|3B)a4x>F(3SpgbXB9Jy&FEzGyJDRJg^kx+du{%fPRy1q~~BoJRUpBe$5q z;aaAgP$HFlF)!IbO56_9D^Br8LN3W@M%DAlWGYEC+)F&D#MJWa&wL%;ZonfonM|%J z^Fw$wWJ2b-l}myBfl>fe+XvO?%m%A-x;<#15Ntk*HT{5PaiMD|g&>9XdXCs26e1jo zugsoQ4Yeq}A`D3_=H89_c5SHJZ1ss2Z?7^NYbtYU`C{aEZHsN!QDxcnL6=UzgGyYK z&iMAA7MG>|WhaEieiz+*X&+|C3t>=A>u%S#h$9tpWc9_h&XohhoSlKoSLc5FKw{8{ z^VaLs*yRFlXGefFsMC^TY;`krcyI@>kk5MU@H7`f>XK28yduqq@0J7jm^^!JFbSAD zoBIZ}H1zhM5{Dkj&U|>C_B0)206ZSJuca>SZae{nOgR?j5=hjcqIIN#afB%tXsq2< zCh_ph>A6ZSnTFnpr-MX$N?r<($*D-aGnKpw$~!nV1(b+>eQ?{MeF|MII!s?0A*+ge zQt764ThS!4DOTQMwT`e@}FSXig08`+$+EKlzCo`A= zw*ZoUU*&Uq->@5(Q~AEy`D%v+2;@dUpVv!nB3}l(>GrnK0#H9ds@7R~4bcHNLUjE5mvdz}T*>}}hm%zoBo~9tPlm^&I<4an+Ow)_m(*A6uuDcu%5kC~jC-;9hqD15vt)?3Q zQFlLvlz4^i9O~<7Oa(0iP^5Y(ra1&52B^oD3qKB#2Llg4^8q(G2t?hJi{$f))T7k< zV0CiijZ>Nyj5uLW<8lgk~fO4 zA_-0*ffVwHbVYFD0*QM?5}dF=xY30@B3%`nA_6Jm6-jW43Z$qwjIGq(pXI~#lDW1`870bR(c(cLa5j9b3 zoycYbn@$w2_k;in*zLI%i3DMhQNXsswIoOomKhZAa(69F637zWY=p6=dSu`o+mp!C z<-Uzv;a%6Wk*_O#8#%)}r)MK?SNk?{hqb?FBY)S(HoDnxnmClP3JV!KYLxfv*jGO? zup$aOeo~>lXO~IF>Llz5N8Yo~kc^c=*qe^LXLlmTQ!DJ)FF!KWeRhf(Pf*`ZacleR z6glqZzCA(mKKl&HxU>59Cdp`5&e8`P*o^+4O$&`Z|1#^nXxwkMuvI;73$Z8uzHbA} z({WpPv^*WRg-6TNaa(w_JRP@%N6XW3TX?iQ9k+$wnZr{{!R>?|A?K diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp index 3e8a202b0f32d585b38d4f8c85247124de5ec73d..013de154913063ed1ce3f154444b9e11f4608eac 100644 GIT binary patch delta 1170 zcmY++OHRU207l^w3bdurmS-tYqATzLiX#ISXKG?~X40j&1P2UVg>l4E+yLt^n*SvC zPEWp^&*gCy6lL*p%p9kddG`I8Y^290F`7Awm z4WnQz&-|6u-#C9hO|#?0&F$U%>i!3Bto>sPY$=#?5nPn?)XZ4P2A)Hs?CHu3*j{*pu;;vk&$a%(($>$asfy z6WmlV=N7mn;~D2RxUFE$9dJj+3Fj`jt6|C{{9tyn%@v~V8s9c diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/pc/DSDT.dimmpxm index f7d6ca1448cf0ae3c609fc1e1391cccc2d7221fc..289ec07c07734f6fb10e1f1f3de7b3de2a4642fd 100644 GIT binary patch delta 1226 zcmZ9^y-vbl7>3~z3Y3pRTUyFrX^ltVzc?5J7B@AqI!V%VaVBBtkr*dN&%zUM@DOy; znCBVZcfE7ve!tvYnY_p!H<@MCeqPOIXl{4wvRIb>YFB-S+w|Tp4(Fw_D4y<2-6(8G=N4y9y^2`z>b7xJi3G~psOH{UBWJ4SHg21dxSl}o`O7j zgdU(L;haaG&@|Y23fEl3w_LY3pegScr1^oa3 delta 1329 zcmaLPyH3IY7(n4R6ey)Yp+L)}5S$#ni-R%LYK)1-Se-N}qnB53ayD_`6?D_V_yjzR z@fqB_#54Z?dh+Ew?98{FBu&od1H&-y-kcBLiC-_XG|s%km)V#97#vvX@;I}z^!(V# z+1VsHbqynD%tqnD;%}Tjoh0ee)%DHo^y2;puPpsz3v4Nva~_rI5)rz1#|YnzKkcFo8YE`Ik&(q8ONO4;I@J}2jD=)yPQLCs9??=a7V@o=PtOb nV9q^oPsV$k`{2HUIY;0~#`~NH;DLfU55dDfY-aDz(Wm(h&iY-i diff --git a/tests/data/acpi/pc/DSDT.hpbridge b/tests/data/acpi/pc/DSDT.hpbridge index aebb29c2a4ae67b732bef3eb8e72c5665bb3a7b3..9520f3b7303a43091e8c77b64d1f76407e85f1f4 100644 GIT binary patch delta 1131 zcmY++OG?8~07l^y`bck+Cg~$hUn#hP`mV#))R_uKXJVG%B3wdu;Y38x6*zO^M!E(; z{sZ?;4o^B_=NKiJXA2}5qR{6ZSxVuU-mC@|70cr diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs index a7b4760817e07cb36e13c835d04abd7bedcabe7a..59a6d5860887b511b7ce5f17d7044a08c14f0f60 100644 GIT binary patch delta 1226 zcmZ9^O-{mK6h`3^3Y3rjQA(lw6ypMnASw>Q;!I7fjx=@+Zov&O=t_(OLtKIzaO7Gv z=6whEPEVekYW}k@d6C~grj#+O~NK%Q$ZeEge}09gi9VB zLI==MkjFM*8?Y_mDUXKG02&2(>=1SUI})Dp=n}esu7W&zgdU(L;W>{!p%3UQ$YVel z00t7Scnk?cz)(RRyM$f9u7npnMuZVyq#%zy!X98x!ZnXEVGI~6$YY94g3TN|*ws66QRP2uFY;1$i73jseFKZh4##P5>tg@;D`& c0!}5o;xQx405b)7oDt3dXMo}RXYyV91&d7xh5!Hn delta 1329 zcmaLPIZnd>6aZ0MaT3R|6FZxoU815SVGCu9K?n&17%GsQGQa`oxd4T)KnVpxfMc_7+t{PrY2T5lTMz;fz82q1>?kG;uYLHfY&fa z^M8`}U7!5&Je_`@`FWAwK4gwld4BcZWB+n%n?rJ(DfD^Lf`Sy}W~iFW|t&?5Klr_aS@- z<7;?{XZ-*5ekARRwddfon1zajt{w3g+AZ zH)OoS*#mnD=G+7~WjyBWgM9^aZh>1ejybo%Z3S}=FO0|j#)f`@%5eZ32o5aBaR?j=4o$e?I0B9YM;7Eb e295>CCcNM{0Zs%b7UVbuP6ele@%wl3S@;EQTN7^p delta 1329 zcmaLPyGp}w7(nra-qJK})3i-`FF3hrz1FcYiU^7rofQ7<=H)G%+#LD@f};-N+=p@U z2?R$kc*gHr4?oWRXtClZX>zuREX)3Sb>BTVez`PhZ2ZIL`KR{~9c0td*f=IVKXx;Y znIxy4Wo4}SELd9pjnk)-Bt5#izPX)V-2LFS)qk7?XBEsj2hPcOopTNMZuh_;Hr$roPDsbV9qsg zO~yN%18|^V&UJ8I#uLsBa6`eIo8YF5W6mKsR50fV9Lac>a|_&3Fy}V7E#ri92i#FG m=PtM_<2}wja8JRU`{2He_c;&10|j#)f`@3zX8*ax1q2#wS3$;RqHtHL>cVNuR>O)y>I))x}3JPCSO258*>- z%>NAEx1RiRzGiQ8Kg+Y5bl^CpyAS^{^e?s#MZPNH^>*_TzD};(e1B1R%l!7z-|>oN zb{#m*j^h>oVe=mCZGOUN_x|}0&S!!y&=qto$gvD83zkiIz_9|X2v#h}u?nmTR!w-w z(F1ydo&`D9fHlFI36D7XKwr?eAjdkeE?76=F~-i$0=|sI2DXPpOWv=FViFjBMtgZjX`O9gN9xrZg@8(wzKX^R)#}?R9Fy}ltFXK(l1#m&ZoQvS1jJG)3 zU|YeQOW=}>C!8IyqhQWua9PINoL#W1V9p-clkpDc3b>+R&Q)+###7Ed*jF&;03678 zmvaqVQ!wW`xGv)v=LWc;V9rf&Q^qmp7PzHg&LKFI@gC<094VM{8{C$0!np(PD425> k+?DY@=N`DHV9tGTU&aTV2jGE%IS;|ZKWt|2lkm&@27uLTz5oCK diff --git a/tests/data/acpi/pc/DSDT.roothp b/tests/data/acpi/pc/DSDT.roothp index bba1612c972948911ca5f5b301b10a380b8d83b7..f9a5164e0cba7c209bd3e52020cb855e8688f682 100644 GIT binary patch delta 1703 zcmZ|JO-{l<7{>8wDNu%%md`?glIT{$hp4zR#iB70F;-WYl%*dFuVC;9+`xDN;|<*C zar6eZ@;)o`ZYGnN`Mv*n89WVT5C&Jm6++p1laHo6`MQb1ab(XvSI_2Qclr_bN0A=+ z!KEQYO6cQoawg`>Q!VWEBHa(K&&A(uyvF<0x3#&Q94=ljf^d3!cmJ@MFQ@V2ct~=t zV3e{3%Ie43=>8KkE$q{Hse-6$B30f{MW$flA1D8kDb@_o(O@((8gI}^!=%ZiS+j#q z1|~x$!y9z6Fj+EL)(p|nVRSM&Z_vrXdqHhmHYbkTH0J zjtOIuFH z8XuhsOodE^H|SJhs${CH8KYB!sgbGi1|0{+A>**-2%S1iolKoK=rmv&WE!jq&~ag0 zGA?h>X~HzgG+8r2rv=j@)8Y*}ZJ0KhHfxU2@nAeM9&ga;z;wuT5~KLe=|H{;|s=oSPdT(9F)86%3MJeOV|=KkoWQFizhuJ$-in@c1;H%#M~Ucwg=fB1S+r|IuSh zcUDCwgbm4dm32(4DcUYw3v0=iZWtRD?Ka&AHX>WPQEXJSJ-Rm5mMz^FHYVB~x(?Qn zE!{XaF4|qX32Z{PbX}|~+C92SY*My#Q`nSf`*hRTv~1~Suo=9(+~z#9JNcc~fr1)C(Bwg3PC diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge index d03e14b24d0841b4003e7954b70cd7601e571902..f8a0bc150f5a249bd5d09be6949c97160de1ef82 100644 GIT binary patch delta 1703 zcmZ|KNlpSm7>40)XrL(?Xy$nkH=1a`850u&wi*)=V{44T1eOk`kSlNnFJN4;aN|br z;4M6X4Se6q{F_SUuX^fD{oGFPl;b+r(=|=gf8W$fU7dd458dw2?te`V>W9tVr@PS_ zn!}EBWoepEGrR8bxi%P|8E(s)cifu`ZGP&l-hT43w7fnWj$SVvxA*Y)^gJ4jd*0>t z;b~aZ&60bgMD4%RlQGOafj9)aH_=YlQ3>ZT;>;z~6FagnQ zu@j^T!USc*PKYK16B5lfJ0^_@W6Fk|FijXHESep56peyWvSBAe6M>0{W|tj{#)7eA z!%mbY3KJF09y>9b7)(qy?8Ir}Fmche*|BMC7+W^%Bxn*a3DNAclcY()BxS=+iY5h< z5>1DlG))>NEgN<+G#QwTXu9lVX|ga`*|3wN$-(4AbHq-bCJ&RB4Lb#z0!%?P4m(Af zB1};>?38FqFeT9(vs0!i!<1#iPKBldQxVMxJ5`!0OjS1Q)M#ojwVBa7?;opG-yboi Bw*3GA delta 1482 zcmaLRNlpSm6oBFCrh%rJ=eZ%ekl+R!F)=Yf%A}ktKX;Dqvg2H{cKwZ&Hl0)b?ajK?72NJ(Vb3?>nF{dAGh7|Ot0(QMTF3W z*>eY%VmR&_Zfh}jAFjo6D<?IM zhNXjb1zv|OAJ`|yJL}(C2G~$w%6_n4j&~^szySrO90UjDc#pCPHWiq12pp2*eaaTt zQeetqa9EBHC`Z5%1*RMYN9FjCats_(V9IfDT#h@G6X1jbQ%-`Da(qNN1x_h28*D2u4*mf?a(WqnkWgf(?M;j=`aR3}9Ix31m-RqM*#^IQfKvGgzl3R3{??Gejo?A)OJ5 FF#zFGBxwKu delta 142 zcmX@$yv3QzCD;*)I@>^1#3f(;GgIpQ5%f_NAh zm>4*mf?a(Wqnn&rf(=08!J&Q(VA;tIipq@flg}wQgY{TK^)NCpL-a7<)1x`LSJ4;% D?2jW; diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 1983fa596b..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,15 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/pc/DSDT", -"tests/data/acpi/pc/DSDT.acpierst", -"tests/data/acpi/pc/DSDT.acpihmat", -"tests/data/acpi/pc/DSDT.bridge", -"tests/data/acpi/pc/DSDT.cphp", -"tests/data/acpi/pc/DSDT.dimmpxm", -"tests/data/acpi/pc/DSDT.hpbridge", -"tests/data/acpi/pc/DSDT.ipmikcs", -"tests/data/acpi/pc/DSDT.memhp", -"tests/data/acpi/pc/DSDT.nohpet", -"tests/data/acpi/pc/DSDT.numamem", -"tests/data/acpi/pc/DSDT.roothp", -"tests/data/acpi/q35/DSDT.bridge", -"tests/data/acpi/q35/DSDT.multi-bridge", From 5d08517fd723a8d2348a93a5706f6bd3aa659adf Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:09 -0400 Subject: [PATCH 0985/1020] tests: acpi: whitelist pc/q35 DSDT before moving _ADR field Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-12-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- tests/qtest/bios-tables-test-allowed-diff.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..1983fa596b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,15 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/pc/DSDT", +"tests/data/acpi/pc/DSDT.acpierst", +"tests/data/acpi/pc/DSDT.acpihmat", +"tests/data/acpi/pc/DSDT.bridge", +"tests/data/acpi/pc/DSDT.cphp", +"tests/data/acpi/pc/DSDT.dimmpxm", +"tests/data/acpi/pc/DSDT.hpbridge", +"tests/data/acpi/pc/DSDT.ipmikcs", +"tests/data/acpi/pc/DSDT.memhp", +"tests/data/acpi/pc/DSDT.nohpet", +"tests/data/acpi/pc/DSDT.numamem", +"tests/data/acpi/pc/DSDT.roothp", +"tests/data/acpi/q35/DSDT.bridge", +"tests/data/acpi/q35/DSDT.multi-bridge", From 366047d6251f931eb72049b8d32b0eb7f894cc4c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:10 -0400 Subject: [PATCH 0986/1020] x86: pci: acpi: reorder Device's _ADR and _SUN fields no functional change, align order of fields in empty slot descriptor with a populated slot ordering. Expected diff: - Name (_SUN, 0x0X) // _SUN: Slot User Number Name (_ADR, 0xY) // _ADR: Address ... + Name (_SUN, 0xX) // _SUN: Slot User Number that will eliminate contextual changes (causing test failures) when follow up patches merge code generating populated and empty slots descriptors. Put mandatory _ADR as the 1st field, then ASUN as it can be present for both pupulated and empty slots and only then _SUN which is present only when slot is hotpluggable. Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-13-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index eb92b05197..6342467af4 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -442,8 +442,8 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, break; } dev = aml_device("S%.02X", devfn); - aml_append(dev, aml_name_decl("ASUN", aml_int(slot))); aml_append(dev, aml_name_decl("_ADR", aml_int(adr))); + aml_append(dev, aml_name_decl("ASUN", aml_int(slot))); aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); aml_append(method, From 3c99559269ed6b6cc3051a1219e1785487b9249c Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:11 -0400 Subject: [PATCH 0987/1020] tests: acpi: update expected blobs Expected change: - Name (_SUN, 0x0X) // _SUN: Slot User Number Name (_ADR, 0xY) // _ADR: Address ... + Name (_SUN, 0xX) // _SUN: Slot User Number Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-14-imammedo@redhat.com> --- tests/data/acpi/pc/DSDT | Bin 6422 -> 6422 bytes tests/data/acpi/pc/DSDT.acpierst | Bin 6382 -> 6382 bytes tests/data/acpi/pc/DSDT.acpihmat | Bin 7747 -> 7747 bytes tests/data/acpi/pc/DSDT.bridge | Bin 9496 -> 9496 bytes tests/data/acpi/pc/DSDT.cphp | Bin 6886 -> 6886 bytes tests/data/acpi/pc/DSDT.dimmpxm | Bin 8076 -> 8076 bytes tests/data/acpi/pc/DSDT.hpbridge | Bin 6382 -> 6382 bytes tests/data/acpi/pc/DSDT.ipmikcs | Bin 6494 -> 6494 bytes tests/data/acpi/pc/DSDT.memhp | Bin 7781 -> 7781 bytes tests/data/acpi/pc/DSDT.nohpet | Bin 6280 -> 6280 bytes tests/data/acpi/pc/DSDT.numamem | Bin 6428 -> 6428 bytes tests/data/acpi/pc/DSDT.roothp | Bin 6656 -> 6656 bytes tests/data/acpi/q35/DSDT.bridge | Bin 11449 -> 11449 bytes tests/data/acpi/q35/DSDT.multi-bridge | Bin 8640 -> 8640 bytes tests/qtest/bios-tables-test-allowed-diff.h | 14 -------------- 15 files changed, 14 deletions(-) diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT index 8282d449ceaefd914b419f507a13f3fb7b318aaf..fd79a602a2aaac0f7d91d2ee2b1af8f2e6cdd4b3 100644 GIT binary patch delta 758 zcmYk(y-LGi6vpvN(>6`>{pO=-zHY!lJG6Ch2&kij;v8>4a26a~osMjK@aXy9keFc02_4YHa_A2 zaX?=ZhloQeJpJYfaYQ!~O+=GEB#sfsrU)F-qtah5MvUoKVuF~^ex%<_5mUOCI7OV&x5NxFqdL~}8RCp?CFY1Zea8AX s6^I3&QFLdX%9$m+WG}Z)FNyw56})1vy8W5#Yk19GZ~XB6IQ`lC1Mb_IlmGw# delta 758 zcmYMxJ5Iw;5QX7EaT3R|uOHWsIDTz_0#YQQps)m#6d-D|0VHZ93R)`ANU2!@h#rX= zi5{^TlIuC5{Xd^#d^d~D;x$)UdwF&44D7Bwxp0XFWOpX;gIei>&Ngg;E#f=X1||*> zhs0lqBg7GL>C2a6#4+&=qK#-1e;`f}C&Ydra|h8OzDArPPKn=wwm-u~bma_pd&aU@ zuH_C7?umOl=cmx>_X@7WmD#Vb_u;;{Z+wma6u<-Vpm*#;cqkqkKf*qON8(ZM*lV~J z*Zi#ipD6~%#E)A3UV@kq|01S{De-T6ouh{ocR5o_-&_vY={I2TZ@n-NFdfOfd=T}HWG;jXn+P-!Init3CMF# ze7FCnGt$hQHmA+;F^GnK|K!bP#?0!UUmhHThM+&kIpUm-5*LUIx(NFma}&|DhVc}W ze&TI?eKlBc3vRJnqtkb2ocA`|X1DeJM)nTeVRzVXr}JI7%kFC5%HD%}>>j)9eYnr= zYv0K}fCucs=xQhX5FXN3JUw587|}YJVvHEmo5Tb$p-+h^VoF^)%@v}eSBXo+C4ETD z5HpI^^iMfr&iBamJ@4e61-xJ{MyEeD{Zk1q*-O3O%f5nF>=nDbQw^`#Ywh>4Z{Q7k e!!G+4-m>$nU%mfk#^pcHH={rR delta 772 zcmXxhyG;W@6ougnT6^E`@xFImfD&k19!xo+4(!R%-)5&;;!D`VDG^_anJazobSVZabNom`v4w@2gb1v;h}h_ zeUE(vkHn+d)gJp89ut41@_Y$mLcGZ&ridx=8)Al-5q~1)h&l0)%UmHU;#b5K;)?hK zu|O<{QzidYB9?NGQs46q_pIQRcr`o!Dfy=wUW?ayf55(hH{y+Pyi*Hr#ar$7*mv+w fyfcn{5AVf$?MLhf_#i&au8!ER;cI&TEv(CbKs2L3 diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat index 33169838bed50710495d45e0d9486ac59b4e504c..973320cb25120818a45ddb3d8e3b3211f0c00adc 100644 GIT binary patch delta 760 zcmYMxy-LGS7{>8PlQvC1@^z9lP1;<79|frpkQ8we2gSL&SK$o^!n+9$u1*Cnp;yq+ zMQ|3p0T<1ApPqLL{C{}}=VV)N>&<1Ht(%LRp=EU}x4FH$_B!rbKj>AR7AHq*7jDCC zcAI@^+<`mnj`oG@yYMc1w{^9UeGlHFXVnDwsEg>*x5PeTpX$WC=^=XbC~<%|pihZI z#33D~W;+S@6v%e=F(dTpc`kYHSX8;e_gVt%2+53G657|S#Ka+g~kJux2 zxu+N&v&Y&S*(xKsurX|KvKj>92Dp5UWGRx2xk)dh&a?i1c_`=YuHMz#t0-;m?r)rd-8PrEF42JORtJ7lXT|ApYil>)hPcuD zTHJ)2;->Z$_7>a{w>noV?1%6n@r!DF{i8ObP5gs6LL3p-v3%(uI>b+iW5hA>7ov;k z5-$^(PY@@>kBC#mDe*pO`gigWJ-Nfvcdl`#5BJ6W&Uu>}{XT#P;(^|uV;{mp@vwKi zQv{F1Bkc|L3a-Re@7TxiSUlFg!9IZ};z{RfgMA85iQhAMz8T_-_zy8d%!sdZ`7%e$ uiC+;5#De%2u|zD1FAAB@5$D9uhzrC8@pmErQ-xT`9o7FGCm#>x=g|R&$ew!u diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge index 407066e1ac46922751969b823000e4fdfa542662..9583da4e4f558cb0bf6912733fbe8db7c1ad255f 100644 GIT binary patch delta 1438 zcmeIyOG?8~6vpu+O`9}*B~6>8P1;zT3T;t*fQX@v3OcX|&bkFRAkGExaVEu?I}o}8 zHy}f*q5I2_2TiE3$CwlvXsI)|PUJ(qU6tLZkLuA}R8)lQa}2j=OG zu>dSkFHC%l8$d%m-pIawi(k(~H$^wo{t)TQ@gj0jZtMtlP1J)>Z<+u&B>4MP#I`qO=2iEDQE5}`+O9!#U2CzZ5j7?yZ zz8F2AN5eI_ZXf82efinCN4&5AJrF%eJJ~(C?-qJX^cFpNfA`%+ZquVDUpWMZ^vxIn yBii@n$qukXH;i3imp&O|U_9>!huZSmt?pv_dtcqf>~HV??;`bsz4>VUUHt`{a3nzh delta 1438 zcmeIwOG?8~6vpwBG;Pz{SJJde+N6!esn8b12Z$KzsGtLj;H+D41L9l|A7@gWxdWjq za0BARks!{+J=i4Y!zDQBq?F(Pp5$`Kd@`RrpV#bodUitQEIvA2{wDwV-rfw4jp=ZA zW+qWfV}(e|4rt2*+remI0Ne+Z3iyo6kmTw3NG2h$2!5ntPKxiYX!`~j>0 zE5sWOIavi(i7$aQV2$_{SO?aLBS*$9phbKEw1GD93$Ouf5dZXK+yOeo2a#YC*d)FM zwty|-FQ5x_iAQU)ZV%|mzPxnZV=T-^_oe$uXR9y!ZlkxQxB1Ea+jj@KL;UE=Zv w{0$6&A@RN^C%eEd@eQyC>=AzgBVa^}fq$s4zQxtIsQ&+3z>% diff --git a/tests/data/acpi/pc/DSDT.cphp b/tests/data/acpi/pc/DSDT.cphp index 013de154913063ed1ce3f154444b9e11f4608eac..27d1fc90f5f51c48a44bace866a19a42d7170129 100644 GIT binary patch delta 758 zcmYk(J4yp#6o%nQCdp(n_sQHcw=KjX7Yo4wwGb3kY-~n%;1=9~Ag2`EfK9;FSlI;x z!3|iL%=z*ktAY37E6)7u*?PA6a^j{wzA`(VZbz@LZ!V0k-n1XObQi(2(ZL#6qcgX5 z5qpR|dXd;i?9;cz0pfrTJvG-6b$XIGL>$tmL<7;FsjucE#1TFE_3jK4(d0AC%^CA- zzEpQuaEsmAI^6}@Zg0bFcDvm#WbeQocBl2F{3jRgvb*fE_uwA8*ZP6%eYnr=v&%k! z2kZgehyR~x3?9>MsD4z47}A@>2r;5xi7{eK=aHHxhzY$)Oc7K1kvKt|&{3@B8Dd7y uv3jN)G3PV#_RJGGvw#=u#n$N|QO{JuOZKwepUS?1SM1fs_usAbWA6{Dl9@*U delta 758 zcmYMxJ4ypl6vpu*nIx0RJnqb7UYXYxVv&c1;DA~P3Mw`>qdRa5Za|Pz3U0tA;A*Vw z0)pTMEKKg458MBbuQ>N^=9~HY%S)Q;n+vOFw$1UCP1GZ^)qyY7GMu%hW&>;xpQ%Ra z*hlOWzaS0}2gKiqL&PERp)Ye2(IkFC93hT~KM^fNi+C2ue2h3IehixK3>(pwGwkgd zi+r(?I~=$p?(CfJLZjQea97;b`z7`s+!Ob-ukcO^uEbU6*!yr_+}D19eE<){gU+!J z;h}iQ_tF11O~4c4+ejWNLX3#t5M#uc_!lujOo-28nWu;;@hf76m=XUVP7$ZXM~TdH x#GLp!k#8yx3pu0EXP)595?+dzJLiW~zNvy&;+5W?Vqe2+@p|j~?@soy_Xi(rnMVKs diff --git a/tests/data/acpi/pc/DSDT.dimmpxm b/tests/data/acpi/pc/DSDT.dimmpxm index 289ec07c07734f6fb10e1f1f3de7b3de2a4642fd..efa46bc7860f0b026f23175ccf3ef1e1eba59c15 100644 GIT binary patch delta 790 zcmYk(J5Iwu6op}nIDR{^@~aW8+gOs mD8G??3vbz5cG-9Ej=iIk?*A{%!E-w9^g}HW7hf-3eDDj{aG22m delta 790 zcmYMxJ5Iwu6oug{;@IO?V#n{Xoj^+!1O&Rs5LzTaw0Hq5fh|Nr;x2$CfJDopSOR!_ zk7)l-XQY|gZ};2J*EH%L9&f#g>bu>2Kr|tKPrET%h!*h=;uLX8++|&1<~E{Dsvpj? z`Ka8~rT6ouh{ocR5o_-&_vY={I2TZ@n-NFdfOfd=T}HWG;jXn+P-!Init3CMF# ze7FCnGt$hQHmA+;F^GnK|K!bP#?0!UUmhHThM+&kIpUm-5*LUIx(NFma}&|DhVc}W ze&TI?eKlBc3vRJnqtkb2ocA`|X1DeJM)nTeVRzVXr}JI7%kFC5%HD%}>>j)9eYnr= zYv0K}fCucs=xQhX5FXN3JUw587|}YJVvHEmo5Tb$p-+h^VoF^)%@v}eSBXo+C4ETD z5HpI^^iMfr&iBamJ@4e61-xJ{MyEeD{Zk1q*-O3O%f5nF>=nDbQw^`#Ywh>4Z{Q7k e!!G+4-m>$nU%mfk#^pcHH={rR delta 772 zcmXxhyG;W@6ougnT6^E`@xFImfD&k19!xo+4(!R%-)5&;;!D`VDG^_anJazobSVZabNom`v4w@2gb1v;h}h_ zeUE(vkHn+d)gJp89ut41@_Y$mLcGZ&ridx=8)Al-5q~1)h&l0)%UmHU;#b5K;)?hK zu|O<{QzidYB9?NGQs46q_pIQRcr`o!Dfy=wUW?ayf55(hH{y+Pyi*Hr#ar$7*mv+w fyfcn{5AVf$?MLhf_#i&au8!ER;cI&TEv(CbKs2L3 diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs index 59a6d5860887b511b7ce5f17d7044a08c14f0f60..67b60cc44a6ebff029524abc27ef48f90868f948 100644 GIT binary patch delta 791 zcmYk(IZnes6vlCjcz5D`ca|$eW^E`8sgOV{qMfXw^i zNBjTj8);^??Y8|~`(fX$?#G%o((LZx@x~p|i{BN9I-+j(JJabdI%(Ro-i8}+gWcFU z-3I!8Z^BJ>Q|%9BZ^12gOZm}qINyfb>^8gX9k|2pC_k3H3wPOFcG-JykKOz8(?sTD z@R+WmZvRjd#0kAi^bvjfmKY!gbRG}$5HX}Ti4kH%UlL=)n3l;fPY@G&O@?nu5mUZK zs;=3|H8Xg|p6#5T)8U(Pc+Q@y{e|occ)?yMzm#_>;U#;?F8c~zu~*7hvajJad(AHU m2HvnYw9fy3(-b_Vr+j#*8RCpSB+e1%^doVBxY%45(ZMh8bDdxS delta 791 zcmYMxIZnes6vpu+*12P?5FUl_*D7PTK;dtZE;&W_72<;ca$Gv@4{ViS3C9|+!Ocy{4~Yf z2m8cVaj!3GhBzaBM+^`H;%~$dF(f`uWF8?##BYc(Vodynm>?#^>s00`VoLm)$}?q% znH(ci$Lw*;9G;8kqw{kn&s4w*@j~q{urJ}Ic&Ypn_f)|v@k%@PHM|zDm2a?b;Ei~r q9s3sEinqKi{-0?Mo)bS6a#0J!1@Q;s5^+iVgSbLm(eAp84}Jk;O`Tu> diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/pc/DSDT.memhp index 47d63dec8f997417d7512a694a4825fee874d995..084957e53fb51e313dc824e5a8733f02ff77542c 100644 GIT binary patch delta 759 zcmYMxO-jR16o%nS(>6`>pPQul$El;*fmZ0ifH)LXoEn@7f*WuPjywxda4NU~H{b%g z4^7V3dq#ox;TxQr-FCPAc#P7ny|}SQqw&aWZ||v#Kek3jtmsI6?o*`!REHOvS>04rfSdd@nd5Kuk nL!tjug;?<&)o|yf+*!kG_PTdEFZF+F;0=58@5i67%5G@uR5)vC=3sl^NfJBSL2G{@# z$Uea1d)oigDelaEx8Hp{Cb_=7yK*LWuP<&~q6yi(34Ewds?EB$jazU_+!|bMw&GLx zl(PjRLX_r?9ed7WG1K7a?}f!S}d580drw-nUcmIC;`C9)T`~k~;lsNzZ diff --git a/tests/data/acpi/pc/DSDT.nohpet b/tests/data/acpi/pc/DSDT.nohpet index 47e4bf62ebe742304783e76984045d7322c3a421..46827e285421d4fb38160f6c15dc9134d7da5446 100644 GIT binary patch delta 770 zcmYMxO-{m46o%m%3Y7l;(LxJ!3osCvnAilJ=|JPeNp%Nq!5N8(i8(_PH{d`LSL4VH zn79E4(tAGcnZ8fIruTNc*e-TYUf9%|E7veOhE-qRT-qIa_3A@35l#A$*hTEpiLamR zA@=B5Vjr7ylyPG19#Y+*6A)Z4|^Bx zvb$=(l)VS{*gfT|xqiP7_t|}R*$41|Jy5=ueFzWPLw4Cm@Q6Ly`zn!n436nG))$o^ zCiE^bMNH{W;t+927m1!{h#9>}%n@_?l{i8i(P^sZW5hANr201%hy@>`P{-WJF-v&K vUbapTL;ag3@Co}w?ayRCg-_Y1%FpGVX7CyNj9vB>ykf8RzWDsezK;F@Q0JT} delta 770 zcmXxhOG?8~6vpu*P1`i@ciKF+&}|L$ZYy6e<^2xa5qAd1-i5p3uJR4`9^4c62FKoq`{Mq=*CFNsI3T_aWaZY?1$$WvhAbyGDH)V*K93xZ5+~Sxy vJQvS<=Z9E+Qvol;3$;JPzJ!0! diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/pc/DSDT.numamem index 1c4e0c80216b53463fbec8fc548007f0326c1829..ebdccc880def932fcba0cef8a7cf47ff7cc67f53 100644 GIT binary patch delta 791 zcmYk(J5Iwu6op}nIF8@(D}KaDyaZ5yK!*&WLlhutZ-pfw-8O81Du|AXEP*Ak0X9Gb zo_jKv_Wyh=&CF)GS#Fy!>e}_4Zx{o^Ztov%-2okj?LL}_COt|VA`a;@YzxdSM9c2_ zzgYAduj=FT&W4ZRBlc16v>luKy$!e7ZM8p}T*9`;1-obNHNnPP_d7GcCXide8OkHHgidSHuUuW5%QY delta 791 zcmYMxJ5Iwu6oug{;`sfx{f#{{hkkqO63vKLem_MGQ6qjpoFmSOKm9&ea~)A9a~S`p z^Gmd;kIn{DxdAuCjnR1@Xw%+=o8qS0A7gL9Epbcv$)Wt;hTG!ygBT))#MiNW86if*Plz#MO#F?QAST4;iOf^P zl=u;Gfw&<4O5~X`#7vHnsbgN?m^nNb&qwF?RGz7T7vhE5Ut(XvOYu_q7WY)aEAeV_ r>}z-}UMs)CzJWL5&E(j(@K(I#kL>@Mmf$7vTPC;HA$IiY zk1fO&eM)R2w&~E*cXkjv^dzy1*rgANJ;WXzC_Oh3O?p&igjeb#_RaO~09Kz$cbOi~ z*CyP8TkKZlbmO=8`vH8wKB)Ig+1qfN-DWTJ^BuUu?$mxFdl&AqyX>;};2yhIdm(!T zSL~|tppd-}_vvb+ztj+MNLz^`#1Z{U3=ji43-mlh4Cz(k7;#Kr5+lTj=AoWX5GV8; z>i-lY#(a*rKIcl#nZOhFq;h%~>;II(Q}(ppU&ua#XY3ife5V|qv*)#6%6^p)q$ZJRVr(}x=nD%2Vf!9aE3Ktyp|x8Me(js+)Y*i8s7#0?1I zSO+e_-kb9c^Z(@wxyg39UA}!sesy<$P41>z-||mX#pbeMFGHdR@u@o3ruhz{L;Rwu zIyMoT#Gi;Q#1`>kEO)jM+r&?Z9mEdt2VxhoOMIYZ?jpLxkGjh2D|v|C{s873J+9QM zI9_aA>pt8U_l@&SuT}2@cpx6w{R;aK9*T#xm-74w9*IZRPq0^TC9Z16K8DBQvGo#r z4cFq@cv52DgZGH92J)r)h<)N6;s9|#{EL_%Cd6ln%u~da_!V)8I3)f;%n&o;MJn?V z;)wV;mH(6@=5mhQo^y?Jj^ShRv2lJF%6}^0g?M527uZkW6Y)vy_)b&!RD5dv68jl^ UCO)ej`#F3rKHvM%`(LJ=f7IirEdT%j diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge index f8a0bc150f5a249bd5d09be6949c97160de1ef82..37ef245f673bcbd5385cb332cc0ccf06d5355485 100644 GIT binary patch delta 846 zcmYk(y-vbV7{>9o6k5txODW|W3}Uc}2}q*oWQ~K9gT{f0cmpKPCfhRS8uPQV4Ysw8g6=be`C1o>`U|Uf__F$lu6kzOjc8= zxziJx?b$KZV)ZP=o|SobzFfQT96ZOKQ+_T~2p+LV z$}eT#gg4on?6QyHF?&qu^#3!pz%4qT>WgY4w&_J;2eCun61#|9Iy%(z9%7H4CH4{f V^d)hCIG|CY=R?Hd`(tu#{Q@-vsJZ|E delta 846 zcmYMxOG?8~6vpw>Jeo9pB~8=x-AJv}fY4gd>d1%#M-CJR9ThhqI2PQ1!!vUgf}@Vy zfZztiwV2#{KAeQ`|M5ZY&2F>XyuT$uc6Wb6?l!x+&7Z|PFQ+U1O`NEZl9C!xNoy(B z6JG3DaiN|8HZ*%i;e+LR>nbxm;8au}A!h*hlOW{~!(!2gFB*G9MxiiC+*$ Yh$G@}#4+NSI7wwbL7dRXQ+jRu0kUnVx&QzG diff --git a/tests/data/acpi/q35/DSDT.multi-bridge b/tests/data/acpi/q35/DSDT.multi-bridge index df91b798f79d4564b049e8a7dbeaa5bb99abe635..e9b67e9ebe1e3b4de513b68129f719018ebeeb2f 100644 GIT binary patch delta 41 lcmX@$e873bECsH3N0%T54#(h7zsXjL!IQr$SfUEG0RSXw4F>=K delta 41 lcmX@$e873bECnvd;7~sXj(A6xpvhK>!IQr$SfUEG0RSX+4F>=K diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index 1983fa596b..dfb8523c8b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,15 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/pc/DSDT", -"tests/data/acpi/pc/DSDT.acpierst", -"tests/data/acpi/pc/DSDT.acpihmat", -"tests/data/acpi/pc/DSDT.bridge", -"tests/data/acpi/pc/DSDT.cphp", -"tests/data/acpi/pc/DSDT.dimmpxm", -"tests/data/acpi/pc/DSDT.hpbridge", -"tests/data/acpi/pc/DSDT.ipmikcs", -"tests/data/acpi/pc/DSDT.memhp", -"tests/data/acpi/pc/DSDT.nohpet", -"tests/data/acpi/pc/DSDT.numamem", -"tests/data/acpi/pc/DSDT.roothp", -"tests/data/acpi/q35/DSDT.bridge", -"tests/data/acpi/q35/DSDT.multi-bridge", From 166cff2b8fa428ec411dd4beea98d8c4aa07f76d Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:12 -0400 Subject: [PATCH 0988/1020] tests: acpi: whitelist pc/q35 DSDT before moving _ADR field Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-15-imammedo@redhat.com> --- tests/qtest/bios-tables-test-allowed-diff.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index dfb8523c8b..1983fa596b 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,15 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/pc/DSDT", +"tests/data/acpi/pc/DSDT.acpierst", +"tests/data/acpi/pc/DSDT.acpihmat", +"tests/data/acpi/pc/DSDT.bridge", +"tests/data/acpi/pc/DSDT.cphp", +"tests/data/acpi/pc/DSDT.dimmpxm", +"tests/data/acpi/pc/DSDT.hpbridge", +"tests/data/acpi/pc/DSDT.ipmikcs", +"tests/data/acpi/pc/DSDT.memhp", +"tests/data/acpi/pc/DSDT.nohpet", +"tests/data/acpi/pc/DSDT.numamem", +"tests/data/acpi/pc/DSDT.roothp", +"tests/data/acpi/q35/DSDT.bridge", +"tests/data/acpi/q35/DSDT.multi-bridge", From 87debd32a8e0fe272135d50ffe52b9287ccbdbd7 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:13 -0400 Subject: [PATCH 0989/1020] x86: pci: acpi: reorder Device's _DSM method align _DSM method in empty slot descriptor with a populated slot position. Expected change: + Device (SE8) + { + Name (_ADR, 0x001D0000) // _ADR: Address + Name (ASUN, 0x1D) Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method { Local0 = Package (0x02) { BSEL, ASUN } Return (PDSM (Arg0, Arg1, Arg2, Arg3, Local0)) } - } - Device (SE8) - { - Name (_ADR, 0x001D0000) // _ADR: Address - Name (ASUN, 0x1D) Name (_SUN, 0x1D) // _SUN: Slot User Number Method (_EJ0, 1, NotSerialized) // _EJx: Eject Device { PCEJ (BSEL, _SUN) } + } i.e. put _DSM right after ASUN, with _SUN/_EJ0 following it. that will eliminate contextual changes (causing test failures) when follow up patches merge code generating populated and empty slots descriptors. Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-16-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 6342467af4..fc23cb08c3 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -444,15 +444,13 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, dev = aml_device("S%.02X", devfn); aml_append(dev, aml_name_decl("_ADR", aml_int(adr))); aml_append(dev, aml_name_decl("ASUN", aml_int(slot))); + aml_append(dev, aml_pci_device_dsm()); aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); aml_append(method, aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) ); aml_append(dev, method); - - aml_append(dev, aml_pci_device_dsm()); - aml_append(parent_scope, dev); build_append_pcihp_notify_entry(notify_method, slot); From 1ccd2220948c8d577ec8a3473a15f52ce2841800 Mon Sep 17 00:00:00 2001 From: Igor Mammedov Date: Fri, 1 Jul 2022 09:35:14 -0400 Subject: [PATCH 0990/1020] tests: acpi: update expected blobs Expected change: + Device (SE8) + { + Name (_ADR, 0x001D0000) // _ADR: Address + Name (ASUN, 0x1D) Method (_DSM, 4, Serialized) // _DSM: Device-Specific Method { Local0 = Package (0x02) { BSEL, ASUN } Return (PDSM (Arg0, Arg1, Arg2, Arg3, Local0)) } - } - Device (SE8) - { - Name (_ADR, 0x001D0000) // _ADR: Address - Name (ASUN, 0x1D) Name (_SUN, 0x1D) // _SUN: Slot User Number Method (_EJ0, 1, NotSerialized) // _EJx: Eject Device { PCEJ (BSEL, _SUN) } + } Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-17-imammedo@redhat.com> --- tests/data/acpi/pc/DSDT | Bin 6422 -> 6422 bytes tests/data/acpi/pc/DSDT.acpierst | Bin 6382 -> 6382 bytes tests/data/acpi/pc/DSDT.acpihmat | Bin 7747 -> 7747 bytes tests/data/acpi/pc/DSDT.bridge | Bin 9496 -> 9496 bytes tests/data/acpi/pc/DSDT.cphp | Bin 6886 -> 6886 bytes tests/data/acpi/pc/DSDT.dimmpxm | Bin 8076 -> 8076 bytes tests/data/acpi/pc/DSDT.hpbridge | Bin 6382 -> 6382 bytes tests/data/acpi/pc/DSDT.ipmikcs | Bin 6494 -> 6494 bytes tests/data/acpi/pc/DSDT.memhp | Bin 7781 -> 7781 bytes tests/data/acpi/pc/DSDT.nohpet | Bin 6280 -> 6280 bytes tests/data/acpi/pc/DSDT.numamem | Bin 6428 -> 6428 bytes tests/data/acpi/pc/DSDT.roothp | Bin 6656 -> 6656 bytes tests/data/acpi/q35/DSDT.bridge | Bin 11449 -> 11449 bytes tests/data/acpi/q35/DSDT.multi-bridge | Bin 8640 -> 8640 bytes tests/qtest/bios-tables-test-allowed-diff.h | 14 -------------- 15 files changed, 14 deletions(-) diff --git a/tests/data/acpi/pc/DSDT b/tests/data/acpi/pc/DSDT index fd79a602a2aaac0f7d91d2ee2b1af8f2e6cdd4b3..da2a3e5c0551ac2d1d8a0a40b92d3235d5757475 100644 GIT binary patch delta 864 zcmY+?y-LGS90l-*wn@``wE1k(q;(Y(B-P?1MB7!t;^Yv006|wlL088>7hl5SE;tLi z3i=2>gx-Ho@=w;o@1A=($vl}S&l^U*um-Y{%}$Th)%@PD^9v&oS$<=L!P&#{+AP`2 zlq{W`Xp+>BlvKzDiT6T`woB23Xp)Fbbd0z|hLA~I7Gj4x6bOaHYbm&+1<@j5c5urs zcc>65iStr$M;oF|Vo``OcW4lr5ZFi)8!dMkbC(XOSENpBK6YtMoHi)?sbwZ*TUOO| zD7&j=UCKUdnMK*UT|H}4c3sOHku6`H@~d6E+NA})ZLD~}3wRJ7iA|>v+~Gs`ByJ0F z$Q?b19*K`qa7O^K{O^V?ZkcdL2oX}pRVlcm578&_R){HgL=ce>_#P4OGUcuqGOoy& XR(%}&BV5C`xYDJ`Y+gVL6k4}0}MLaGvD!l4LPO(dQ?G(G|^K%!R?FOzWLB{V(= zXA=@%fQK-+GdtVsKfnF&?#wpd=AW02VV2A12kRUPH-Im12(M0pS&g#n<^8d?%x_Dx zEap$Prs>j>*`=ccE66kKJXFkqvKYwj>nm~f~F?r5NBz{pc> zx#12Ag$3)1;EpDWChS!);SL*x4VkapGU1LEiWaPdfQ?VXbZAC!keMs9QJb76v$f28 zneAoPmRT0i*+6D1nRO@=ODy=cA-*;gOAM=U#vhLmMgm3z#V%*u7$b~f*HI>P&sAL% zT{u<*cO)nhn1)KnoI6q!DST7}cl1#7;8zt3?&zcF!#GlIS#ZYy#Q@%ffL%m$9?}Hh ND6y-LGS7{>7gY;&wN&B=GFrh}t`);d&hNp)7RI634J^a2#b-Ray&!5h$76kHVq zXQ9`idGaRjIqRQao|Bv`$IJ1ebd@c0Rl39M>fwB4elRUXS)5+p(0T zG1+fLmqZuB9?-^wHyjd9B^*&!dye{%L4DdGZwZn@lcJL9YmjMe6>ZnkTMzBdXlrQi zM(d-Er2gzW+Ktg%w3oW6Pf6c3<+t_dZ9RPXj^7CWa!Eo$+&1EfH+&L4#9J$PBOnn# zuc>0SQk)Z%C+3 zcmWcg!QjrFxwI$eo|!xQ{=UB`ZA|SBYEC!(_AipF@Aq(*0I)& z!5te7G8)Jntuc^>Nrs7uZahfCBE!O}GVtr9rd1v$pW@pO4!hyjRjkQu%Iu8Unpulk z=Bc;m%qGliW-DfnV%PsS$z@xYwsoroT_sk>%jM%9i5|Xu?KF>)^2zYAJ2IpZkP%=Q zXpKS|AsHd&M}{;aG9qksVGV76s;$*dQvw^z(&%(~1r%reE6H_1=!59yMsfB*mh diff --git a/tests/data/acpi/pc/DSDT.acpihmat b/tests/data/acpi/pc/DSDT.acpihmat index 973320cb25120818a45ddb3d8e3b3211f0c00adc..884d4871a2a0b87db2c0dd7e6f32486ba9b7e424 100644 GIT binary patch delta 842 zcmY+>ze>YU7zOZ(Rns(WqDkBQYw`$o(ApuOrLB{Hz@m#o9>AAScSX6Ipy2Ex_yp1? zaC1_e1$_V=^qzdlce5UTIp5`EmdujJBU?P%(UO)<5BKzWaqrmT()N_BitN3VEgMmSy6`@x9~o{pxhBmul&7d|*^6T16YmE1GNbdG zxT8*@4)KUFma2gG2-3G#4A((InA?cqs&Tm?TUoXkSxqlTG0prOZM0UCLU>wmkLQHnQtd){$BE>Jh)%rB}OH;K!pC zN4$VX0{vpgCo$#@pM;N&+d^oY)Cm9p delta 847 zcmZ9}KTZNc6vy#3q72LON0e+E?3EC2ui diff --git a/tests/data/acpi/pc/DSDT.bridge b/tests/data/acpi/pc/DSDT.bridge index 9583da4e4f558cb0bf6912733fbe8db7c1ad255f..31a79aa47673c14f7e564475c39bd38c872f8165 100644 GIT binary patch delta 1069 zcmbQ?HN$H|GT-DyymD+D@xh^f43j4c3QI&c`LYBXSj2P0JGun%FfcGOa5w@b87FTP zfU08zsbh(5@@JWRgx8oIte1-kAt=UY!Ui&riy0&~xtm`Sq<32-X8t#|aiIgosV<5|o-eR|aC{Z6Ny{l&vEqHQ8Pk zB3=t*Pk^$|0of0sY~pJ zAp}5CBh70s0v}Q3OjkJ$+JZuZtVxM-$2<9fNWb)h`6DG)Z{)08yXJc;BdH) zA|?SAGY|vofvS@Pi#4K%NrA=IDniVDEhaVjACzq)E;ZR-2_oJLWG{fS?*Z8#p=^B# W>CG7u;!I%2k4EtDj9_QwtBe5r@-&P9 delta 1082 zcmeH^u}Z^G6o!+uV2sixxm9zMRBN4uxV1wm6{kQA8k{<0aB%Jm2lLhFXYhb^xFB*t3_(my13qz zBw12h;mxHC?_8jrUXTyZJRvAt&=jZ??M($5X+;i=9CWz>4@C-N`^Sb)#!KW=okG*$ z`90$S@*Cqha>bxqYQ&zTZNrsGHWQ&MGEHP-H}Q5vwsa}@Chu>SDU6T@j2Fmr#to9$ zq?Ycg<0d-ve;Mhn1{wy;vPM1aFwrom=wZDCqs?B>!YR{O-AzldPk4^!(k+mgcA>r}L|svYB1zMz*7SBFj#7-&@?AZ_RfP zQaO#2OI4B@k{k=!AaP%ay>Tg;5KR&vrQnVhM2o~>AGhpthYTT;xGe>Dv?1Cg-U|_N zhXSFH7!Pnu#2p=o4vA$UCfuPys6t>PRcw^+GT|-_QmaUf)?660CQf%Ld#YtU%6@B^ zPT9GgHAR-cI_6hfc(p|fJX+Z3m=~}iY!W}E;0_1EA#rA- zO-{l<6bJAcDJ`WH+R{%x^ay^{xE+LTjS^Q)>;X819>I42E&08?oP+O&@DWVlrk`QfqU@^rd~PjnA8Wf7vsc$J zOv4t(DN_!c1hW&oyH>D`unmr%AL~(Ym4(8BN*DLsVWY5N-4NW-LD7MOE(-2&P&iNq z+C2*H=%VPtN*52@;i7P1-w@p4q3}S2r&FK`X_*(aBUr1fr?P{}`YJ02H0!HurLsU} zdzFPM6A{f0D3hNk__h(=Hj&15CS0XB^jh`lWuUF>kh`i{!uV^A zd24jZ=)w>IWz0CkBEyn~?UXXlst#kX?l$8rn@n3VZE03nm?+Evd(_w-*q6q7UVm_UX;H-_Gn-yH)oc!XeC|jjHV9>(yE>?t~-Sr?;_TSccQC-(N-+xRGu& zWDL+4fY6O4XAIF8Lf11m!$!jfGrqh6MV#4=IKS+`UmBdd!6&gRVh3U)Vs4^luZam_ zV`3e#8)9avW?jW@FFU#CwjQ?iWI<1fa(NAZe1hTxep79E4M+KC_%P2jy-LGS7{>7gY;&wN&B=GFrh}t`);d&hNp)7RI634J^a2#b-Ray&!5h$76kHVq zXQ9`idGaRjIqRQao|Bv`$IJ1ebd@c0Rl39M>fwB4elRUXS)5+p(0T zG1+fLmqZuB9?-^wHyjd9B^*&!dye{%L4DdGZwZn@lcJL9YmjMe6>ZnkTMzBdXlrQi zM(d-Er2gzW+Ktg%w3oW6Pf6c3<+t_dZ9RPXj^7CWa!Eo$+&1EfH+&L4#9J$PBOnn# zuc>0SQk)Z%C+3 zcmWcg!QjrFxwI$eo|!xQ{=UB`ZA|SBYEC!(_AipF@Aq(*0I)& z!5te7G8)Jntuc^>Nrs7uZahfCBE!O}GVtr9rd1v$pW@pO4!hyjRjkQu%Iu8Unpulk z=Bc;m%qGliW-DfnV%PsS$z@xYwsoroT_sk>%jM%9i5|Xu?KF>)^2zYAJ2IpZkP%=Q zXpKS|AsHd&M}{;aG9qksVGV76s;$*dQvw^z(&%(~1r%reE6H_1=!59yMsfB*mh diff --git a/tests/data/acpi/pc/DSDT.ipmikcs b/tests/data/acpi/pc/DSDT.ipmikcs index 67b60cc44a6ebff029524abc27ef48f90868f948..e819ce69461a36b6fab5e2ffeba90dfe558724a7 100644 GIT binary patch delta 800 zcmY+CJ5Iwu5QdFp6BCHv51f$X3c*E43Xm)T1&APss8aY0J^~b!P`Css2Y>>J%TOg8 z03;3o687)0XSZ8@`sUx6*{((huy2X!U`Li%y9M?ru{PMJ#J0iqZPeyx zHqABWZadU%2a`Y5#sN=mkWuaCt1&pkB*R3;p+mP!IKv{tg7MH8oMDq;!&ukGlrtPM z92g^)Zkck1ONI;Mwl)&Z@W}8=gI>`qcT~M%!dX6}pSP1qfv0bp4 zFV;q2ONn*Cek9fdO9HWWuVhu%C){^v@HB2p zFCg>+1!>>BnV0RyH$Q$evn{s8_fo)03}7kpwElQD7sYL3HRZ!g&oE5GDi^PnZNjc) zOv&h=(Sfmh%77;~?OM%o>KyzaJm$g|u`aPcVivJ`Pt9HsTM@H~?TB3x8~bXur`XMD zpF3{rU|UBPbd)F;pYY-WMFDo8oo2#OE*dV>x-sPp4-F4CErTqf~L5gHNfTLx#uXv9!P@`-h%j@ef?f(@~R*n!v;u_{)xDX}%N0kJ)? zA+fTrX0H{KPkiLI8Me*j6SKBB=f!grb1CLZl;56n;t0hNyd^_;7unBe@_Y6VYPGlp diff --git a/tests/data/acpi/pc/DSDT.memhp b/tests/data/acpi/pc/DSDT.memhp index 084957e53fb51e313dc824e5a8733f02ff77542c..03a9decdc1563f5e759e34dffdab4bb34645d9b3 100644 GIT binary patch delta 863 zcmY+?y-LGS90l+eOOvKaY)zW)M4Vj&>j&7SA37?vI0*)4L03Vi?k?s*EVv5#0J{4E zeGk3=oZSD-didRQFDF@#)}z&8x|Twy_2LSQyaOjOQt#9cO|tw@{3-1XIgHz|9rWj)G% zYFVGMEKtvGQT9;F9Lm0GnM+weRL>4XR=#?|ulDe2j}~|evC)JV@F9E>-<6nhM*tC! zNF#Jixg&%qf2#XR%(x?hh^XUJ3hsy@ViLU=x14fE0+Eoom4Z7`h*SuC&6IaJ delta 861 zcmZ9}y-vbl6b9fDu`Q*bwWa@5oJov{zX>b|I%CV}KpTLKQuz;nXU{>d>7ErcJS?~GnzCJxY zDeZDJd2|iKH0;r~$y9|V!9>9;h898#zJhc+Qi(IEvQgO3@90808Ymht*TuPXI4B%g zSA=vlQ8b|lwJ8_U;i7P1RuR(CLeYYiE-s~`jiL=+^fv|i5iN6%b_8?I_BmT~=5bcU z^z8v>GtPX@R-6T#c?o^np-dg|T3#FCYeRL!@E?>Pj}S%*Mg-L@$I=)hjA4*!TOLbQ zf+B&1E+*2EqDbMpBBUcjk->4MO}UYd97PVV6(Jp66kYhx#jSJ{C<-{r)h!1(?evf~ J@V>}DYrlC)%KZQU diff --git a/tests/data/acpi/pc/DSDT.nohpet b/tests/data/acpi/pc/DSDT.nohpet index 46827e285421d4fb38160f6c15dc9134d7da5446..b413d9f31d483eca02f45ad09af2f556581ec381 100644 GIT binary patch delta 842 zcmY+>PfEi;6bA4JX_F>R+cbaLBwDY~Y74p$jLp^x7B?0Qu02IvbtOoag?a#86x@0c zcV0ly11M;|yyVSnKYsJgym_n9YP4Nj+0q_lYby*E_ZRB?V3_J@oLn{)MOE~8el;^x zh|fwKRiZ|s2657&jzjLKlc+;HRDwG+5*oxuDaPEPlh7fCZMtR59Ssrlprx14c@Pr`@TRDwHtBzh2ErI>O@ zpF|(x)TLXd+!2r{rhP0$!W|)rFz=u(hWQ^ATTHksA{hxX!f)Pr;wE;Hy-C>~GRqg; R0NIU{?f+-)>(+nY`2!^e#-IQI delta 839 zcmY+>Pfo%>6bA4b3oV8IW74FQ8K;o8*cndB- zLZENnn{L1S=9`)KmXqaV`|DbEHTx`_O9(vyU;a2Pzu(N+{as~OGXLlqhH2RHBusF; zOcPHeS}0mj>f(Vr+9=wvZV2wMP*`x##gsd26gCvT_KqocbWn6)rHe=Ia8Nj~ZwT(_ zqUeGQ&bL4rq&TCVnh~rib16Ge=22FJ>a0)Min4&RJ!K(fvaineRd##c%`?AN;A=&_ zMA3wjKOP~BY8WY4Z(DL>j4+0U(5C#tRSAj&b`8ND0~7;rBdz0=JBBERFmDL%NKvG) x(M8T38H(&D)-K7pVuWA>@3nwMtVVjJ1^_$Ct|@a9<;IlFDZ5eG-zNFLI09ThzxDtC diff --git a/tests/data/acpi/pc/DSDT.numamem b/tests/data/acpi/pc/DSDT.numamem index ebdccc880def932fcba0cef8a7cf47ff7cc67f53..9e701b2983f9ec45af9c26d801545c2b5d112a10 100644 GIT binary patch delta 800 zcmY+>O-_SA7{>9MP{0<;H%P1P5o+i{Tq#ZC%CFeCGKQ-dPoQC2P2ASRXk2=V?%a9- zJ%A>fd3fQS+5Yq6VHg(aB7GV6%9S%L$Gv`Xd2_1G)1AUB^4Yo7YH2MqpI@AGG>Gd) zWQ}N(XhW=OG2soJgf4_(7Gh5?UtPa?+l03al7=J=Atp&hvLvm0o4RV$Y+-OVna)~3_i`0}4xWc=k02?yfHqm7I=ToNwCeJ%EQ!z1BA zd^LhMd=fsyzE5w-c_SbZK-@NhH$oC2#Ahw0yb+OzgrL6|i94$P;*_^ylCdOX+~#{A z-|!}y70N9^yHZ*o?OAC9v_GY7p`AtY-Zt8!(uSf{r#|FUkLc7R+(0)Tyv^c|wSNky B%^&~( delta 790 zcmY+B&rZTX5Ql40Xu;a;|5{Y)8)(YGa-(Rxp+w@zklwxd3cdlEDu`xUKEFdU$aR!!+z_^7_;^VR2-X zWHiudz*aYUoY6$12?L=`>2ZdIh6OWez?aA@yFN^|;UfqS-QbT{i`d9hUYpp0*eS6s zF^AZ|S8vaV&4{^*UH|Xoj@t@sD`Y{TM7g|@KklLE!F!;6yyPe!4IehT(dUc+jR2fb z%jk1Ph(-ug-KaPtLL-9Jk--@;8Zqp2W5^i^8VQUet;divQZ!OnN&_~LTJX8r5je48 t8L=s`4zU%n3t~HBm&C@2%DW=AB-T|-9`TXe=GZouN6eM@eV_iG>;Xco#{2*P diff --git a/tests/data/acpi/pc/DSDT.roothp b/tests/data/acpi/pc/DSDT.roothp index f9aacee095bbb62251fc8231532f0d6e9f555a58..8c3956c9ecc63133cc800f1d2d07a1392a35d548 100644 GIT binary patch delta 937 zcmY+>O-{l<7{+lv3X}>h^pjRaFJJsfPv7>P+5YpJr^B!uE{AV%Gg_G4C~o?l+3HG}_KxT3JRILN3WZ`p4X3x0 zBEX66`?J-xGVS+rP)dPTf>`ST37#mEC_{W^V!#^;2?gT7pp5}u+GMvX)bV!uUS8S;ioLWNl5f;Z|U>WQeS^Uc#}^(fS>^j9D8mPS$&q?X9&vh53P z3+-8I4YVJrHPOyY@vM&aC^ZA^TWT$|z9pV*CoR48h;MDutxdeZlSOYd;uo+;SP*e0 zLf)`R*bt{SZG^nxkZ>R#GI7ouE(sUnD;K=sk?6bA6N6k00Kf6&sZ=n<%5q8pMbJ0d0$S6%cB-hglc7H>1JSwHtOhf17EbyCJ-LgF&%;Hs{0p(k}DKYfIB~&CY*; zeqy?0*TwS1oM%H~hG33ya*iQkA|UtG5Z2(klm1N<;)bhC6edhvRd7cgMIF|vxaE!p ziU#Z}f;%h}7K}Y*%7{B`6gI3Xf;*Zhny^#F9d|e=9LW6B6qx#nC3bWscLZz7T9oZ6 zYg0B3cWRJrq6Is^XD5A`}rED}p;>6fw+t%9JPW=%eVvrXsi_L6N{g6%+1AQKXPZ;xCIx g?(|%40JfA}Py-vbV7{>962&EKg#Sds{`KTXQqtQgAi4zeSHA)=%?0`Ok6Pv7?KS^xQ+rzfZ5;duD^-0)9Yc19iz&W2 z1vm3=BC)#_3x$LN@fi!=$dkxJSWEPkJ>F1Bs1TR2;Ee)_0>pbHI=oRNQH0Qz=_?)H zD3K^ZTtvd-4UL2r2>K6N@J8Xgc)X>P)Du$2YwoWk|HLfXlhDd&ze1Zs+gweaokzPD z+5*~-&=%2}?c~`?(860E@U5$K>+pX+w&{&}`~n6E18+2m1#g%nOo)v&+BoEm8i^Xj lT`YLRB4I&%N21RgHVGS|;nG+7yiq4nhq!jlw->jR`UCcd%hdn? delta 891 zcmY+By-LGS6o6x`ZIY%xvHmnkleX4Wtxz1)779W!b`caT9g0KI7w`pyf^)&)tga4j zf>SqNKNcrf6^~gGL6r+mdn24Fe4WrZIyXSv0b+kc~Dsa%kkB zA-8zvei)EeO_&~1pvTorEwQ({G83u0@;T03HPo!Erf z2C+G@O=7iOF Date: Fri, 1 Jul 2022 09:35:15 -0400 Subject: [PATCH 0991/1020] x86: pci: acpi: consolidate PCI slots creation No functional changes nor AML bytecode changes. Consolidate code that generates empty and populated slot descriptors. Besides eliminating duplication, it helps consolidate conditions for generating parts of Device{} desriptor in one place, which makes code more compact and easier to read. Signed-off-by: Igor Mammedov Message-Id: <20220701133515.137890-18-imammedo@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/i386/acpi-build.c | 111 +++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 57 deletions(-) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index fc23cb08c3..4f54b61904 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -427,13 +427,41 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, int func = PCI_FUNC(devfn); /* ACPI spec: 1.0b: Table 6-2 _ADR Object Bus Types, PCI type */ int adr = slot << 16 | func; - bool hotplug_enabled_dev; - bool bridge_in_acpi; - bool cold_plugged_bridge; + bool hotpluggbale_slot = false; + bool bridge_in_acpi = false; + bool cold_plugged_bridge = false; + bool is_vga = false; + + if (pdev) { + pc = PCI_DEVICE_GET_CLASS(pdev); + dc = DEVICE_GET_CLASS(pdev); + + if (pc->class_id == PCI_CLASS_BRIDGE_ISA) { + continue; + } + + is_vga = pc->class_id == PCI_CLASS_DISPLAY_VGA; - if (!pdev) { /* - * add hotplug slots for non present devices. + * Cold plugged bridges aren't themselves hot-pluggable. + * Hotplugged bridges *are* hot-pluggable. + */ + cold_plugged_bridge = pc->is_bridge && !DEVICE(pdev)->hotplugged; + bridge_in_acpi = cold_plugged_bridge && pcihp_bridge_en; + + hotpluggbale_slot = bsel && dc->hotpluggable && + !cold_plugged_bridge; + + /* + * allow describing coldplugged bridges in ACPI even if they are not + * on function 0, as they are not unpluggable, for all other devices + * generate description only for function 0 per slot + */ + if (func && !bridge_in_acpi) { + continue; + } + } else { + /* * hotplug is supported only for non-multifunction device * so generate device description only for function 0 */ @@ -441,46 +469,11 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, if (pci_bus_is_express(bus) && slot > 0) { break; } - dev = aml_device("S%.02X", devfn); - aml_append(dev, aml_name_decl("_ADR", aml_int(adr))); - aml_append(dev, aml_name_decl("ASUN", aml_int(slot))); - aml_append(dev, aml_pci_device_dsm()); - aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); - method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); - aml_append(method, - aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) - ); - aml_append(dev, method); - aml_append(parent_scope, dev); - - build_append_pcihp_notify_entry(notify_method, slot); + /* mark it as empty hotpluggable slot */ + hotpluggbale_slot = true; + } else { + continue; } - continue; - } - - pc = PCI_DEVICE_GET_CLASS(pdev); - dc = DEVICE_GET_CLASS(pdev); - - /* - * Cold plugged bridges aren't themselves hot-pluggable. - * Hotplugged bridges *are* hot-pluggable. - */ - cold_plugged_bridge = pc->is_bridge && !DEVICE(pdev)->hotplugged; - bridge_in_acpi = cold_plugged_bridge && pcihp_bridge_en; - - hotplug_enabled_dev = bsel && dc->hotpluggable && !cold_plugged_bridge; - - if (pc->class_id == PCI_CLASS_BRIDGE_ISA) { - continue; - } - - /* - * allow describing coldplugged bridges in ACPI even if they are not - * on function 0, as they are not unpluggable, for all other devices - * generate description only for function 0 per slot - */ - if (func && !bridge_in_acpi) { - continue; } /* start to compose PCI device descriptor */ @@ -496,7 +489,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, aml_append(dev, aml_pci_device_dsm()); } - if (pc->class_id == PCI_CLASS_DISPLAY_VGA) { + if (is_vga) { /* add VGA specific AML methods */ int s3d; @@ -517,19 +510,10 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, method = aml_method("_S3D", 0, AML_NOTSERIALIZED); aml_append(method, aml_return(aml_int(s3d))); aml_append(dev, method); - } else if (hotplug_enabled_dev) { - aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); - /* add _EJ0 to make slot hotpluggable */ - method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); - aml_append(method, - aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) - ); - aml_append(dev, method); + } - if (bsel) { - build_append_pcihp_notify_entry(notify_method, slot); - } - } else if (bridge_in_acpi) { + bridge_in_acpi = cold_plugged_bridge && pcihp_bridge_en; + if (bridge_in_acpi) { /* * device is coldplugged bridge, * add child device descriptions into its scope @@ -538,6 +522,19 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus, build_append_pci_bus_devices(dev, sec_bus, pcihp_bridge_en); } + + if (hotpluggbale_slot) { + aml_append(dev, aml_name_decl("_SUN", aml_int(slot))); + /* add _EJ0 to make slot hotpluggable */ + method = aml_method("_EJ0", 1, AML_NOTSERIALIZED); + aml_append(method, + aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN")) + ); + aml_append(dev, method); + + build_append_pcihp_notify_entry(notify_method, slot); + } + /* device descriptor has been composed, add it into parent context */ aml_append(parent_scope, dev); } From bbde13cd14ad4eec18529ce0bf5876058464e124 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Fri, 30 Sep 2022 12:38:24 +0100 Subject: [PATCH 0992/1020] target/arm/kvm: Retry KVM_CREATE_VM call if it fails EINTR Occasionally the KVM_CREATE_VM ioctl can return EINTR, even though there is no pending signal to be taken. In commit 94ccff13382055 we added a retry-on-EINTR loop to the KVM_CREATE_VM call in the generic KVM code. Adopt the same approach for the use of the ioctl in the Arm-specific KVM code (where we use it to create a scratch VM for probing for various things). For more information, see the mailing list thread: https://lore.kernel.org/qemu-devel/8735e0s1zw.wl-maz@kernel.org/ Reported-by: Vitaly Chikunov Signed-off-by: Peter Maydell Reviewed-by: Vitaly Chikunov Reviewed-by: Eric Auger Acked-by: Marc Zyngier Message-id: 20220930113824.1933293-1-peter.maydell@linaro.org --- target/arm/kvm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/target/arm/kvm.c b/target/arm/kvm.c index e5c1bd50d2..1e4de9b42e 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -79,7 +79,9 @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try, if (max_vm_pa_size < 0) { max_vm_pa_size = 0; } - vmfd = ioctl(kvmfd, KVM_CREATE_VM, max_vm_pa_size); + do { + vmfd = ioctl(kvmfd, KVM_CREATE_VM, max_vm_pa_size); + } while (vmfd == -1 && errno == EINTR); if (vmfd < 0) { goto err; } From 06f2adccfa26be55237ac966c376a42c52efb299 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Tue, 4 Oct 2022 09:23:54 +0200 Subject: [PATCH 0993/1020] target/arm: allow setting SCR_EL3.EnTP2 when FEAT_SME is implemented Updates write_scr() to allow setting SCR_EL3.EnTP2 when FEAT_SME is implemented. SCR_EL3 being a 64-bit register, valid_mask is changed to uint64_t and the SCR_* constants in target/arm/cpu.h are extended to 64-bit so that masking and bitwise not (~) behave as expected. This enables booting Linux with Trusted Firmware-A at EL3 with "-M virt,secure=on -cpu max". Cc: qemu-stable@nongnu.org Fixes: 78cb9776662a ("target/arm: Enable SME for -cpu max") Signed-off-by: Jerome Forissier Reviewed-by: Andre Przywara Reviewed-by: Richard Henderson Message-id: 20221004072354.27037-1-jerome.forissier@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 54 ++++++++++++++++++++++----------------------- target/arm/helper.c | 5 ++++- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 429ed42eec..68d99565ac 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1664,33 +1664,33 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask) #define HPFAR_NS (1ULL << 63) -#define SCR_NS (1U << 0) -#define SCR_IRQ (1U << 1) -#define SCR_FIQ (1U << 2) -#define SCR_EA (1U << 3) -#define SCR_FW (1U << 4) -#define SCR_AW (1U << 5) -#define SCR_NET (1U << 6) -#define SCR_SMD (1U << 7) -#define SCR_HCE (1U << 8) -#define SCR_SIF (1U << 9) -#define SCR_RW (1U << 10) -#define SCR_ST (1U << 11) -#define SCR_TWI (1U << 12) -#define SCR_TWE (1U << 13) -#define SCR_TLOR (1U << 14) -#define SCR_TERR (1U << 15) -#define SCR_APK (1U << 16) -#define SCR_API (1U << 17) -#define SCR_EEL2 (1U << 18) -#define SCR_EASE (1U << 19) -#define SCR_NMEA (1U << 20) -#define SCR_FIEN (1U << 21) -#define SCR_ENSCXT (1U << 25) -#define SCR_ATA (1U << 26) -#define SCR_FGTEN (1U << 27) -#define SCR_ECVEN (1U << 28) -#define SCR_TWEDEN (1U << 29) +#define SCR_NS (1ULL << 0) +#define SCR_IRQ (1ULL << 1) +#define SCR_FIQ (1ULL << 2) +#define SCR_EA (1ULL << 3) +#define SCR_FW (1ULL << 4) +#define SCR_AW (1ULL << 5) +#define SCR_NET (1ULL << 6) +#define SCR_SMD (1ULL << 7) +#define SCR_HCE (1ULL << 8) +#define SCR_SIF (1ULL << 9) +#define SCR_RW (1ULL << 10) +#define SCR_ST (1ULL << 11) +#define SCR_TWI (1ULL << 12) +#define SCR_TWE (1ULL << 13) +#define SCR_TLOR (1ULL << 14) +#define SCR_TERR (1ULL << 15) +#define SCR_APK (1ULL << 16) +#define SCR_API (1ULL << 17) +#define SCR_EEL2 (1ULL << 18) +#define SCR_EASE (1ULL << 19) +#define SCR_NMEA (1ULL << 20) +#define SCR_FIEN (1ULL << 21) +#define SCR_ENSCXT (1ULL << 25) +#define SCR_ATA (1ULL << 26) +#define SCR_FGTEN (1ULL << 27) +#define SCR_ECVEN (1ULL << 28) +#define SCR_TWEDEN (1ULL << 29) #define SCR_TWEDEL MAKE_64BIT_MASK(30, 4) #define SCR_TME (1ULL << 34) #define SCR_AMVOFFEN (1ULL << 35) diff --git a/target/arm/helper.c b/target/arm/helper.c index db3b1ea72d..c08a7b35a0 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1752,7 +1752,7 @@ static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri, static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { /* Begin with base v8.0 state. */ - uint32_t valid_mask = 0x3fff; + uint64_t valid_mask = 0x3fff; ARMCPU *cpu = env_archcpu(env); /* @@ -1789,6 +1789,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) if (cpu_isar_feature(aa64_doublefault, cpu)) { valid_mask |= SCR_EASE | SCR_NMEA; } + if (cpu_isar_feature(aa64_sme, cpu)) { + valid_mask |= SCR_ENTP2; + } } else { valid_mask &= ~(SCR_RW | SCR_ST); if (cpu_isar_feature(aa32_ras, cpu)) { From 86a85d73e3167c97da8f9680536af89e66943b76 Mon Sep 17 00:00:00 2001 From: Joel Stanley Date: Tue, 4 Oct 2022 15:30:42 +1030 Subject: [PATCH 0994/1020] docs/nuvoton: Update URL for images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit openpower.xyz was retired some time ago. The OpenBMC Jenkins is where images can be found these days. Signed-off-by: Joel Stanley Reviewed-by: Hao Wu Reviewed-by: Philippe Mathieu-Daudé Tested-by: Philippe Mathieu-Daudé Message-id: 20221004050042.22681-1-joel@jms.id.au Signed-off-by: Peter Maydell --- docs/system/arm/nuvoton.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst index ef2792076a..c38df32bde 100644 --- a/docs/system/arm/nuvoton.rst +++ b/docs/system/arm/nuvoton.rst @@ -82,9 +82,9 @@ Boot options The Nuvoton machines can boot from an OpenBMC firmware image, or directly into a kernel using the ``-kernel`` option. OpenBMC images for ``quanta-gsj`` and -possibly others can be downloaded from the OpenPOWER jenkins : +possibly others can be downloaded from the OpenBMC jenkins : - https://openpower.xyz/ + https://jenkins.openbmc.org/ The firmware image should be attached as an MTD drive. Example : From c7637be307d36ad8c51bd0e9852e09115969bc29 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:37 -0700 Subject: [PATCH 0995/1020] target/arm: Split s2walk_secure from ipa_secure in get_phys_addr The starting security state comes with the translation regime, not the current state of arm_is_secure_below_el3(). Create a new local variable, s2walk_secure, which does not need to be written back to result->attrs.secure -- we compute that value later, after the S2 walk is complete. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-id: 20221001162318.153420-2-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 2ddfc028ab..b8c494ad9f 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2298,7 +2298,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, hwaddr ipa; int s1_prot; int ret; - bool ipa_secure; + bool ipa_secure, s2walk_secure; ARMCacheAttrs cacheattrs1; ARMMMUIdx s2_mmu_idx; bool is_el0; @@ -2313,17 +2313,17 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, ipa = result->phys; ipa_secure = result->attrs.secure; - if (arm_is_secure_below_el3(env)) { - if (ipa_secure) { - result->attrs.secure = !(env->cp15.vstcr_el2 & VSTCR_SW); - } else { - result->attrs.secure = !(env->cp15.vtcr_el2 & VTCR_NSW); - } + if (is_secure) { + /* Select TCR based on the NS bit from the S1 walk. */ + s2walk_secure = !(ipa_secure + ? env->cp15.vstcr_el2 & VSTCR_SW + : env->cp15.vtcr_el2 & VTCR_NSW); } else { assert(!ipa_secure); + s2walk_secure = false; } - s2_mmu_idx = (result->attrs.secure + s2_mmu_idx = (s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2); is_el0 = mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_SE10_0; @@ -2366,7 +2366,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, result->cacheattrs); /* Check if IPA translates to secure or non-secure PA space. */ - if (arm_is_secure_below_el3(env)) { + if (is_secure) { if (ipa_secure) { result->attrs.secure = !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)); From 9b5ba97ac77889b9bf7d27d40da232ee8ff40b09 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Fri, 7 Oct 2022 08:21:59 -0700 Subject: [PATCH 0996/1020] target/arm: Make the final stage1+2 write to secure be unconditional While the stage2 call to get_phys_addr_lpae should never set attrs.secure when given a non-secure input, it's just as easy to make the final update to attrs.secure be unconditional and false in the case of non-secure input. Suggested-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221007152159.1414065-1-richard.henderson@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target/arm/ptw.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index b8c494ad9f..7d763a5847 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2365,17 +2365,16 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, result->cacheattrs = combine_cacheattrs(env, cacheattrs1, result->cacheattrs); - /* Check if IPA translates to secure or non-secure PA space. */ - if (is_secure) { - if (ipa_secure) { - result->attrs.secure = - !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)); - } else { - result->attrs.secure = - !((env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW)) - || (env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW))); - } - } + /* + * Check if IPA translates to secure or non-secure PA space. + * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA. + */ + result->attrs.secure = + (is_secure + && !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)) + && (ipa_secure + || !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW)))); + return 0; } else { /* From c23f08a56cf01f947e2554339b42f641d5853d32 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:38 -0700 Subject: [PATCH 0997/1020] target/arm: Add is_secure parameter to get_phys_addr_lpae MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from get_phys_addr_lpae, using the new parameter instead. Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-3-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 7d763a5847..96ed8e13af 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -16,8 +16,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - bool s1_is_el0, GetPhysAddrResult *result, - ARMMMUFaultInfo *fi) + bool is_secure, bool s1_is_el0, + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) __attribute__((nonnull)); /* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */ @@ -207,8 +207,8 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, GetPhysAddrResult s2 = {}; int ret; - ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx, false, - &s2, fi); + ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx, + *is_secure, false, &s2, fi); if (ret) { assert(fi->type != ARMFault_None); fi->s2addr = addr; @@ -965,8 +965,8 @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level, */ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, MMUAccessType access_type, ARMMMUIdx mmu_idx, - bool s1_is_el0, GetPhysAddrResult *result, - ARMMMUFaultInfo *fi) + bool is_secure, bool s1_is_el0, + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { ARMCPU *cpu = env_archcpu(env); /* Read an LPAE long-descriptor translation table. */ @@ -1183,7 +1183,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, * remain non-secure. We implement this by just ORing in the NSTable/NS * bits at each step. */ - tableattrs = regime_is_secure(env, mmu_idx) ? 0 : (1 << 4); + tableattrs = is_secure ? 0 : (1 << 4); for (;;) { uint64_t descriptor; bool nstable; @@ -2337,7 +2337,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, memset(result, 0, sizeof(*result)); ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx, - is_el0, result, fi); + s2walk_secure, is_el0, result, fi); fi->s2addr = ipa; /* Combine the S1 and S2 perms. */ @@ -2504,8 +2504,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, } if (regime_using_lpae_format(env, mmu_idx)) { - return get_phys_addr_lpae(env, address, access_type, mmu_idx, false, - result, fi); + return get_phys_addr_lpae(env, address, access_type, mmu_idx, + is_secure, false, result, fi); } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { return get_phys_addr_v6(env, address, access_type, mmu_idx, is_secure, result, fi); From bf25b7b079c523c8eeebb35c0f914dd2cf3fba24 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:39 -0700 Subject: [PATCH 0998/1020] target/arm: Fix S2 disabled check in S1_ptw_translate Pass the correct stage2 mmu_idx to regime_translation_disabled, which we computed afterward. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-id: 20221001162318.153420-4-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 96ed8e13af..631d1e25f1 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -200,10 +200,10 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, hwaddr addr, bool *is_secure, ARMMMUFaultInfo *fi) { + ARMMMUIdx s2_mmu_idx = *is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2; + if (arm_mmu_idx_is_stage1_of_2(mmu_idx) && - !regime_translation_disabled(env, ARMMMUIdx_Stage2)) { - ARMMMUIdx s2_mmu_idx = *is_secure ? ARMMMUIdx_Stage2_S - : ARMMMUIdx_Stage2; + !regime_translation_disabled(env, s2_mmu_idx)) { GetPhysAddrResult s2 = {}; int ret; From 7e80c0a4ff68da09e1de292e4660f959ffed6fcd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:40 -0700 Subject: [PATCH 0999/1020] target/arm: Add is_secure parameter to regime_translation_disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from regime_translation_disabled, using the new parameter instead. This fixes a bug in S1_ptw_translate and get_phys_addr where we had passed ARMMMUIdx_Stage2 and not ARMMMUIdx_Stage2_S to determine if Stage2 is disabled, affecting FEAT_SEL2. Reviewed-by: Peter Maydell Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-5-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 631d1e25f1..d789807b08 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -131,12 +131,13 @@ static uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, int ttbrn) } /* Return true if the specified stage of address translation is disabled */ -static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx) +static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx, + bool is_secure) { uint64_t hcr_el2; if (arm_feature(env, ARM_FEATURE_M)) { - switch (env->v7m.mpu_ctrl[regime_is_secure(env, mmu_idx)] & + switch (env->v7m.mpu_ctrl[is_secure] & (R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) { case R_V7M_MPU_CTRL_ENABLE_MASK: /* Enabled, but not for HardFault and NMI */ @@ -163,7 +164,7 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx) if (hcr_el2 & HCR_TGE) { /* TGE means that NS EL0/1 act as if SCTLR_EL1.M is zero */ - if (!regime_is_secure(env, mmu_idx) && regime_el(env, mmu_idx) == 1) { + if (!is_secure && regime_el(env, mmu_idx) == 1) { return true; } } @@ -203,7 +204,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, ARMMMUIdx s2_mmu_idx = *is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2; if (arm_mmu_idx_is_stage1_of_2(mmu_idx) && - !regime_translation_disabled(env, s2_mmu_idx)) { + !regime_translation_disabled(env, s2_mmu_idx, *is_secure)) { GetPhysAddrResult s2 = {}; int ret; @@ -1357,7 +1358,7 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, uint32_t base; bool is_user = regime_is_user(env, mmu_idx); - if (regime_translation_disabled(env, mmu_idx)) { + if (regime_translation_disabled(env, mmu_idx, is_secure)) { /* MPU disabled. */ result->phys = address; result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; @@ -1521,7 +1522,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, result->page_size = TARGET_PAGE_SIZE; result->prot = 0; - if (regime_translation_disabled(env, mmu_idx) || + if (regime_translation_disabled(env, mmu_idx, secure) || m_is_ppb_region(env, address)) { /* * MPU disabled or M profile PPB access: use default memory map. @@ -1733,7 +1734,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, * are done in arm_v7m_load_vector(), which always does a direct * read using address_space_ldl(), rather than going via this function. */ - if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */ + if (regime_translation_disabled(env, mmu_idx, secure)) { /* MPU disabled */ hit = true; } else if (m_is_ppb_region(env, address)) { hit = true; @@ -2307,7 +2308,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, result, fi); /* If S1 fails or S2 is disabled, return early. */ - if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2)) { + if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2, + is_secure)) { return ret; } @@ -2437,7 +2439,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, /* Definitely a real MMU, not an MPU */ - if (regime_translation_disabled(env, mmu_idx)) { + if (regime_translation_disabled(env, mmu_idx, is_secure)) { uint64_t hcr; uint8_t memattr; From def8aa5b80a1c12a3a758801d585c0950867ac94 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:41 -0700 Subject: [PATCH 1000/1020] target/arm: Split out get_phys_addr_with_secure Retain the existing get_phys_addr interface using the security state derived from mmu_idx. Move the kerneldoc comments to the header file where they belong. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-6-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/internals.h | 40 ++++++++++++++++++++++++++++++++++++++ target/arm/ptw.c | 44 ++++++++++++++---------------------------- 2 files changed, 55 insertions(+), 29 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index 307a596505..3524d11dc5 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1145,6 +1145,46 @@ typedef struct GetPhysAddrResult { ARMCacheAttrs cacheattrs; } GetPhysAddrResult; +/** + * get_phys_addr_with_secure: get the physical address for a virtual address + * @env: CPUARMState + * @address: virtual address to get physical address for + * @access_type: 0 for read, 1 for write, 2 for execute + * @mmu_idx: MMU index indicating required translation regime + * @is_secure: security state for the access + * @result: set on translation success. + * @fi: set to fault info if the translation fails + * + * Find the physical address corresponding to the given virtual address, + * by doing a translation table walk on MMU based systems or using the + * MPU state on MPU based systems. + * + * Returns false if the translation was successful. Otherwise, phys_ptr, attrs, + * prot and page_size may not be filled in, and the populated fsr value provides + * information on why the translation aborted, in the format of a + * DFSR/IFSR fault register, with the following caveats: + * * we honour the short vs long DFSR format differences. + * * the WnR bit is never set (the caller must do this). + * * for PSMAv5 based systems we don't bother to return a full FSR format + * value. + */ +bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, + MMUAccessType access_type, + ARMMMUIdx mmu_idx, bool is_secure, + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) + __attribute__((nonnull)); + +/** + * get_phys_addr: get the physical address for a virtual address + * @env: CPUARMState + * @address: virtual address to get physical address for + * @access_type: 0 for read, 1 for write, 2 for execute + * @mmu_idx: MMU index indicating required translation regime + * @result: set on translation success. + * @fi: set to fault info if the translation fails + * + * Similarly, but use the security regime of @mmu_idx. + */ bool get_phys_addr(CPUARMState *env, target_ulong address, MMUAccessType access_type, ARMMMUIdx mmu_idx, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index d789807b08..74dcb843fe 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2260,35 +2260,12 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env, return ret; } -/** - * get_phys_addr - get the physical address for this virtual address - * - * Find the physical address corresponding to the given virtual address, - * by doing a translation table walk on MMU based systems or using the - * MPU state on MPU based systems. - * - * Returns false if the translation was successful. Otherwise, phys_ptr, attrs, - * prot and page_size may not be filled in, and the populated fsr value provides - * information on why the translation aborted, in the format of a - * DFSR/IFSR fault register, with the following caveats: - * * we honour the short vs long DFSR format differences. - * * the WnR bit is never set (the caller must do this). - * * for PSMAv5 based systems we don't bother to return a full FSR format - * value. - * - * @env: CPUARMState - * @address: virtual address to get physical address for - * @access_type: 0 for read, 1 for write, 2 for execute - * @mmu_idx: MMU index indicating required translation regime - * @result: set on translation success. - * @fi: set to fault info if the translation fails - */ -bool get_phys_addr(CPUARMState *env, target_ulong address, - MMUAccessType access_type, ARMMMUIdx mmu_idx, - GetPhysAddrResult *result, ARMMMUFaultInfo *fi) +bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, + MMUAccessType access_type, ARMMMUIdx mmu_idx, + bool is_secure, GetPhysAddrResult *result, + ARMMMUFaultInfo *fi) { ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx); - bool is_secure = regime_is_secure(env, mmu_idx); if (mmu_idx != s1_mmu_idx) { /* @@ -2304,8 +2281,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, ARMMMUIdx s2_mmu_idx; bool is_el0; - ret = get_phys_addr(env, address, access_type, s1_mmu_idx, - result, fi); + ret = get_phys_addr_with_secure(env, address, access_type, + s1_mmu_idx, is_secure, result, fi); /* If S1 fails or S2 is disabled, return early. */ if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2, @@ -2517,6 +2494,15 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, } } +bool get_phys_addr(CPUARMState *env, target_ulong address, + MMUAccessType access_type, ARMMMUIdx mmu_idx, + GetPhysAddrResult *result, ARMMMUFaultInfo *fi) +{ + return get_phys_addr_with_secure(env, address, access_type, mmu_idx, + regime_is_secure(env, mmu_idx), + result, fi); +} + hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, MemTxAttrs *attrs) { From 9cd5f1710e2d786042f747f128bc9e954fd7f6c6 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:42 -0700 Subject: [PATCH 1001/1020] target/arm: Add is_secure parameter to v7m_read_half_insn MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the use of regime_is_secure from v7m_read_half_insn, using the new parameter instead. As it happens, both callers pass true, propagated from the argument to arm_v7m_mmu_idx_for_secstate which created the mmu_idx argument, but that is a detail of v7m_handle_execute_nsc we need not expose to the callee. Reviewed-by: Peter Maydell Reviewed-by: Alex Bennée Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-7-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/m_helper.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 5ee4ee15b3..203ba411f6 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -1981,7 +1981,7 @@ static bool do_v7m_function_return(ARMCPU *cpu) return true; } -static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, +static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, bool secure, uint32_t addr, uint16_t *insn) { /* @@ -2003,8 +2003,7 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, ARMMMUFaultInfo fi = {}; MemTxResult txres; - v8m_security_lookup(env, addr, MMU_INST_FETCH, mmu_idx, - regime_is_secure(env, mmu_idx), &sattrs); + v8m_security_lookup(env, addr, MMU_INST_FETCH, mmu_idx, secure, &sattrs); if (!sattrs.nsc || sattrs.ns) { /* * This must be the second half of the insn, and it straddles a @@ -2109,7 +2108,7 @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu) /* We want to do the MPU lookup as secure; work out what mmu_idx that is */ mmu_idx = arm_v7m_mmu_idx_for_secstate(env, true); - if (!v7m_read_half_insn(cpu, mmu_idx, env->regs[15], &insn)) { + if (!v7m_read_half_insn(cpu, mmu_idx, true, env->regs[15], &insn)) { return false; } @@ -2125,7 +2124,7 @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu) goto gen_invep; } - if (!v7m_read_half_insn(cpu, mmu_idx, env->regs[15] + 2, &insn)) { + if (!v7m_read_half_insn(cpu, mmu_idx, true, env->regs[15] + 2, &insn)) { return false; } From a393dee0194488d3e5f5f83e4ef7ea1f3556f44f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:43 -0700 Subject: [PATCH 1002/1020] target/arm: Add TBFLAG_M32.SECURE Remove the use of regime_is_secure from arm_tr_init_disas_context. Instead, provide the value of v8m_secure directly from tb_flags. Rather than use regime_is_secure, use the env->v7m.secure directly, as per arm_mmu_idx_el. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-8-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 2 ++ target/arm/helper.c | 4 ++++ target/arm/translate.c | 3 +-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 68d99565ac..a085c17297 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -3203,6 +3203,8 @@ FIELD(TBFLAG_M32, NEW_FP_CTXT_NEEDED, 3, 1) /* Not cached. */ FIELD(TBFLAG_M32, FPCCR_S_WRONG, 4, 1) /* Not cached. */ /* Set if MVE insns are definitely not predicated by VPR or LTPSIZE */ FIELD(TBFLAG_M32, MVE_NO_PRED, 5, 1) /* Not cached. */ +/* Set if in secure mode */ +FIELD(TBFLAG_M32, SECURE, 6, 1) /* * Bit usage when in AArch64 state diff --git a/target/arm/helper.c b/target/arm/helper.c index c08a7b35a0..8d82c14762 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -10948,6 +10948,10 @@ static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el, DP_TBFLAG_M32(flags, STACKCHECK, 1); } + if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) { + DP_TBFLAG_M32(flags, SECURE, 1); + } + return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags); } diff --git a/target/arm/translate.c b/target/arm/translate.c index 5aaccbbf71..ac647e0262 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -9351,8 +9351,7 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs) dc->vfp_enabled = 1; dc->be_data = MO_TE; dc->v7m_handler_mode = EX_TBFLAG_M32(tb_flags, HANDLER); - dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) && - regime_is_secure(env, dc->mmu_idx); + dc->v8m_secure = EX_TBFLAG_M32(tb_flags, SECURE); dc->v8m_stackcheck = EX_TBFLAG_M32(tb_flags, STACKCHECK); dc->v8m_fpccr_s_wrong = EX_TBFLAG_M32(tb_flags, FPCCR_S_WRONG); dc->v7m_new_fp_ctxt_needed = From 03bea66e7fa3af42976ceafb20512c59abf2e699 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:44 -0700 Subject: [PATCH 1003/1020] target/arm: Merge regime_is_secure into get_phys_addr This is the last use of regime_is_secure; remove it entirely before changing the layout of ARMMMUIdx. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-9-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/internals.h | 42 ---------------------------------------- target/arm/ptw.c | 44 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 44 deletions(-) diff --git a/target/arm/internals.h b/target/arm/internals.h index 3524d11dc5..14428730d4 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -670,48 +670,6 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx) } } -/* Return true if this address translation regime is secure */ -static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx) -{ - switch (mmu_idx) { - case ARMMMUIdx_E10_0: - case ARMMMUIdx_E10_1: - case ARMMMUIdx_E10_1_PAN: - case ARMMMUIdx_E20_0: - case ARMMMUIdx_E20_2: - case ARMMMUIdx_E20_2_PAN: - case ARMMMUIdx_Stage1_E0: - case ARMMMUIdx_Stage1_E1: - case ARMMMUIdx_Stage1_E1_PAN: - case ARMMMUIdx_E2: - case ARMMMUIdx_Stage2: - case ARMMMUIdx_MPrivNegPri: - case ARMMMUIdx_MUserNegPri: - case ARMMMUIdx_MPriv: - case ARMMMUIdx_MUser: - return false; - case ARMMMUIdx_SE3: - case ARMMMUIdx_SE10_0: - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: - case ARMMMUIdx_SE20_0: - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: - case ARMMMUIdx_Stage1_SE0: - case ARMMMUIdx_Stage1_SE1: - case ARMMMUIdx_Stage1_SE1_PAN: - case ARMMMUIdx_SE2: - case ARMMMUIdx_Stage2_S: - case ARMMMUIdx_MSPrivNegPri: - case ARMMMUIdx_MSUserNegPri: - case ARMMMUIdx_MSPriv: - case ARMMMUIdx_MSUser: - return true; - default: - g_assert_not_reached(); - } -} - static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx) { switch (mmu_idx) { diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 74dcb843fe..55e8f33c50 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2498,9 +2498,49 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, MMUAccessType access_type, ARMMMUIdx mmu_idx, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { + bool is_secure; + + switch (mmu_idx) { + case ARMMMUIdx_E10_0: + case ARMMMUIdx_E10_1: + case ARMMMUIdx_E10_1_PAN: + case ARMMMUIdx_E20_0: + case ARMMMUIdx_E20_2: + case ARMMMUIdx_E20_2_PAN: + case ARMMMUIdx_Stage1_E0: + case ARMMMUIdx_Stage1_E1: + case ARMMMUIdx_Stage1_E1_PAN: + case ARMMMUIdx_E2: + case ARMMMUIdx_Stage2: + case ARMMMUIdx_MPrivNegPri: + case ARMMMUIdx_MUserNegPri: + case ARMMMUIdx_MPriv: + case ARMMMUIdx_MUser: + is_secure = false; + break; + case ARMMMUIdx_SE3: + case ARMMMUIdx_SE10_0: + case ARMMMUIdx_SE10_1: + case ARMMMUIdx_SE10_1_PAN: + case ARMMMUIdx_SE20_0: + case ARMMMUIdx_SE20_2: + case ARMMMUIdx_SE20_2_PAN: + case ARMMMUIdx_Stage1_SE0: + case ARMMMUIdx_Stage1_SE1: + case ARMMMUIdx_Stage1_SE1_PAN: + case ARMMMUIdx_SE2: + case ARMMMUIdx_Stage2_S: + case ARMMMUIdx_MSPrivNegPri: + case ARMMMUIdx_MSUserNegPri: + case ARMMMUIdx_MSPriv: + case ARMMMUIdx_MSUser: + is_secure = true; + break; + default: + g_assert_not_reached(); + } return get_phys_addr_with_secure(env, address, access_type, mmu_idx, - regime_is_secure(env, mmu_idx), - result, fi); + is_secure, result, fi); } hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, From 7aee3cb9569f83353b17df05dc9d3a7f791b5fdf Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:45 -0700 Subject: [PATCH 1004/1020] target/arm: Add is_secure parameter to do_ats_write Use get_phys_addr_with_secure directly. For a-profile, this is the one place where the value of is_secure may not equal arm_is_secure(env). Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-10-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index 8d82c14762..fd4663a946 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3191,7 +3191,8 @@ static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri, #ifdef CONFIG_TCG static uint64_t do_ats_write(CPUARMState *env, uint64_t value, - MMUAccessType access_type, ARMMMUIdx mmu_idx) + MMUAccessType access_type, ARMMMUIdx mmu_idx, + bool is_secure) { bool ret; uint64_t par64; @@ -3199,7 +3200,8 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, ARMMMUFaultInfo fi = {}; GetPhysAddrResult res = {}; - ret = get_phys_addr(env, value, access_type, mmu_idx, &res, &fi); + ret = get_phys_addr_with_secure(env, value, access_type, mmu_idx, + is_secure, &res, &fi); /* * ATS operations only do S1 or S1+S2 translations, so we never @@ -3371,6 +3373,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) switch (el) { case 3: mmu_idx = ARMMMUIdx_SE3; + secure = true; break; case 2: g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */ @@ -3392,6 +3395,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) switch (el) { case 3: mmu_idx = ARMMMUIdx_SE10_0; + secure = true; break; case 2: g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */ @@ -3407,16 +3411,18 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) case 4: /* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */ mmu_idx = ARMMMUIdx_E10_1; + secure = false; break; case 6: /* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */ mmu_idx = ARMMMUIdx_E10_0; + secure = false; break; default: g_assert_not_reached(); } - par64 = do_ats_write(env, value, access_type, mmu_idx); + par64 = do_ats_write(env, value, access_type, mmu_idx, secure); A32_BANKED_CURRENT_REG_SET(env, par, par64); #else @@ -3432,7 +3438,8 @@ static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri, MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD; uint64_t par64; - par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2); + /* There is no SecureEL2 for AArch32. */ + par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2, false); A32_BANKED_CURRENT_REG_SET(env, par, par64); #else @@ -3475,6 +3482,7 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, break; case 6: /* AT S1E3R, AT S1E3W */ mmu_idx = ARMMMUIdx_SE3; + secure = true; break; default: g_assert_not_reached(); @@ -3493,7 +3501,8 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, g_assert_not_reached(); } - env->cp15.par_el[1] = do_ats_write(env, value, access_type, mmu_idx); + env->cp15.par_el[1] = do_ats_write(env, value, access_type, + mmu_idx, secure); #else /* Handled by hardware accelerator. */ g_assert_not_reached(); From d902ae7558690a8442bf3560d5707167e485ab92 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:46 -0700 Subject: [PATCH 1005/1020] target/arm: Fold secure and non-secure a-profile mmu indexes For a-profile aarch64, which does not bank system registers, it takes quite a lot of code to switch between security states. In the process, registers such as TCR_EL{1,2} must be swapped, which in itself requires the flushing of softmmu tlbs. Therefore it doesn't buy us anything to separate tlbs by security state. Retain the distinction between Stage2 and Stage2_S. This will be important as we implement FEAT_RME, and do not wish to add a third set of mmu indexes for Realm state. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-11-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu-param.h | 2 +- target/arm/cpu.h | 72 +++++++------------ target/arm/helper.c | 144 +++++++++++++------------------------ target/arm/internals.h | 31 +------- target/arm/ptw.c | 25 ++----- target/arm/translate-a64.c | 8 --- target/arm/translate.c | 6 +- 7 files changed, 85 insertions(+), 203 deletions(-) diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h index 68ffb12427..08681828ac 100644 --- a/target/arm/cpu-param.h +++ b/target/arm/cpu-param.h @@ -32,6 +32,6 @@ # define TARGET_PAGE_BITS_MIN 10 #endif -#define NB_MMU_MODES 15 +#define NB_MMU_MODES 8 #endif diff --git a/target/arm/cpu.h b/target/arm/cpu.h index a085c17297..53f4c236e1 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -2884,26 +2884,27 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync); * table over and over. * 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access * Never (PAN) bit within PSTATE. + * 7. we fold together the secure and non-secure regimes for A-profile, + * because there are no banked system registers for aarch64, so the + * process of switching between secure and non-secure is + * already heavyweight. * * This gives us the following list of cases: * - * NS EL0 EL1&0 stage 1+2 (aka NS PL0) - * NS EL1 EL1&0 stage 1+2 (aka NS PL1) - * NS EL1 EL1&0 stage 1+2 +PAN - * NS EL0 EL2&0 - * NS EL2 EL2&0 - * NS EL2 EL2&0 +PAN - * NS EL2 (aka NS PL2) - * S EL0 EL1&0 (aka S PL0) - * S EL1 EL1&0 (not used if EL3 is 32 bit) - * S EL1 EL1&0 +PAN - * S EL3 (aka S PL1) + * EL0 EL1&0 stage 1+2 (aka NS PL0) + * EL1 EL1&0 stage 1+2 (aka NS PL1) + * EL1 EL1&0 stage 1+2 +PAN + * EL0 EL2&0 + * EL2 EL2&0 + * EL2 EL2&0 +PAN + * EL2 (aka NS PL2) + * EL3 (aka S PL1) * - * for a total of 11 different mmu_idx. + * for a total of 8 different mmu_idx. * * R profile CPUs have an MPU, but can use the same set of MMU indexes - * as A profile. They only need to distinguish NS EL0 and NS EL1 (and - * NS EL2 if we ever model a Cortex-R52). + * as A profile. They only need to distinguish EL0 and EL1 (and + * EL2 if we ever model a Cortex-R52). * * M profile CPUs are rather different as they do not have a true MMU. * They have the following different MMU indexes: @@ -2942,9 +2943,6 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync); #define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */ #define ARM_MMU_IDX_M 0x40 /* M profile */ -/* Meanings of the bits for A profile mmu idx values */ -#define ARM_MMU_IDX_A_NS 0x8 - /* Meanings of the bits for M profile mmu idx values */ #define ARM_MMU_IDX_M_PRIV 0x1 #define ARM_MMU_IDX_M_NEGPRI 0x2 @@ -2958,22 +2956,14 @@ typedef enum ARMMMUIdx { /* * A-profile. */ - ARMMMUIdx_SE10_0 = 0 | ARM_MMU_IDX_A, - ARMMMUIdx_SE20_0 = 1 | ARM_MMU_IDX_A, - ARMMMUIdx_SE10_1 = 2 | ARM_MMU_IDX_A, - ARMMMUIdx_SE20_2 = 3 | ARM_MMU_IDX_A, - ARMMMUIdx_SE10_1_PAN = 4 | ARM_MMU_IDX_A, - ARMMMUIdx_SE20_2_PAN = 5 | ARM_MMU_IDX_A, - ARMMMUIdx_SE2 = 6 | ARM_MMU_IDX_A, - ARMMMUIdx_SE3 = 7 | ARM_MMU_IDX_A, - - ARMMMUIdx_E10_0 = ARMMMUIdx_SE10_0 | ARM_MMU_IDX_A_NS, - ARMMMUIdx_E20_0 = ARMMMUIdx_SE20_0 | ARM_MMU_IDX_A_NS, - ARMMMUIdx_E10_1 = ARMMMUIdx_SE10_1 | ARM_MMU_IDX_A_NS, - ARMMMUIdx_E20_2 = ARMMMUIdx_SE20_2 | ARM_MMU_IDX_A_NS, - ARMMMUIdx_E10_1_PAN = ARMMMUIdx_SE10_1_PAN | ARM_MMU_IDX_A_NS, - ARMMMUIdx_E20_2_PAN = ARMMMUIdx_SE20_2_PAN | ARM_MMU_IDX_A_NS, - ARMMMUIdx_E2 = ARMMMUIdx_SE2 | ARM_MMU_IDX_A_NS, + ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A, + ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A, + ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A, + ARMMMUIdx_E20_2 = 3 | ARM_MMU_IDX_A, + ARMMMUIdx_E10_1_PAN = 4 | ARM_MMU_IDX_A, + ARMMMUIdx_E20_2_PAN = 5 | ARM_MMU_IDX_A, + ARMMMUIdx_E2 = 6 | ARM_MMU_IDX_A, + ARMMMUIdx_E3 = 7 | ARM_MMU_IDX_A, /* * These are not allocated TLBs and are used only for AT system @@ -2982,9 +2972,6 @@ typedef enum ARMMMUIdx { ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB, ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB, ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB, - ARMMMUIdx_Stage1_SE0 = 3 | ARM_MMU_IDX_NOTLB, - ARMMMUIdx_Stage1_SE1 = 4 | ARM_MMU_IDX_NOTLB, - ARMMMUIdx_Stage1_SE1_PAN = 5 | ARM_MMU_IDX_NOTLB, /* * Not allocated a TLB: used only for second stage of an S12 page * table walk, or for descriptor loads during first stage of an S1 @@ -2992,8 +2979,8 @@ typedef enum ARMMMUIdx { * then various TLB flush insns which currently are no-ops or flush * only stage 1 MMU indexes will need to change to flush stage 2. */ - ARMMMUIdx_Stage2 = 6 | ARM_MMU_IDX_NOTLB, - ARMMMUIdx_Stage2_S = 7 | ARM_MMU_IDX_NOTLB, + ARMMMUIdx_Stage2 = 3 | ARM_MMU_IDX_NOTLB, + ARMMMUIdx_Stage2_S = 4 | ARM_MMU_IDX_NOTLB, /* * M-profile. @@ -3023,14 +3010,7 @@ typedef enum ARMMMUIdxBit { TO_CORE_BIT(E2), TO_CORE_BIT(E20_2), TO_CORE_BIT(E20_2_PAN), - TO_CORE_BIT(SE10_0), - TO_CORE_BIT(SE20_0), - TO_CORE_BIT(SE10_1), - TO_CORE_BIT(SE20_2), - TO_CORE_BIT(SE10_1_PAN), - TO_CORE_BIT(SE20_2_PAN), - TO_CORE_BIT(SE2), - TO_CORE_BIT(SE3), + TO_CORE_BIT(E3), TO_CORE_BIT(MUser), TO_CORE_BIT(MPriv), diff --git a/target/arm/helper.c b/target/arm/helper.c index fd4663a946..b1b8725628 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1754,6 +1754,7 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) /* Begin with base v8.0 state. */ uint64_t valid_mask = 0x3fff; ARMCPU *cpu = env_archcpu(env); + uint64_t changed; /* * Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset always @@ -1816,7 +1817,22 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) /* Clear all-context RES0 bits. */ value &= valid_mask; - raw_write(env, ri, value); + changed = env->cp15.scr_el3 ^ value; + env->cp15.scr_el3 = value; + + /* + * If SCR_EL3.NS changes, i.e. arm_is_secure_below_el3, then + * we must invalidate all TLBs below EL3. + */ + if (changed & SCR_NS) { + tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 | + ARMMMUIdxBit_E20_0 | + ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E20_2 | + ARMMMUIdxBit_E10_1_PAN | + ARMMMUIdxBit_E20_2_PAN | + ARMMMUIdxBit_E2)); + } } static void scr_reset(CPUARMState *env, const ARMCPRegInfo *ri) @@ -2647,9 +2663,6 @@ static int gt_phys_redir_timeridx(CPUARMState *env) case ARMMMUIdx_E20_0: case ARMMMUIdx_E20_2: case ARMMMUIdx_E20_2_PAN: - case ARMMMUIdx_SE20_0: - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: return GTIMER_HYP; default: return GTIMER_PHYS; @@ -2662,9 +2675,6 @@ static int gt_virt_redir_timeridx(CPUARMState *env) case ARMMMUIdx_E20_0: case ARMMMUIdx_E20_2: case ARMMMUIdx_E20_2_PAN: - case ARMMMUIdx_SE20_0: - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: return GTIMER_HYPVIRT; default: return GTIMER_VIRT; @@ -3372,7 +3382,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) /* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */ switch (el) { case 3: - mmu_idx = ARMMMUIdx_SE3; + mmu_idx = ARMMMUIdx_E3; secure = true; break; case 2: @@ -3380,10 +3390,9 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) /* fall through */ case 1: if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) { - mmu_idx = (secure ? ARMMMUIdx_Stage1_SE1_PAN - : ARMMMUIdx_Stage1_E1_PAN); + mmu_idx = ARMMMUIdx_Stage1_E1_PAN; } else { - mmu_idx = secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stage1_E1; + mmu_idx = ARMMMUIdx_Stage1_E1; } break; default: @@ -3394,7 +3403,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) /* stage 1 current state PL0: ATS1CUR, ATS1CUW */ switch (el) { case 3: - mmu_idx = ARMMMUIdx_SE10_0; + mmu_idx = ARMMMUIdx_E10_0; secure = true; break; case 2: @@ -3402,7 +3411,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) mmu_idx = ARMMMUIdx_Stage1_E0; break; case 1: - mmu_idx = secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0; + mmu_idx = ARMMMUIdx_Stage1_E0; break; default: g_assert_not_reached(); @@ -3471,17 +3480,16 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, switch (ri->opc1) { case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */ if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) { - mmu_idx = (secure ? ARMMMUIdx_Stage1_SE1_PAN - : ARMMMUIdx_Stage1_E1_PAN); + mmu_idx = ARMMMUIdx_Stage1_E1_PAN; } else { - mmu_idx = secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stage1_E1; + mmu_idx = ARMMMUIdx_Stage1_E1; } break; case 4: /* AT S1E2R, AT S1E2W */ - mmu_idx = secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2; + mmu_idx = ARMMMUIdx_E2; break; case 6: /* AT S1E3R, AT S1E3W */ - mmu_idx = ARMMMUIdx_SE3; + mmu_idx = ARMMMUIdx_E3; secure = true; break; default: @@ -3489,13 +3497,13 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, } break; case 2: /* AT S1E0R, AT S1E0W */ - mmu_idx = secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0; + mmu_idx = ARMMMUIdx_Stage1_E0; break; case 4: /* AT S12E1R, AT S12E1W */ - mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_E10_1; + mmu_idx = ARMMMUIdx_E10_1; break; case 6: /* AT S12E0R, AT S12E0W */ - mmu_idx = secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_E10_0; + mmu_idx = ARMMMUIdx_E10_0; break; default: g_assert_not_reached(); @@ -3765,11 +3773,6 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, uint16_t mask = ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_2_PAN | ARMMMUIdxBit_E20_0; - - if (arm_is_secure_below_el3(env)) { - mask >>= ARM_MMU_IDX_A_NS; - } - tlb_flush_by_mmuidx(env_cpu(env), mask); } raw_write(env, ri, value); @@ -3789,11 +3792,6 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint16_t mask = ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_1_PAN | ARMMMUIdxBit_E10_0; - - if (arm_is_secure_below_el3(env)) { - mask >>= ARM_MMU_IDX_A_NS; - } - tlb_flush_by_mmuidx(cs, mask); raw_write(env, ri, value); } @@ -4264,11 +4262,6 @@ static int vae1_tlbmask(CPUARMState *env) ARMMMUIdxBit_E10_1_PAN | ARMMMUIdxBit_E10_0; } - - if (arm_is_secure_below_el3(env)) { - mask >>= ARM_MMU_IDX_A_NS; - } - return mask; } @@ -4295,10 +4288,6 @@ static int vae1_tlbbits(CPUARMState *env, uint64_t addr) mmu_idx = ARMMMUIdx_E10_0; } - if (arm_is_secure_below_el3(env)) { - mmu_idx &= ~ARM_MMU_IDX_A_NS; - } - return tlbbits_for_regime(env, mmu_idx, addr); } @@ -4331,30 +4320,17 @@ static int alle1_tlbmask(CPUARMState *env) * stage 2 translations, whereas most other scopes only invalidate * stage 1 translations. */ - if (arm_is_secure_below_el3(env)) { - return ARMMMUIdxBit_SE10_1 | - ARMMMUIdxBit_SE10_1_PAN | - ARMMMUIdxBit_SE10_0; - } else { - return ARMMMUIdxBit_E10_1 | - ARMMMUIdxBit_E10_1_PAN | - ARMMMUIdxBit_E10_0; - } + return (ARMMMUIdxBit_E10_1 | + ARMMMUIdxBit_E10_1_PAN | + ARMMMUIdxBit_E10_0); } static int e2_tlbmask(CPUARMState *env) { - if (arm_is_secure_below_el3(env)) { - return ARMMMUIdxBit_SE20_0 | - ARMMMUIdxBit_SE20_2 | - ARMMMUIdxBit_SE20_2_PAN | - ARMMMUIdxBit_SE2; - } else { - return ARMMMUIdxBit_E20_0 | - ARMMMUIdxBit_E20_2 | - ARMMMUIdxBit_E20_2_PAN | - ARMMMUIdxBit_E2; - } + return (ARMMMUIdxBit_E20_0 | + ARMMMUIdxBit_E20_2 | + ARMMMUIdxBit_E20_2_PAN | + ARMMMUIdxBit_E2); } static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4381,7 +4357,7 @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri, ARMCPU *cpu = env_archcpu(env); CPUState *cs = CPU(cpu); - tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_SE3); + tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3); } static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4407,7 +4383,7 @@ static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri, { CPUState *cs = env_cpu(env); - tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_SE3); + tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E3); } static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4435,7 +4411,7 @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri, CPUState *cs = CPU(cpu); uint64_t pageaddr = sextract64(value << 12, 0, 56); - tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_SE3); + tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3); } static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4474,12 +4450,10 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri, { CPUState *cs = env_cpu(env); uint64_t pageaddr = sextract64(value << 12, 0, 56); - bool secure = arm_is_secure_below_el3(env); - int mask = secure ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2; - int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2, - pageaddr); + int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr); - tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits); + tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, + ARMMMUIdxBit_E2, bits); } static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri, @@ -4487,10 +4461,10 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri, { CPUState *cs = env_cpu(env); uint64_t pageaddr = sextract64(value << 12, 0, 56); - int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr); + int bits = tlbbits_for_regime(env, ARMMMUIdx_E3, pageaddr); tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, - ARMMMUIdxBit_SE3, bits); + ARMMMUIdxBit_E3, bits); } #ifdef TARGET_AARCH64 @@ -4596,8 +4570,7 @@ static void tlbi_aa64_rvae1is_write(CPUARMState *env, static int vae2_tlbmask(CPUARMState *env) { - return (arm_is_secure_below_el3(env) - ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2); + return ARMMMUIdxBit_E2; } static void tlbi_aa64_rvae2_write(CPUARMState *env, @@ -4643,8 +4616,7 @@ static void tlbi_aa64_rvae3_write(CPUARMState *env, * flush-last-level-only. */ - do_rvae_write(env, value, ARMMMUIdxBit_SE3, - tlb_force_broadcast(env)); + do_rvae_write(env, value, ARMMMUIdxBit_E3, tlb_force_broadcast(env)); } static void tlbi_aa64_rvae3is_write(CPUARMState *env, @@ -4658,7 +4630,7 @@ static void tlbi_aa64_rvae3is_write(CPUARMState *env, * flush-last-level-only or inner/outer specific flushes. */ - do_rvae_write(env, value, ARMMMUIdxBit_SE3, true); + do_rvae_write(env, value, ARMMMUIdxBit_E3, true); } #endif @@ -10271,8 +10243,7 @@ uint64_t arm_sctlr(CPUARMState *env, int el) /* Only EL0 needs to be adjusted for EL1&0 or EL2&0. */ if (el == 0) { ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0); - el = (mmu_idx == ARMMMUIdx_E20_0 || mmu_idx == ARMMMUIdx_SE20_0) - ? 2 : 1; + el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1; } return env->cp15.sctlr_el[el]; } @@ -10816,22 +10787,15 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx) switch (mmu_idx) { case ARMMMUIdx_E10_0: case ARMMMUIdx_E20_0: - case ARMMMUIdx_SE10_0: - case ARMMMUIdx_SE20_0: return 0; case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: return 1; case ARMMMUIdx_E2: case ARMMMUIdx_E20_2: case ARMMMUIdx_E20_2_PAN: - case ARMMMUIdx_SE2: - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: return 2; - case ARMMMUIdx_SE3: + case ARMMMUIdx_E3: return 3; default: g_assert_not_reached(); @@ -10884,15 +10848,11 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el) } break; case 3: - return ARMMMUIdx_SE3; + return ARMMMUIdx_E3; default: g_assert_not_reached(); } - if (arm_is_secure_below_el3(env)) { - idx &= ~ARM_MMU_IDX_A_NS; - } - return idx; } @@ -11095,15 +11055,11 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, switch (mmu_idx) { case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: /* TODO: ARMv8.3-NV */ DP_TBFLAG_A64(flags, UNPRIV, 1); break; case ARMMMUIdx_E20_2: case ARMMMUIdx_E20_2_PAN: - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: /* * Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is * gated by HCR_EL2. == '11', and so is LDTR. diff --git a/target/arm/internals.h b/target/arm/internals.h index 14428730d4..b509d70851 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -649,21 +649,12 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx) case ARMMMUIdx_Stage1_E0: case ARMMMUIdx_Stage1_E1: case ARMMMUIdx_Stage1_E1_PAN: - case ARMMMUIdx_Stage1_SE0: - case ARMMMUIdx_Stage1_SE1: - case ARMMMUIdx_Stage1_SE1_PAN: case ARMMMUIdx_E10_0: case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: case ARMMMUIdx_E20_0: case ARMMMUIdx_E20_2: case ARMMMUIdx_E20_2_PAN: - case ARMMMUIdx_SE10_0: - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: - case ARMMMUIdx_SE20_0: - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: return true; default: return false; @@ -674,11 +665,8 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx) { switch (mmu_idx) { case ARMMMUIdx_Stage1_E1_PAN: - case ARMMMUIdx_Stage1_SE1_PAN: case ARMMMUIdx_E10_1_PAN: case ARMMMUIdx_E20_2_PAN: - case ARMMMUIdx_SE10_1_PAN: - case ARMMMUIdx_SE20_2_PAN: return true; default: return false; @@ -689,30 +677,20 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx) static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx) { switch (mmu_idx) { - case ARMMMUIdx_SE20_0: - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: case ARMMMUIdx_E20_0: case ARMMMUIdx_E20_2: case ARMMMUIdx_E20_2_PAN: case ARMMMUIdx_Stage2: case ARMMMUIdx_Stage2_S: - case ARMMMUIdx_SE2: case ARMMMUIdx_E2: return 2; - case ARMMMUIdx_SE3: + case ARMMMUIdx_E3: return 3; - case ARMMMUIdx_SE10_0: - case ARMMMUIdx_Stage1_SE0: - return arm_el_is_aa64(env, 3) ? 1 : 3; - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: + case ARMMMUIdx_E10_0: case ARMMMUIdx_Stage1_E0: + return arm_el_is_aa64(env, 3) || !arm_is_secure_below_el3(env) ? 1 : 3; case ARMMMUIdx_Stage1_E1: case ARMMMUIdx_Stage1_E1_PAN: - case ARMMMUIdx_Stage1_SE1: - case ARMMMUIdx_Stage1_SE1_PAN: - case ARMMMUIdx_E10_0: case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: case ARMMMUIdx_MPrivNegPri: @@ -954,9 +932,6 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx) case ARMMMUIdx_Stage1_E0: case ARMMMUIdx_Stage1_E1: case ARMMMUIdx_Stage1_E1_PAN: - case ARMMMUIdx_Stage1_SE0: - case ARMMMUIdx_Stage1_SE1: - case ARMMMUIdx_Stage1_SE1_PAN: return true; default: return false; diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 55e8f33c50..2055d684e6 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -65,12 +65,6 @@ unsigned int arm_pamax(ARMCPU *cpu) ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx) { switch (mmu_idx) { - case ARMMMUIdx_SE10_0: - return ARMMMUIdx_Stage1_SE0; - case ARMMMUIdx_SE10_1: - return ARMMMUIdx_Stage1_SE1; - case ARMMMUIdx_SE10_1_PAN: - return ARMMMUIdx_Stage1_SE1_PAN; case ARMMMUIdx_E10_0: return ARMMMUIdx_Stage1_E0; case ARMMMUIdx_E10_1: @@ -95,11 +89,8 @@ static bool regime_translation_big_endian(CPUARMState *env, ARMMMUIdx mmu_idx) static bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx) { switch (mmu_idx) { - case ARMMMUIdx_SE10_0: case ARMMMUIdx_E20_0: - case ARMMMUIdx_SE20_0: case ARMMMUIdx_Stage1_E0: - case ARMMMUIdx_Stage1_SE0: case ARMMMUIdx_MUser: case ARMMMUIdx_MSUser: case ARMMMUIdx_MUserNegPri: @@ -2304,7 +2295,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, s2_mmu_idx = (s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2); - is_el0 = mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_SE10_0; + is_el0 = mmu_idx == ARMMMUIdx_E10_0; /* * S1 is done, now do S2 translation. @@ -2511,6 +2502,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, case ARMMMUIdx_Stage1_E1: case ARMMMUIdx_Stage1_E1_PAN: case ARMMMUIdx_E2: + is_secure = arm_is_secure_below_el3(env); + break; case ARMMMUIdx_Stage2: case ARMMMUIdx_MPrivNegPri: case ARMMMUIdx_MUserNegPri: @@ -2518,17 +2511,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address, case ARMMMUIdx_MUser: is_secure = false; break; - case ARMMMUIdx_SE3: - case ARMMMUIdx_SE10_0: - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: - case ARMMMUIdx_SE20_0: - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: - case ARMMMUIdx_Stage1_SE0: - case ARMMMUIdx_Stage1_SE1: - case ARMMMUIdx_Stage1_SE1_PAN: - case ARMMMUIdx_SE2: + case ARMMMUIdx_E3: case ARMMMUIdx_Stage2_S: case ARMMMUIdx_MSPrivNegPri: case ARMMMUIdx_MSUserNegPri: diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 78b2d91ed4..5b67375f4e 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -111,14 +111,6 @@ static int get_a64_user_mem_index(DisasContext *s) case ARMMMUIdx_E20_2_PAN: useridx = ARMMMUIdx_E20_0; break; - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: - useridx = ARMMMUIdx_SE10_0; - break; - case ARMMMUIdx_SE20_2: - case ARMMMUIdx_SE20_2_PAN: - useridx = ARMMMUIdx_SE20_0; - break; default: g_assert_not_reached(); } diff --git a/target/arm/translate.c b/target/arm/translate.c index ac647e0262..2f72afe019 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -237,16 +237,12 @@ static inline int get_a32_user_mem_index(DisasContext *s) * otherwise, access as if at PL0. */ switch (s->mmu_idx) { + case ARMMMUIdx_E3: case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */ case ARMMMUIdx_E10_0: case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: return arm_to_core_mmu_idx(ARMMMUIdx_E10_0); - case ARMMMUIdx_SE3: - case ARMMMUIdx_SE10_0: - case ARMMMUIdx_SE10_1: - case ARMMMUIdx_SE10_1_PAN: - return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0); case ARMMMUIdx_MUser: case ARMMMUIdx_MPriv: return arm_to_core_mmu_idx(ARMMMUIdx_MUser); From 3b2af99313504b65f582e034cf505fea839984e9 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:47 -0700 Subject: [PATCH 1006/1020] target/arm: Reorg regime_translation_disabled Use a switch on mmu_idx for the a-profile indexes, instead of three different if's vs regime_el and arm_mmu_idx_is_stage1_of_2. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-12-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 2055d684e6..a514a78c92 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -148,21 +148,39 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx, hcr_el2 = arm_hcr_el2_eff(env); - if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) { + switch (mmu_idx) { + case ARMMMUIdx_Stage2: + case ARMMMUIdx_Stage2_S: /* HCR.DC means HCR.VM behaves as 1 */ return (hcr_el2 & (HCR_DC | HCR_VM)) == 0; - } - if (hcr_el2 & HCR_TGE) { + case ARMMMUIdx_E10_0: + case ARMMMUIdx_E10_1: + case ARMMMUIdx_E10_1_PAN: /* TGE means that NS EL0/1 act as if SCTLR_EL1.M is zero */ - if (!is_secure && regime_el(env, mmu_idx) == 1) { + if (!is_secure && (hcr_el2 & HCR_TGE)) { return true; } - } + break; - if ((hcr_el2 & HCR_DC) && arm_mmu_idx_is_stage1_of_2(mmu_idx)) { + case ARMMMUIdx_Stage1_E0: + case ARMMMUIdx_Stage1_E1: + case ARMMMUIdx_Stage1_E1_PAN: /* HCR.DC means SCTLR_EL1.M behaves as 0 */ - return true; + if (hcr_el2 & HCR_DC) { + return true; + } + break; + + case ARMMMUIdx_E20_0: + case ARMMMUIdx_E20_2: + case ARMMMUIdx_E20_2_PAN: + case ARMMMUIdx_E2: + case ARMMMUIdx_E3: + break; + + default: + g_assert_not_reached(); } return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0; From fdf12933390119a06cfb74dc892c5ce868b6a963 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:48 -0700 Subject: [PATCH 1007/1020] target/arm: Drop secure check for HCR.TGE vs SCTLR_EL1.M The effect of TGE does not only apply to non-secure state, now that Secure EL2 exists. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-13-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index a514a78c92..b3e0db1936 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -157,8 +157,8 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx, case ARMMMUIdx_E10_0: case ARMMMUIdx_E10_1: case ARMMMUIdx_E10_1_PAN: - /* TGE means that NS EL0/1 act as if SCTLR_EL1.M is zero */ - if (!is_secure && (hcr_el2 & HCR_TGE)) { + /* TGE means that EL0/1 act as if SCTLR_EL1.M is zero */ + if (hcr_el2 & HCR_TGE) { return true; } break; From b74c04431d0afac930634794c8a7b74ec0d8572b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:49 -0700 Subject: [PATCH 1008/1020] target/arm: Introduce arm_hcr_el2_eff_secstate For page walking, we may require HCR for a security state that is not "current". Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-14-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/cpu.h | 20 +++++++++++++------- target/arm/helper.c | 11 ++++++++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 53f4c236e1..d541392170 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -2412,15 +2412,15 @@ static inline bool arm_is_secure(CPUARMState *env) * Return true if the current security state has AArch64 EL2 or AArch32 Hyp. * This corresponds to the pseudocode EL2Enabled() */ +static inline bool arm_is_el2_enabled_secstate(CPUARMState *env, bool secure) +{ + return arm_feature(env, ARM_FEATURE_EL2) + && (!secure || (env->cp15.scr_el3 & SCR_EEL2)); +} + static inline bool arm_is_el2_enabled(CPUARMState *env) { - if (arm_feature(env, ARM_FEATURE_EL2)) { - if (arm_is_secure_below_el3(env)) { - return (env->cp15.scr_el3 & SCR_EEL2) != 0; - } - return true; - } - return false; + return arm_is_el2_enabled_secstate(env, arm_is_secure_below_el3(env)); } #else @@ -2434,6 +2434,11 @@ static inline bool arm_is_secure(CPUARMState *env) return false; } +static inline bool arm_is_el2_enabled_secstate(CPUARMState *env, bool secure) +{ + return false; +} + static inline bool arm_is_el2_enabled(CPUARMState *env) { return false; @@ -2446,6 +2451,7 @@ static inline bool arm_is_el2_enabled(CPUARMState *env) * "for all purposes other than a direct read or write access of HCR_EL2." * Not included here is HCR_RW. */ +uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, bool secure); uint64_t arm_hcr_el2_eff(CPUARMState *env); uint64_t arm_hcrx_el2_eff(CPUARMState *env); diff --git a/target/arm/helper.c b/target/arm/helper.c index b1b8725628..f1266bb157 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -5229,15 +5229,15 @@ static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri, } /* - * Return the effective value of HCR_EL2. + * Return the effective value of HCR_EL2, at the given security state. * Bits that are not included here: * RW (read from SCR_EL3.RW as needed) */ -uint64_t arm_hcr_el2_eff(CPUARMState *env) +uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, bool secure) { uint64_t ret = env->cp15.hcr_el2; - if (!arm_is_el2_enabled(env)) { + if (!arm_is_el2_enabled_secstate(env, secure)) { /* * "This register has no effect if EL2 is not enabled in the * current Security state". This is ARMv8.4-SecEL2 speak for @@ -5296,6 +5296,11 @@ uint64_t arm_hcr_el2_eff(CPUARMState *env) return ret; } +uint64_t arm_hcr_el2_eff(CPUARMState *env) +{ + return arm_hcr_el2_eff_secstate(env, arm_is_secure_below_el3(env)); +} + /* * Corresponds to ARM pseudocode function ELIsInHost(). */ From ab1f78859dd711fed72b1aeb7e46e05b0273a017 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:50 -0700 Subject: [PATCH 1009/1020] target/arm: Hoist read of *is_secure in S1_ptw_translate Rename the argument to is_secure_ptr, and introduce a local variable is_secure with the value. We only write back to the pointer toward the end of the function. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-15-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index b3e0db1936..b40b4586f8 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -207,24 +207,25 @@ static bool ptw_attrs_are_device(CPUARMState *env, ARMCacheAttrs cacheattrs) /* Translate a S1 pagetable walk through S2 if needed. */ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, - hwaddr addr, bool *is_secure, + hwaddr addr, bool *is_secure_ptr, ARMMMUFaultInfo *fi) { - ARMMMUIdx s2_mmu_idx = *is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2; + bool is_secure = *is_secure_ptr; + ARMMMUIdx s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2; if (arm_mmu_idx_is_stage1_of_2(mmu_idx) && - !regime_translation_disabled(env, s2_mmu_idx, *is_secure)) { + !regime_translation_disabled(env, s2_mmu_idx, is_secure)) { GetPhysAddrResult s2 = {}; int ret; ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx, - *is_secure, false, &s2, fi); + is_secure, false, &s2, fi); if (ret) { assert(fi->type != ARMFault_None); fi->s2addr = addr; fi->stage2 = true; fi->s1ptw = true; - fi->s1ns = !*is_secure; + fi->s1ns = !is_secure; return ~0; } if ((arm_hcr_el2_eff(env) & HCR_PTW) && @@ -237,19 +238,20 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, fi->s2addr = addr; fi->stage2 = true; fi->s1ptw = true; - fi->s1ns = !*is_secure; + fi->s1ns = !is_secure; return ~0; } if (arm_is_secure_below_el3(env)) { /* Check if page table walk is to secure or non-secure PA space. */ - if (*is_secure) { - *is_secure = !(env->cp15.vstcr_el2 & VSTCR_SW); + if (is_secure) { + is_secure = !(env->cp15.vstcr_el2 & VSTCR_SW); } else { - *is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW); + is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW); } + *is_secure_ptr = is_secure; } else { - assert(!*is_secure); + assert(!is_secure); } addr = s2.phys; From 72cef09caa2ce23324777676979c62bbdd02cb35 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:51 -0700 Subject: [PATCH 1010/1020] target/arm: Remove env argument from combined_attrs_fwb This value is unused. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-id: 20221001162318.153420-16-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index b40b4586f8..7d607c2e7b 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2172,8 +2172,7 @@ static uint8_t force_cacheattr_nibble_wb(uint8_t attr) * s1 and s2 for the HCR_EL2.FWB == 1 case, returning the * combined attributes in MAIR_EL1 format. */ -static uint8_t combined_attrs_fwb(CPUARMState *env, - ARMCacheAttrs s1, ARMCacheAttrs s2) +static uint8_t combined_attrs_fwb(ARMCacheAttrs s1, ARMCacheAttrs s2) { switch (s2.attrs) { case 7: @@ -2246,7 +2245,7 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env, /* Combine memory type and cacheability attributes */ if (arm_hcr_el2_eff(env) & HCR_FWB) { - ret.attrs = combined_attrs_fwb(env, s1, s2); + ret.attrs = combined_attrs_fwb(s1, s2); } else { ret.attrs = combined_attrs_nofwb(env, s1, s2); } From ac76c2e508871e8180780338aa035c67ece75888 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:52 -0700 Subject: [PATCH 1011/1020] target/arm: Pass HCR to attribute subroutines. These subroutines did not need ENV for anything except retrieving the effective value of HCR anyway. We have computed the effective value of HCR in the callers, and this will be especially important for interpreting HCR in a non-current security state. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-17-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 7d607c2e7b..b4fd4d3fac 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -186,7 +186,7 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx, return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0; } -static bool ptw_attrs_are_device(CPUARMState *env, ARMCacheAttrs cacheattrs) +static bool ptw_attrs_are_device(uint64_t hcr, ARMCacheAttrs cacheattrs) { /* * For an S1 page table walk, the stage 1 attributes are always @@ -198,7 +198,7 @@ static bool ptw_attrs_are_device(CPUARMState *env, ARMCacheAttrs cacheattrs) * when cacheattrs.attrs bit [2] is 0. */ assert(cacheattrs.is_s2_format); - if (arm_hcr_el2_eff(env) & HCR_FWB) { + if (hcr & HCR_FWB) { return (cacheattrs.attrs & 0x4) == 0; } else { return (cacheattrs.attrs & 0xc) == 0; @@ -216,6 +216,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, if (arm_mmu_idx_is_stage1_of_2(mmu_idx) && !regime_translation_disabled(env, s2_mmu_idx, is_secure)) { GetPhysAddrResult s2 = {}; + uint64_t hcr; int ret; ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx, @@ -228,8 +229,9 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, fi->s1ns = !is_secure; return ~0; } - if ((arm_hcr_el2_eff(env) & HCR_PTW) && - ptw_attrs_are_device(env, s2.cacheattrs)) { + + hcr = arm_hcr_el2_eff(env); + if ((hcr & HCR_PTW) && ptw_attrs_are_device(hcr, s2.cacheattrs)) { /* * PTW set and S1 walk touched S2 Device memory: * generate Permission fault. @@ -2059,14 +2061,14 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, * ref: shared/translation/attrs/S2AttrDecode() * .../S2ConvertAttrsHints() */ -static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs) +static uint8_t convert_stage2_attrs(uint64_t hcr, uint8_t s2attrs) { uint8_t hiattr = extract32(s2attrs, 2, 2); uint8_t loattr = extract32(s2attrs, 0, 2); uint8_t hihint = 0, lohint = 0; if (hiattr != 0) { /* normal memory */ - if (arm_hcr_el2_eff(env) & HCR_CD) { /* cache disabled */ + if (hcr & HCR_CD) { /* cache disabled */ hiattr = loattr = 1; /* non-cacheable */ } else { if (hiattr != 1) { /* Write-through or write-back */ @@ -2112,12 +2114,12 @@ static uint8_t combine_cacheattr_nibble(uint8_t s1, uint8_t s2) * s1 and s2 for the HCR_EL2.FWB == 0 case, returning the * combined attributes in MAIR_EL1 format. */ -static uint8_t combined_attrs_nofwb(CPUARMState *env, +static uint8_t combined_attrs_nofwb(uint64_t hcr, ARMCacheAttrs s1, ARMCacheAttrs s2) { uint8_t s1lo, s2lo, s1hi, s2hi, s2_mair_attrs, ret_attrs; - s2_mair_attrs = convert_stage2_attrs(env, s2.attrs); + s2_mair_attrs = convert_stage2_attrs(hcr, s2.attrs); s1lo = extract32(s1.attrs, 0, 4); s2lo = extract32(s2_mair_attrs, 0, 4); @@ -2217,7 +2219,7 @@ static uint8_t combined_attrs_fwb(ARMCacheAttrs s1, ARMCacheAttrs s2) * @s1: Attributes from stage 1 walk * @s2: Attributes from stage 2 walk */ -static ARMCacheAttrs combine_cacheattrs(CPUARMState *env, +static ARMCacheAttrs combine_cacheattrs(uint64_t hcr, ARMCacheAttrs s1, ARMCacheAttrs s2) { ARMCacheAttrs ret; @@ -2244,10 +2246,10 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env, } /* Combine memory type and cacheability attributes */ - if (arm_hcr_el2_eff(env) & HCR_FWB) { + if (hcr & HCR_FWB) { ret.attrs = combined_attrs_fwb(s1, s2); } else { - ret.attrs = combined_attrs_nofwb(env, s1, s2); + ret.attrs = combined_attrs_nofwb(hcr, s1, s2); } /* @@ -2290,6 +2292,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, ARMCacheAttrs cacheattrs1; ARMMMUIdx s2_mmu_idx; bool is_el0; + uint64_t hcr; ret = get_phys_addr_with_secure(env, address, access_type, s1_mmu_idx, is_secure, result, fi); @@ -2338,7 +2341,8 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, } /* Combine the S1 and S2 cache attributes. */ - if (arm_hcr_el2_eff(env) & HCR_DC) { + hcr = arm_hcr_el2_eff(env); + if (hcr & HCR_DC) { /* * HCR.DC forces the first stage attributes to * Normal Non-Shareable, @@ -2351,7 +2355,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, } cacheattrs1.shareability = 0; } - result->cacheattrs = combine_cacheattrs(env, cacheattrs1, + result->cacheattrs = combine_cacheattrs(hcr, cacheattrs1, result->cacheattrs); /* From 2189c79858a9eadd85851afc2369d8679ecd563a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:53 -0700 Subject: [PATCH 1012/1020] target/arm: Fix ATS12NSO* from S PL1 Use arm_hcr_el2_eff_secstate instead of arm_hcr_el2_eff, so that we use is_secure instead of the current security state. These AT* operations have been broken since arm_hcr_el2_eff gained a check for "el2 enabled" for Secure EL2. Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-18-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index b4fd4d3fac..a589cec8e3 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -146,7 +146,7 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx, } } - hcr_el2 = arm_hcr_el2_eff(env); + hcr_el2 = arm_hcr_el2_eff_secstate(env, is_secure); switch (mmu_idx) { case ARMMMUIdx_Stage2: @@ -230,7 +230,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, return ~0; } - hcr = arm_hcr_el2_eff(env); + hcr = arm_hcr_el2_eff_secstate(env, is_secure); if ((hcr & HCR_PTW) && ptw_attrs_are_device(hcr, s2.cacheattrs)) { /* * PTW set and S1 walk touched S2 Device memory: @@ -2341,7 +2341,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, } /* Combine the S1 and S2 cache attributes. */ - hcr = arm_hcr_el2_eff(env); + hcr = arm_hcr_el2_eff_secstate(env, is_secure); if (hcr & HCR_DC) { /* * HCR.DC forces the first stage attributes to @@ -2473,7 +2473,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, result->page_size = TARGET_PAGE_SIZE; /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */ - hcr = arm_hcr_el2_eff(env); + hcr = arm_hcr_el2_eff_secstate(env, is_secure); result->cacheattrs.shareability = 0; result->cacheattrs.is_s2_format = false; if (hcr & HCR_DC) { From 448e42fdc1013b3497c9a6902f8052488fc8af1a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:54 -0700 Subject: [PATCH 1013/1020] target/arm: Split out get_phys_addr_disabled Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson Message-id: 20221001162318.153420-19-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 138 +++++++++++++++++++++++++---------------------- 1 file changed, 74 insertions(+), 64 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index a589cec8e3..96ab99c7b6 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2272,6 +2272,78 @@ static ARMCacheAttrs combine_cacheattrs(uint64_t hcr, return ret; } +/* + * MMU disabled. S1 addresses within aa64 translation regimes are + * still checked for bounds -- see AArch64.S1DisabledOutput(). + */ +static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address, + MMUAccessType access_type, + ARMMMUIdx mmu_idx, bool is_secure, + GetPhysAddrResult *result, + ARMMMUFaultInfo *fi) +{ + uint64_t hcr; + uint8_t memattr; + + if (mmu_idx != ARMMMUIdx_Stage2 && mmu_idx != ARMMMUIdx_Stage2_S) { + int r_el = regime_el(env, mmu_idx); + if (arm_el_is_aa64(env, r_el)) { + int pamax = arm_pamax(env_archcpu(env)); + uint64_t tcr = env->cp15.tcr_el[r_el]; + int addrtop, tbi; + + tbi = aa64_va_parameter_tbi(tcr, mmu_idx); + if (access_type == MMU_INST_FETCH) { + tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx); + } + tbi = (tbi >> extract64(address, 55, 1)) & 1; + addrtop = (tbi ? 55 : 63); + + if (extract64(address, pamax, addrtop - pamax + 1) != 0) { + fi->type = ARMFault_AddressSize; + fi->level = 0; + fi->stage2 = false; + return 1; + } + + /* + * When TBI is disabled, we've just validated that all of the + * bits above PAMax are zero, so logically we only need to + * clear the top byte for TBI. But it's clearer to follow + * the pseudocode set of addrdesc.paddress. + */ + address = extract64(address, 0, 52); + } + } + + result->phys = address; + result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + result->page_size = TARGET_PAGE_SIZE; + + /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */ + hcr = arm_hcr_el2_eff_secstate(env, is_secure); + result->cacheattrs.shareability = 0; + result->cacheattrs.is_s2_format = false; + if (hcr & HCR_DC) { + if (hcr & HCR_DCT) { + memattr = 0xf0; /* Tagged, Normal, WB, RWA */ + } else { + memattr = 0xff; /* Normal, WB, RWA */ + } + } else if (access_type == MMU_INST_FETCH) { + if (regime_sctlr(env, mmu_idx) & SCTLR_I) { + memattr = 0xee; /* Normal, WT, RA, NT */ + } else { + memattr = 0x44; /* Normal, NC, No */ + } + result->cacheattrs.shareability = 2; /* outer sharable */ + } else { + memattr = 0x00; /* Device, nGnRnE */ + } + result->cacheattrs.attrs = memattr; + return 0; +} + bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, MMUAccessType access_type, ARMMMUIdx mmu_idx, bool is_secure, GetPhysAddrResult *result, @@ -2431,71 +2503,9 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, /* Definitely a real MMU, not an MPU */ if (regime_translation_disabled(env, mmu_idx, is_secure)) { - uint64_t hcr; - uint8_t memattr; - - /* - * MMU disabled. S1 addresses within aa64 translation regimes are - * still checked for bounds -- see AArch64.TranslateAddressS1Off. - */ - if (mmu_idx != ARMMMUIdx_Stage2 && mmu_idx != ARMMMUIdx_Stage2_S) { - int r_el = regime_el(env, mmu_idx); - if (arm_el_is_aa64(env, r_el)) { - int pamax = arm_pamax(env_archcpu(env)); - uint64_t tcr = env->cp15.tcr_el[r_el]; - int addrtop, tbi; - - tbi = aa64_va_parameter_tbi(tcr, mmu_idx); - if (access_type == MMU_INST_FETCH) { - tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx); - } - tbi = (tbi >> extract64(address, 55, 1)) & 1; - addrtop = (tbi ? 55 : 63); - - if (extract64(address, pamax, addrtop - pamax + 1) != 0) { - fi->type = ARMFault_AddressSize; - fi->level = 0; - fi->stage2 = false; - return 1; - } - - /* - * When TBI is disabled, we've just validated that all of the - * bits above PAMax are zero, so logically we only need to - * clear the top byte for TBI. But it's clearer to follow - * the pseudocode set of addrdesc.paddress. - */ - address = extract64(address, 0, 52); - } - } - result->phys = address; - result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - result->page_size = TARGET_PAGE_SIZE; - - /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */ - hcr = arm_hcr_el2_eff_secstate(env, is_secure); - result->cacheattrs.shareability = 0; - result->cacheattrs.is_s2_format = false; - if (hcr & HCR_DC) { - if (hcr & HCR_DCT) { - memattr = 0xf0; /* Tagged, Normal, WB, RWA */ - } else { - memattr = 0xff; /* Normal, WB, RWA */ - } - } else if (access_type == MMU_INST_FETCH) { - if (regime_sctlr(env, mmu_idx) & SCTLR_I) { - memattr = 0xee; /* Normal, WT, RA, NT */ - } else { - memattr = 0x44; /* Normal, NC, No */ - } - result->cacheattrs.shareability = 2; /* outer sharable */ - } else { - memattr = 0x00; /* Device, nGnRnE */ - } - result->cacheattrs.attrs = memattr; - return 0; + return get_phys_addr_disabled(env, address, access_type, mmu_idx, + is_secure, result, fi); } - if (regime_using_lpae_format(env, mmu_idx)) { return get_phys_addr_lpae(env, address, access_type, mmu_idx, is_secure, false, result, fi); From 5b74f9b4ed9033dc5427cd69f5ee37e7b726ecfd Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:55 -0700 Subject: [PATCH 1014/1020] target/arm: Fix cacheattr in get_phys_addr_disabled Do not apply memattr or shareability for Stage2 translations. Make sure to apply HCR_{DC,DCT} only to Regime_EL10, per the pseudocode in AArch64.S1DisabledOutput. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-id: 20221001162318.153420-20-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/ptw.c | 48 +++++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 96ab99c7b6..15c37b52c9 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2282,11 +2282,12 @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address, GetPhysAddrResult *result, ARMMMUFaultInfo *fi) { - uint64_t hcr; - uint8_t memattr; + uint8_t memattr = 0x00; /* Device nGnRnE */ + uint8_t shareability = 0; /* non-sharable */ if (mmu_idx != ARMMMUIdx_Stage2 && mmu_idx != ARMMMUIdx_Stage2_S) { int r_el = regime_el(env, mmu_idx); + if (arm_el_is_aa64(env, r_el)) { int pamax = arm_pamax(env_archcpu(env)); uint64_t tcr = env->cp15.tcr_el[r_el]; @@ -2314,32 +2315,33 @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address, */ address = extract64(address, 0, 52); } + + /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */ + if (r_el == 1) { + uint64_t hcr = arm_hcr_el2_eff_secstate(env, is_secure); + if (hcr & HCR_DC) { + if (hcr & HCR_DCT) { + memattr = 0xf0; /* Tagged, Normal, WB, RWA */ + } else { + memattr = 0xff; /* Normal, WB, RWA */ + } + } + } + if (memattr == 0 && access_type == MMU_INST_FETCH) { + if (regime_sctlr(env, mmu_idx) & SCTLR_I) { + memattr = 0xee; /* Normal, WT, RA, NT */ + } else { + memattr = 0x44; /* Normal, NC, No */ + } + shareability = 2; /* outer sharable */ + } + result->cacheattrs.is_s2_format = false; } result->phys = address; result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; result->page_size = TARGET_PAGE_SIZE; - - /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */ - hcr = arm_hcr_el2_eff_secstate(env, is_secure); - result->cacheattrs.shareability = 0; - result->cacheattrs.is_s2_format = false; - if (hcr & HCR_DC) { - if (hcr & HCR_DCT) { - memattr = 0xf0; /* Tagged, Normal, WB, RWA */ - } else { - memattr = 0xff; /* Normal, WB, RWA */ - } - } else if (access_type == MMU_INST_FETCH) { - if (regime_sctlr(env, mmu_idx) & SCTLR_I) { - memattr = 0xee; /* Normal, WT, RA, NT */ - } else { - memattr = 0x44; /* Normal, NC, No */ - } - result->cacheattrs.shareability = 2; /* outer sharable */ - } else { - memattr = 0x00; /* Device, nGnRnE */ - } + result->cacheattrs.shareability = shareability; result->cacheattrs.attrs = memattr; return 0; } From 7fa7ea8f480cd6f3f5f2a9453eea5733510b6c8b Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sat, 1 Oct 2022 09:22:56 -0700 Subject: [PATCH 1015/1020] target/arm: Use tlb_set_page_full Adjust GetPhysAddrResult to fill in CPUTLBEntryFull, so that it may be passed directly to tlb_set_page_full. The change is large, but mostly mechanical. The major non-mechanical change is page_size -> lg_page_size. Most of the time this is obvious, and is related to TARGET_PAGE_BITS. Signed-off-by: Richard Henderson Reviewed-by: Peter Maydell Message-id: 20221001162318.153420-21-richard.henderson@linaro.org Signed-off-by: Peter Maydell --- target/arm/helper.c | 12 +-- target/arm/internals.h | 5 +- target/arm/m_helper.c | 20 ++--- target/arm/ptw.c | 179 ++++++++++++++++++++-------------------- target/arm/tlb_helper.c | 9 +- 5 files changed, 111 insertions(+), 114 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index f1266bb157..e1338ed6e2 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -3323,8 +3323,8 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, /* Create a 64-bit PAR */ par64 = (1 << 11); /* LPAE bit always set */ if (!ret) { - par64 |= res.phys & ~0xfffULL; - if (!res.attrs.secure) { + par64 |= res.f.phys_addr & ~0xfffULL; + if (!res.f.attrs.secure) { par64 |= (1 << 9); /* NS */ } par64 |= (uint64_t)res.cacheattrs.attrs << 56; /* ATTR */ @@ -3348,13 +3348,13 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value, */ if (!ret) { /* We do not set any attribute bits in the PAR */ - if (res.page_size == (1 << 24) + if (res.f.lg_page_size == 24 && arm_feature(env, ARM_FEATURE_V7)) { - par64 = (res.phys & 0xff000000) | (1 << 1); + par64 = (res.f.phys_addr & 0xff000000) | (1 << 1); } else { - par64 = res.phys & 0xfffff000; + par64 = res.f.phys_addr & 0xfffff000; } - if (!res.attrs.secure) { + if (!res.f.attrs.secure) { par64 |= (1 << 9); /* NS */ } } else { diff --git a/target/arm/internals.h b/target/arm/internals.h index b509d70851..fd17aee459 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1071,10 +1071,7 @@ typedef struct ARMCacheAttrs { /* Fields that are valid upon success. */ typedef struct GetPhysAddrResult { - hwaddr phys; - target_ulong page_size; - int prot; - MemTxAttrs attrs; + CPUTLBEntryFull f; ARMCacheAttrs cacheattrs; } GetPhysAddrResult; diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c index 203ba411f6..355cd4d60a 100644 --- a/target/arm/m_helper.c +++ b/target/arm/m_helper.c @@ -223,8 +223,8 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value, } goto pend_fault; } - address_space_stl_le(arm_addressspace(cs, res.attrs), res.phys, value, - res.attrs, &txres); + address_space_stl_le(arm_addressspace(cs, res.f.attrs), res.f.phys_addr, + value, res.f.attrs, &txres); if (txres != MEMTX_OK) { /* BusFault trying to write the data */ if (mode == STACK_LAZYFP) { @@ -298,8 +298,8 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr, goto pend_fault; } - value = address_space_ldl(arm_addressspace(cs, res.attrs), res.phys, - res.attrs, &txres); + value = address_space_ldl(arm_addressspace(cs, res.f.attrs), + res.f.phys_addr, res.f.attrs, &txres); if (txres != MEMTX_OK) { /* BusFault trying to read the data */ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.UNSTKERR\n"); @@ -2022,8 +2022,8 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, bool secure, qemu_log_mask(CPU_LOG_INT, "...really MemManage with CFSR.IACCVIOL\n"); return false; } - *insn = address_space_lduw_le(arm_addressspace(cs, res.attrs), res.phys, - res.attrs, &txres); + *insn = address_space_lduw_le(arm_addressspace(cs, res.f.attrs), + res.f.phys_addr, res.f.attrs, &txres); if (txres != MEMTX_OK) { env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_IBUSERR_MASK; armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false); @@ -2069,8 +2069,8 @@ static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx, } return false; } - value = address_space_ldl(arm_addressspace(cs, res.attrs), res.phys, - res.attrs, &txres); + value = address_space_ldl(arm_addressspace(cs, res.f.attrs), + res.f.phys_addr, res.f.attrs, &txres); if (txres != MEMTX_OK) { /* BusFault trying to read the data */ qemu_log_mask(CPU_LOG_INT, @@ -2817,8 +2817,8 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op) } else { mrvalid = true; } - r = res.prot & PAGE_READ; - rw = res.prot & PAGE_WRITE; + r = res.f.prot & PAGE_READ; + rw = res.f.prot & PAGE_WRITE; } else { r = false; rw = false; diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 15c37b52c9..ddacffa7ee 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -256,7 +256,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, assert(!is_secure); } - addr = s2.phys; + addr = s2.f.phys_addr; } return addr; } @@ -476,7 +476,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, /* 1Mb section. */ phys_addr = (desc & 0xfff00000) | (address & 0x000fffff); ap = (desc >> 10) & 3; - result->page_size = 1024 * 1024; + result->f.lg_page_size = 20; /* 1MB */ } else { /* Lookup l2 entry. */ if (type == 1) { @@ -497,12 +497,12 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, case 1: /* 64k page. */ phys_addr = (desc & 0xffff0000) | (address & 0xffff); ap = (desc >> (4 + ((address >> 13) & 6))) & 3; - result->page_size = 0x10000; + result->f.lg_page_size = 16; break; case 2: /* 4k page. */ phys_addr = (desc & 0xfffff000) | (address & 0xfff); ap = (desc >> (4 + ((address >> 9) & 6))) & 3; - result->page_size = 0x1000; + result->f.lg_page_size = 12; break; case 3: /* 1k page, or ARMv6/XScale "extended small (4k) page" */ if (type == 1) { @@ -510,7 +510,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, if (arm_feature(env, ARM_FEATURE_XSCALE) || arm_feature(env, ARM_FEATURE_V6)) { phys_addr = (desc & 0xfffff000) | (address & 0xfff); - result->page_size = 0x1000; + result->f.lg_page_size = 12; } else { /* * UNPREDICTABLE in ARMv5; we choose to take a @@ -521,7 +521,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, } } else { phys_addr = (desc & 0xfffffc00) | (address & 0x3ff); - result->page_size = 0x400; + result->f.lg_page_size = 10; } ap = (desc >> 4) & 3; break; @@ -530,14 +530,14 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address, g_assert_not_reached(); } } - result->prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); - result->prot |= result->prot ? PAGE_EXEC : 0; - if (!(result->prot & (1 << access_type))) { + result->f.prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); + result->f.prot |= result->f.prot ? PAGE_EXEC : 0; + if (!(result->f.prot & (1 << access_type))) { /* Access permission fault. */ fi->type = ARMFault_Permission; goto do_fault; } - result->phys = phys_addr; + result->f.phys_addr = phys_addr; return false; do_fault: fi->domain = domain; @@ -607,11 +607,11 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, phys_addr = (desc & 0xff000000) | (address & 0x00ffffff); phys_addr |= (uint64_t)extract32(desc, 20, 4) << 32; phys_addr |= (uint64_t)extract32(desc, 5, 4) << 36; - result->page_size = 0x1000000; + result->f.lg_page_size = 24; /* 16MB */ } else { /* Section. */ phys_addr = (desc & 0xfff00000) | (address & 0x000fffff); - result->page_size = 0x100000; + result->f.lg_page_size = 20; /* 1MB */ } ap = ((desc >> 10) & 3) | ((desc >> 13) & 4); xn = desc & (1 << 4); @@ -636,12 +636,12 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, case 1: /* 64k page. */ phys_addr = (desc & 0xffff0000) | (address & 0xffff); xn = desc & (1 << 15); - result->page_size = 0x10000; + result->f.lg_page_size = 16; break; case 2: case 3: /* 4k page. */ phys_addr = (desc & 0xfffff000) | (address & 0xfff); xn = desc & 1; - result->page_size = 0x1000; + result->f.lg_page_size = 12; break; default: /* Never happens, but compiler isn't smart enough to tell. */ @@ -649,7 +649,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, } } if (domain_prot == 3) { - result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; } else { if (pxn && !regime_is_user(env, mmu_idx)) { xn = 1; @@ -667,14 +667,14 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, fi->type = ARMFault_AccessFlag; goto do_fault; } - result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1); + result->f.prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1); } else { - result->prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); + result->f.prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot); } - if (result->prot && !xn) { - result->prot |= PAGE_EXEC; + if (result->f.prot && !xn) { + result->f.prot |= PAGE_EXEC; } - if (!(result->prot & (1 << access_type))) { + if (!(result->f.prot & (1 << access_type))) { /* Access permission fault. */ fi->type = ARMFault_Permission; goto do_fault; @@ -685,9 +685,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, * the CPU doesn't support TZ or this is a non-secure translation * regime, because the attribute will already be non-secure. */ - result->attrs.secure = false; + result->f.attrs.secure = false; } - result->phys = phys_addr; + result->f.phys_addr = phys_addr; return false; do_fault: fi->domain = domain; @@ -1298,16 +1298,16 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) { ns = mmu_idx == ARMMMUIdx_Stage2; xn = extract32(attrs, 11, 2); - result->prot = get_S2prot(env, ap, xn, s1_is_el0); + result->f.prot = get_S2prot(env, ap, xn, s1_is_el0); } else { ns = extract32(attrs, 3, 1); xn = extract32(attrs, 12, 1); pxn = extract32(attrs, 11, 1); - result->prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn); + result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn); } fault_type = ARMFault_Permission; - if (!(result->prot & (1 << access_type))) { + if (!(result->f.prot & (1 << access_type))) { goto do_fault; } @@ -1317,11 +1317,11 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, * the CPU doesn't support TZ or this is a non-secure translation * regime, because the attribute will already be non-secure. */ - result->attrs.secure = false; + result->f.attrs.secure = false; } /* When in aarch64 mode, and BTI is enabled, remember GP in the IOTLB. */ if (aarch64 && guarded && cpu_isar_feature(aa64_bti, cpu)) { - arm_tlb_bti_gp(&result->attrs) = true; + arm_tlb_bti_gp(&result->f.attrs) = true; } if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) { @@ -1347,8 +1347,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, result->cacheattrs.shareability = extract32(attrs, 6, 2); } - result->phys = descaddr; - result->page_size = page_size; + result->f.phys_addr = descaddr; + result->f.lg_page_size = ctz64(page_size); return false; do_fault: @@ -1373,12 +1373,12 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, if (regime_translation_disabled(env, mmu_idx, is_secure)) { /* MPU disabled. */ - result->phys = address; - result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + result->f.phys_addr = address; + result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; return false; } - result->phys = address; + result->f.phys_addr = address; for (n = 7; n >= 0; n--) { base = env->cp15.c6_region[n]; if ((base & 1) == 0) { @@ -1414,16 +1414,16 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, fi->level = 1; return true; } - result->prot = PAGE_READ | PAGE_WRITE; + result->f.prot = PAGE_READ | PAGE_WRITE; break; case 2: - result->prot = PAGE_READ; + result->f.prot = PAGE_READ; if (!is_user) { - result->prot |= PAGE_WRITE; + result->f.prot |= PAGE_WRITE; } break; case 3: - result->prot = PAGE_READ | PAGE_WRITE; + result->f.prot = PAGE_READ | PAGE_WRITE; break; case 5: if (is_user) { @@ -1431,10 +1431,10 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, fi->level = 1; return true; } - result->prot = PAGE_READ; + result->f.prot = PAGE_READ; break; case 6: - result->prot = PAGE_READ; + result->f.prot = PAGE_READ; break; default: /* Bad permission. */ @@ -1442,12 +1442,12 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address, fi->level = 1; return true; } - result->prot |= PAGE_EXEC; + result->f.prot |= PAGE_EXEC; return false; } static void get_phys_addr_pmsav7_default(CPUARMState *env, ARMMMUIdx mmu_idx, - int32_t address, int *prot) + int32_t address, uint8_t *prot) { if (!arm_feature(env, ARM_FEATURE_M)) { *prot = PAGE_READ | PAGE_WRITE; @@ -1531,9 +1531,9 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, int n; bool is_user = regime_is_user(env, mmu_idx); - result->phys = address; - result->page_size = TARGET_PAGE_SIZE; - result->prot = 0; + result->f.phys_addr = address; + result->f.lg_page_size = TARGET_PAGE_BITS; + result->f.prot = 0; if (regime_translation_disabled(env, mmu_idx, secure) || m_is_ppb_region(env, address)) { @@ -1545,7 +1545,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, * which always does a direct read using address_space_ldl(), rather * than going via this function, so we don't need to check that here. */ - get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot); + get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->f.prot); } else { /* MPU enabled */ for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) { /* region search */ @@ -1587,7 +1587,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, if (ranges_overlap(base, rmask, address & TARGET_PAGE_MASK, TARGET_PAGE_SIZE)) { - result->page_size = 1; + result->f.lg_page_size = 0; } continue; } @@ -1625,7 +1625,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, continue; } if (rsize < TARGET_PAGE_BITS) { - result->page_size = 1 << rsize; + result->f.lg_page_size = rsize; } break; } @@ -1636,7 +1636,8 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, fi->type = ARMFault_Background; return true; } - get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot); + get_phys_addr_pmsav7_default(env, mmu_idx, address, + &result->f.prot); } else { /* a MPU hit! */ uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3); uint32_t xn = extract32(env->pmsav7.dracr[n], 12, 1); @@ -1653,16 +1654,16 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, case 5: break; /* no access */ case 3: - result->prot |= PAGE_WRITE; + result->f.prot |= PAGE_WRITE; /* fall through */ case 2: case 6: - result->prot |= PAGE_READ | PAGE_EXEC; + result->f.prot |= PAGE_READ | PAGE_EXEC; break; case 7: /* for v7M, same as 6; for R profile a reserved value */ if (arm_feature(env, ARM_FEATURE_M)) { - result->prot |= PAGE_READ | PAGE_EXEC; + result->f.prot |= PAGE_READ | PAGE_EXEC; break; } /* fall through */ @@ -1678,16 +1679,16 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, case 1: case 2: case 3: - result->prot |= PAGE_WRITE; + result->f.prot |= PAGE_WRITE; /* fall through */ case 5: case 6: - result->prot |= PAGE_READ | PAGE_EXEC; + result->f.prot |= PAGE_READ | PAGE_EXEC; break; case 7: /* for v7M, same as 6; for R profile a reserved value */ if (arm_feature(env, ARM_FEATURE_M)) { - result->prot |= PAGE_READ | PAGE_EXEC; + result->f.prot |= PAGE_READ | PAGE_EXEC; break; } /* fall through */ @@ -1700,14 +1701,14 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, /* execute never */ if (xn) { - result->prot &= ~PAGE_EXEC; + result->f.prot &= ~PAGE_EXEC; } } } fi->type = ARMFault_Permission; fi->level = 1; - return !(result->prot & (1 << access_type)); + return !(result->f.prot & (1 << access_type)); } bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, @@ -1733,9 +1734,9 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, uint32_t addr_page_base = address & TARGET_PAGE_MASK; uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1); - result->page_size = TARGET_PAGE_SIZE; - result->phys = address; - result->prot = 0; + result->f.lg_page_size = TARGET_PAGE_BITS; + result->f.phys_addr = address; + result->f.prot = 0; if (mregion) { *mregion = -1; } @@ -1785,13 +1786,13 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, ranges_overlap(base, limit - base + 1, addr_page_base, TARGET_PAGE_SIZE)) { - result->page_size = 1; + result->f.lg_page_size = 0; } continue; } if (base > addr_page_base || limit < addr_page_limit) { - result->page_size = 1; + result->f.lg_page_size = 0; } if (matchregion != -1) { @@ -1817,7 +1818,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, if (matchregion == -1) { /* hit using the background region */ - get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot); + get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->f.prot); } else { uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2); uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1); @@ -1832,9 +1833,9 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, xn = 1; } - result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap); - if (result->prot && !xn && !(pxn && !is_user)) { - result->prot |= PAGE_EXEC; + result->f.prot = simple_ap_to_rw_prot(env, mmu_idx, ap); + if (result->f.prot && !xn && !(pxn && !is_user)) { + result->f.prot |= PAGE_EXEC; } /* * We don't need to look the attribute up in the MAIR0/MAIR1 @@ -1847,7 +1848,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, fi->type = ARMFault_Permission; fi->level = 1; - return !(result->prot & (1 << access_type)); + return !(result->f.prot & (1 << access_type)); } static bool v8m_is_sau_exempt(CPUARMState *env, @@ -2011,9 +2012,9 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, } else { fi->type = ARMFault_QEMU_SFault; } - result->page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE; - result->phys = address; - result->prot = 0; + result->f.lg_page_size = sattrs.subpage ? 0 : TARGET_PAGE_BITS; + result->f.phys_addr = address; + result->f.prot = 0; return true; } } else { @@ -2023,7 +2024,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, * might downgrade a secure access to nonsecure. */ if (sattrs.ns) { - result->attrs.secure = false; + result->f.attrs.secure = false; } else if (!secure) { /* * NS access to S memory must fault. @@ -2036,9 +2037,9 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, * for M_FAKE_FSR_SFAULT in arm_v7m_cpu_do_interrupt(). */ fi->type = ARMFault_QEMU_SFault; - result->page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE; - result->phys = address; - result->prot = 0; + result->f.lg_page_size = sattrs.subpage ? 0 : TARGET_PAGE_BITS; + result->f.phys_addr = address; + result->f.prot = 0; return true; } } @@ -2047,7 +2048,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address, ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, secure, result, fi, NULL); if (sattrs.subpage) { - result->page_size = 1; + result->f.lg_page_size = 0; } return ret; } @@ -2338,9 +2339,9 @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address, result->cacheattrs.is_s2_format = false; } - result->phys = address; - result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; - result->page_size = TARGET_PAGE_SIZE; + result->f.phys_addr = address; + result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC; + result->f.lg_page_size = TARGET_PAGE_BITS; result->cacheattrs.shareability = shareability; result->cacheattrs.attrs = memattr; return 0; @@ -2377,8 +2378,8 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, return ret; } - ipa = result->phys; - ipa_secure = result->attrs.secure; + ipa = result->f.phys_addr; + ipa_secure = result->f.attrs.secure; if (is_secure) { /* Select TCR based on the NS bit from the S1 walk. */ s2walk_secure = !(ipa_secure @@ -2398,7 +2399,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, * Save the stage1 results so that we may merge * prot and cacheattrs later. */ - s1_prot = result->prot; + s1_prot = result->f.prot; cacheattrs1 = result->cacheattrs; memset(result, 0, sizeof(*result)); @@ -2407,7 +2408,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, fi->s2addr = ipa; /* Combine the S1 and S2 perms. */ - result->prot &= s1_prot; + result->f.prot &= s1_prot; /* If S2 fails, return early. */ if (ret) { @@ -2436,7 +2437,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, * Check if IPA translates to secure or non-secure PA space. * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA. */ - result->attrs.secure = + result->f.attrs.secure = (is_secure && !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)) && (ipa_secure @@ -2456,8 +2457,8 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, * cannot upgrade an non-secure translation regime's attributes * to secure. */ - result->attrs.secure = is_secure; - result->attrs.user = regime_is_user(env, mmu_idx); + result->f.attrs.secure = is_secure; + result->f.attrs.user = regime_is_user(env, mmu_idx); /* * Fast Context Switch Extension. This doesn't exist at all in v8. @@ -2474,7 +2475,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, if (arm_feature(env, ARM_FEATURE_PMSA)) { bool ret; - result->page_size = TARGET_PAGE_SIZE; + result->f.lg_page_size = TARGET_PAGE_BITS; if (arm_feature(env, ARM_FEATURE_V8)) { /* PMSAv8 */ @@ -2495,9 +2496,9 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, (access_type == MMU_DATA_STORE ? "writing" : "execute"), (uint32_t)address, mmu_idx, ret ? "Miss" : "Hit", - result->prot & PAGE_READ ? 'r' : '-', - result->prot & PAGE_WRITE ? 'w' : '-', - result->prot & PAGE_EXEC ? 'x' : '-'); + result->f.prot & PAGE_READ ? 'r' : '-', + result->f.prot & PAGE_WRITE ? 'w' : '-', + result->f.prot & PAGE_EXEC ? 'x' : '-'); return ret; } @@ -2572,10 +2573,10 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, bool ret; ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &res, &fi); - *attrs = res.attrs; + *attrs = res.f.attrs; if (ret) { return -1; } - return res.phys; + return res.f.phys_addr; } diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c index ad225b1cb2..49601394ec 100644 --- a/target/arm/tlb_helper.c +++ b/target/arm/tlb_helper.c @@ -227,17 +227,16 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size, * target page size are handled specially, so for those we * pass in the exact addresses. */ - if (res.page_size >= TARGET_PAGE_SIZE) { - res.phys &= TARGET_PAGE_MASK; + if (res.f.lg_page_size >= TARGET_PAGE_BITS) { + res.f.phys_addr &= TARGET_PAGE_MASK; address &= TARGET_PAGE_MASK; } /* Notice and record tagged memory. */ if (cpu_isar_feature(aa64_mte, cpu) && res.cacheattrs.attrs == 0xf0) { - arm_tlb_mte_tagged(&res.attrs) = true; + arm_tlb_mte_tagged(&res.f.attrs) = true; } - tlb_set_page_with_attrs(cs, address, res.phys, res.attrs, - res.prot, mmu_idx, res.page_size); + tlb_set_page_full(cs, mmu_idx, address, &res.f); return true; } else if (probe) { return false; From 0ff993193fe759b735e382fbe06b8258b537f95d Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Mon, 3 Oct 2022 16:56:41 +0200 Subject: [PATCH 1016/1020] hw/arm/boot: set CPTR_EL3.ESM and SCR_EL3.EnTP2 when booting Linux with EL3 According to the Linux kernel booting.rst [1], CPTR_EL3.ESM and SCR_EL3.EnTP2 must be initialized to 1 when EL3 is present and FEAT_SME is advertised. This has to be taken care of when QEMU boots directly into the kernel (i.e., "-M virt,secure=on -cpu max -kernel Image"). Cc: qemu-stable@nongnu.org Fixes: 78cb9776662a ("target/arm: Enable SME for -cpu max") Link: [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/arm64/booting.rst?h=v6.0#n321 Signed-off-by: Jerome Forissier Message-id: 20221003145641.1921467-1-jerome.forissier@linaro.org Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/arm/boot.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index ada2717f76..ee3858b673 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -763,6 +763,10 @@ static void do_cpu_reset(void *opaque) if (cpu_isar_feature(aa64_sve, cpu)) { env->cp15.cptr_el[3] |= R_CPTR_EL3_EZ_MASK; } + if (cpu_isar_feature(aa64_sme, cpu)) { + env->cp15.cptr_el[3] |= R_CPTR_EL3_ESM_MASK; + env->cp15.scr_el3 |= SCR_ENTP2; + } /* AArch64 kernels never boot in secure mode */ assert(!info->secure_boot); /* This hook is only supported for AArch32 currently: From 104f703d93c9f12984a165985af653f83527c84e Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 3 Oct 2022 17:23:13 +0100 Subject: [PATCH 1017/1020] target/arm: Don't allow guest to use unimplemented granule sizes Arm CPUs support some subset of the granule (page) sizes 4K, 16K and 64K. The guest selects the one it wants using bits in the TCR_ELx registers. If it tries to program these registers with a value that is either reserved or which requests a size that the CPU does not implement, the architecture requires that the CPU behaves as if the field was programmed to some size that has been implemented. Currently we don't implement this, and instead let the guest use any granule size, even if the CPU ID register fields say it isn't present. Make aa64_va_parameters() check against the supported granule size and force use of a different one if it is not implemented. (A subsequent commit will make ARMVAParameters use the new enum rather than the current pair of using16k/using64k bools.) Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20221003162315.2833797-2-peter.maydell@linaro.org --- target/arm/cpu.h | 33 +++++++++++++ target/arm/helper.c | 102 +++++++++++++++++++++++++++++++++++++---- target/arm/internals.h | 9 ++++ 3 files changed, 136 insertions(+), 8 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index d541392170..1a909a1b43 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -4097,6 +4097,39 @@ static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id) return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id)); } +static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0; +} + +static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id) +{ + return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1; +} + +static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id) +{ + return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0; +} + +static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id)); +} + +static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id)); +} + +static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id) +{ + unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2); + return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id)); +} + static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id) { return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0; diff --git a/target/arm/helper.c b/target/arm/helper.c index e1338ed6e2..d7f578f2ba 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -10287,20 +10287,105 @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx) } } +static ARMGranuleSize tg0_to_gran_size(int tg) +{ + switch (tg) { + case 0: + return Gran4K; + case 1: + return Gran64K; + case 2: + return Gran16K; + default: + return GranInvalid; + } +} + +static ARMGranuleSize tg1_to_gran_size(int tg) +{ + switch (tg) { + case 1: + return Gran16K; + case 2: + return Gran4K; + case 3: + return Gran64K; + default: + return GranInvalid; + } +} + +static inline bool have4k(ARMCPU *cpu, bool stage2) +{ + return stage2 ? cpu_isar_feature(aa64_tgran4_2, cpu) + : cpu_isar_feature(aa64_tgran4, cpu); +} + +static inline bool have16k(ARMCPU *cpu, bool stage2) +{ + return stage2 ? cpu_isar_feature(aa64_tgran16_2, cpu) + : cpu_isar_feature(aa64_tgran16, cpu); +} + +static inline bool have64k(ARMCPU *cpu, bool stage2) +{ + return stage2 ? cpu_isar_feature(aa64_tgran64_2, cpu) + : cpu_isar_feature(aa64_tgran64, cpu); +} + +static ARMGranuleSize sanitize_gran_size(ARMCPU *cpu, ARMGranuleSize gran, + bool stage2) +{ + switch (gran) { + case Gran4K: + if (have4k(cpu, stage2)) { + return gran; + } + break; + case Gran16K: + if (have16k(cpu, stage2)) { + return gran; + } + break; + case Gran64K: + if (have64k(cpu, stage2)) { + return gran; + } + break; + case GranInvalid: + break; + } + /* + * If the guest selects a granule size that isn't implemented, + * the architecture requires that we behave as if it selected one + * that is (with an IMPDEF choice of which one to pick). We choose + * to implement the smallest supported granule size. + */ + if (have4k(cpu, stage2)) { + return Gran4K; + } + if (have16k(cpu, stage2)) { + return Gran16K; + } + assert(have64k(cpu, stage2)); + return Gran64K; +} + ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, ARMMMUIdx mmu_idx, bool data) { uint64_t tcr = regime_tcr(env, mmu_idx); bool epd, hpd, using16k, using64k, tsz_oob, ds; int select, tsz, tbi, max_tsz, min_tsz, ps, sh; + ARMGranuleSize gran; ARMCPU *cpu = env_archcpu(env); + bool stage2 = mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S; if (!regime_has_2_ranges(mmu_idx)) { select = 0; tsz = extract32(tcr, 0, 6); - using64k = extract32(tcr, 14, 1); - using16k = extract32(tcr, 15, 1); - if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) { + gran = tg0_to_gran_size(extract32(tcr, 14, 2)); + if (stage2) { /* VTCR_EL2 */ hpd = false; } else { @@ -10318,16 +10403,13 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, select = extract64(va, 55, 1); if (!select) { tsz = extract32(tcr, 0, 6); + gran = tg0_to_gran_size(extract32(tcr, 14, 2)); epd = extract32(tcr, 7, 1); sh = extract32(tcr, 12, 2); - using64k = extract32(tcr, 14, 1); - using16k = extract32(tcr, 15, 1); hpd = extract64(tcr, 41, 1); } else { - int tg = extract32(tcr, 30, 2); - using16k = tg == 1; - using64k = tg == 3; tsz = extract32(tcr, 16, 6); + gran = tg1_to_gran_size(extract32(tcr, 30, 2)); epd = extract32(tcr, 23, 1); sh = extract32(tcr, 28, 2); hpd = extract64(tcr, 42, 1); @@ -10336,6 +10418,10 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, ds = extract64(tcr, 59, 1); } + gran = sanitize_gran_size(cpu, gran, stage2); + using64k = gran == Gran64K; + using16k = gran == Gran16K; + if (cpu_isar_feature(aa64_st, cpu)) { max_tsz = 48 - using64k; } else { diff --git a/target/arm/internals.h b/target/arm/internals.h index fd17aee459..6166ac0a98 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -998,6 +998,15 @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id) return valid; } +/* Granule size (i.e. page size) */ +typedef enum ARMGranuleSize { + /* Same order as TG0 encoding */ + Gran4K, + Gran64K, + Gran16K, + GranInvalid, +} ARMGranuleSize; + /* * Parameters of a given virtual address, as extracted from the * translation control register (TCR) for a given regime. From 3c003f7029eb322c15f137b33af1120096e14f4d Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 3 Oct 2022 17:23:14 +0100 Subject: [PATCH 1018/1020] target/arm: Use ARMGranuleSize in ARMVAParameters Now we have an enum for the granule size, use it in the ARMVAParameters struct instead of the using16k/using64k bools. Signed-off-by: Peter Maydell Reviewed-by: Richard Henderson Message-id: 20221003162315.2833797-3-peter.maydell@linaro.org --- target/arm/helper.c | 39 ++++++++++++++++++++++++++++----------- target/arm/internals.h | 23 +++++++++++++++++++++-- target/arm/ptw.c | 8 +------- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/target/arm/helper.c b/target/arm/helper.c index d7f578f2ba..dde64a487a 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -4473,6 +4473,24 @@ typedef struct { uint64_t length; } TLBIRange; +static ARMGranuleSize tlbi_range_tg_to_gran_size(int tg) +{ + /* + * Note that the TLBI range TG field encoding differs from both + * TG0 and TG1 encodings. + */ + switch (tg) { + case 1: + return Gran4K; + case 2: + return Gran16K; + case 3: + return Gran64K; + default: + return GranInvalid; + } +} + static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, uint64_t value) { @@ -4481,17 +4499,19 @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx, uint64_t select = sextract64(value, 36, 1); ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true); TLBIRange ret = { }; + ARMGranuleSize gran; page_size_granule = extract64(value, 46, 2); + gran = tlbi_range_tg_to_gran_size(page_size_granule); /* The granule encoded in value must match the granule in use. */ - if (page_size_granule != (param.using64k ? 3 : param.using16k ? 2 : 1)) { + if (gran != param.gran) { qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\n", page_size_granule); return ret; } - page_shift = (page_size_granule - 1) * 2 + 12; + page_shift = arm_granule_bits(gran); num = extract64(value, 39, 5); scale = extract64(value, 44, 2); exponent = (5 * scale) + 1; @@ -10375,7 +10395,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, ARMMMUIdx mmu_idx, bool data) { uint64_t tcr = regime_tcr(env, mmu_idx); - bool epd, hpd, using16k, using64k, tsz_oob, ds; + bool epd, hpd, tsz_oob, ds; int select, tsz, tbi, max_tsz, min_tsz, ps, sh; ARMGranuleSize gran; ARMCPU *cpu = env_archcpu(env); @@ -10419,11 +10439,9 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, } gran = sanitize_gran_size(cpu, gran, stage2); - using64k = gran == Gran64K; - using16k = gran == Gran16K; if (cpu_isar_feature(aa64_st, cpu)) { - max_tsz = 48 - using64k; + max_tsz = 48 - (gran == Gran64K); } else { max_tsz = 39; } @@ -10433,7 +10451,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, * adjust the effective value of DS, as documented. */ min_tsz = 16; - if (using64k) { + if (gran == Gran64K) { if (cpu_isar_feature(aa64_lva, cpu)) { min_tsz = 12; } @@ -10442,14 +10460,14 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, switch (mmu_idx) { case ARMMMUIdx_Stage2: case ARMMMUIdx_Stage2_S: - if (using16k) { + if (gran == Gran16K) { ds = cpu_isar_feature(aa64_tgran16_2_lpa2, cpu); } else { ds = cpu_isar_feature(aa64_tgran4_2_lpa2, cpu); } break; default: - if (using16k) { + if (gran == Gran16K) { ds = cpu_isar_feature(aa64_tgran16_lpa2, cpu); } else { ds = cpu_isar_feature(aa64_tgran4_lpa2, cpu); @@ -10486,10 +10504,9 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, .tbi = tbi, .epd = epd, .hpd = hpd, - .using16k = using16k, - .using64k = using64k, .tsz_oob = tsz_oob, .ds = ds, + .gran = gran, }; } diff --git a/target/arm/internals.h b/target/arm/internals.h index 6166ac0a98..9566364dca 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -1007,6 +1007,26 @@ typedef enum ARMGranuleSize { GranInvalid, } ARMGranuleSize; +/** + * arm_granule_bits: Return address size of the granule in bits + * + * Return the address size of the granule in bits. This corresponds + * to the pseudocode TGxGranuleBits(). + */ +static inline int arm_granule_bits(ARMGranuleSize gran) +{ + switch (gran) { + case Gran64K: + return 16; + case Gran16K: + return 14; + case Gran4K: + return 12; + default: + g_assert_not_reached(); + } +} + /* * Parameters of a given virtual address, as extracted from the * translation control register (TCR) for a given regime. @@ -1019,10 +1039,9 @@ typedef struct ARMVAParameters { bool tbi : 1; bool epd : 1; bool hpd : 1; - bool using16k : 1; - bool using64k : 1; bool tsz_oob : 1; /* tsz has been clamped to legal range */ bool ds : 1; + ARMGranuleSize gran : 2; } ARMVAParameters; ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va, diff --git a/target/arm/ptw.c b/target/arm/ptw.c index ddacffa7ee..23f16f4ff7 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -1062,13 +1062,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address, } } - if (param.using64k) { - stride = 13; - } else if (param.using16k) { - stride = 11; - } else { - stride = 9; - } + stride = arm_granule_bits(param.gran) - 3; /* * Note that QEMU ignores shareability and cacheability attributes, From 915f62844cf62e428c7c178149b5ff1cbe129b07 Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Mon, 3 Oct 2022 17:23:15 +0100 Subject: [PATCH 1019/1020] docs/system/arm/emulation.rst: Report FEAT_GTG support FEAT_GTG is a change tho the ID register ID_AA64MMFR0_EL1 so that it can report a different set of supported granule (page) sizes for stage 1 and stage 2 translation tables. As of commit c20281b2a5048 we already report the granule sizes that way for '-cpu max', and now we also correctly make attempts to use unimplemented granule sizes fail, so we can report the support of the feature in the documentation. Reviewed-by: Richard Henderson Signed-off-by: Peter Maydell Message-id: 20221003162315.2833797-4-peter.maydell@linaro.org --- docs/system/arm/emulation.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst index be7bbffe59..cfb4b0768b 100644 --- a/docs/system/arm/emulation.rst +++ b/docs/system/arm/emulation.rst @@ -31,6 +31,7 @@ the following architecture extensions: - FEAT_FRINTTS (Floating-point to integer instructions) - FEAT_FlagM (Flag manipulation instructions v2) - FEAT_FlagM2 (Enhancements to flag manipulation instructions) +- FEAT_GTG (Guest translation granule size) - FEAT_HCX (Support for the HCRX_EL2 register) - FEAT_HPDS (Hierarchical permission disables) - FEAT_I8MM (AArch64 Int8 matrix multiplication instructions) From fde10960ed6a6435d89315d4fd3af9d0b51aebb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Tue, 11 Oct 2022 12:34:16 +0100 Subject: [PATCH 1020/1020] Revert "configure: build ROMs with container-based cross compilers" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 730fe750fba63023e294ff0acf0f874369f1946f. Unconditionally building all the bios for all arches was a little too far too fast. Signed-off-by: Alex Bennée Cc: Paolo Bonzini Reviewed-by: Daniel Henrique Barboza Tested-by: Daniel Henrique Barboza Message-Id: <20221011113417.794841-4-alex.bennee@linaro.org> --- configure | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/configure b/configure index baa69189f0..45ee6f4eb3 100755 --- a/configure +++ b/configure @@ -2121,7 +2121,7 @@ probe_target_compiler() { target_ranlib= target_strip= fi - test -n "$target_cc" || test -n "$container_image" + test -n "$target_cc" } write_target_makefile() { @@ -2268,7 +2268,7 @@ if test "$targetos" != "darwin" && test "$targetos" != "sunos" && \ config_mak=pc-bios/optionrom/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak echo "TOPSRC_DIR=$source_path" >> $config_mak - write_target_makefile pc-bios/optionrom/all >> $config_mak + write_target_makefile >> $config_mak fi if test "$softmmu" = yes && probe_target_compiler ppc-softmmu; then @@ -2276,31 +2276,25 @@ if test "$softmmu" = yes && probe_target_compiler ppc-softmmu; then config_mak=pc-bios/vof/config.mak echo "# Automatically generated by configure - do not modify" > $config_mak echo "SRC_DIR=$source_path/pc-bios/vof" >> $config_mak - write_target_makefile pc-bios/vof/all >> $config_mak + write_target_makefile >> $config_mak fi # Only build s390-ccw bios if the compiler has -march=z900 or -march=z10 # (which is the lowest architecture level that Clang supports) if test "$softmmu" = yes && probe_target_compiler s390x-softmmu; then - got_cross_cc=no - if test -n "$target_cc"; then - write_c_skeleton - do_compiler "$target_cc" $target_cc_cflags -march=z900 -o $TMPO -c $TMPC - has_z900=$? - if [ $has_z900 = 0 ] || do_compiler "$target_cc" $target_cc_cflags -march=z10 -msoft-float -Werror -o $TMPO -c $TMPC; then - if [ $has_z900 != 0 ]; then - echo "WARNING: Your compiler does not support the z900!" - echo " The s390-ccw bios will only work with guest CPUs >= z10." - fi - got_cross_cc=yes + write_c_skeleton + do_compiler "$target_cc" $target_cc_cflags -march=z900 -o $TMPO -c $TMPC + has_z900=$? + if [ $has_z900 = 0 ] || do_compiler "$target_cc" $target_cc_cflags -march=z10 -msoft-float -Werror -o $TMPO -c $TMPC; then + if [ $has_z900 != 0 ]; then + echo "WARNING: Your compiler does not support the z900!" + echo " The s390-ccw bios will only work with guest CPUs >= z10." fi - fi - if test "$got_cross_cc" = yes || test -n "$container_image"; then roms="$roms pc-bios/s390-ccw" config_mak=pc-bios/s390-ccw/config-host.mak echo "# Automatically generated by configure - do not modify" > $config_mak echo "SRC_PATH=$source_path/pc-bios/s390-ccw" >> $config_mak - write_target_makefile pc-bios/s390-ccw/all >> $config_mak + write_target_makefile >> $config_mak # SLOF is required for building the s390-ccw firmware on s390x, # since it is using the libnet code from SLOF for network booting. git_submodules="${git_submodules} roms/SLOF" @@ -2488,7 +2482,7 @@ for target in $target_list; do ;; esac - if probe_target_compiler $target; then + if probe_target_compiler $target || test -n "$container_image"; then test -n "$container_image" && build_static=y mkdir -p "tests/tcg/$target" config_target_mak=tests/tcg/$target/config-target.mak